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
|
||||
- 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>
|
||||
</data>
|
||||
<data name="label21.Text" xml:space="preserve">
|
||||
<value>允许不安全连接(allowInsecure)</value>
|
||||
<value>跳过证书验证(allowInsecure)</value>
|
||||
</data>
|
||||
<data name="cmbAllowInsecure.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>223, 7</value>
|
||||
|
||||
@@ -1298,7 +1298,16 @@ namespace v2rayN.Forms
|
||||
try
|
||||
{
|
||||
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)
|
||||
{
|
||||
menuExit_Click(null, null);
|
||||
|
||||
@@ -444,7 +444,7 @@ namespace v2rayN.Forms
|
||||
|
||||
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>
|
||||
</data>
|
||||
<data name="chkdefAllowInsecure.Text" xml:space="preserve">
|
||||
<value>底层传输安全选tls时,默认允许不安全连接(allowInsecure)</value>
|
||||
<value>底层传输安全选tls时,默认跳过证书验证(allowInsecure)</value>
|
||||
</data>
|
||||
<data name="label16.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>53, 12</value>
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace v2rayN
|
||||
#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 UpdateUrl = AboutUrl + @"/releases";
|
||||
|
||||
|
||||
@@ -54,8 +54,8 @@ namespace v2rayN.Handler
|
||||
|
||||
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 readonly string coreLatestUrl = "https://github.com/v2ray/v2ray-core/releases/latest";
|
||||
private const string coreUrl = "https://github.com/v2ray/v2ray-core/releases/download/{0}/v2ray-windows-{1}.zip";
|
||||
private readonly string coreLatestUrl = "https://github.com/v2fly/v2ray-core/releases/latest";
|
||||
private const string coreUrl = "https://github.com/v2fly/v2ray-core/releases/download/{0}/v2ray-windows-{1}.zip";
|
||||
|
||||
public async void CheckUpdateAsync(string type)
|
||||
{
|
||||
@@ -101,7 +101,7 @@ namespace v2rayN.Handler
|
||||
string filePath = Utils.GetPath("V2ray.exe");
|
||||
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);
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ namespace v2rayN.Handler
|
||||
_updateFunc(testCounter, args.GetException().Message);
|
||||
};
|
||||
|
||||
var timeout = 12;
|
||||
var timeout = 10;
|
||||
foreach (int itemIndex in _selecteds)
|
||||
{
|
||||
if (itemIndex >= _config.vmess.Count)
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using v2rayN.Base;
|
||||
using v2rayN.Mode;
|
||||
|
||||
@@ -392,7 +396,7 @@ namespace v2rayN.Handler
|
||||
|
||||
outbound.mux.enabled = false;
|
||||
outbound.mux.concurrency = -1;
|
||||
|
||||
|
||||
|
||||
outbound.protocol = "shadowsocks";
|
||||
outbound.settings.vnext = null;
|
||||
@@ -454,7 +458,7 @@ namespace v2rayN.Handler
|
||||
{
|
||||
//远程服务器底层传输配置
|
||||
streamSettings.network = config.network();
|
||||
string host = config.requestHost();
|
||||
string host = config.requestHost();
|
||||
//if tls
|
||||
if (config.streamSecurity() == Global.StreamSecurity)
|
||||
{
|
||||
@@ -1195,7 +1199,7 @@ namespace v2rayN.Handler
|
||||
int indexSplit = result.IndexOf("?");
|
||||
if (indexSplit > 0)
|
||||
{
|
||||
vmessItem = ResolveVmess4Kitsunebi(result);
|
||||
vmessItem = ResolveStdVmess(result) ?? ResolveVmess4Kitsunebi(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1242,46 +1246,21 @@ namespace v2rayN.Handler
|
||||
{
|
||||
msg = UIRes.I18N("ConfigurationFormatIncorrect");
|
||||
|
||||
vmessItem.configType = (int)EConfigType.Shadowsocks;
|
||||
result = result.Substring(Global.ssProtocol.Length);
|
||||
//remark
|
||||
int indexRemark = result.IndexOf("#");
|
||||
if (indexRemark > 0)
|
||||
vmessItem = ResolveSSLegacy(result);
|
||||
if (vmessItem == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
vmessItem.remarks = WebUtility.UrlDecode(result.Substring(indexRemark + 1, result.Length - indexRemark - 1));
|
||||
}
|
||||
catch { }
|
||||
result = result.Substring(0, indexRemark);
|
||||
vmessItem = ResolveSip002(result);
|
||||
}
|
||||
//part decode
|
||||
int indexS = result.IndexOf("@");
|
||||
if (indexS > 0)
|
||||
if (vmessItem == null)
|
||||
{
|
||||
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('@');
|
||||
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];
|
||||
vmessItem.configType = (int)EConfigType.Shadowsocks;
|
||||
}
|
||||
else if (result.StartsWith(Global.socksProtocol))
|
||||
{
|
||||
@@ -1406,6 +1385,177 @@ namespace v2rayN.Handler
|
||||
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
|
||||
|
||||
#region Gen speedtest config
|
||||
@@ -1427,7 +1577,7 @@ namespace v2rayN.Handler
|
||||
|
||||
msg = UIRes.I18N("InitialConfiguration");
|
||||
|
||||
Config configCopy = Utils.DeepCopy(config);
|
||||
Config configCopy = Utils.DeepCopy(config);
|
||||
|
||||
string result = Utils.GetEmbedText(SampleClient);
|
||||
if (Utils.IsNullOrEmpty(result))
|
||||
|
||||
@@ -174,7 +174,7 @@ namespace v2rayN.Handler
|
||||
}
|
||||
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);
|
||||
}
|
||||
return fileName;
|
||||
|
||||
@@ -32,4 +32,4 @@ using System.Runtime.InteropServices;
|
||||
// 方法是按如下所示使用“*”:
|
||||
//[assembly: AssemblyVersion("1.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.Http" />
|
||||
<Reference Include="System.Net.Http.WebRequest" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user