Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f3f52c5e0 | ||
|
|
1dcb72e9dc | ||
|
|
153c8a0a74 | ||
|
|
4e8ea374d8 | ||
|
|
e313e004eb | ||
|
|
93b8dec63e | ||
|
|
5c9c35c199 | ||
|
|
4a6b8968d5 | ||
|
|
088d2e6834 | ||
|
|
4f39f7a932 | ||
|
|
2615b72cee | ||
|
|
a799420d0f | ||
|
|
70069a05e6 | ||
|
|
d385b44a48 | ||
|
|
56c1557f4a |
@@ -7,4 +7,4 @@
|
|||||||
|
|
||||||
### Requirements
|
### Requirements
|
||||||
- Microsoft [.NET Framework 4.6](https://docs.microsoft.com/zh-cn/dotnet/framework/install/guide-for-developers) or higher
|
- Microsoft [.NET Framework 4.6](https://docs.microsoft.com/zh-cn/dotnet/framework/install/guide-for-developers) or higher
|
||||||
- Project V core [https://github.com/v2ray/v2ray-core/releases](https://github.com/v2ray/v2ray-core/releases)
|
- Project V core [https://github.com/v2fly/v2ray-core/releases](https://github.com/v2fly/v2ray-core/releases)
|
||||||
|
|||||||
@@ -149,7 +149,7 @@
|
|||||||
<value>203, 12</value>
|
<value>203, 12</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="label21.Text" xml:space="preserve">
|
<data name="label21.Text" xml:space="preserve">
|
||||||
<value>允许不安全连接(allowInsecure)</value>
|
<value>跳过证书验证(allowInsecure)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="cmbAllowInsecure.Location" type="System.Drawing.Point, System.Drawing">
|
<data name="cmbAllowInsecure.Location" type="System.Drawing.Point, System.Drawing">
|
||||||
<value>223, 7</value>
|
<value>223, 7</value>
|
||||||
|
|||||||
@@ -1298,7 +1298,16 @@ namespace v2rayN.Forms
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
string fileName = Utils.GetPath(downloadHandle.DownloadFileName);
|
string fileName = Utils.GetPath(downloadHandle.DownloadFileName);
|
||||||
Process process = Process.Start("v2rayUpgrade.exe", "\"" + fileName + "\"");
|
Process process = new Process
|
||||||
|
{
|
||||||
|
StartInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = "v2rayUpgrade.exe",
|
||||||
|
Arguments = "\"" + fileName + "\"",
|
||||||
|
WorkingDirectory = Utils.StartupPath()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
process.Start();
|
||||||
if (process.Id > 0)
|
if (process.Id > 0)
|
||||||
{
|
{
|
||||||
menuExit_Click(null, null);
|
menuExit_Click(null, null);
|
||||||
|
|||||||
@@ -444,7 +444,7 @@ namespace v2rayN.Forms
|
|||||||
|
|
||||||
private void linkLabelRoutingDoc_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
private void linkLabelRoutingDoc_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||||
{
|
{
|
||||||
System.Diagnostics.Process.Start("https://www.v2fly.org/chapter_02/03_routing.html");
|
System.Diagnostics.Process.Start("https://www.v2fly.org/config/routing.html");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -128,7 +128,7 @@
|
|||||||
<value>222, 16</value>
|
<value>222, 16</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="chkdefAllowInsecure.Text" xml:space="preserve">
|
<data name="chkdefAllowInsecure.Text" xml:space="preserve">
|
||||||
<value>底层传输安全选tls时,默认允许不安全连接(allowInsecure)</value>
|
<value>底层传输安全选tls时,默认跳过证书验证(allowInsecure)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="label16.Size" type="System.Drawing.Size, System.Drawing">
|
<data name="label16.Size" type="System.Drawing.Size, System.Drawing">
|
||||||
<value>53, 12</value>
|
<value>53, 12</value>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace v2rayN
|
|||||||
#region 常量
|
#region 常量
|
||||||
|
|
||||||
|
|
||||||
public const string v2rayWebsiteUrl = @"https://www.v2ray.com/";
|
public const string v2rayWebsiteUrl = @"https://www.v2fly.org/";
|
||||||
public const string AboutUrl = @"https://github.com/2dust/v2rayN";
|
public const string AboutUrl = @"https://github.com/2dust/v2rayN";
|
||||||
public const string UpdateUrl = AboutUrl + @"/releases";
|
public const string UpdateUrl = AboutUrl + @"/releases";
|
||||||
|
|
||||||
|
|||||||
@@ -54,8 +54,8 @@ namespace v2rayN.Handler
|
|||||||
|
|
||||||
private readonly string nLatestUrl = "https://github.com/2dust/v2rayN/releases/latest";
|
private readonly string nLatestUrl = "https://github.com/2dust/v2rayN/releases/latest";
|
||||||
private const string nUrl = "https://github.com/2dust/v2rayN/releases/download/{0}/v2rayN.zip";
|
private const string nUrl = "https://github.com/2dust/v2rayN/releases/download/{0}/v2rayN.zip";
|
||||||
private readonly string coreLatestUrl = "https://github.com/v2ray/v2ray-core/releases/latest";
|
private readonly string coreLatestUrl = "https://github.com/v2fly/v2ray-core/releases/latest";
|
||||||
private const string coreUrl = "https://github.com/v2ray/v2ray-core/releases/download/{0}/v2ray-windows-{1}.zip";
|
private const string coreUrl = "https://github.com/v2fly/v2ray-core/releases/download/{0}/v2ray-windows-{1}.zip";
|
||||||
|
|
||||||
public async void CheckUpdateAsync(string type)
|
public async void CheckUpdateAsync(string type)
|
||||||
{
|
{
|
||||||
@@ -101,7 +101,7 @@ namespace v2rayN.Handler
|
|||||||
string filePath = Utils.GetPath("V2ray.exe");
|
string filePath = Utils.GetPath("V2ray.exe");
|
||||||
if (!File.Exists(filePath))
|
if (!File.Exists(filePath))
|
||||||
{
|
{
|
||||||
string msg = string.Format(UIRes.I18N("NotFoundCore"), @"https://github.com/v2ray/v2ray-core/releases");
|
string msg = string.Format(UIRes.I18N("NotFoundCore"), @"https://github.com/v2fly/v2ray-core/releases");
|
||||||
//ShowMsg(true, msg);
|
//ShowMsg(true, msg);
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ namespace v2rayN.Handler
|
|||||||
_updateFunc(testCounter, args.GetException().Message);
|
_updateFunc(testCounter, args.GetException().Message);
|
||||||
};
|
};
|
||||||
|
|
||||||
var timeout = 12;
|
var timeout = 10;
|
||||||
foreach (int itemIndex in _selecteds)
|
foreach (int itemIndex in _selecteds)
|
||||||
{
|
{
|
||||||
if (itemIndex >= _config.vmess.Count)
|
if (itemIndex >= _config.vmess.Count)
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Web;
|
||||||
using v2rayN.Base;
|
using v2rayN.Base;
|
||||||
using v2rayN.Mode;
|
using v2rayN.Mode;
|
||||||
|
|
||||||
@@ -1195,7 +1199,7 @@ namespace v2rayN.Handler
|
|||||||
int indexSplit = result.IndexOf("?");
|
int indexSplit = result.IndexOf("?");
|
||||||
if (indexSplit > 0)
|
if (indexSplit > 0)
|
||||||
{
|
{
|
||||||
vmessItem = ResolveVmess4Kitsunebi(result);
|
vmessItem = ResolveStdVmess(result) ?? ResolveVmess4Kitsunebi(result);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1242,46 +1246,21 @@ namespace v2rayN.Handler
|
|||||||
{
|
{
|
||||||
msg = UIRes.I18N("ConfigurationFormatIncorrect");
|
msg = UIRes.I18N("ConfigurationFormatIncorrect");
|
||||||
|
|
||||||
vmessItem.configType = (int)EConfigType.Shadowsocks;
|
vmessItem = ResolveSSLegacy(result);
|
||||||
result = result.Substring(Global.ssProtocol.Length);
|
if (vmessItem == null)
|
||||||
//remark
|
|
||||||
int indexRemark = result.IndexOf("#");
|
|
||||||
if (indexRemark > 0)
|
|
||||||
{
|
{
|
||||||
try
|
vmessItem = ResolveSip002(result);
|
||||||
{
|
|
||||||
vmessItem.remarks = WebUtility.UrlDecode(result.Substring(indexRemark + 1, result.Length - indexRemark - 1));
|
|
||||||
}
|
}
|
||||||
catch { }
|
if (vmessItem == null)
|
||||||
result = result.Substring(0, indexRemark);
|
|
||||||
}
|
|
||||||
//part decode
|
|
||||||
int indexS = result.IndexOf("@");
|
|
||||||
if (indexS > 0)
|
|
||||||
{
|
{
|
||||||
result = Utils.Base64Decode(result.Substring(0, indexS)) + result.Substring(indexS, result.Length - indexS);
|
return null;
|
||||||
}
|
}
|
||||||
else
|
if (vmessItem.address.Length == 0 || vmessItem.port == 0 || vmessItem.security.Length == 0 || vmessItem.id.Length == 0)
|
||||||
{
|
{
|
||||||
result = Utils.Base64Decode(result);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
string[] arr1 = result.Split('@');
|
vmessItem.configType = (int)EConfigType.Shadowsocks;
|
||||||
if (arr1.Length != 2)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
string[] arr21 = arr1[0].Split(':');
|
|
||||||
//string[] arr22 = arr1[1].Split(':');
|
|
||||||
int indexPort = arr1[1].LastIndexOf(":");
|
|
||||||
if (arr21.Length != 2 || indexPort < 0)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
vmessItem.address = arr1[1].Substring(0, indexPort);
|
|
||||||
vmessItem.port = Utils.ToInt(arr1[1].Substring(indexPort + 1, arr1[1].Length - (indexPort + 1)));
|
|
||||||
vmessItem.security = arr21[0];
|
|
||||||
vmessItem.id = arr21[1];
|
|
||||||
}
|
}
|
||||||
else if (result.StartsWith(Global.socksProtocol))
|
else if (result.StartsWith(Global.socksProtocol))
|
||||||
{
|
{
|
||||||
@@ -1406,6 +1385,177 @@ namespace v2rayN.Handler
|
|||||||
return vmessItem;
|
return vmessItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static VmessItem ResolveSip002(string result)
|
||||||
|
{
|
||||||
|
Uri parsedUrl;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
parsedUrl = new Uri(result);
|
||||||
|
}
|
||||||
|
catch (UriFormatException)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
VmessItem server = new VmessItem
|
||||||
|
{
|
||||||
|
remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped),
|
||||||
|
address = parsedUrl.IdnHost,
|
||||||
|
port = parsedUrl.Port,
|
||||||
|
};
|
||||||
|
|
||||||
|
// parse base64 UserInfo
|
||||||
|
string rawUserInfo = parsedUrl.GetComponents(UriComponents.UserInfo, UriFormat.Unescaped);
|
||||||
|
string base64 = rawUserInfo.Replace('-', '+').Replace('_', '/'); // Web-safe base64 to normal base64
|
||||||
|
string userInfo;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
userInfo = Encoding.UTF8.GetString(Convert.FromBase64String(
|
||||||
|
base64.PadRight(base64.Length + (4 - base64.Length % 4) % 4, '=')));
|
||||||
|
}
|
||||||
|
catch (FormatException)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
string[] userInfoParts = userInfo.Split(new char[] { ':' }, 2);
|
||||||
|
if (userInfoParts.Length != 2)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
server.security = userInfoParts[0];
|
||||||
|
server.id = userInfoParts[1];
|
||||||
|
|
||||||
|
NameValueCollection queryParameters = HttpUtility.ParseQueryString(parsedUrl.Query);
|
||||||
|
if (queryParameters["plugin"] != null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly Regex UrlFinder = new Regex(@"ss://(?<base64>[A-Za-z0-9+-/=_]+)(?:#(?<tag>\S+))?", RegexOptions.IgnoreCase);
|
||||||
|
private static readonly Regex DetailsParser = new Regex(@"^((?<method>.+?):(?<password>.*)@(?<hostname>.+?):(?<port>\d+?))$", RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
|
private static VmessItem ResolveSSLegacy(string result)
|
||||||
|
{
|
||||||
|
var match = UrlFinder.Match(result);
|
||||||
|
if (!match.Success)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
VmessItem server = new VmessItem();
|
||||||
|
var base64 = match.Groups["base64"].Value.TrimEnd('/');
|
||||||
|
var tag = match.Groups["tag"].Value;
|
||||||
|
if (!tag.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
server.remarks = HttpUtility.UrlDecode(tag, Encoding.UTF8);
|
||||||
|
}
|
||||||
|
Match details;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
details = DetailsParser.Match(Encoding.UTF8.GetString(Convert.FromBase64String(
|
||||||
|
base64.PadRight(base64.Length + (4 - base64.Length % 4) % 4, '='))));
|
||||||
|
}
|
||||||
|
catch (FormatException)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (!details.Success)
|
||||||
|
return null;
|
||||||
|
server.security = details.Groups["method"].Value;
|
||||||
|
server.id = details.Groups["password"].Value;
|
||||||
|
server.address = details.Groups["hostname"].Value;
|
||||||
|
server.port = int.Parse(details.Groups["port"].Value);
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static readonly Regex StdVmessUserInfo = new Regex(
|
||||||
|
@"^(?<network>[a-z]+)(\+(?<streamSecurity>[a-z]+))?:(?<id>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})-(?<alterId>[0-9]+)$");
|
||||||
|
|
||||||
|
private static VmessItem ResolveStdVmess(string result)
|
||||||
|
{
|
||||||
|
VmessItem i = new VmessItem
|
||||||
|
{
|
||||||
|
configType = (int)EConfigType.Vmess,
|
||||||
|
security = "auto"
|
||||||
|
};
|
||||||
|
|
||||||
|
Uri u = new Uri(result);
|
||||||
|
|
||||||
|
i.address = u.IdnHost;
|
||||||
|
i.port = u.Port;
|
||||||
|
i.remarks = u.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
|
||||||
|
var q = HttpUtility.ParseQueryString(u.Query);
|
||||||
|
|
||||||
|
var m = StdVmessUserInfo.Match(u.UserInfo);
|
||||||
|
if (!m.Success) return null;
|
||||||
|
|
||||||
|
i.id = m.Groups["id"].Value;
|
||||||
|
if (!int.TryParse(m.Groups["alterId"].Value, out int aid))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
i.alterId = aid;
|
||||||
|
|
||||||
|
if (m.Groups["streamSecurity"].Success)
|
||||||
|
{
|
||||||
|
i.streamSecurity = m.Groups["streamSecurity"].Value;
|
||||||
|
}
|
||||||
|
switch (i.streamSecurity)
|
||||||
|
{
|
||||||
|
case "tls":
|
||||||
|
// TODO tls config
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (!string.IsNullOrWhiteSpace(i.streamSecurity))
|
||||||
|
return null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
i.network = m.Groups["network"].Value;
|
||||||
|
switch (i.network)
|
||||||
|
{
|
||||||
|
case "tcp":
|
||||||
|
string t1 = q["type"] ?? "none";
|
||||||
|
i.headerType = t1;
|
||||||
|
// TODO http option
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "kcp":
|
||||||
|
i.headerType = q["type"] ?? "none";
|
||||||
|
// TODO kcp seed
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "ws":
|
||||||
|
string p1 = q["path"] ?? "/";
|
||||||
|
string h1 = q["host"] ?? "";
|
||||||
|
i.requestHost = h1;
|
||||||
|
i.path = p1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "http":
|
||||||
|
i.network = "h2";
|
||||||
|
string p2 = q["path"] ?? "/";
|
||||||
|
string h2 = q["host"] ?? "";
|
||||||
|
i.requestHost = h2;
|
||||||
|
i.path = p2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "quic":
|
||||||
|
string s = q["security"] ?? "none";
|
||||||
|
string k = q["key"] ?? "";
|
||||||
|
string t3 = q["type"] ?? "none";
|
||||||
|
i.headerType = t3;
|
||||||
|
i.requestHost = s;
|
||||||
|
i.path = k;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Gen speedtest config
|
#region Gen speedtest config
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ namespace v2rayN.Handler
|
|||||||
}
|
}
|
||||||
if (Utils.IsNullOrEmpty(fileName))
|
if (Utils.IsNullOrEmpty(fileName))
|
||||||
{
|
{
|
||||||
string msg = string.Format(UIRes.I18N("NotFoundCore"), @"https://github.com/v2ray/v2ray-core/releases");
|
string msg = string.Format(UIRes.I18N("NotFoundCore"), @"https://github.com/v2fly/v2ray-core/releases");
|
||||||
ShowMsg(false, msg);
|
ShowMsg(false, msg);
|
||||||
}
|
}
|
||||||
return fileName;
|
return fileName;
|
||||||
|
|||||||
@@ -32,4 +32,4 @@ using System.Runtime.InteropServices;
|
|||||||
// 方法是按如下所示使用“*”:
|
// 方法是按如下所示使用“*”:
|
||||||
//[assembly: AssemblyVersion("1.0.*")]
|
//[assembly: AssemblyVersion("1.0.*")]
|
||||||
//[assembly: AssemblyVersion("1.0.0")]
|
//[assembly: AssemblyVersion("1.0.0")]
|
||||||
[assembly: AssemblyFileVersion("3.17")]
|
[assembly: AssemblyFileVersion("3.19")]
|
||||||
|
|||||||
@@ -93,6 +93,7 @@
|
|||||||
<Reference Include="System.Net" />
|
<Reference Include="System.Net" />
|
||||||
<Reference Include="System.Net.Http" />
|
<Reference Include="System.Net.Http" />
|
||||||
<Reference Include="System.Net.Http.WebRequest" />
|
<Reference Include="System.Net.Http.WebRequest" />
|
||||||
|
<Reference Include="System.Web" />
|
||||||
<Reference Include="System.Windows.Forms" />
|
<Reference Include="System.Windows.Forms" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user