mirror of
https://github.com/netchx/netch.git
synced 2026-05-11 23:45:06 +08:00
Enable Nullable
This commit is contained in:
@@ -4,7 +4,7 @@ namespace Netch.Servers.Shadowsocks.Form
|
||||
{
|
||||
public class ShadowsocksForm : ServerForm
|
||||
{
|
||||
public ShadowsocksForm(Shadowsocks server = default)
|
||||
public ShadowsocksForm(Shadowsocks? server = default)
|
||||
{
|
||||
server ??= new Shadowsocks();
|
||||
Server = server;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
#nullable disable
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Netch.Servers.Shadowsocks.Models.SSD
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
namespace Netch.Servers.Shadowsocks.Models.SSD
|
||||
#nullable disable
|
||||
namespace Netch.Servers.Shadowsocks.Models.SSD
|
||||
{
|
||||
public class SSDServer
|
||||
{
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#nullable disable
|
||||
namespace Netch.Servers.Shadowsocks.Models
|
||||
{
|
||||
public class ShadowsocksConfig
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Netch.Servers.Shadowsocks
|
||||
|
||||
public ushort? Socks5LocalPort { get; set; }
|
||||
|
||||
public string LocalAddress { get; set; }
|
||||
public string? LocalAddress { get; set; }
|
||||
|
||||
public void Start(in Server s, in Mode mode)
|
||||
{
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace Netch.Servers.Shadowsocks
|
||||
if (text.StartsWith("ssd://"))
|
||||
return ParseSsdUri(text);
|
||||
|
||||
return null;
|
||||
throw new FormatException();
|
||||
}
|
||||
|
||||
public bool CheckServer(Server s)
|
||||
@@ -102,93 +102,82 @@ namespace Netch.Servers.Shadowsocks
|
||||
var data = new Shadowsocks();
|
||||
|
||||
text = text.Replace("/?", "?");
|
||||
try
|
||||
if (text.Contains("#"))
|
||||
{
|
||||
if (text.Contains("#"))
|
||||
{
|
||||
data.Remark = HttpUtility.UrlDecode(text.Split('#')[1]);
|
||||
text = text.Split('#')[0];
|
||||
}
|
||||
|
||||
if (text.Contains("?"))
|
||||
{
|
||||
var finder = new Regex(@"^(?<data>.+?)\?(.+)$");
|
||||
var match = finder.Match(text);
|
||||
|
||||
if (match.Success)
|
||||
{
|
||||
var plugins = HttpUtility.UrlDecode(HttpUtility.ParseQueryString(new Uri(text).Query).Get("plugin"));
|
||||
if (plugins != null)
|
||||
{
|
||||
var plugin = plugins.Substring(0, plugins.IndexOf(";", StringComparison.Ordinal));
|
||||
var pluginopts = plugins.Substring(plugins.IndexOf(";", StringComparison.Ordinal) + 1);
|
||||
switch (plugin)
|
||||
{
|
||||
case "obfs-local":
|
||||
case "simple-obfs":
|
||||
plugin = "simple-obfs";
|
||||
if (!pluginopts.Contains("obfs="))
|
||||
pluginopts = "obfs=http;obfs-host=" + pluginopts;
|
||||
|
||||
break;
|
||||
case "simple-obfs-tls":
|
||||
plugin = "simple-obfs";
|
||||
if (!pluginopts.Contains("obfs="))
|
||||
pluginopts = "obfs=tls;obfs-host=" + pluginopts;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
data.Plugin = plugin;
|
||||
data.PluginOption = pluginopts;
|
||||
}
|
||||
|
||||
text = match.Groups["data"].Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new FormatException();
|
||||
}
|
||||
}
|
||||
|
||||
if (text.Contains("@"))
|
||||
{
|
||||
var finder = new Regex(@"^ss://(?<base64>.+?)@(?<server>.+):(?<port>\d+)");
|
||||
var parser = new Regex(@"^(?<method>.+?):(?<password>.+)$");
|
||||
var match = finder.Match(text);
|
||||
if (!match.Success)
|
||||
throw new FormatException();
|
||||
|
||||
data.Hostname = match.Groups["server"].Value;
|
||||
data.Port = ushort.Parse(match.Groups["port"].Value);
|
||||
|
||||
var base64 = ShareLink.URLSafeBase64Decode(match.Groups["base64"].Value);
|
||||
match = parser.Match(base64);
|
||||
if (!match.Success)
|
||||
throw new FormatException();
|
||||
|
||||
data.EncryptMethod = match.Groups["method"].Value;
|
||||
data.Password = match.Groups["password"].Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
var parser = new Regex(@"^((?<method>.+?):(?<password>.+)@(?<server>.+):(?<port>\d+))");
|
||||
var match = parser.Match(ShareLink.URLSafeBase64Decode(text.Replace("ss://", "")));
|
||||
if (!match.Success)
|
||||
throw new FormatException();
|
||||
|
||||
data.Hostname = match.Groups["server"].Value;
|
||||
data.Port = ushort.Parse(match.Groups["port"].Value);
|
||||
data.EncryptMethod = match.Groups["method"].Value;
|
||||
data.Password = match.Groups["password"].Value;
|
||||
}
|
||||
|
||||
return CheckServer(data) ? data : null;
|
||||
data.Remark = HttpUtility.UrlDecode(text.Split('#')[1]);
|
||||
text = text.Split('#')[0];
|
||||
}
|
||||
catch (FormatException)
|
||||
|
||||
if (text.Contains("?"))
|
||||
{
|
||||
return null;
|
||||
var finder = new Regex(@"^(?<data>.+?)\?(.+)$");
|
||||
var match = finder.Match(text);
|
||||
|
||||
if (!match.Success)
|
||||
throw new FormatException();
|
||||
|
||||
var plugins = HttpUtility.UrlDecode(HttpUtility.ParseQueryString(new Uri(text).Query).Get("plugin"));
|
||||
if (plugins != null)
|
||||
{
|
||||
var plugin = plugins.Substring(0, plugins.IndexOf(";", StringComparison.Ordinal));
|
||||
var pluginopts = plugins.Substring(plugins.IndexOf(";", StringComparison.Ordinal) + 1);
|
||||
switch (plugin)
|
||||
{
|
||||
case "obfs-local":
|
||||
case "simple-obfs":
|
||||
plugin = "simple-obfs";
|
||||
if (!pluginopts.Contains("obfs="))
|
||||
pluginopts = "obfs=http;obfs-host=" + pluginopts;
|
||||
|
||||
break;
|
||||
case "simple-obfs-tls":
|
||||
plugin = "simple-obfs";
|
||||
if (!pluginopts.Contains("obfs="))
|
||||
pluginopts = "obfs=tls;obfs-host=" + pluginopts;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
data.Plugin = plugin;
|
||||
data.PluginOption = pluginopts;
|
||||
}
|
||||
|
||||
text = match.Groups["data"].Value;
|
||||
}
|
||||
|
||||
if (text.Contains("@"))
|
||||
{
|
||||
var finder = new Regex(@"^ss://(?<base64>.+?)@(?<server>.+):(?<port>\d+)");
|
||||
var parser = new Regex(@"^(?<method>.+?):(?<password>.+)$");
|
||||
var match = finder.Match(text);
|
||||
if (!match.Success)
|
||||
throw new FormatException();
|
||||
|
||||
data.Hostname = match.Groups["server"].Value;
|
||||
data.Port = ushort.Parse(match.Groups["port"].Value);
|
||||
|
||||
var base64 = ShareLink.URLSafeBase64Decode(match.Groups["base64"].Value);
|
||||
match = parser.Match(base64);
|
||||
if (!match.Success)
|
||||
throw new FormatException();
|
||||
|
||||
data.EncryptMethod = match.Groups["method"].Value;
|
||||
data.Password = match.Groups["password"].Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
var parser = new Regex(@"^((?<method>.+?):(?<password>.+)@(?<server>.+):(?<port>\d+))");
|
||||
var match = parser.Match(ShareLink.URLSafeBase64Decode(text.Replace("ss://", "")));
|
||||
if (!match.Success)
|
||||
throw new FormatException();
|
||||
|
||||
data.Hostname = match.Groups["server"].Value;
|
||||
data.Port = ushort.Parse(match.Groups["port"].Value);
|
||||
data.EncryptMethod = match.Groups["method"].Value;
|
||||
data.Password = match.Groups["password"].Value;
|
||||
}
|
||||
|
||||
return CheckServer(data) ? data : throw new FormatException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,17 +15,17 @@ namespace Netch.Servers.Shadowsocks
|
||||
/// <summary>
|
||||
/// 密码
|
||||
/// </summary>
|
||||
public string Password { get; set; }
|
||||
public string? Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 插件
|
||||
/// </summary>
|
||||
public string Plugin { get; set; }
|
||||
public string? Plugin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 插件参数
|
||||
/// </summary>
|
||||
public string PluginOption { get; set; }
|
||||
public string? PluginOption { get; set; }
|
||||
|
||||
public bool HasPlugin()
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Netch.Servers.ShadowsocksR.Form
|
||||
{
|
||||
public class ShadowsocksRForm : ServerForm
|
||||
{
|
||||
public ShadowsocksRForm(ShadowsocksR server = default)
|
||||
public ShadowsocksRForm(ShadowsocksR? server = default)
|
||||
{
|
||||
server ??= new ShadowsocksR();
|
||||
Server = server;
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Netch.Servers.ShadowsocksR
|
||||
|
||||
public ushort? Socks5LocalPort { get; set; }
|
||||
|
||||
public string LocalAddress { get; set; }
|
||||
public string? LocalAddress { get; set; }
|
||||
|
||||
public void Start(in Server s, in Mode mode)
|
||||
{
|
||||
|
||||
@@ -20,12 +20,12 @@ namespace Netch.Servers.ShadowsocksR
|
||||
/// <summary>
|
||||
/// 混淆参数
|
||||
/// </summary>
|
||||
public string OBFSParam { get; set; }
|
||||
public string? OBFSParam { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 密码
|
||||
/// </summary>
|
||||
public string Password { get; set; }
|
||||
public string Password { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 协议
|
||||
@@ -35,7 +35,7 @@ namespace Netch.Servers.ShadowsocksR
|
||||
/// <summary>
|
||||
/// 协议参数
|
||||
/// </summary>
|
||||
public string ProtocolParam { get; set; }
|
||||
public string? ProtocolParam { get; set; }
|
||||
}
|
||||
|
||||
public class SSRGlobal
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Netch.Servers.Socks5.Form
|
||||
{
|
||||
public class Socks5Form : ServerForm
|
||||
{
|
||||
public Socks5Form(Socks5 server = default)
|
||||
public Socks5Form(Socks5? server = default)
|
||||
{
|
||||
server ??= new Socks5();
|
||||
Server = server;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Netch.Controllers;
|
||||
using Netch.Models;
|
||||
@@ -57,7 +58,7 @@ namespace Netch.Servers.Socks5
|
||||
.ToDictionary(splited => splited[0], splited => splited[1]);
|
||||
|
||||
if (!dict.ContainsKey("server") || !dict.ContainsKey("port"))
|
||||
return null;
|
||||
throw new FormatException();
|
||||
|
||||
var data = new Socks5
|
||||
{
|
||||
|
||||
@@ -7,12 +7,12 @@ namespace Netch.Servers.Socks5
|
||||
/// <summary>
|
||||
/// 密码
|
||||
/// </summary>
|
||||
public string Password;
|
||||
public string? Password;
|
||||
|
||||
/// <summary>
|
||||
/// 账号
|
||||
/// </summary>
|
||||
public string Username;
|
||||
public string? Username;
|
||||
|
||||
public override string Type { get; } = "Socks5";
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Netch.Servers.Trojan.Form
|
||||
{
|
||||
public class TrojanForm : ServerForm
|
||||
{
|
||||
public TrojanForm(Trojan server = default)
|
||||
public TrojanForm(Trojan? server = default)
|
||||
{
|
||||
server ??= new Trojan();
|
||||
Server = server;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
#nullable disable
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Netch.Servers.Trojan.Models
|
||||
{
|
||||
|
||||
@@ -9,11 +9,11 @@ namespace Netch.Servers.Trojan
|
||||
/// <summary>
|
||||
/// 密码
|
||||
/// </summary>
|
||||
public string Password { get; set; }
|
||||
public string Password { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 伪装域名
|
||||
/// </summary>
|
||||
public string Host { get; set; }
|
||||
public string? Host { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ namespace Netch.Servers.Trojan
|
||||
|
||||
public ushort? Socks5LocalPort { get; set; }
|
||||
|
||||
public string LocalAddress { get; set; }
|
||||
public string? LocalAddress { get; set; }
|
||||
|
||||
public void Start(in Server s, in Mode mode)
|
||||
{
|
||||
|
||||
@@ -52,49 +52,38 @@ namespace Netch.Servers.Trojan
|
||||
var data = new Trojan();
|
||||
|
||||
text = text.Replace("/?", "?");
|
||||
try
|
||||
if (text.Contains("#"))
|
||||
{
|
||||
if (text.Contains("#"))
|
||||
{
|
||||
data.Remark = HttpUtility.UrlDecode(text.Split('#')[1]);
|
||||
text = text.Split('#')[0];
|
||||
}
|
||||
data.Remark = HttpUtility.UrlDecode(text.Split('#')[1]);
|
||||
text = text.Split('#')[0];
|
||||
}
|
||||
|
||||
if (text.Contains("?"))
|
||||
{
|
||||
var reg = new Regex(@"^(?<data>.+?)\?(.+)$");
|
||||
var regmatch = reg.Match(text);
|
||||
if (text.Contains("?"))
|
||||
{
|
||||
var reg = new Regex(@"^(?<data>.+?)\?(.+)$");
|
||||
var regmatch = reg.Match(text);
|
||||
|
||||
if (regmatch.Success)
|
||||
{
|
||||
var peer = HttpUtility.UrlDecode(HttpUtility.ParseQueryString(new Uri(text).Query).Get("peer"));
|
||||
|
||||
if (peer != null)
|
||||
data.Host = peer;
|
||||
|
||||
text = regmatch.Groups["data"].Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new FormatException();
|
||||
}
|
||||
}
|
||||
|
||||
var finder = new Regex(@"^trojan://(?<psk>.+?)@(?<server>.+):(?<port>\d+)");
|
||||
var match = finder.Match(text);
|
||||
if (!match.Success)
|
||||
if (!regmatch.Success)
|
||||
throw new FormatException();
|
||||
|
||||
data.Password = match.Groups["psk"].Value;
|
||||
data.Hostname = match.Groups["server"].Value;
|
||||
data.Port = ushort.Parse(match.Groups["port"].Value);
|
||||
var peer = HttpUtility.UrlDecode(HttpUtility.ParseQueryString(new Uri(text).Query).Get("peer"));
|
||||
|
||||
return new[] {data};
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
return null;
|
||||
if (peer != null)
|
||||
data.Host = peer;
|
||||
|
||||
text = regmatch.Groups["data"].Value;
|
||||
}
|
||||
|
||||
var finder = new Regex(@"^trojan://(?<psk>.+?)@(?<server>.+):(?<port>\d+)");
|
||||
var match = finder.Match(text);
|
||||
if (!match.Success)
|
||||
throw new FormatException();
|
||||
|
||||
data.Password = match.Groups["psk"].Value;
|
||||
data.Hostname = match.Groups["server"].Value;
|
||||
data.Port = ushort.Parse(match.Groups["port"].Value);
|
||||
|
||||
return new[] {data};
|
||||
}
|
||||
|
||||
public bool CheckServer(Server s)
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
#nullable disable
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Netch.Servers.V2ray.Models
|
||||
{
|
||||
public class V2rayConfig
|
||||
{
|
||||
public List<Inbounds> inbounds { get; set; }
|
||||
public List<Inbounds> inbounds { get; } = new();
|
||||
|
||||
public List<Outbounds> outbounds { get; set; }
|
||||
public List<Outbounds> outbounds { get; } = new();
|
||||
|
||||
public Routing routing { get; set; }
|
||||
public Routing routing { get; } = new();
|
||||
}
|
||||
|
||||
public class Inbounds
|
||||
@@ -160,7 +161,7 @@ namespace Netch.Servers.V2ray.Models
|
||||
{
|
||||
public string domainStrategy { get; set; }
|
||||
|
||||
public List<RulesItem> rules { get; set; }
|
||||
public List<RulesItem> rules { get; } = new();
|
||||
}
|
||||
|
||||
public class StreamSettings
|
||||
|
||||
@@ -11,24 +11,17 @@ namespace Netch.Servers.V2ray.Utils
|
||||
{
|
||||
public static string GenerateClientConfig(Server server, Mode mode)
|
||||
{
|
||||
try
|
||||
{
|
||||
var v2rayConfig = new V2rayConfig();
|
||||
var v2rayConfig = new V2rayConfig();
|
||||
|
||||
inbound(server, ref v2rayConfig);
|
||||
inbound(server, ref v2rayConfig);
|
||||
|
||||
routing(server, mode, ref v2rayConfig);
|
||||
routing(server, mode, ref v2rayConfig);
|
||||
|
||||
outbound(server, mode, ref v2rayConfig);
|
||||
outbound(server, mode, ref v2rayConfig);
|
||||
|
||||
return JsonConvert.SerializeObject(v2rayConfig,
|
||||
Formatting.Indented,
|
||||
new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore});
|
||||
}
|
||||
catch
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return JsonConvert.SerializeObject(v2rayConfig,
|
||||
Formatting.Indented,
|
||||
new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore});
|
||||
}
|
||||
|
||||
private static void inbound(Server server, ref V2rayConfig v2rayConfig)
|
||||
@@ -46,10 +39,7 @@ namespace Netch.Servers.V2ray.Utils
|
||||
}
|
||||
};
|
||||
|
||||
v2rayConfig.inbounds = new List<Inbounds>
|
||||
{
|
||||
inbound
|
||||
};
|
||||
v2rayConfig.inbounds.Add(inbound);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -99,18 +89,13 @@ namespace Netch.Servers.V2ray.Utils
|
||||
if (mode.Type is 0 or 1 or 2)
|
||||
blockRuleObject.ip.Add("geoip:private");
|
||||
|
||||
v2rayConfig.routing = new Routing
|
||||
{
|
||||
rules = new List<RulesItem>()
|
||||
};
|
||||
|
||||
static bool CheckRuleItem(ref RulesItem rulesItem)
|
||||
{
|
||||
bool ipResult, domainResult;
|
||||
if (!(ipResult = rulesItem.ip.Any()))
|
||||
if (!(ipResult = rulesItem.ip?.Any() ?? false))
|
||||
rulesItem.ip = null;
|
||||
|
||||
if (!(domainResult = rulesItem.domain.Any()))
|
||||
if (!(domainResult = rulesItem.domain?.Any() ?? false))
|
||||
rulesItem.domain = null;
|
||||
|
||||
return ipResult || domainResult;
|
||||
@@ -242,7 +227,7 @@ namespace Netch.Servers.V2ray.Utils
|
||||
}
|
||||
}
|
||||
|
||||
v2rayConfig.outbounds = new List<Outbounds>
|
||||
v2rayConfig.outbounds.AddRange(new[]
|
||||
{
|
||||
outbound,
|
||||
new()
|
||||
@@ -253,7 +238,7 @@ namespace Netch.Servers.V2ray.Utils
|
||||
{
|
||||
tag = "block", protocol = "blackhole"
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -321,7 +306,7 @@ namespace Netch.Servers.V2ray.Utils
|
||||
{
|
||||
host = new List<string>
|
||||
{
|
||||
string.IsNullOrWhiteSpace(server.Host) ? server.Hostname : server.Host
|
||||
string.IsNullOrWhiteSpace(server.Host) ? server.Hostname : server.Host!
|
||||
},
|
||||
path = server.Path
|
||||
};
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Netch.Servers.V2ray
|
||||
|
||||
public ushort? Socks5LocalPort { get; set; }
|
||||
|
||||
public string LocalAddress { get; set; }
|
||||
public string? LocalAddress { get; set; }
|
||||
|
||||
public virtual void Start(in Server s, in Mode mode)
|
||||
{
|
||||
@@ -35,7 +35,7 @@ namespace Netch.Servers.V2ray
|
||||
{
|
||||
base.InitInstance(argument);
|
||||
if (!Global.Settings.V2RayConfig.XrayCone)
|
||||
Instance.StartInfo.Environment["XRAY_CONE_DISABLED"] = "true";
|
||||
Instance!.StartInfo.Environment["XRAY_CONE_DISABLED"] = "true";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,77 +8,66 @@ using Netch.Utils;
|
||||
|
||||
namespace Netch.Servers.V2ray
|
||||
{
|
||||
internal static class V2rayUtils
|
||||
public static class V2rayUtils
|
||||
{
|
||||
public static IEnumerable<Server> ParseVUri(string text)
|
||||
{
|
||||
var scheme = ShareLink.GetUriScheme(text).ToLower();
|
||||
try
|
||||
var server = scheme switch {"vmess" => new VMess.VMess(), "vless" => new VLESS.VLESS(), _ => throw new ArgumentOutOfRangeException()};
|
||||
if (text.Contains("#"))
|
||||
{
|
||||
var server = scheme switch {"vmess" => new VMess.VMess(), "vless" => new VLESS.VLESS(), _ => throw new ArgumentOutOfRangeException()};
|
||||
if (text.Contains("#"))
|
||||
server.Remark = Uri.UnescapeDataString(text.Split('#')[1]);
|
||||
text = text.Split('#')[0];
|
||||
}
|
||||
|
||||
if (text.Contains("?"))
|
||||
{
|
||||
var parameter = HttpUtility.ParseQueryString(text.Split('?')[1]);
|
||||
text = text.Substring(0, text.IndexOf("?", StringComparison.Ordinal));
|
||||
server.TransferProtocol = parameter.Get("type") ?? "tcp";
|
||||
server.EncryptMethod = parameter.Get("encryption") ?? scheme switch {"vless" => "none", _ => "auto"};
|
||||
switch (server.TransferProtocol)
|
||||
{
|
||||
server.Remark = Uri.UnescapeDataString(text.Split('#')[1]);
|
||||
text = text.Split('#')[0];
|
||||
case "tcp":
|
||||
break;
|
||||
case "kcp":
|
||||
server.FakeType = parameter.Get("headerType") ?? "none";
|
||||
server.Path = Uri.UnescapeDataString(parameter.Get("seed") ?? "");
|
||||
break;
|
||||
case "ws":
|
||||
server.Path = Uri.UnescapeDataString(parameter.Get("path") ?? "/");
|
||||
server.Host = Uri.UnescapeDataString(parameter.Get("host") ?? "");
|
||||
break;
|
||||
case "h2":
|
||||
server.Path = Uri.UnescapeDataString(parameter.Get("path") ?? "/");
|
||||
server.Host = Uri.UnescapeDataString(parameter.Get("host") ?? "");
|
||||
break;
|
||||
case "quic":
|
||||
server.QUICSecure = parameter.Get("quicSecurity") ?? "none";
|
||||
server.QUICSecret = parameter.Get("key") ?? "";
|
||||
server.FakeType = parameter.Get("headerType") ?? "none";
|
||||
break;
|
||||
}
|
||||
|
||||
if (text.Contains("?"))
|
||||
server.TLSSecureType = parameter.Get("security") ?? "none";
|
||||
if (server.TLSSecureType != "none")
|
||||
{
|
||||
var parameter = HttpUtility.ParseQueryString(text.Split('?')[1]);
|
||||
text = text.Substring(0, text.IndexOf("?", StringComparison.Ordinal));
|
||||
server.TransferProtocol = parameter.Get("type") ?? "tcp";
|
||||
server.EncryptMethod = parameter.Get("encryption") ?? scheme switch {"vless" => "none", _ => "auto"};
|
||||
switch (server.TransferProtocol)
|
||||
{
|
||||
case "tcp":
|
||||
break;
|
||||
case "kcp":
|
||||
server.FakeType = parameter.Get("headerType") ?? "none";
|
||||
server.Path = Uri.UnescapeDataString(parameter.Get("seed") ?? "");
|
||||
break;
|
||||
case "ws":
|
||||
server.Path = Uri.UnescapeDataString(parameter.Get("path") ?? "/");
|
||||
server.Host = Uri.UnescapeDataString(parameter.Get("host") ?? "");
|
||||
break;
|
||||
case "h2":
|
||||
server.Path = Uri.UnescapeDataString(parameter.Get("path") ?? "/");
|
||||
server.Host = Uri.UnescapeDataString(parameter.Get("host") ?? "");
|
||||
break;
|
||||
case "quic":
|
||||
server.QUICSecure = parameter.Get("quicSecurity") ?? "none";
|
||||
server.QUICSecret = parameter.Get("key") ?? "";
|
||||
server.FakeType = parameter.Get("headerType") ?? "none";
|
||||
break;
|
||||
}
|
||||
|
||||
server.TLSSecureType = parameter.Get("security") ?? "none";
|
||||
if (server.TLSSecureType != "none")
|
||||
{
|
||||
server.Host = parameter.Get("sni") ?? "";
|
||||
if (server.TLSSecureType == "xtls")
|
||||
((VLESS.VLESS) server).Flow = parameter.Get("flow") ?? "";
|
||||
}
|
||||
server.Host = parameter.Get("sni") ?? "";
|
||||
if (server.TLSSecureType == "xtls")
|
||||
((VLESS.VLESS) server).Flow = parameter.Get("flow") ?? "";
|
||||
}
|
||||
|
||||
var finder = new Regex(@$"^{scheme}://(?<guid>.+?)@(?<server>.+):(?<port>\d+)");
|
||||
var match = finder.Match(text.Split('?')[0]);
|
||||
if (!match.Success)
|
||||
throw new FormatException();
|
||||
|
||||
server.UserID = match.Groups["guid"].Value;
|
||||
server.Hostname = match.Groups["server"].Value;
|
||||
server.Port = ushort.Parse(match.Groups["port"].Value);
|
||||
|
||||
return new[]
|
||||
{
|
||||
server
|
||||
};
|
||||
}
|
||||
catch (FormatException e)
|
||||
{
|
||||
Logging.Error(e.ToString());
|
||||
return null;
|
||||
}
|
||||
|
||||
var finder = new Regex(@$"^{scheme}://(?<guid>.+?)@(?<server>.+):(?<port>\d+)");
|
||||
var match = finder.Match(text.Split('?')[0]);
|
||||
if (!match.Success)
|
||||
throw new FormatException();
|
||||
|
||||
server.UserID = match.Groups["guid"].Value;
|
||||
server.Hostname = match.Groups["server"].Value;
|
||||
server.Port = ushort.Parse(match.Groups["port"].Value);
|
||||
|
||||
return new[] {server};
|
||||
}
|
||||
|
||||
public static string GetVShareLink(Server s, string scheme = "vmess")
|
||||
@@ -102,26 +91,27 @@ namespace Netch.Servers.V2ray
|
||||
parameter.Add("headerType", server.FakeType);
|
||||
|
||||
if (!server.Path.IsNullOrWhiteSpace())
|
||||
parameter.Add("seed", Uri.EscapeDataString(server.Path));
|
||||
parameter.Add("seed", Uri.EscapeDataString(server.Path!));
|
||||
|
||||
break;
|
||||
case "ws":
|
||||
parameter.Add("path", Uri.EscapeDataString(server.Path.IsNullOrWhiteSpace() ? "/" : server.Path));
|
||||
parameter.Add("path", Uri.EscapeDataString(server.Path.IsNullOrWhiteSpace() ? "/" : server.Path!));
|
||||
if (!server.Host.IsNullOrWhiteSpace())
|
||||
parameter.Add("host", Uri.EscapeDataString(server.Host));
|
||||
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.IsNullOrWhiteSpace() ? "/" : server.Path!));
|
||||
if (!server.Host.IsNullOrWhiteSpace())
|
||||
parameter.Add("host", Uri.EscapeDataString(server.Host));
|
||||
parameter.Add("host", Uri.EscapeDataString(server.Host!));
|
||||
|
||||
break;
|
||||
case "quic":
|
||||
if (server.QUICSecure != "none")
|
||||
if (server.QUICSecure is not (null or "none"))
|
||||
{
|
||||
parameter.Add("quicSecurity", server.QUICSecure);
|
||||
parameter.Add("key", server.QUICSecret);
|
||||
parameter.Add("key", server.QUICSecret!);
|
||||
// TODO Import and Create null value Check
|
||||
}
|
||||
|
||||
if (server.FakeType != "none")
|
||||
@@ -135,13 +125,13 @@ namespace Netch.Servers.V2ray
|
||||
parameter.Add("security", server.TLSSecureType);
|
||||
|
||||
if (!server.Host.IsNullOrWhiteSpace())
|
||||
parameter.Add("sni", server.Host);
|
||||
parameter.Add("sni", server.Host!);
|
||||
|
||||
if (server.TLSSecureType == "xtls")
|
||||
{
|
||||
var flow = ((VLESS.VLESS) server).Flow.Replace("-udp443", "");
|
||||
var flow = ((VLESS.VLESS) server).Flow;
|
||||
if (!flow.IsNullOrWhiteSpace())
|
||||
parameter.Add("flow", flow);
|
||||
parameter.Add("flow", flow!.Replace("-udp443", ""));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Netch.Servers.VLESS
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
public string Flow { get; set; }
|
||||
public string? Flow { get; set; }
|
||||
}
|
||||
|
||||
public class VLESSGlobal
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Netch.Servers.VLESS.VLESSForm
|
||||
{
|
||||
internal class VLESSForm : ServerForm
|
||||
{
|
||||
public VLESSForm(VLESS server = default)
|
||||
public VLESSForm(VLESS? server = default)
|
||||
{
|
||||
server ??= new VLESS();
|
||||
Server = server;
|
||||
|
||||
@@ -50,7 +50,6 @@ namespace Netch.Servers.VLESS
|
||||
|
||||
public bool CheckServer(Server s)
|
||||
{
|
||||
// TODO
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Netch.Servers.VMess.Form
|
||||
{
|
||||
public class VMessForm : ServerForm
|
||||
{
|
||||
public VMessForm(VMess server = default)
|
||||
public VMessForm(VMess? server = default)
|
||||
{
|
||||
server ??= new VMess();
|
||||
Server = server;
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Netch.Servers.VMess
|
||||
/// <summary>
|
||||
/// 用户 ID
|
||||
/// </summary>
|
||||
public string UserID { get; set; }
|
||||
public string UserID { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 额外 ID
|
||||
@@ -37,22 +37,22 @@ namespace Netch.Servers.VMess
|
||||
/// <summary>
|
||||
/// 伪装域名
|
||||
/// </summary>
|
||||
public string Host { get; set; }
|
||||
public string? Host { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 传输路径
|
||||
/// </summary>
|
||||
public string Path { get; set; }
|
||||
public string? Path { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// QUIC 加密方式
|
||||
/// </summary>
|
||||
public string QUICSecure { get; set; } = VMessGlobal.QUIC[0];
|
||||
public string? QUICSecure { get; set; } = VMessGlobal.QUIC[0];
|
||||
|
||||
/// <summary>
|
||||
/// QUIC 加密密钥
|
||||
/// </summary>
|
||||
public string QUICSecret { get; set; } = string.Empty;
|
||||
public string? QUICSecret { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// TLS 底层传输安全
|
||||
|
||||
@@ -24,16 +24,7 @@ namespace Netch.Servers.VMess
|
||||
|
||||
public Server ParseJObject(in JObject j)
|
||||
{
|
||||
// TODO Remove Migrate code
|
||||
var server = j.ToObject<VMess>();
|
||||
if (server == null)
|
||||
return null;
|
||||
|
||||
string quic;
|
||||
if ((quic = j.GetValue("QUIC")?.ToString()) != null)
|
||||
server.QUICSecure = quic;
|
||||
|
||||
return server;
|
||||
return j.ToObject<VMess>();
|
||||
}
|
||||
|
||||
public void Edit(Server s)
|
||||
@@ -117,31 +108,11 @@ namespace Netch.Servers.VMess
|
||||
data.TLSSecureType = vmess.tls;
|
||||
data.EncryptMethod = "auto"; // V2Ray 加密方式不包括在链接中,主动添加一个
|
||||
|
||||
return CheckServer(data) ? new[] {data} : null;
|
||||
return new[] {data};
|
||||
}
|
||||
|
||||
public bool CheckServer(Server s)
|
||||
{
|
||||
var server = (VMess) s;
|
||||
if (!VMessGlobal.TransferProtocols.Contains(server.TransferProtocol))
|
||||
{
|
||||
Logging.Error($"不支持的 VMess 传输协议:{server.TransferProtocol}");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (server.FakeType.Length != 0 && !VMessGlobal.FakeTypes.Contains(server.FakeType))
|
||||
{
|
||||
Logging.Error($"不支持的 VMess 伪装类型:{server.FakeType}");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (server.TransferProtocol == "quic")
|
||||
if (!VMessGlobal.QUIC.Contains(server.QUICSecure))
|
||||
{
|
||||
Logging.Error($"不支持的 VMess QUIC 加密方式:{server.QUICSecure}");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user