Compare commits

...

7 Commits

Author SHA1 Message Date
Amazing_DM
bdaab4f1ac 此处修复一个诡异的BUG 感谢@ColinWood Tap模式 Mux不能为Null 否则Netch内存占用极大 2020-03-27 12:03:31 +08:00
Amazing_DM
9ad5e16f47 Update submodule 2020-03-26 14:48:30 +08:00
Amazing_DM
c861ed4116 Merge pull request #256 from VCStardust/master
Change STUN Test Server
2020-03-25 21:57:45 -05:00
Col. Schwi
c39b758fe6 Change STUN Server 2020-03-25 21:28:15 +08:00
Amazing_DM
e1901587a5 :art:订阅更新超时改为10s
:art:微调设置界面
2020-03-24 18:29:46 +08:00
Amazing_DM
8aea21a2c6 :bug:fix a bug. catch复制链接按钮 2020-03-23 14:43:38 +08:00
Amazing_DM
d97d461354 :art:改进SSR链接解析 2020-03-23 14:40:22 +08:00
7 changed files with 213 additions and 75 deletions

View File

@@ -127,14 +127,18 @@ namespace Netch.Controllers
enabled = server.UseMux
}
},
new Models.Information.VMess.Outbounds
//此处修复一个诡异的BUG 感谢@ColinWood Tap模式 Mux不能为Null 否则Netch内存占用极大
/*new Models.Information.VMess.Outbounds
{
tag = "direct",
protocol = "freedom",
settings = null,
streamSettings = null,
*//*mux = new Models.Information.VMess.OutboundMux(){
enabled = true
}*//*
mux = null
}
}*/
},
routing = new Models.Information.VMess.Routing
{
@@ -147,7 +151,7 @@ namespace Netch.Controllers
{
"geoip:cn",
"geoip:private"
},
domain = new List<string>
{

View File

@@ -1254,7 +1254,15 @@ namespace Netch.Forms
if (ServerComboBox.SelectedIndex != -1)
{
var selectedMode = (Models.Server)ServerComboBox.SelectedItem;
Clipboard.SetText(Utils.ShareLink.GetShareLink(selectedMode));
try
{
//听说巨硬BUG经常会炸所以Catch一下 :D
Clipboard.SetText(Utils.ShareLink.GetShareLink(selectedMode));
}
catch (Exception)
{
}
}
else
{

View File

@@ -329,7 +329,7 @@
// BypassModeCheckBox
//
this.BypassModeCheckBox.AutoSize = true;
this.BypassModeCheckBox.Location = new System.Drawing.Point(276, 232);
this.BypassModeCheckBox.Location = new System.Drawing.Point(276, 236);
this.BypassModeCheckBox.Name = "BypassModeCheckBox";
this.BypassModeCheckBox.Size = new System.Drawing.Size(135, 21);
this.BypassModeCheckBox.TabIndex = 14;
@@ -340,7 +340,7 @@
// Redirector2checkBox
//
this.Redirector2checkBox.AutoSize = true;
this.Redirector2checkBox.Location = new System.Drawing.Point(152, 232);
this.Redirector2checkBox.Location = new System.Drawing.Point(152, 235);
this.Redirector2checkBox.Name = "Redirector2checkBox";
this.Redirector2checkBox.Size = new System.Drawing.Size(118, 21);
this.Redirector2checkBox.TabIndex = 11;
@@ -350,7 +350,7 @@
// ExperimentalFunction_Label
//
this.ExperimentalFunction_Label.AutoSize = true;
this.ExperimentalFunction_Label.Location = new System.Drawing.Point(6, 233);
this.ExperimentalFunction_Label.Location = new System.Drawing.Point(6, 236);
this.ExperimentalFunction_Label.Name = "ExperimentalFunction_Label";
this.ExperimentalFunction_Label.Size = new System.Drawing.Size(133, 17);
this.ExperimentalFunction_Label.TabIndex = 13;
@@ -358,7 +358,7 @@
//
// STUN_ServerPortTextBox
//
this.STUN_ServerPortTextBox.Location = new System.Drawing.Point(117, 203);
this.STUN_ServerPortTextBox.Location = new System.Drawing.Point(117, 206);
this.STUN_ServerPortTextBox.Name = "STUN_ServerPortTextBox";
this.STUN_ServerPortTextBox.Size = new System.Drawing.Size(294, 23);
this.STUN_ServerPortTextBox.TabIndex = 8;

View File

@@ -147,12 +147,12 @@ namespace Netch.Models
/// <summary>
/// STUN测试服务器
/// </summary>
public string STUN_Server = "stun.stunprotocol.org";
public string STUN_Server = "stun.l.google.com";
/// <summary>
/// STUN测试服务器
/// </summary>
public int STUN_Server_Port = 3478;
public int STUN_Server_Port = 19302;
/// <summary>
/// 是否切换为2号核心

View File

@@ -8,8 +8,8 @@ namespace Netch.Override
protected override WebRequest GetWebRequest(Uri address)
{
var request = base.GetWebRequest(address);
request.Timeout = 4000;
((HttpWebRequest)request).ReadWriteTimeout = 4000;
request.Timeout = 10000;
((HttpWebRequest)request).ReadWriteTimeout = 10000;
return request;
}

View File

@@ -290,80 +290,88 @@ namespace Netch.Utils
}
else if (text.StartsWith("ssr://"))
{
var data = new Server();
data.Type = "SSR";
text = text.Substring(6);
list.Add(SsrServerFromLink(text));
var parser = new Regex(@"^(?<server>.+):(?<port>(-?\d+?)):(?<protocol>.+?):(?<method>.+?):(?<obfs>.+?):(?<password>.+?)/\?(?<info>.*)$");
var match = parser.Match(URLSafeBase64Decode(text));
/* var data = new Server();
data.Type = "SSR";
if (match.Success)
{
data.Hostname = match.Groups["server"].Value;
data.Port = int.Parse(match.Groups["port"].Value);
if (data.Port < 0)
{
data.Port += 65536;
}
data.Password = URLSafeBase64Decode(match.Groups["password"].Value);
text = text.Substring(6);
data.EncryptMethod = match.Groups["method"].Value;
if (!Global.EncryptMethods.SSR.Contains(data.EncryptMethod))
{
Logging.Info(string.Format("不支持的 SSR 加密方式:{0}", data.EncryptMethod));
return null;
}
var parser = new Regex(@"^(?<server>.+):(?<port>(-?\d+?)):(?<protocol>.+?):(?<method>.+?):(?<obfs>.+?):(?<password>.+?)/\?(?<info>.*)$");
var parser2 = new Regex(@"^(?<server>.+):(?<port>(-?\d+?)):(?<protocol>.+?):(?<method>.+?):(?<obfs>.+?):(?<password>.+?)/$");
var match = parser2.Match(URLSafeBase64Decode(text));
if (!match.Success)
{
match = parser2.Match(UnBase64String(text));
}
data.Protocol = match.Groups["protocol"].Value;
if (!Global.Protocols.Contains(data.Protocol))
{
Logging.Info(string.Format("不支持的 SSR 协议:{0}", data.Protocol));
return null;
}
if (match.Success)
{
data.Hostname = match.Groups["server"].Value;
data.Port = int.Parse(match.Groups["port"].Value);
if (data.Port < 0)
{
data.Port += 65536;
}
data.Password = URLSafeBase64Decode(match.Groups["password"].Value);
data.OBFS = match.Groups["obfs"].Value;
if (data.OBFS == @"tls1.2_ticket_fastauth")
{
data.OBFS = @"tls1.2_ticket_auth";
}
if (!Global.OBFSs.Contains(data.OBFS))
{
Logging.Info(string.Format("不支持的 SSR 混淆:{0}", data.OBFS));
return null;
}
data.EncryptMethod = match.Groups["method"].Value;
if (!Global.EncryptMethods.SSR.Contains(data.EncryptMethod))
{
Logging.Info(string.Format("不支持的 SSR 加密方式:{0}", data.EncryptMethod));
return null;
}
var info = match.Groups["info"].Value;
var dict = new Dictionary<string, string>();
foreach (var str in info.Split('&'))
{
var splited = str.Split('=');
dict.Add(splited[0], splited[1]);
}
data.Protocol = match.Groups["protocol"].Value;
if (!Global.Protocols.Contains(data.Protocol))
{
Logging.Info(string.Format("不支持的 SSR 协议:{0}", data.Protocol));
return null;
}
if (dict.ContainsKey("remarks"))
{
data.Remark = URLSafeBase64Decode(dict["remarks"]);
}
data.OBFS = match.Groups["obfs"].Value;
if (data.OBFS == @"tls1.2_ticket_fastauth")
{
data.OBFS = @"tls1.2_ticket_auth";
}
if (!Global.OBFSs.Contains(data.OBFS))
{
Logging.Info(string.Format("不支持的 SSR 混淆:{0}", data.OBFS));
return null;
}
if (dict.ContainsKey("protoparam"))
{
data.ProtocolParam = URLSafeBase64Decode(dict["protoparam"]);
}
var info = match.Groups["info"].Value;
var dict = new Dictionary<string, string>();
foreach (var str in info.Split('&'))
{
var splited = str.Split('=');
dict.Add(splited[0], splited[1]);
}
if (dict.ContainsKey("obfsparam"))
{
data.OBFSParam = URLSafeBase64Decode(dict["obfsparam"]);
}
if (dict.ContainsKey("remarks"))
{
data.Remark = URLSafeBase64Decode(dict["remarks"]);
}
if (Global.EncryptMethods.SS.Contains(data.EncryptMethod) && data.Protocol == "origin" && data.OBFS == "plain")
{
data.OBFS = "";
data.Type = "SS";
}
}
if (dict.ContainsKey("protoparam"))
{
data.ProtocolParam = URLSafeBase64Decode(dict["protoparam"]);
}
if (dict.ContainsKey("obfsparam"))
{
data.OBFSParam = URLSafeBase64Decode(dict["obfsparam"]);
}
if (Global.EncryptMethods.SS.Contains(data.EncryptMethod) && data.Protocol == "origin" && data.OBFS == "plain")
{
data.OBFS = "";
data.Type = "SS";
}
list.Add(data);
}*/
list.Add(data);
}
else if (text.StartsWith("vmess://"))
{
@@ -517,5 +525,123 @@ namespace Netch.Utils
return list;
}
public static string UnBase64String(string value)
{
if (value == null || value == "")
{
return "";
}
byte[] bytes = Convert.FromBase64String(value);
return Encoding.UTF8.GetString(bytes);
}
public static string ToBase64String(string value)
{
if (value == null || value == "")
{
return "";
}
byte[] bytes = Encoding.UTF8.GetBytes(value);
return Convert.ToBase64String(bytes);
}
/// <summary>
/// SSR链接解析器
/// Copy From https://github.com/HMBSbige/ShadowsocksR-Windows/blob/d9dc8d032a6e04c14b9dc6c8f673c9cc5aa9f607/shadowsocks-csharp/Model/Server.cs#L428
/// Thx :D
/// </summary>
/// <param name="ssrUrl"></param>
/// <returns></returns>
public static Server SsrServerFromLink(string ssrUrl)
{
// ssr://host:port:protocol:method:obfs:base64pass/?obfsparam=base64&remarks=base64&group=base64&udpport=0&uot=1
var ssr = Regex.Match(ssrUrl, "ssr://([A-Za-z0-9_-]+)", RegexOptions.IgnoreCase);
if (!ssr.Success)
throw new FormatException();
var data = URLSafeBase64Decode(ssr.Groups[1].Value);
var params_dict = new Dictionary<string, string>();
var param_start_pos = data.IndexOf("?", StringComparison.Ordinal);
if (param_start_pos > 0)
{
params_dict = ParseParam(data.Substring(param_start_pos + 1));
data = data.Substring(0, param_start_pos);
}
if (data.IndexOf("/", StringComparison.Ordinal) >= 0)
{
data = data.Substring(0, data.LastIndexOf("/", StringComparison.Ordinal));
}
var UrlFinder = new Regex("^(.+):([^:]+):([^:]*):([^:]+):([^:]*):([^:]+)");
var match = UrlFinder.Match(data);
if (match == null || !match.Success)
throw new FormatException();
var serverAddr = match.Groups[1].Value;
var Server_Port = ushort.Parse(match.Groups[2].Value);
var Protocol = match.Groups[3].Value.Length == 0 ? "origin" : match.Groups[3].Value;
Protocol = Protocol.Replace("_compatible", "");
var Method = match.Groups[4].Value;
var obfs = match.Groups[5].Value.Length == 0 ? "plain" : match.Groups[5].Value;
obfs = obfs.Replace("_compatible", "");
var Password = URLSafeBase64Decode(match.Groups[6].Value);
var ProtocolParam = "";
var ObfsParam = "";
var Remarks = "";
var Group = "";
if (params_dict.ContainsKey("protoparam"))
{
ProtocolParam = URLSafeBase64Decode(params_dict["protoparam"]);
}
if (params_dict.ContainsKey("obfsparam"))
{
ObfsParam = URLSafeBase64Decode(params_dict["obfsparam"]);
}
if (params_dict.ContainsKey("remarks"))
{
Remarks = URLSafeBase64Decode(params_dict["remarks"]);
}
Group = params_dict.ContainsKey("group") ? URLSafeBase64Decode(params_dict["group"]) : string.Empty;
/*if (params_dict.ContainsKey("uot"))
{
UdpOverTcp = int.Parse(params_dict["uot"]) != 0;
}
if (params_dict.ContainsKey("udpport"))
{
Server_Udp_Port = ushort.Parse(params_dict["udpport"]);
}*/
Server server = new Server();
server.Type = "SSR";
server.Hostname = serverAddr;
server.Port = Server_Port;
server.Protocol = Protocol;
server.EncryptMethod = Method;
server.OBFS = obfs;
server.Password = Password;
server.ProtocolParam = ProtocolParam;
server.OBFSParam = ObfsParam;
server.Remark = Remarks;
server.Group = Group;
return server;
}
private static Dictionary<string, string> ParseParam(string paramStr)
{
var paramsDict = new Dictionary<string, string>();
var obfsParams = paramStr.Split('&');
foreach (var p in obfsParams)
{
if (p.IndexOf('=') > 0)
{
var index = p.IndexOf('=');
var key = p.Substring(0, index);
var val = p.Substring(index + 1);
paramsDict[key] = val;
}
}
return paramsDict;
}
}
}

2
modes

Submodule modes updated: 0062332e64...de2c3c7cf1