WIP: URI Parser and TLS
Signed-off-by: Vasiliy Doylov <nekocwd@mainlining.org>
This commit is contained in:
parent
e432987032
commit
95e1c233e7
7 changed files with 221 additions and 5 deletions
3
src/logic/error.vala
Normal file
3
src/logic/error.vala
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
errordomain ParseError {
|
||||||
|
NOT_IMPLEMENTED,
|
||||||
|
}
|
|
@ -13,4 +13,6 @@ singularity_sources += [
|
||||||
outbounds_sources,
|
outbounds_sources,
|
||||||
transports_sources,
|
transports_sources,
|
||||||
config_sources,
|
config_sources,
|
||||||
|
'logic/tls.vala',
|
||||||
|
'logic/error.vala',
|
||||||
]
|
]
|
||||||
|
|
|
@ -2,4 +2,5 @@ outbounds_sources = [
|
||||||
'logic/outbounds/outbound.vala',
|
'logic/outbounds/outbound.vala',
|
||||||
'logic/outbounds/dial.vala',
|
'logic/outbounds/dial.vala',
|
||||||
'logic/outbounds/trojan.vala',
|
'logic/outbounds/trojan.vala',
|
||||||
|
'logic/outbounds/vless.vala',
|
||||||
]
|
]
|
||||||
|
|
|
@ -17,8 +17,120 @@
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Singularity.Outbound.Outbound : Object, Json.Serializable {
|
class Singularity.Outbound.Outbound : Object, Json.Serializable {
|
||||||
// We can't use name `type` in vala
|
// We can't use name `type` in vala
|
||||||
public string type_name { get; construct set; default = ""; }
|
public string type_name { get; construct set; default = ""; }
|
||||||
public string tag { get; set; default = ""; }
|
public string tag { get; set; default = "proxy"; }
|
||||||
|
|
||||||
|
public static Outbound parse_uri (string profile) throws UriError, ParseError {
|
||||||
|
Uri uri = null;
|
||||||
|
uri = Uri.parse (profile, UriFlags.HAS_PASSWORD | UriFlags.NON_DNS | UriFlags.PARSE_RELAXED);
|
||||||
|
|
||||||
|
var scheme = uri.get_scheme ();
|
||||||
|
if (!(scheme == "trojan" || scheme == "vless"))// Stupid check for now
|
||||||
|
throw new ParseError.NOT_IMPLEMENTED ("Protocol %s not implemented yet", scheme);
|
||||||
|
|
||||||
|
var host = uri.get_host ();
|
||||||
|
var port = uri.get_port ();
|
||||||
|
var user = uri.get_user ();
|
||||||
|
var name = uri.get_fragment ();
|
||||||
|
HashTable<string, string> params = null;
|
||||||
|
|
||||||
|
if (uri.get_query () != null) {
|
||||||
|
params = Uri.parse_params (uri.get_query ());
|
||||||
|
} else {
|
||||||
|
params = new HashTable<string, string> (null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Outbound outbound = null;
|
||||||
|
TLS tls = null;
|
||||||
|
Transport.Transport transport = null;
|
||||||
|
tls = new TLS (){
|
||||||
|
enabled = true,
|
||||||
|
insecure = true,
|
||||||
|
server_name = params["sni"]
|
||||||
|
};
|
||||||
|
|
||||||
|
params["type"] = params["headerType"] ?? params["type"];
|
||||||
|
switch (params["type"] ?? "none") {
|
||||||
|
case "ws":
|
||||||
|
var ws = new Transport.WebSocket () {
|
||||||
|
path = params["path"],
|
||||||
|
};
|
||||||
|
ws.headers["Host"] = params["host"];
|
||||||
|
transport = ws;
|
||||||
|
break;
|
||||||
|
case "grpc":
|
||||||
|
transport = new Transport.GRPC () {
|
||||||
|
service_name = params["serviceName"],
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case "httpupgrade":
|
||||||
|
transport = new Transport.HttpUpgrade () {
|
||||||
|
path = params["path"],
|
||||||
|
host = params["host"],
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case "http":
|
||||||
|
var t = new Transport.Http () {
|
||||||
|
path = params["path"],
|
||||||
|
method = "GET",
|
||||||
|
};
|
||||||
|
t.headers["Host"] = params["host"];
|
||||||
|
transport = t;
|
||||||
|
break;
|
||||||
|
case "xhttp":
|
||||||
|
throw new ParseError.NOT_IMPLEMENTED ("Transport %s not implemented yet", params["type"]);
|
||||||
|
case "tcp":
|
||||||
|
case "none":
|
||||||
|
case "raw":
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
warning ("Unknown transport type %s", params["type"]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params["pbk"] != null) {
|
||||||
|
tls.reality = new TLS.Reality ();
|
||||||
|
tls.reality.enabled = true;
|
||||||
|
tls.reality.public_key = params["pbk"] ?? "";
|
||||||
|
tls.reality.short_id = params["sid"] ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (params["fp"] != null || tls.reality != null) {
|
||||||
|
tls.utls = new TLS.UTLS ();
|
||||||
|
tls.utls.enabled = true;
|
||||||
|
tls.utls.fingerprint = params["fp"];
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (scheme) {
|
||||||
|
case "vless":
|
||||||
|
outbound = new Vless () {
|
||||||
|
uuid = user,
|
||||||
|
server = host,
|
||||||
|
server_port = port,
|
||||||
|
transport = transport,
|
||||||
|
tls = tls,
|
||||||
|
packet_encoding = params["packetEncoding"]
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case "trojan":
|
||||||
|
outbound = new Trojan () {
|
||||||
|
password = user,
|
||||||
|
server = host,
|
||||||
|
server_port = port,
|
||||||
|
transport = transport,
|
||||||
|
tls = tls,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
warning ("Unknown scheme %s", scheme);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return outbound;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,7 @@ class Singularity.Outbound.Trojan : Dial, Json.Serializable {
|
||||||
public string network { get; set; default = null; }
|
public string network { get; set; default = null; }
|
||||||
public Transport.Transport transport { get; set; default = null; }
|
public Transport.Transport transport { get; set; default = null; }
|
||||||
|
|
||||||
/*
|
public TLS tls { get; set; default = null; }
|
||||||
* public TLS tls { get; set; default = null; }
|
|
||||||
* TODO: Implement TLS
|
|
||||||
*/
|
|
||||||
/*
|
/*
|
||||||
* public Multiplex multiplex { get; set; default = null; }
|
* public Multiplex multiplex { get; set; default = null; }
|
||||||
* TODO: Implement Multiplex
|
* TODO: Implement Multiplex
|
||||||
|
@ -48,6 +45,9 @@ class Singularity.Outbound.Trojan : Dial, Json.Serializable {
|
||||||
Utils.fix_type (ref node);
|
Utils.fix_type (ref node);
|
||||||
Utils.fix_dash (ref node);
|
Utils.fix_dash (ref node);
|
||||||
}
|
}
|
||||||
|
if (property_name == "tls" && tls != null) {
|
||||||
|
Utils.fix_dash (ref node);
|
||||||
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
54
src/logic/outbounds/vless.vala
Normal file
54
src/logic/outbounds/vless.vala
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/* vless.vala
|
||||||
|
*
|
||||||
|
* Copyright 2025 Vasiliy Doylov (NekoCWD) <nekocwd@mainlining.org>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Vless outbound.
|
||||||
|
* DASH and TYPE FIX REQUIRED
|
||||||
|
*/
|
||||||
|
class Singularity.Outbound.Vless : Dial, Json.Serializable {
|
||||||
|
public string server { get; set; default = null; }
|
||||||
|
public int64 server_port { get; set; default = 1080; }
|
||||||
|
public string uuid { get; set; default = null; }
|
||||||
|
public string flow { get; set; default = null; }
|
||||||
|
public string network { get; set; default = null; }
|
||||||
|
public TLS tls { get; set; default = null; }
|
||||||
|
public string packet_encoding { get; set; default = null; }
|
||||||
|
public Transport.Transport transport { get; set; default = null; }
|
||||||
|
/*
|
||||||
|
* public Multiplex multiplex { get; set; default = null; }
|
||||||
|
* TODO: Implement Multiplex
|
||||||
|
*/
|
||||||
|
|
||||||
|
construct {
|
||||||
|
type_name = "vless";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Json.Node serialize_property (string property_name, GLib.Value value, GLib.ParamSpec pspec) {
|
||||||
|
var node = default_serialize_property (property_name, value, pspec);
|
||||||
|
if (property_name == "transport" && transport != null) {
|
||||||
|
Utils.fix_type (ref node);
|
||||||
|
Utils.fix_dash (ref node);
|
||||||
|
}
|
||||||
|
if (property_name == "tls" && tls != null) {
|
||||||
|
Utils.fix_dash (ref node);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
44
src/logic/tls.vala
Normal file
44
src/logic/tls.vala
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/* tls.vala
|
||||||
|
*
|
||||||
|
* Copyright 2025 Vasiliy Doylov (NekoCWD) <nekocwd@mainlining.org>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
class Singularity.TLS : Object, Json.Serializable {
|
||||||
|
public class Reality : Object, Json.Serializable {
|
||||||
|
public bool enabled { get; set; default = false; }
|
||||||
|
public string public_key { get; set; default = null; }
|
||||||
|
public string short_id { get; set; default = null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UTLS : Object, Json.Serializable {
|
||||||
|
public bool enabled { get; set; }
|
||||||
|
public string fingerprint { get; set; default = ""; }
|
||||||
|
}
|
||||||
|
public bool enabled { get; construct set; }
|
||||||
|
public bool insecure { get; construct set; }
|
||||||
|
public string server_name { get; set; default = null; }
|
||||||
|
public Reality reality { get; set; default = null; }
|
||||||
|
public UTLS utls { get; set; default = null; }
|
||||||
|
|
||||||
|
public override Json.Node serialize_property (string property_name, GLib.Value value, GLib.ParamSpec pspec) {
|
||||||
|
var node = default_serialize_property (property_name, value, pspec);
|
||||||
|
if (property_name == "reality" && reality != null) {
|
||||||
|
Utils.fix_dash (ref node);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue