diff --git a/Netch/Servers/VMess/Models/V2rayConfig.cs b/Netch/Servers/VMess/Models/V2rayConfig.cs new file mode 100644 index 00000000..88ece854 --- /dev/null +++ b/Netch/Servers/VMess/Models/V2rayConfig.cs @@ -0,0 +1,287 @@ +using System.Collections.Generic; + +namespace Netch.Servers.VMess.Models +{ + public class V2rayConfig + { + public List inbounds { get; set; } + + public List outbounds { get; set; } + + public Routing routing { get; set; } + } + + public class Inbounds + { + public string tag { get; set; } + + public int port { get; set; } + + public string listen { get; set; } + + public string protocol { get; set; } + + public Sniffing sniffing { get; set; } + + public Inboundsettings settings { get; set; } + + public StreamSettings streamSettings { get; set; } + } + + public class Inboundsettings + { + public string auth { get; set; } + + public bool udp { get; set; } + + public string ip { get; set; } + + public string address { get; set; } + + public List clients { get; set; } + + + public string decryption { get; set; } + } + + public class UsersItem + { + public string id { get; set; } + + public int alterId { get; set; } + + public string email { get; set; } + + public string security { get; set; } + + public string encryption { get; set; } + + public string flow { get; set; } + } + + public class Sniffing + { + public bool enabled { get; set; } + + public List destOverride { get; set; } + } + + public class Outbounds + { + public string tag { get; set; } + + public string protocol { get; set; } + + public Outboundsettings settings { get; set; } + + public StreamSettings streamSettings { get; set; } + + public Mux mux { get; set; } + } + + public class Outboundsettings + { + public List vnext { get; set; } + + public List servers { get; set; } + + public Response response { get; set; } + } + + public class VnextItem + { + public string address { get; set; } + + public int port { get; set; } + + public List users { get; set; } + } + + public class ServersItem + { + public string email { get; set; } + + public string address { get; set; } + + public string method { get; set; } + + public bool ota { get; set; } + + public string password { get; set; } + + public int port { get; set; } + + public int level { get; set; } + + public List users { get; set; } + } + + public class SocksUsersItem + { + public string user { get; set; } + + public string pass { get; set; } + + public int level { get; set; } + } + + + public class Mux + { + public bool enabled { get; set; } + + public int concurrency { get; set; } + } + + public class Response + { + public string type { get; set; } + } + + public class Dns + { + public List servers { get; set; } + } + + public class RulesItem + { + public string type { get; set; } + + public string port { get; set; } + + public List inboundTag { get; set; } + + public string outboundTag { get; set; } + + public List ip { get; set; } + + public List domain { get; set; } + } + + public class Routing + { + public string domainStrategy { get; set; } + + public List rules { get; set; } + } + + public class StreamSettings + { + public string network { get; set; } + + public string security { get; set; } + + public TlsSettings tlsSettings { get; set; } + + public TcpSettings tcpSettings { get; set; } + + public KcpSettings kcpSettings { get; set; } + + public WsSettings wsSettings { get; set; } + + public HttpSettings httpSettings { get; set; } + + public QuicSettings quicSettings { get; set; } + + public TlsSettings xtlsSettings { get; set; } + } + + public class TlsSettings + { + public bool allowInsecure { get; set; } + + public string serverName { get; set; } + } + + public class TcpSettings + { + public bool connectionReuse { get; set; } + + public Header header { get; set; } + } + + public class Header + { + public string type { get; set; } + + public TCPRequest request { get; set; } + + public object response { get; set; } + } + + public class TCPRequest + { + public string version = "1.1"; + + public string method = "GET"; + + public string path = "/"; + + public TCPRequestHeaders headers; + } + + + public class TCPRequestHeaders + { + public string Host; + + //public string User_Agent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36"; + + public string Accept_Encoding = "gzip, deflate"; + + public string Connection = "keep-alive"; + + public string Pragma = "no-cache"; + } + + public class KcpSettings + { + public int mtu { get; set; } + + public int tti { get; set; } + + public int uplinkCapacity { get; set; } + + public int downlinkCapacity { get; set; } + + public bool congestion { get; set; } + + public int readBufferSize { get; set; } + + public int writeBufferSize { get; set; } + + public Header header { get; set; } + + public string seed { get; set; } + } + + public class WsSettings + { + public bool connectionReuse { get; set; } + + public string path { get; set; } + + public Headers headers { get; set; } + } + + public class Headers + { + public string Host { get; set; } + } + + public class HttpSettings + { + public string path { get; set; } + + public List host { get; set; } + } + + public class QuicSettings + { + public string security { get; set; } + + public string key { get; set; } + + public Header header { get; set; } + } +} \ No newline at end of file diff --git a/Netch/Servers/VMess/Models/VMessJObject.cs b/Netch/Servers/VMess/Models/V2rayNSharing.cs similarity index 97% rename from Netch/Servers/VMess/Models/VMessJObject.cs rename to Netch/Servers/VMess/Models/V2rayNSharing.cs index dd4fd282..e63bfd09 100644 --- a/Netch/Servers/VMess/Models/VMessJObject.cs +++ b/Netch/Servers/VMess/Models/V2rayNSharing.cs @@ -3,7 +3,7 @@ /// /// 使用 v2rayN 定义的 VMess 链接格式 /// - public class VMessJObject + public class V2rayNSharing { /// /// 链接版本 diff --git a/Netch/Servers/VMess/Models/VMessConfig.cs b/Netch/Servers/VMess/Models/VMessConfig.cs deleted file mode 100644 index 02a171b3..00000000 --- a/Netch/Servers/VMess/Models/VMessConfig.cs +++ /dev/null @@ -1,206 +0,0 @@ -using System.Collections.Generic; - -namespace Netch.Servers.VMess.Models -{ - public class VMessConfig - { - public class InboundSettings - { - public bool udp = true; - } - - public class Inbounds - { - public string listen = "127.0.0.1"; - - public int port = 2801; - - public string protocol = "socks"; - - public InboundSettings settings; - } - - public class User - { - public string id; - - public int alterId; - - public string security; - } - - public class VNext - { - public string address; - - public int port; - - public List users; - } - - public class WSHeaders - { - public string Host; - } - - public class TCPRequestHeaders - { - public string Host; - - //public string User_Agent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36"; - - public string Accept_Encoding = "gzip, deflate"; - - public string Connection = "keep-alive"; - - public string Pragma = "no-cache"; - } - - public class TCPRequest - { - public string version = "1.1"; - - public string method = "GET"; - - public string path = "/"; - - public TCPRequestHeaders headers; - } - - public class TCPHeaders - { - public string type; - - public TCPRequest request; - } - - public class WebSocketSettings - { - public bool connectionReuse = true; - - public string path = "/"; - - public WSHeaders headers; - } - - public class TCPSettings - { - public bool connectionReuse = true; - - public TCPHeaders header; - } - - public class QUICSettings - { - public string security; - - public string key; - - public TCPHeaders header; - } - - public class KCPSettings - { - public int mtu = 1350; - - public int tti = 50; - - public int uplinkCapacity = 12; - - public int downlinkCapacity = 100; - - public bool congestion = false; - - public int readBufferSize = 2; - - public int writeBufferSize = 2; - - public TCPHeaders header; - } - - public class HTTPSettings - { - public string host; - - public string path; - } - - public class TLSSettings - { - public bool allowInsecure = true; - - public string serverName; - } - - public class OutboundSettings - { - public List vnext; - } - - public class OutboundMux - { - public bool enabled = false; - } - - public class StreamSettings - { - public string network; - - public string security; - - public TCPSettings tcpSettings; - - public WebSocketSettings wsSettings; - - public KCPSettings kcpSettings; - - public QUICSettings quicSettings; - - public HTTPSettings httpSettings; - - public TLSSettings tlsSettings; - } - - public class Outbounds - { - public string tag = "proxy"; - - public string protocol = "vmess"; - - public OutboundSettings settings; - - public StreamSettings streamSettings; - - public OutboundMux mux; - } - - public class RoutingRules - { - public string type = "field"; - - public List port; - - public string outboundTag; - - public List ip; - - public List domain; - } - - public class Routing - { - public string domainStrategy = "IPIfNonMatch"; - - public List rules; - } - - public class Config - { - public List inbounds; - - public List outbounds; - - public Routing routing; - } - } -} \ No newline at end of file diff --git a/Netch/Servers/VMess/Utils/V2rayConfigUtils.cs b/Netch/Servers/VMess/Utils/V2rayConfigUtils.cs new file mode 100644 index 00000000..29f5e0ae --- /dev/null +++ b/Netch/Servers/VMess/Utils/V2rayConfigUtils.cs @@ -0,0 +1,362 @@ +using System.Collections.Generic; +using Netch.Controllers; +using Netch.Models; +using Netch.Servers.VMess.Models; +using Newtonsoft.Json; + +namespace Netch.Servers.VMess.Utils +{ + public static class V2rayConfigUtils + { + public static string GenerateClientConfig(Server server, Mode mode) + { + try + { + var v2rayConfig = new V2rayConfig(); + + inbound(server, ref v2rayConfig); + + routing(server, mode, ref v2rayConfig); + + outbound(server, ref v2rayConfig); + + return JsonConvert.SerializeObject(v2rayConfig); + } + catch + { + return ""; + } + } + + private static void inbound(Server server, ref V2rayConfig v2rayConfig) + { + try + { + var inbound = new Inbounds + { + port = MainController.ServerController.Socks5LocalPort(), + protocol = "socks", + listen = MainController.ServerController.LocalAddress(), + settings = new Inboundsettings + { + udp = true + } + }; + + v2rayConfig.inbounds = new List + { + inbound + }; + } + catch + { + // ignored + } + } + + private static void routing(Server server, Mode mode, ref V2rayConfig v2rayConfig) + { + try + { + RulesItem rulesItem; + if (mode.BypassChina) + { + rulesItem = new RulesItem + { + type = "field", + ip = new List + { + "geoip:cn", + "geoip:private" + }, + domain = new List + { + "geosite:cn" + }, + outboundTag = "direct" + }; + } + else + { + rulesItem = new RulesItem + { + type = "field", + ip = new List + { + "geoip:private" + }, + outboundTag = "direct" + }; + } + + v2rayConfig.routing = new Routing + { + rules = new List + { + rulesItem + } + }; + } + catch + { + // ignored + } + } + + private static void outbound(Server server, ref V2rayConfig v2rayConfig) + { + try + { + var outbound = new Outbounds + { + settings = new Outboundsettings(), + mux = new Mux(), + streamSettings = new StreamSettings + { + network = "tcp" + } + }; + + switch (server) + { + case Socks5.Socks5 socks5: + { + var serversItem = new ServersItem + { + users = new List() + }; + outbound.settings.servers = new List + { + serversItem + }; + + serversItem.address = server.AutoResolveHostname(); + serversItem.port = server.Port; + serversItem.method = null; + serversItem.password = null; + + if (socks5.Auth()) + { + var socksUsersItem = new SocksUsersItem + { + user = socks5.Username, + pass = socks5.Password, + level = 1 + }; + + serversItem.users.Add(socksUsersItem); + } + + outbound.mux.enabled = false; + outbound.mux.concurrency = -1; + outbound.protocol = "socks"; + break; + } + case VMess vmess: + { + var vnextItem = new VnextItem + { + users = new List() + }; + outbound.settings.vnext = new List + { + vnextItem + }; + + vnextItem.address = server.AutoResolveHostname(); + vnextItem.port = server.Port; + + var usersItem = new UsersItem(); + vnextItem.users.Add(usersItem); + + usersItem.id = vmess.UserID; + usersItem.alterId = vmess.AlterID; + usersItem.security = vmess.EncryptMethod; + + outbound.mux.enabled = vmess.UseMux; + outbound.mux.concurrency = vmess.UseMux ? 8 : -1; + + var streamSettings = outbound.streamSettings; + boundStreamSettings(vmess, ref streamSettings); + + outbound.protocol = "vmess"; + break; + } + } + + v2rayConfig.outbounds = new List {outbound}; + } + catch + { + // ignored + } + } + + private static void boundStreamSettings(VMess server, ref StreamSettings streamSettings) + { + try + { + streamSettings.network = server.TransferProtocol; + var host = server.Host; + if (server.TLSSecure) + { + streamSettings.security = "tls"; + + var tlsSettings = new TlsSettings + { + allowInsecure = true + }; + if (!string.IsNullOrWhiteSpace(host)) + { + tlsSettings.serverName = host; + } + + streamSettings.tlsSettings = tlsSettings; + } + else + { + streamSettings.security = ""; + } + + if (server.TransferProtocol == "xtls") + { + streamSettings.security = server.TransferProtocol; + + TlsSettings xtlsSettings = new TlsSettings + { + allowInsecure = true + }; + if (!string.IsNullOrWhiteSpace(host)) + { + xtlsSettings.serverName = host; + } + + streamSettings.xtlsSettings = xtlsSettings; + } + + switch (server.TransferProtocol) + { + case "kcp": + var kcpSettings = new KcpSettings + { + header = new Header + { + type = server.FakeType + } + }; + + /* TODO KCP Settings + KcpSettings kcpSettings = new KcpSettings + { + mtu = server.kcpItem.mtu, + tti = server.kcpItem.tti + }; + if (iobound.Equals("out")) + { + kcpSettings.uplinkCapacity = server.kcpItem.uplinkCapacity; + kcpSettings.downlinkCapacity = server.kcpItem.downlinkCapacity; + } + else if (iobound.Equals("in")) + { + kcpSettings.uplinkCapacity = server.kcpItem.downlinkCapacity; + ; + kcpSettings.downlinkCapacity = server.kcpItem.downlinkCapacity; + } + else + { + kcpSettings.uplinkCapacity = server.kcpItem.uplinkCapacity; + kcpSettings.downlinkCapacity = server.kcpItem.downlinkCapacity; + } + + kcpSettings.congestion = server.kcpItem.congestion; + kcpSettings.readBufferSize = server.kcpItem.readBufferSize; + kcpSettings.writeBufferSize = server.kcpItem.writeBufferSize; + kcpSettings.header = new Header + { + type = server.FakeType + }; + if (!string.IsNullOrEmpty(server.Path)) + { + kcpSettings.seed = server.Path; + }*/ + + streamSettings.kcpSettings = kcpSettings; + break; + case "ws": + var path = server.Path; + var wsSettings = new WsSettings + { + connectionReuse = true, + headers = !string.IsNullOrWhiteSpace(host) + ? new Headers + { + Host = host + } + : null, + path = !string.IsNullOrWhiteSpace(path) ? path : null + }; + + streamSettings.wsSettings = wsSettings; + break; + case "h2": + var httpSettings = new HttpSettings() + { + host = new List + { + string.IsNullOrWhiteSpace(server.Host) ? server.Hostname : server.Host + }, + path = server.Path + }; + + streamSettings.httpSettings = httpSettings; + break; + case "quic": + var quicsettings = new QuicSettings + { + security = host, + key = server.Path, + header = new Header + { + type = server.FakeType + } + }; + if (server.TLSSecure) + { + streamSettings.tlsSettings.serverName = server.Hostname; + } + + streamSettings.quicSettings = quicsettings; + break; + default: + if (server.FakeType == "http") + { + var tcpSettings = new TcpSettings + { + connectionReuse = true, + header = new Header + { + type = server.FakeType, + request = new TCPRequest + { + path = string.IsNullOrWhiteSpace(server.Path) ? "/" : server.Path, + headers = new TCPRequestHeaders + { + Host = string.IsNullOrWhiteSpace(server.Host) ? server.Hostname : server.Host + } + } + } + }; + + streamSettings.tcpSettings = tcpSettings; + } + + break; + } + } + catch + { + // ignored + } + } + } +} \ No newline at end of file diff --git a/Netch/Servers/VMess/VMessController.cs b/Netch/Servers/VMess/VMessController.cs index bef270ef..c7b97fb0 100644 --- a/Netch/Servers/VMess/VMessController.cs +++ b/Netch/Servers/VMess/VMessController.cs @@ -1,10 +1,6 @@ -using System.Collections.Generic; -using System.IO; +using System.IO; using Netch.Controllers; using Netch.Models; -using Netch.Servers.VMess.Models; -using Netch.Utils; -using Newtonsoft.Json; namespace Netch.Servers.VMess { @@ -16,7 +12,6 @@ namespace Netch.Servers.VMess StoppedKeywords.AddRange(new[] {"config file not readable", "failed to"}); } - public override string Name { get; protected set; } = "V2Ray"; public override string MainFile { get; protected set; } = "v2ray.exe"; public int? Socks5LocalPort { get; set; } @@ -25,154 +20,7 @@ namespace Netch.Servers.VMess public bool Start(Server s, Mode mode) { - var server = (VMess) s; - File.WriteAllText("data\\last.json", JsonConvert.SerializeObject(new VMessConfig.Config() - { - inbounds = new List - { - new VMessConfig.Inbounds - { - settings = new VMessConfig.InboundSettings(), - port = this.Socks5LocalPort(), - listen = this.LocalAddress() - } - }, - outbounds = new List - { - new VMessConfig.Outbounds - { - settings = new VMessConfig.OutboundSettings - { - vnext = new List - { - new VMessConfig.VNext - { - address = server.AutoResolveHostname(), - port = server.Port, - users = new List - { - new VMessConfig.User - { - id = server.UserID, - alterId = server.AlterID, - security = server.EncryptMethod - } - } - } - } - }, - streamSettings = new VMessConfig.StreamSettings - { - network = server.TransferProtocol, - security = server.TLSSecure ? "tls" : string.Empty, - wsSettings = server.TransferProtocol == "ws" - ? new VMessConfig.WebSocketSettings - { - path = server.Path == string.Empty ? "/" : server.Path, - headers = new VMessConfig.WSHeaders - { - Host = server.Host == string.Empty ? server.Hostname : server.Host - } - } - : null, - tcpSettings = server.FakeType == "http" - ? new VMessConfig.TCPSettings - { - header = new VMessConfig.TCPHeaders - { - type = server.FakeType, - request = new VMessConfig.TCPRequest - { - path = server.Path == string.Empty ? "/" : server.Path, - headers = new VMessConfig.TCPRequestHeaders - { - Host = server.Host == string.Empty ? server.Hostname : server.Host - } - } - } - } - : null, - kcpSettings = server.TransferProtocol == "kcp" - ? new VMessConfig.KCPSettings - { - header = new VMessConfig.TCPHeaders - { - type = server.FakeType - } - } - : null, - quicSettings = server.TransferProtocol == "quic" - ? new VMessConfig.QUICSettings - { - security = server.QUICSecure, - key = server.QUICSecret, - header = new VMessConfig.TCPHeaders - { - type = server.FakeType - } - } - : null, - httpSettings = server.TransferProtocol == "h2" - ? new VMessConfig.HTTPSettings - { - host = server.Host == "" ? server.Hostname : server.Host, - path = server.Path == "" ? "/" : server.Path - } - : null, - tlsSettings = new VMessConfig.TLSSettings - { - allowInsecure = true, - serverName = server.Host == "" ? server.Hostname : server.Host - } - }, - mux = new VMessConfig.OutboundMux - { - enabled = server.UseMux - } - }, - mode.Type == 0 || mode.Type == 1 || mode.Type == 2 - ? new VMessConfig.Outbounds - { - tag = "TUNTAP", - protocol = "freedom" - } - : new VMessConfig.Outbounds - { - tag = "direct", - protocol = "freedom" - } - }, - routing = new VMessConfig.Routing - { - rules = new List - { - mode.BypassChina - ? new VMessConfig.RoutingRules - { - type = "field", - ip = new List - { - "geoip:cn", - "geoip:private" - }, - domain = new List - { - "geosite:cn" - }, - outboundTag = "direct" - } - : new VMessConfig.RoutingRules - { - type = "field", - ip = new List - { - "geoip:private" - }, - outboundTag = "direct" - } - } - } - })); + File.WriteAllText("data\\last.json", Utils.V2rayConfigUtils.GenerateClientConfig(s, mode)); if (StartInstanceAuto("-config ..\\data\\last.json")) { diff --git a/Netch/Servers/VMess/VMessUtil.cs b/Netch/Servers/VMess/VMessUtil.cs index d02d4e33..649b826d 100644 --- a/Netch/Servers/VMess/VMessUtil.cs +++ b/Netch/Servers/VMess/VMessUtil.cs @@ -64,10 +64,10 @@ namespace Netch.Servers.VMess var data = new VMess(); text = text.Substring(8); - VMessJObject vmess; + V2rayNSharing vmess; try { - vmess = JsonConvert.DeserializeObject(ShareLink.URLSafeBase64Decode(text)); + vmess = JsonConvert.DeserializeObject(ShareLink.URLSafeBase64Decode(text)); } catch (Exception e) {