mirror of
https://github.com/netchx/netch.git
synced 2026-04-01 19:15:09 +08:00
Feature: Xray ServerName(sni) Support
Refactor Generate Xray config file
This commit is contained in:
@@ -1,57 +1,21 @@
|
||||
#nullable disable
|
||||
using System.Collections.Generic;
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace Netch.Servers.Models
|
||||
namespace Netch.Servers.V2ray.Models
|
||||
{
|
||||
public class V2rayConfig
|
||||
public struct V2rayConfig
|
||||
{
|
||||
public List<Inbounds> inbounds { get; } = new();
|
||||
public object[] inbounds { get; set; }
|
||||
|
||||
public List<Outbounds> outbounds { get; } = new();
|
||||
|
||||
public Routing routing { get; } = new();
|
||||
public Outbound[] outbounds { get; set; }
|
||||
}
|
||||
|
||||
public class Inbounds
|
||||
{
|
||||
public string tag { get; set; }
|
||||
|
||||
public ushort 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<UsersItem> clients { get; set; }
|
||||
|
||||
public string decryption { get; set; }
|
||||
}
|
||||
|
||||
public class UsersItem
|
||||
public class User
|
||||
{
|
||||
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; }
|
||||
@@ -59,33 +23,22 @@ namespace Netch.Servers.Models
|
||||
public string flow { get; set; }
|
||||
}
|
||||
|
||||
public class Sniffing
|
||||
public class Outbound
|
||||
{
|
||||
public bool enabled { get; set; }
|
||||
|
||||
public List<string> destOverride { get; set; }
|
||||
}
|
||||
|
||||
public class Outbounds
|
||||
{
|
||||
public string tag { get; set; }
|
||||
|
||||
public string protocol { get; set; }
|
||||
|
||||
public Outboundsettings settings { get; set; }
|
||||
public OutboundConfiguration settings { get; set; }
|
||||
|
||||
public StreamSettings streamSettings { get; set; }
|
||||
|
||||
public Mux mux { get; set; }
|
||||
}
|
||||
|
||||
public class Outboundsettings
|
||||
public class OutboundConfiguration
|
||||
{
|
||||
public List<VnextItem> vnext { get; set; }
|
||||
public VnextItem[] vnext { get; set; }
|
||||
|
||||
public List<ServersItem> servers { get; set; }
|
||||
|
||||
public Response response { get; set; }
|
||||
public object[] servers { get; set; }
|
||||
}
|
||||
|
||||
public class VnextItem
|
||||
@@ -94,35 +47,7 @@ namespace Netch.Servers.Models
|
||||
|
||||
public ushort port { get; set; }
|
||||
|
||||
public List<UsersItem> 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 ushort port { get; set; }
|
||||
|
||||
public int level { get; set; }
|
||||
|
||||
public List<SocksUsersItem> users { get; set; }
|
||||
}
|
||||
|
||||
public class SocksUsersItem
|
||||
{
|
||||
public string user { get; set; }
|
||||
|
||||
public string pass { get; set; }
|
||||
|
||||
public int level { get; set; }
|
||||
public User[] users { get; set; }
|
||||
}
|
||||
|
||||
public class Mux
|
||||
@@ -132,38 +57,6 @@ namespace Netch.Servers.Models
|
||||
public int concurrency { get; set; }
|
||||
}
|
||||
|
||||
public class Response
|
||||
{
|
||||
public string type { get; set; }
|
||||
}
|
||||
|
||||
public class Dns
|
||||
{
|
||||
public List<string> servers { get; set; }
|
||||
}
|
||||
|
||||
public class RulesItem
|
||||
{
|
||||
public string type { get; set; }
|
||||
|
||||
public string port { get; set; }
|
||||
|
||||
public List<string> inboundTag { get; set; }
|
||||
|
||||
public string outboundTag { get; set; }
|
||||
|
||||
public List<string> ip { get; set; }
|
||||
|
||||
public List<string> domain { get; set; }
|
||||
}
|
||||
|
||||
public class Routing
|
||||
{
|
||||
public string domainStrategy { get; set; }
|
||||
|
||||
public List<RulesItem> rules { get; } = new();
|
||||
}
|
||||
|
||||
public class StreamSettings
|
||||
{
|
||||
public string network { get; set; }
|
||||
@@ -187,6 +80,8 @@ namespace Netch.Servers.Models
|
||||
public GrpcSettings grpcSettings { get; set; }
|
||||
}
|
||||
|
||||
#region Transport
|
||||
|
||||
public class TlsSettings
|
||||
{
|
||||
public bool allowInsecure { get; set; }
|
||||
@@ -196,40 +91,14 @@ namespace Netch.Servers.Models
|
||||
|
||||
public class TcpSettings
|
||||
{
|
||||
public Header header { get; set; }
|
||||
public object header { get; set; }
|
||||
}
|
||||
|
||||
public class Header
|
||||
public class WsSettings
|
||||
{
|
||||
public string type { get; set; }
|
||||
public string path { get; set; }
|
||||
|
||||
public TCPRequest request { get; set; }
|
||||
|
||||
public object response { get; set; }
|
||||
}
|
||||
|
||||
public class TCPRequest
|
||||
{
|
||||
public TCPRequestHeaders headers { get; set; }
|
||||
|
||||
public string method { get; set; } = "GET";
|
||||
|
||||
public string path { get; set; } = "/";
|
||||
|
||||
public string version { get; set; } = "1.1";
|
||||
}
|
||||
|
||||
public class TCPRequestHeaders
|
||||
{
|
||||
//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 { get; set; } = "gzip, deflate";
|
||||
|
||||
public string Connection { get; set; } = "keep-alive";
|
||||
|
||||
public string Host { get; set; }
|
||||
|
||||
public string Pragma { get; set; } = "no-cache";
|
||||
public object headers { get; set; }
|
||||
}
|
||||
|
||||
public class KcpSettings
|
||||
@@ -248,28 +117,16 @@ namespace Netch.Servers.Models
|
||||
|
||||
public int writeBufferSize { get; set; }
|
||||
|
||||
public Header header { get; set; }
|
||||
public object header { get; set; }
|
||||
|
||||
public string seed { get; set; }
|
||||
}
|
||||
|
||||
public class WsSettings
|
||||
{
|
||||
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<string> host { get; set; }
|
||||
public string[] host { get; set; }
|
||||
}
|
||||
|
||||
public class QuicSettings
|
||||
@@ -278,7 +135,7 @@ namespace Netch.Servers.Models
|
||||
|
||||
public string key { get; set; }
|
||||
|
||||
public Header header { get; set; }
|
||||
public object header { get; set; }
|
||||
}
|
||||
|
||||
public class GrpcSettings
|
||||
@@ -287,4 +144,6 @@ namespace Netch.Servers.Models
|
||||
|
||||
public bool multiMode { get; set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Diagnostics;
|
||||
using System.Text.Json;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.Models;
|
||||
using V2rayConfig = Netch.Servers.Models.V2rayConfig;
|
||||
using Netch.Servers.V2ray.Models;
|
||||
using Netch.Utils;
|
||||
using V2rayConfig = Netch.Servers.V2ray.Models.V2rayConfig;
|
||||
|
||||
namespace Netch.Servers.Utils
|
||||
{
|
||||
@@ -11,342 +11,252 @@ namespace Netch.Servers.Utils
|
||||
{
|
||||
public static string GenerateClientConfig(Server server)
|
||||
{
|
||||
var v2rayConfig = new V2rayConfig();
|
||||
|
||||
inbound(server, ref v2rayConfig);
|
||||
|
||||
routing(server, ref v2rayConfig);
|
||||
var v2rayConfig = new V2rayConfig
|
||||
{
|
||||
inbounds = new object[]
|
||||
{
|
||||
new
|
||||
{
|
||||
port = Global.Settings.Socks5LocalPort,
|
||||
protocol = "socks",
|
||||
listen = Global.Settings.LocalAddress,
|
||||
settings = new
|
||||
{
|
||||
udp = true
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
outbound(server, ref v2rayConfig);
|
||||
|
||||
return JsonSerializer.Serialize(v2rayConfig, Global.NewDefaultJsonSerializerOptions);
|
||||
}
|
||||
|
||||
private static void inbound(Server server, ref V2rayConfig v2rayConfig)
|
||||
{
|
||||
try
|
||||
{
|
||||
var inbound = new Inbounds
|
||||
{
|
||||
port = Global.Settings.Socks5LocalPort,
|
||||
protocol = "socks",
|
||||
listen = Global.Settings.LocalAddress,
|
||||
settings = new Inboundsettings
|
||||
{
|
||||
udp = true
|
||||
}
|
||||
};
|
||||
|
||||
v2rayConfig.inbounds.Add(inbound);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
private static void routing(Server server, ref V2rayConfig v2rayConfig)
|
||||
{
|
||||
try
|
||||
{
|
||||
var directRuleObject = new RulesItem
|
||||
{
|
||||
type = "field",
|
||||
ip = new List<string>(),
|
||||
domain = new List<string>(),
|
||||
outboundTag = "direct"
|
||||
};
|
||||
|
||||
var blockRuleObject = new RulesItem
|
||||
{
|
||||
type = "field",
|
||||
ip = new List<string>(),
|
||||
domain = new List<string>(),
|
||||
outboundTag = "block"
|
||||
};
|
||||
|
||||
static bool CheckRuleItem(ref RulesItem rulesItem)
|
||||
{
|
||||
bool ipResult, domainResult;
|
||||
if (!(ipResult = rulesItem.ip?.Any() ?? false))
|
||||
rulesItem.ip = null;
|
||||
|
||||
if (!(domainResult = rulesItem.domain?.Any() ?? false))
|
||||
rulesItem.domain = null;
|
||||
|
||||
return ipResult || domainResult;
|
||||
}
|
||||
|
||||
if (CheckRuleItem(ref directRuleObject))
|
||||
v2rayConfig.routing.rules.Add(directRuleObject);
|
||||
|
||||
if (CheckRuleItem(ref blockRuleObject))
|
||||
v2rayConfig.routing.rules.Add(blockRuleObject);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
private static void outbound(Server server, ref V2rayConfig v2rayConfig)
|
||||
{
|
||||
try
|
||||
var outbound = new Outbound
|
||||
{
|
||||
var outbound = new Outbounds
|
||||
settings = new OutboundConfiguration(),
|
||||
mux = new Mux(),
|
||||
streamSettings = new StreamSettings
|
||||
{
|
||||
settings = new Outboundsettings(),
|
||||
mux = new Mux(),
|
||||
streamSettings = new StreamSettings
|
||||
{
|
||||
network = "tcp"
|
||||
}
|
||||
};
|
||||
network = "tcp"
|
||||
}
|
||||
};
|
||||
|
||||
switch (server)
|
||||
v2rayConfig.outbounds = new[] { outbound };
|
||||
|
||||
switch (server)
|
||||
{
|
||||
case Socks5 socks5:
|
||||
{
|
||||
case Socks5 socks5:
|
||||
outbound.protocol = "socks";
|
||||
outbound.settings.servers = new object[]
|
||||
{
|
||||
outbound.settings.servers = new List<ServersItem>
|
||||
new
|
||||
{
|
||||
new()
|
||||
{
|
||||
users = socks5.Auth()
|
||||
? new List<SocksUsersItem>
|
||||
users = socks5.Auth()
|
||||
? new []
|
||||
{
|
||||
new
|
||||
{
|
||||
new()
|
||||
{
|
||||
user = socks5.Username,
|
||||
pass = socks5.Password,
|
||||
level = 1
|
||||
}
|
||||
user = socks5.Username,
|
||||
pass = socks5.Password,
|
||||
level = 1
|
||||
}
|
||||
: null,
|
||||
address = server.AutoResolveHostname(),
|
||||
port = server.Port
|
||||
}
|
||||
};
|
||||
}
|
||||
: null,
|
||||
address = server.AutoResolveHostname(),
|
||||
port = server.Port
|
||||
}
|
||||
};
|
||||
|
||||
outbound.mux.enabled = false;
|
||||
outbound.mux.concurrency = -1;
|
||||
break;
|
||||
}
|
||||
case VLESS vless:
|
||||
{
|
||||
outbound.protocol = "vless";
|
||||
outbound.settings.vnext = new[]
|
||||
{
|
||||
new VnextItem
|
||||
{
|
||||
address = server.AutoResolveHostname(),
|
||||
port = server.Port,
|
||||
users = new[]
|
||||
{
|
||||
new User
|
||||
{
|
||||
id = vless.UserID,
|
||||
alterId = 0,
|
||||
flow = vless.Flow.ValueOrDefault(),
|
||||
encryption = vless.EncryptMethod
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var streamSettings = outbound.streamSettings;
|
||||
boundStreamSettings(vless, ref streamSettings);
|
||||
|
||||
if (vless.TLSSecureType == "xtls")
|
||||
{
|
||||
outbound.mux.enabled = false;
|
||||
outbound.mux.concurrency = -1;
|
||||
outbound.protocol = "socks";
|
||||
break;
|
||||
}
|
||||
case VLESS vless:
|
||||
else
|
||||
{
|
||||
var vnextItem = new VnextItem
|
||||
{
|
||||
users = new List<UsersItem>(),
|
||||
address = server.AutoResolveHostname(),
|
||||
port = server.Port
|
||||
};
|
||||
|
||||
outbound.settings.vnext = new List<VnextItem> { vnextItem };
|
||||
|
||||
var usersItem = new UsersItem
|
||||
{
|
||||
id = vless.UserID,
|
||||
alterId = 0,
|
||||
flow = string.Empty,
|
||||
encryption = vless.EncryptMethod
|
||||
};
|
||||
|
||||
vnextItem.users.Add(usersItem);
|
||||
|
||||
var streamSettings = outbound.streamSettings;
|
||||
boundStreamSettings(vless, ref streamSettings);
|
||||
|
||||
if (vless.TLSSecureType == "xtls")
|
||||
{
|
||||
usersItem.flow = string.IsNullOrEmpty(vless.Flow) ? "xtls-rprx-origin" : vless.Flow;
|
||||
|
||||
outbound.mux.enabled = false;
|
||||
outbound.mux.concurrency = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
outbound.mux.enabled = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux;
|
||||
outbound.mux.concurrency = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1;
|
||||
}
|
||||
|
||||
outbound.protocol = "vless";
|
||||
outbound.settings.servers = null;
|
||||
break;
|
||||
outbound.mux.enabled = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux;
|
||||
outbound.mux.concurrency = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1;
|
||||
}
|
||||
case VMess.VMess vmess:
|
||||
{
|
||||
var vnextItem = new VnextItem
|
||||
{
|
||||
users = new List<UsersItem>(),
|
||||
address = server.AutoResolveHostname(),
|
||||
port = server.Port
|
||||
};
|
||||
|
||||
outbound.settings.vnext = new List<VnextItem> { vnextItem };
|
||||
|
||||
var usersItem = new UsersItem
|
||||
{
|
||||
id = vmess.UserID,
|
||||
alterId = vmess.AlterID,
|
||||
security = vmess.EncryptMethod
|
||||
};
|
||||
|
||||
vnextItem.users.Add(usersItem);
|
||||
|
||||
var streamSettings = outbound.streamSettings;
|
||||
boundStreamSettings(vmess, ref streamSettings);
|
||||
|
||||
outbound.mux.enabled = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux;
|
||||
outbound.mux.concurrency = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1;
|
||||
outbound.protocol = "vmess";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
v2rayConfig.outbounds.AddRange(new[]
|
||||
case VMess vmess:
|
||||
{
|
||||
outbound,
|
||||
new()
|
||||
outbound.protocol = "vmess";
|
||||
outbound.settings.vnext = new[]
|
||||
{
|
||||
tag = "direct", protocol = "freedom"
|
||||
},
|
||||
new()
|
||||
{
|
||||
tag = "block", protocol = "blackhole"
|
||||
}
|
||||
});
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
new VnextItem
|
||||
{
|
||||
address = server.AutoResolveHostname(),
|
||||
port = server.Port,
|
||||
users = new[]
|
||||
{
|
||||
new User
|
||||
{
|
||||
id = vmess.UserID,
|
||||
alterId = vmess.AlterID,
|
||||
security = vmess.EncryptMethod
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var streamSettings = outbound.streamSettings;
|
||||
boundStreamSettings(vmess, ref streamSettings);
|
||||
|
||||
outbound.mux.enabled = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux;
|
||||
outbound.mux.concurrency = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void boundStreamSettings(VMess.VMess server, ref StreamSettings streamSettings)
|
||||
private static void boundStreamSettings(VMess server, ref StreamSettings streamSettings)
|
||||
{
|
||||
try
|
||||
streamSettings.network = server.TransferProtocol;
|
||||
streamSettings.security = server.TLSSecureType;
|
||||
|
||||
if (server.TLSSecureType != "none")
|
||||
{
|
||||
streamSettings.network = server.TransferProtocol;
|
||||
|
||||
if ((streamSettings.security = server.TLSSecureType) != "none")
|
||||
var tlsSettings = new TlsSettings
|
||||
{
|
||||
var tlsSettings = new TlsSettings
|
||||
{
|
||||
allowInsecure = Global.Settings.V2RayConfig.AllowInsecure
|
||||
};
|
||||
allowInsecure = Global.Settings.V2RayConfig.AllowInsecure,
|
||||
serverName = server.ServerName.ValueOrDefault() ?? server.Hostname
|
||||
};
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(server.Host))
|
||||
tlsSettings.serverName = server.Host;
|
||||
else if (Global.Settings.ResolveServerHostname)
|
||||
tlsSettings.serverName = server.Hostname;
|
||||
|
||||
switch (server.TLSSecureType)
|
||||
{
|
||||
case "tls":
|
||||
streamSettings.tlsSettings = tlsSettings;
|
||||
break;
|
||||
case "xtls":
|
||||
streamSettings.xtlsSettings = tlsSettings;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (server.TransferProtocol)
|
||||
switch (server.TLSSecureType)
|
||||
{
|
||||
case "kcp":
|
||||
var kcpSettings = new KcpSettings
|
||||
{
|
||||
mtu = Global.Settings.V2RayConfig.KcpConfig.mtu,
|
||||
tti = Global.Settings.V2RayConfig.KcpConfig.tti,
|
||||
uplinkCapacity = Global.Settings.V2RayConfig.KcpConfig.uplinkCapacity,
|
||||
downlinkCapacity = Global.Settings.V2RayConfig.KcpConfig.downlinkCapacity,
|
||||
congestion = Global.Settings.V2RayConfig.KcpConfig.congestion,
|
||||
readBufferSize = Global.Settings.V2RayConfig.KcpConfig.readBufferSize,
|
||||
writeBufferSize = Global.Settings.V2RayConfig.KcpConfig.writeBufferSize,
|
||||
header = new Header
|
||||
{
|
||||
type = server.FakeType
|
||||
},
|
||||
seed = !string.IsNullOrWhiteSpace(server.Path) ? server.Path : null
|
||||
};
|
||||
|
||||
streamSettings.kcpSettings = kcpSettings;
|
||||
case "tls":
|
||||
streamSettings.tlsSettings = tlsSettings;
|
||||
break;
|
||||
case "ws":
|
||||
var wsSettings = new WsSettings
|
||||
{
|
||||
headers = !string.IsNullOrWhiteSpace(server.Host) ? new Headers { Host = server.Host } : null,
|
||||
path = !string.IsNullOrWhiteSpace(server.Path) ? server.Path : null
|
||||
};
|
||||
|
||||
streamSettings.wsSettings = wsSettings;
|
||||
break;
|
||||
case "h2":
|
||||
var httpSettings = new HttpSettings
|
||||
{
|
||||
host = new List<string>
|
||||
{
|
||||
string.IsNullOrWhiteSpace(server.Host) ? server.Hostname : server.Host!
|
||||
},
|
||||
path = server.Path
|
||||
};
|
||||
|
||||
streamSettings.httpSettings = httpSettings;
|
||||
break;
|
||||
case "quic":
|
||||
var quicSettings = new QuicSettings
|
||||
{
|
||||
security = server.QUICSecure,
|
||||
key = server.QUICSecret,
|
||||
header = new Header
|
||||
{
|
||||
type = server.FakeType
|
||||
}
|
||||
};
|
||||
|
||||
if (server.TLSSecureType != "none")
|
||||
// tls or xtls
|
||||
streamSettings.tlsSettings.serverName = server.Hostname;
|
||||
|
||||
streamSettings.quicSettings = quicSettings;
|
||||
break;
|
||||
case "grpc":
|
||||
var grpcSettings = new GrpcSettings
|
||||
{
|
||||
serviceName = server.Path,
|
||||
multiMode = server.FakeType == "multi"
|
||||
};
|
||||
|
||||
streamSettings.grpcSettings = grpcSettings;
|
||||
break;
|
||||
default:
|
||||
if (server.FakeType == "http")
|
||||
{
|
||||
var tcpSettings = new TcpSettings
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
case "xtls":
|
||||
streamSettings.xtlsSettings = tlsSettings;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch
|
||||
|
||||
switch (server.TransferProtocol)
|
||||
{
|
||||
// ignored
|
||||
case "tcp":
|
||||
if (server.FakeType == "http")
|
||||
{
|
||||
streamSettings.tcpSettings = new TcpSettings
|
||||
{
|
||||
header = new
|
||||
{
|
||||
request = new
|
||||
{
|
||||
path = server.Path.SplitOrDefault(),
|
||||
headers = new
|
||||
{
|
||||
Host = server.Host.SplitOrDefault()
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new MessageException($"invalid tcp type {server.FakeType}");
|
||||
}
|
||||
|
||||
break;
|
||||
case "ws":
|
||||
|
||||
streamSettings.wsSettings = new WsSettings
|
||||
{
|
||||
path = server.Path.ValueOrDefault(),
|
||||
headers = new { Host = server.Host.ValueOrDefault() },
|
||||
};
|
||||
|
||||
break;
|
||||
case "kcp":
|
||||
|
||||
streamSettings.kcpSettings = new KcpSettings
|
||||
{
|
||||
mtu = Global.Settings.V2RayConfig.KcpConfig.mtu,
|
||||
tti = Global.Settings.V2RayConfig.KcpConfig.tti,
|
||||
uplinkCapacity = Global.Settings.V2RayConfig.KcpConfig.uplinkCapacity,
|
||||
downlinkCapacity = Global.Settings.V2RayConfig.KcpConfig.downlinkCapacity,
|
||||
congestion = Global.Settings.V2RayConfig.KcpConfig.congestion,
|
||||
readBufferSize = Global.Settings.V2RayConfig.KcpConfig.readBufferSize,
|
||||
writeBufferSize = Global.Settings.V2RayConfig.KcpConfig.writeBufferSize,
|
||||
header = new
|
||||
{
|
||||
type = server.FakeType
|
||||
},
|
||||
seed = server.Path.ValueOrDefault()
|
||||
};
|
||||
|
||||
break;
|
||||
case "h2":
|
||||
|
||||
streamSettings.httpSettings = new HttpSettings
|
||||
{
|
||||
host = server.Host.SplitOrDefault(),
|
||||
path = server.Path.ValueOrDefault()
|
||||
};
|
||||
|
||||
break;
|
||||
case "quic":
|
||||
|
||||
streamSettings.quicSettings = new QuicSettings
|
||||
{
|
||||
security = server.QUICSecure,
|
||||
key = server.QUICSecret,
|
||||
header = new
|
||||
{
|
||||
type = server.FakeType
|
||||
}
|
||||
};
|
||||
|
||||
break;
|
||||
case "grpc":
|
||||
|
||||
streamSettings.grpcSettings = new GrpcSettings
|
||||
{
|
||||
serviceName = server.Path,
|
||||
multiMode = server.FakeType == "multi"
|
||||
};
|
||||
|
||||
break;
|
||||
default:
|
||||
Trace.Assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Servers
|
||||
{
|
||||
@@ -13,7 +13,7 @@ namespace Netch.Servers
|
||||
public static IEnumerable<Server> ParseVUri(string text)
|
||||
{
|
||||
var scheme = ShareLink.GetUriScheme(text).ToLower();
|
||||
var server = scheme switch { "vmess" => new VMess.VMess(), "vless" => new VLESS(), _ => throw new ArgumentOutOfRangeException() };
|
||||
var server = scheme switch { "vmess" => new VMess(), "vless" => new VLESS(), _ => throw new ArgumentOutOfRangeException() };
|
||||
if (text.Contains("#"))
|
||||
{
|
||||
server.Remark = Uri.UnescapeDataString(text.Split('#')[1]);
|
||||
@@ -56,7 +56,7 @@ namespace Netch.Servers
|
||||
server.TLSSecureType = parameter.Get("security") ?? "none";
|
||||
if (server.TLSSecureType != "none")
|
||||
{
|
||||
server.Host = parameter.Get("sni") ?? "";
|
||||
server.ServerName = parameter.Get("sni") ?? "";
|
||||
if (server.TLSSecureType == "xtls")
|
||||
((VLESS)server).Flow = parameter.Get("flow") ?? "";
|
||||
}
|
||||
@@ -77,7 +77,7 @@ namespace Netch.Servers
|
||||
public static string GetVShareLink(Server s, string scheme = "vmess")
|
||||
{
|
||||
// https://github.com/XTLS/Xray-core/issues/91
|
||||
var server = (VMess.VMess)s;
|
||||
var server = (VMess)s;
|
||||
var parameter = new Dictionary<string, string>();
|
||||
// protocol-specific fields
|
||||
parameter.Add("type", server.TransferProtocol);
|
||||
@@ -97,13 +97,13 @@ namespace Netch.Servers
|
||||
|
||||
break;
|
||||
case "ws":
|
||||
parameter.Add("path", Uri.EscapeDataString(server.Path.IsNullOrWhiteSpace() ? "/" : server.Path!));
|
||||
parameter.Add("path", Uri.EscapeDataString(server.Path.ValueOrDefault() ?? "/"));
|
||||
if (!server.Host.IsNullOrWhiteSpace())
|
||||
parameter.Add("host", Uri.EscapeDataString(server.Host!));
|
||||
|
||||
break;
|
||||
case "h2":
|
||||
parameter.Add("path", Uri.EscapeDataString(server.Path.IsNullOrWhiteSpace() ? "/" : server.Path!));
|
||||
parameter.Add("path", Uri.EscapeDataString(server.Path.ValueOrDefault() ?? "/"));
|
||||
if (!server.Host.IsNullOrWhiteSpace())
|
||||
parameter.Add("host", Uri.EscapeDataString(server.Host!));
|
||||
|
||||
@@ -113,7 +113,6 @@ namespace Netch.Servers
|
||||
{
|
||||
parameter.Add("quicSecurity", server.QUICSecure);
|
||||
parameter.Add("key", server.QUICSecret!);
|
||||
// TODO Import and Create null value Check
|
||||
}
|
||||
|
||||
if (server.FakeType != "none")
|
||||
@@ -124,7 +123,7 @@ namespace Netch.Servers
|
||||
if (!string.IsNullOrEmpty(server.Path))
|
||||
parameter.Add("serviceName", server.Path);
|
||||
|
||||
if (server.FakeType == "gun" || server.FakeType == "multi")
|
||||
if (server.FakeType is "gun" or "multi")
|
||||
parameter.Add("mode", server.FakeType);
|
||||
|
||||
break;
|
||||
@@ -146,7 +145,7 @@ namespace Netch.Servers
|
||||
}
|
||||
|
||||
return
|
||||
$"{scheme}://{server.UserID}@{server.Hostname}:{server.Port}?{string.Join("&", parameter.Select(p => $"{p.Key}={p.Value}"))}{(server.Remark.IsNullOrWhiteSpace() ? "" : $"#{Uri.EscapeDataString(server.Remark)}")}";
|
||||
$"{scheme}://{server.UserID}@{server.Hostname}:{server.Port}?{string.Join("&", parameter.Select(p => $"{p.Key}={p.Value}"))}{(!server.Remark.IsNullOrWhiteSpace() ? $"#{Uri.EscapeDataString(server.Remark)}" : "")}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
using Netch.Servers.VMess;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Netch.Servers
|
||||
{
|
||||
public class VLESS : VMess.VMess
|
||||
public class VLESS : VMess
|
||||
{
|
||||
public override string Type { get; } = "VLESS";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Netch.Forms;
|
||||
using System.Collections.Generic;
|
||||
using Netch.Forms;
|
||||
|
||||
namespace Netch.Servers.VLESSForm
|
||||
{
|
||||
@@ -9,6 +9,7 @@ namespace Netch.Servers.VLESSForm
|
||||
{
|
||||
server ??= new VLESS();
|
||||
Server = server;
|
||||
CreateTextBox("Sni", "ServerName(Sni)", s => true, s => server.ServerName = s, server.ServerName);
|
||||
CreateTextBox("UUID", "UUID", s => true, s => server.UserID = s, server.UserID);
|
||||
CreateTextBox("EncryptMethod",
|
||||
"Encrypt Method",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Netch.Forms;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using Netch.Forms;
|
||||
|
||||
namespace Netch.Servers.VMess.Form
|
||||
namespace Netch.Servers.Form
|
||||
{
|
||||
public class VMessForm : ServerForm
|
||||
{
|
||||
@@ -9,6 +9,7 @@ namespace Netch.Servers.VMess.Form
|
||||
{
|
||||
server ??= new VMess();
|
||||
Server = server;
|
||||
CreateTextBox("Sni", "ServerName(Sni)", s => true, s => server.ServerName = s, server.ServerName);
|
||||
CreateTextBox("UserId", "User ID", s => true, s => server.UserID = s, server.UserID);
|
||||
CreateTextBox("AlterId", "Alter ID", s => int.TryParse(s, out _), s => server.AlterID = int.Parse(s), server.AlterID.ToString(), 76);
|
||||
CreateComboBox("EncryptMethod", "Encrypt Method", VMessGlobal.EncryptMethods, s => server.EncryptMethod = s, server.EncryptMethod);
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
using Netch.Models;
|
||||
|
||||
namespace Netch.Servers.VMess
|
||||
namespace Netch.Servers
|
||||
{
|
||||
public class VMess : Server
|
||||
{
|
||||
private string _tlsSecureType = VMessGlobal.TLSSecure[0];
|
||||
|
||||
public override string Type { get; } = "VMess";
|
||||
|
||||
public override string MaskedData()
|
||||
{
|
||||
var maskedData = $"{EncryptMethod} + {TransferProtocol} + {FakeType}";
|
||||
@@ -25,6 +26,7 @@ namespace Netch.Servers.VMess
|
||||
case "kcp":
|
||||
break;
|
||||
}
|
||||
|
||||
return maskedData;
|
||||
}
|
||||
|
||||
@@ -91,7 +93,9 @@ namespace Netch.Servers.VMess
|
||||
/// <summary>
|
||||
/// Mux 多路复用
|
||||
/// </summary>
|
||||
public bool? UseMux { get; set; } = false;
|
||||
public bool? UseMux { get; set; }
|
||||
|
||||
public string? ServerName { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class VMessGlobal
|
||||
|
||||
@@ -5,12 +5,11 @@ using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Netch.Interfaces;
|
||||
using Netch.Models;
|
||||
using Netch.Servers;
|
||||
using Netch.Servers.Form;
|
||||
using Netch.Servers.Models;
|
||||
using Netch.Servers.VMess.Form;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Servers.VMess
|
||||
namespace Netch.Servers
|
||||
{
|
||||
public class VMessUtil : IServerUtil
|
||||
{
|
||||
@@ -92,7 +91,6 @@ namespace Netch.Servers.VMess
|
||||
data.Remark = vmess.ps;
|
||||
data.Hostname = vmess.add;
|
||||
data.Port = vmess.port;
|
||||
data.UserID = vmess.id;
|
||||
data.AlterID = vmess.aid;
|
||||
data.TransferProtocol = vmess.net;
|
||||
data.FakeType = vmess.type;
|
||||
|
||||
@@ -72,5 +72,15 @@ namespace Netch.Utils
|
||||
{
|
||||
return value.Split(separator, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
|
||||
public static string? ValueOrDefault(this string? value)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(value) ? null : value;
|
||||
}
|
||||
|
||||
public static string[]? SplitOrDefault(this string? value)
|
||||
{
|
||||
return !string.IsNullOrWhiteSpace(value) ? value.Split(',') : default;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user