mirror of
https://github.com/netchx/netch.git
synced 2026-05-11 23:45:06 +08:00
Compare commits
67 Commits
1.4.10
...
1.4.12-Bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a15fa7375 | ||
|
|
e10c994e38 | ||
|
|
54a263ad06 | ||
|
|
8a56dd4582 | ||
|
|
cd891cec33 | ||
|
|
635a033434 | ||
|
|
6fd3aa48a5 | ||
|
|
a319833bd5 | ||
|
|
70e5d8324e | ||
|
|
1cecccb173 | ||
|
|
281c67aced | ||
|
|
a779295525 | ||
|
|
e665850fc9 | ||
|
|
2537fdd8fe | ||
|
|
cc459d3f59 | ||
|
|
7c051413d3 | ||
|
|
17165e4623 | ||
|
|
a6fd0764e1 | ||
|
|
d27c7c016c | ||
|
|
b5c1cdaf83 | ||
|
|
aa581b2586 | ||
|
|
6d6d747da9 | ||
|
|
8c07273e02 | ||
|
|
aa74948074 | ||
|
|
30b8ed9ac5 | ||
|
|
116b8de135 | ||
|
|
13ed6256d1 | ||
|
|
3c648ebc27 | ||
|
|
452b2c312b | ||
|
|
9f27c4bcf9 | ||
|
|
d2f886ef4b | ||
|
|
52ad3b3b80 | ||
|
|
77c3ae59de | ||
|
|
cdafa14ced | ||
|
|
4d66462416 | ||
|
|
3c0a0d5f80 | ||
|
|
3bdabd7acc | ||
|
|
f605bfa437 | ||
|
|
c8f28f29f1 | ||
|
|
525c9c40fa | ||
|
|
8f1f8de906 | ||
|
|
19fe0a5526 | ||
|
|
401e348402 | ||
|
|
6e4cb9a534 | ||
|
|
ccfb3fe4ce | ||
|
|
0a30ce1b52 | ||
|
|
797e34997f | ||
|
|
6439e8394c | ||
|
|
5ffb5a8235 | ||
|
|
eda75dd681 | ||
|
|
56a40665f1 | ||
|
|
394a56dd76 | ||
|
|
e76b0d5c13 | ||
|
|
c1ef32b420 | ||
|
|
f1e3cc505c | ||
|
|
47dd3e2208 | ||
|
|
bc2fa59672 | ||
|
|
6a6de3eeb8 | ||
|
|
ead8318cb0 | ||
|
|
f4b74092bf | ||
|
|
0d341d3766 | ||
|
|
1568c3b498 | ||
|
|
482eaf28b5 | ||
|
|
40f74252a9 | ||
|
|
47044548b1 | ||
|
|
2f74c36b26 | ||
|
|
9665e6c788 |
@@ -1,83 +1,45 @@
|
||||
using Netch.Forms;
|
||||
using System;
|
||||
using Netch.Utils;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class DNSController
|
||||
public class DNSController : Controller
|
||||
{
|
||||
/// <summary>
|
||||
/// 进程实例
|
||||
/// </summary>
|
||||
public Process Instance;
|
||||
public DNSController()
|
||||
{
|
||||
Name = "DNS Service";
|
||||
MainFile = "unbound.exe";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启动DNS服务
|
||||
/// 启动DNS服务
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool Start()
|
||||
{
|
||||
MainForm.Instance.StatusText($"{Utils.i18N.Translate("Starting dns Service")}");
|
||||
Instance = GetProcess();
|
||||
Instance.StartInfo.Arguments = "-c unbound-service.conf -v";
|
||||
|
||||
Instance.OutputDataReceived += OnOutputDataReceived;
|
||||
Instance.ErrorDataReceived += OnOutputDataReceived;
|
||||
|
||||
try
|
||||
{
|
||||
if (!File.Exists("bin\\unbound.exe") && !File.Exists("bin\\unbound-service.conf") && !File.Exists("bin\\forward-zone.conf"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Instance = MainController.GetProcess();
|
||||
Instance.StartInfo.FileName = "bin\\unbound.exe";
|
||||
|
||||
Instance.StartInfo.Arguments = "-c unbound-service.conf -v";
|
||||
|
||||
Instance.OutputDataReceived += OnOutputDataReceived;
|
||||
Instance.ErrorDataReceived += OnOutputDataReceived;
|
||||
|
||||
Instance.Start();
|
||||
Instance.BeginOutputReadLine();
|
||||
Instance.BeginErrorReadLine();
|
||||
Logging.Info("dns-unbound 启动完毕");
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception e)
|
||||
{
|
||||
Utils.Logging.Info("dns-unbound 进程出错");
|
||||
Stop();
|
||||
Logging.Error("dns-unbound 进程出错:\n" + e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
public override void Stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Instance != null && !Instance.HasExited)
|
||||
{
|
||||
Instance.Kill();
|
||||
Instance.WaitForExit();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Utils.Logging.Info(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(e.Data))
|
||||
{
|
||||
if (File.Exists("logging\\dns-unbound.log"))
|
||||
{
|
||||
File.Delete("logging\\dns-unbound.log");
|
||||
}
|
||||
File.AppendAllText("logging\\dns-unbound.log", $"{e.Data}\r\n");
|
||||
}
|
||||
StopInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
93
Netch/Controllers/EncryptedProxy/SSController.cs
Normal file
93
Netch/Controllers/EncryptedProxy/SSController.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class SSController : EncryptedProxy
|
||||
{
|
||||
public SSController()
|
||||
{
|
||||
Name = "Shadowsocks";
|
||||
MainFile = "Shadowsocks.exe";
|
||||
StartedKeywords("listening at");
|
||||
StoppedKeywords("Invalid config path","usage","plugin service exit unexpectedly");
|
||||
}
|
||||
|
||||
public override bool Start(Server server, Mode mode)
|
||||
{
|
||||
//从DLL启动Shaowsocks
|
||||
if (Global.Settings.BootShadowsocksFromDLL && (mode.Type == 0 || mode.Type == 1 || mode.Type == 2 || mode.Type == 3))
|
||||
{
|
||||
State = State.Starting;
|
||||
var client = Encoding.UTF8.GetBytes($"0.0.0.0:{Global.Settings.Socks5LocalPort}");
|
||||
var remote = Encoding.UTF8.GetBytes($"{server.Hostname}:{server.Port}");
|
||||
var passwd = Encoding.UTF8.GetBytes($"{server.Password}");
|
||||
var method = Encoding.UTF8.GetBytes($"{server.EncryptMethod}");
|
||||
if (!NativeMethods.Shadowsocks.Info(client, remote, passwd, method))
|
||||
{
|
||||
State = State.Stopped;
|
||||
Logging.Error("DLL SS INFO 设置失败!");
|
||||
return false;
|
||||
}
|
||||
|
||||
Logging.Info("DLL SS INFO 设置成功!");
|
||||
|
||||
if (!NativeMethods.Shadowsocks.Start())
|
||||
{
|
||||
State = State.Stopped;
|
||||
Logging.Error("DLL SS 启动失败!");
|
||||
return false;
|
||||
}
|
||||
|
||||
Logging.Info("DLL SS 启动成功!");
|
||||
State = State.Started;
|
||||
return true;
|
||||
}
|
||||
|
||||
Instance = GetProcess();
|
||||
|
||||
Instance.StartInfo.Arguments = $"-s {server.Hostname} -p {server.Port} -b {Global.Settings.LocalAddress} -l {Global.Settings.Socks5LocalPort} -m {server.EncryptMethod} -k \"{server.Password}\" -u";
|
||||
if (!string.IsNullOrWhiteSpace(server.Plugin) && !string.IsNullOrWhiteSpace(server.PluginOption))
|
||||
Instance.StartInfo.Arguments += $" --plugin {server.Plugin} --plugin-opts \"{server.PluginOption}\"";
|
||||
if (mode.BypassChina) Instance.StartInfo.Arguments += " --acl default.acl";
|
||||
Instance.OutputDataReceived += OnOutputDataReceived;
|
||||
Instance.ErrorDataReceived += OnOutputDataReceived;
|
||||
|
||||
State = State.Starting;
|
||||
Instance.Start();
|
||||
Instance.BeginOutputReadLine();
|
||||
Instance.BeginErrorReadLine();
|
||||
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
|
||||
if (State == State.Started) return true;
|
||||
|
||||
if (State == State.Stopped)
|
||||
{
|
||||
Logging.Error("SS 进程启动失败");
|
||||
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Logging.Error("SS 进程启动超时");
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SSController 停止
|
||||
/// </summary>
|
||||
public override void Stop()
|
||||
{
|
||||
if (Global.Settings.BootShadowsocksFromDLL) NativeMethods.Shadowsocks.Stop();
|
||||
else
|
||||
StopInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
73
Netch/Controllers/EncryptedProxy/SSRController.cs
Normal file
73
Netch/Controllers/EncryptedProxy/SSRController.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System.Threading;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class SSRController : EncryptedProxy
|
||||
{
|
||||
public SSRController()
|
||||
{
|
||||
Name = "ShadowsocksR";
|
||||
MainFile = "ShadowsocksR.exe";
|
||||
StartedKeywords("listening at");
|
||||
StoppedKeywords("Invalid config path","usage");
|
||||
}
|
||||
|
||||
public override bool Start(Server server, Mode mode)
|
||||
{
|
||||
Instance = GetProcess();
|
||||
Instance.OutputDataReceived += OnOutputDataReceived;
|
||||
Instance.ErrorDataReceived += OnOutputDataReceived;
|
||||
|
||||
Instance.StartInfo.Arguments = $"-s {server.Hostname} -p {server.Port} -k \"{server.Password}\" -m {server.EncryptMethod} -t 120";
|
||||
|
||||
if (!string.IsNullOrEmpty(server.Protocol))
|
||||
{
|
||||
Instance.StartInfo.Arguments += $" -O {server.Protocol}";
|
||||
|
||||
if (!string.IsNullOrEmpty(server.ProtocolParam)) Instance.StartInfo.Arguments += $" -G \"{server.ProtocolParam}\"";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(server.OBFS))
|
||||
{
|
||||
Instance.StartInfo.Arguments += $" -o {server.OBFS}";
|
||||
|
||||
if (!string.IsNullOrEmpty(server.OBFSParam)) Instance.StartInfo.Arguments += $" -g \"{server.OBFSParam}\"";
|
||||
}
|
||||
|
||||
Instance.StartInfo.Arguments += $" -b {Global.Settings.LocalAddress} -l {Global.Settings.Socks5LocalPort} -u";
|
||||
|
||||
if (mode.BypassChina) Instance.StartInfo.Arguments += " --acl default.acl";
|
||||
|
||||
State = State.Starting;
|
||||
Instance.Start();
|
||||
Instance.BeginOutputReadLine();
|
||||
Instance.BeginErrorReadLine();
|
||||
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
|
||||
if (State == State.Started) return true;
|
||||
|
||||
if (State == State.Stopped)
|
||||
{
|
||||
Logging.Error("SSR 进程启动失败");
|
||||
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Logging.Error("SSR 进程启动超时");
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
StopInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
69
Netch/Controllers/EncryptedProxy/TrojanController.cs
Normal file
69
Netch/Controllers/EncryptedProxy/TrojanController.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class TrojanController : EncryptedProxy
|
||||
{
|
||||
public TrojanController()
|
||||
{
|
||||
Name = "Trojan";
|
||||
MainFile = "Trojan.exe";
|
||||
StartedKeywords("started");
|
||||
StoppedKeywords("exiting");
|
||||
}
|
||||
|
||||
public override bool Start(Server server, Mode mode)
|
||||
{
|
||||
|
||||
File.WriteAllText("data\\last.json", JsonConvert.SerializeObject(new Trojan
|
||||
{
|
||||
local_addr = Global.Settings.LocalAddress,
|
||||
local_port = Global.Settings.Socks5LocalPort,
|
||||
remote_addr = server.Hostname,
|
||||
remote_port = server.Port,
|
||||
password = new List<string>
|
||||
{
|
||||
server.Password
|
||||
}
|
||||
}));
|
||||
|
||||
Instance = GetProcess();
|
||||
Instance.StartInfo.Arguments = "-c ..\\data\\last.json";
|
||||
Instance.OutputDataReceived += OnOutputDataReceived;
|
||||
Instance.ErrorDataReceived += OnOutputDataReceived;
|
||||
|
||||
State = State.Starting;
|
||||
Instance.Start();
|
||||
Instance.BeginOutputReadLine();
|
||||
Instance.BeginErrorReadLine();
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
|
||||
if (State == State.Started) return true;
|
||||
|
||||
if (State == State.Stopped)
|
||||
{
|
||||
Logging.Error("Trojan 进程启动失败");
|
||||
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Logging.Error("Trojan 进程启动超时");
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
StopInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
211
Netch/Controllers/EncryptedProxy/VMessController.cs
Normal file
211
Netch/Controllers/EncryptedProxy/VMessController.cs
Normal file
@@ -0,0 +1,211 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
using Newtonsoft.Json;
|
||||
using VMess = Netch.Models.Information.VMess;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class VMessController : EncryptedProxy
|
||||
{
|
||||
public VMessController()
|
||||
{
|
||||
Name = "V2Ray";
|
||||
MainFile = "v2ray.exe";
|
||||
StartedKeywords("started");
|
||||
StoppedKeywords("config file not readable", "failed to");
|
||||
}
|
||||
|
||||
public override bool Start(Server server, Mode mode)
|
||||
{
|
||||
File.WriteAllText("data\\last.json", JsonConvert.SerializeObject(new VMess.Config
|
||||
{
|
||||
inbounds = new List<VMess.Inbounds>
|
||||
{
|
||||
new VMess.Inbounds
|
||||
{
|
||||
settings = new VMess.InboundSettings(),
|
||||
port = Global.Settings.Socks5LocalPort,
|
||||
listen = Global.Settings.LocalAddress
|
||||
}
|
||||
},
|
||||
outbounds = new List<VMess.Outbounds>
|
||||
{
|
||||
new VMess.Outbounds
|
||||
{
|
||||
settings = new VMess.OutboundSettings
|
||||
{
|
||||
vnext = new List<VMess.VNext>
|
||||
{
|
||||
new VMess.VNext
|
||||
{
|
||||
address = server.Hostname,
|
||||
port = server.Port,
|
||||
users = new List<VMess.User>
|
||||
{
|
||||
new VMess.User
|
||||
{
|
||||
id = server.UserID,
|
||||
alterId = server.AlterID,
|
||||
security = server.EncryptMethod
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
streamSettings = new VMess.StreamSettings
|
||||
{
|
||||
network = server.TransferProtocol,
|
||||
security = server.TLSSecure ? "tls" : string.Empty,
|
||||
wsSettings = server.TransferProtocol == "ws"
|
||||
? new VMess.WebSocketSettings
|
||||
{
|
||||
path = server.Path == string.Empty ? "/" : server.Path,
|
||||
headers = new VMess.WSHeaders
|
||||
{
|
||||
Host = server.Host == string.Empty ? server.Hostname : server.Host
|
||||
}
|
||||
}
|
||||
: null,
|
||||
tcpSettings = server.FakeType == "http"
|
||||
? new VMess.TCPSettings
|
||||
{
|
||||
header = new VMess.TCPHeaders
|
||||
{
|
||||
type = server.FakeType,
|
||||
request = new VMess.TCPRequest
|
||||
{
|
||||
path = server.Path == string.Empty ? "/" : server.Path,
|
||||
headers = new VMess.TCPRequestHeaders
|
||||
{
|
||||
Host = server.Host == string.Empty ? server.Hostname : server.Host
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
: null,
|
||||
kcpSettings = server.TransferProtocol == "kcp"
|
||||
? new VMess.KCPSettings
|
||||
{
|
||||
header = new VMess.TCPHeaders
|
||||
{
|
||||
type = server.FakeType
|
||||
}
|
||||
}
|
||||
: null,
|
||||
quicSettings = server.TransferProtocol == "quic"
|
||||
? new VMess.QUICSettings
|
||||
{
|
||||
security = server.QUICSecure,
|
||||
key = server.QUICSecret,
|
||||
header = new VMess.TCPHeaders
|
||||
{
|
||||
type = server.FakeType
|
||||
}
|
||||
}
|
||||
: null,
|
||||
httpSettings = server.TransferProtocol == "h2"
|
||||
? new VMess.HTTPSettings
|
||||
{
|
||||
host = server.Host == "" ? server.Hostname : server.Host,
|
||||
path = server.Path == "" ? "/" : server.Path
|
||||
}
|
||||
: null,
|
||||
tlsSettings = new VMess.TLSSettings
|
||||
{
|
||||
allowInsecure = true,
|
||||
serverName = server.Host == "" ? server.Hostname : server.Host
|
||||
}
|
||||
},
|
||||
mux = new VMess.OutboundMux
|
||||
{
|
||||
enabled = server.UseMux
|
||||
}
|
||||
},
|
||||
mode.Type == 0 || mode.Type == 1 || mode.Type == 2
|
||||
? new VMess.Outbounds
|
||||
{
|
||||
tag = "TUNTAP",
|
||||
protocol = "freedom"
|
||||
}
|
||||
: new VMess.Outbounds
|
||||
{
|
||||
tag = "direct",
|
||||
protocol = "freedom"
|
||||
}
|
||||
},
|
||||
routing = new VMess.Routing
|
||||
{
|
||||
rules = new List<VMess.RoutingRules>
|
||||
{
|
||||
mode.BypassChina
|
||||
? new VMess.RoutingRules
|
||||
{
|
||||
type = "field",
|
||||
ip = new List<string>
|
||||
{
|
||||
"geoip:cn",
|
||||
"geoip:private"
|
||||
},
|
||||
domain = new List<string>
|
||||
{
|
||||
"geosite:cn"
|
||||
},
|
||||
outboundTag = "direct"
|
||||
}
|
||||
: new VMess.RoutingRules
|
||||
{
|
||||
type = "field",
|
||||
ip = new List<string>
|
||||
{
|
||||
"geoip:private"
|
||||
},
|
||||
outboundTag = "direct"
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
Instance = GetProcess();
|
||||
Instance.StartInfo.Arguments = "-config ..\\data\\last.json";
|
||||
|
||||
Instance.OutputDataReceived += OnOutputDataReceived;
|
||||
Instance.ErrorDataReceived += OnOutputDataReceived;
|
||||
|
||||
State = State.Starting;
|
||||
Instance.Start();
|
||||
Instance.BeginOutputReadLine();
|
||||
Instance.BeginErrorReadLine();
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
|
||||
if (State == State.Started)
|
||||
{
|
||||
if (File.Exists("data\\last.json")) File.Delete("data\\last.json");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (State == State.Stopped)
|
||||
{
|
||||
Logging.Error("V2Ray 进程启动失败");
|
||||
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Logging.Error("V2Ray 进程启动超时");
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
StopInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
using Netch.Utils;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class HTTPController
|
||||
{
|
||||
/// <summary>
|
||||
/// 实例
|
||||
/// </summary>
|
||||
public PrivoxyController pPrivoxyController = new PrivoxyController();
|
||||
|
||||
/// <summary>
|
||||
/// 启动
|
||||
/// </summary>
|
||||
/// <param name="server">服务器</param>
|
||||
/// <param name="mode">模式</param>
|
||||
/// <returns>是否启动成功</returns>
|
||||
public bool Start(Models.Server server, Models.Mode mode)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (server.Type == "Socks5")
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(server.Username) && !string.IsNullOrWhiteSpace(server.Password))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pPrivoxyController.Start(server, mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
pPrivoxyController.Start(server, mode);
|
||||
}
|
||||
|
||||
if (mode.Type != 5)
|
||||
{
|
||||
NativeMethods.SetGlobal($"127.0.0.1:{Global.Settings.HTTPLocalPort}", "<local>");
|
||||
|
||||
// HTTP 系统代理模式,启动系统代理
|
||||
/*
|
||||
using (var registry = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true))
|
||||
{
|
||||
registry.SetValue("ProxyEnable", 1);
|
||||
registry.SetValue("ProxyServer", $"127.0.0.1:{Global.Settings.HTTPLocalPort}");
|
||||
|
||||
Win32Native.InternetSetOption(IntPtr.Zero, 39, IntPtr.Zero, 0);
|
||||
Win32Native.InternetSetOption(IntPtr.Zero, 37, IntPtr.Zero, 0);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (System.Windows.Forms.MessageBox.Show(i18N.Translate("Failed to set the system proxy, it may be caused by the lack of dependent programs. Do you want to jump to Netch's official website to download dependent programs?"), i18N.Translate("Information"), MessageBoxButtons.OKCancel, MessageBoxIcon.Information) == DialogResult.OK)
|
||||
{
|
||||
System.Diagnostics.Process.Start("https://netch.org/#/?id=%e4%be%9d%e8%b5%96");
|
||||
}
|
||||
Utils.Logging.Info("设置系统代理失败" + e.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
pPrivoxyController.Stop();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Utils.Logging.Info(e.ToString());
|
||||
}
|
||||
|
||||
NativeMethods.SetDIRECT();
|
||||
|
||||
/*
|
||||
using (var registry = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true))
|
||||
{
|
||||
registry.SetValue("ProxyEnable", 0);
|
||||
registry.DeleteValue("ProxyServer", false);
|
||||
|
||||
Win32Native.InternetSetOption(IntPtr.Zero, 39, IntPtr.Zero, 0);
|
||||
Win32Native.InternetSetOption(IntPtr.Zero, 37, IntPtr.Zero, 0);
|
||||
}
|
||||
*/
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Utils.Logging.Info(e.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
169
Netch/Controllers/Interface/Controller.cs
Normal file
169
Netch/Controllers/Interface/Controller.cs
Normal file
@@ -0,0 +1,169 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public abstract class Controller
|
||||
{
|
||||
/// <summary>
|
||||
/// 控制器名
|
||||
/// </summary>
|
||||
public string Name;
|
||||
|
||||
/// <summary>
|
||||
/// 进程实例
|
||||
/// </summary>
|
||||
public Process Instance;
|
||||
|
||||
/// <summary>
|
||||
/// 主程序名(不含扩展名)
|
||||
/// </summary>
|
||||
public string MainFile;
|
||||
|
||||
private List<string> _startedKeywords = new List<string>();
|
||||
|
||||
private List<string> _stoppedKeywords = new List<string>();
|
||||
|
||||
protected bool RedirectStd = true;
|
||||
|
||||
protected void StartedKeywords(params string[] texts)
|
||||
{
|
||||
foreach (var text in texts)
|
||||
{
|
||||
_startedKeywords.Add(text);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void StoppedKeywords(params string[] texts)
|
||||
{
|
||||
foreach (var text in texts)
|
||||
{
|
||||
_stoppedKeywords.Add(text);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 当前状态
|
||||
/// </summary>
|
||||
protected State State = State.Waiting;
|
||||
|
||||
public abstract void Stop();
|
||||
|
||||
/// <summary>
|
||||
/// 停止
|
||||
/// </summary>
|
||||
protected void StopInstance()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Instance == null || Instance.HasExited) return;
|
||||
Instance.Kill();
|
||||
Instance.WaitForExit();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Error($"停止 {MainFile} 错误:\n" + e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void ClearLog()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists($"logging\\{Name}.log")) File.Delete($"logging\\{Name}.log");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写日志
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <returns><see cref="s" />是否为空</returns>
|
||||
protected bool Write(string s)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(s)) return false;
|
||||
try
|
||||
{
|
||||
File.AppendAllText($"logging\\{Name}.log", s + Global.EOF);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Error($"写入{Name}日志错误:\n" + e);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Process GetProcess()
|
||||
{
|
||||
var p = new Process
|
||||
{
|
||||
StartInfo =
|
||||
{
|
||||
FileName = Path.GetFullPath($"bin\\{MainFile}"),
|
||||
WorkingDirectory = $"{Global.NetchDir}\\bin",
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardError = RedirectStd,
|
||||
RedirectStandardInput = RedirectStd,
|
||||
RedirectStandardOutput = RedirectStd,
|
||||
UseShellExecute = false
|
||||
},
|
||||
EnableRaisingEvents = true
|
||||
};
|
||||
return p;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 接收输出数据
|
||||
/// </summary>
|
||||
/// <param name="sender">发送者</param>
|
||||
/// <param name="e">数据</param>
|
||||
protected void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
// 写入日志
|
||||
if (!Write(e.Data)) return;
|
||||
|
||||
// 检查启动
|
||||
if (State == State.Starting)
|
||||
{
|
||||
if (Instance.HasExited)
|
||||
{
|
||||
State = State.Stopped;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var s in _startedKeywords)
|
||||
{
|
||||
if (e.Data.Contains(s))
|
||||
{
|
||||
State = State.Started;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var s in _stoppedKeywords)
|
||||
{
|
||||
if (e.Data.Contains(s))
|
||||
{
|
||||
State = State.Stopped;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Netch/Controllers/Interface/EncryptedProxy.cs
Normal file
15
Netch/Controllers/Interface/EncryptedProxy.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Netch.Models;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public abstract class EncryptedProxy : Controller
|
||||
{
|
||||
/// <summary>
|
||||
/// 启动
|
||||
/// </summary>
|
||||
/// <param name="server">服务器</param>
|
||||
/// <param name="mode">模式</param>
|
||||
/// <returns>是否启动成功</returns>
|
||||
public abstract bool Start(Server server, Mode mode);
|
||||
}
|
||||
}
|
||||
15
Netch/Controllers/Interface/ModeController.cs
Normal file
15
Netch/Controllers/Interface/ModeController.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Netch.Models;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public abstract class ModeController : Controller
|
||||
{
|
||||
/// <summary>
|
||||
/// 启动
|
||||
/// </summary>
|
||||
/// <param name="server">服务器</param>
|
||||
/// <param name="mode">模式</param>
|
||||
/// <returns>是否成功</returns>
|
||||
public abstract bool Start(Server server, Mode mode);
|
||||
}
|
||||
}
|
||||
@@ -1,283 +1,172 @@
|
||||
using Netch.Forms;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Forms;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class MainController
|
||||
{
|
||||
/// <summary>
|
||||
/// 记录当前使用的端口
|
||||
/// <see cref="MainForm.LocalPortText"/>
|
||||
/// </summary>
|
||||
public static readonly List<int> UsingPorts = new List<int>();
|
||||
|
||||
public EncryptedProxy pEncryptedProxyController;
|
||||
|
||||
public ModeController pModeController;
|
||||
|
||||
/// <summary>
|
||||
/// NTT 控制器
|
||||
/// </summary>
|
||||
public NTTController pNTTController = new NTTController();
|
||||
|
||||
[DllImport("dnsapi", EntryPoint = "DnsFlushResolverCache")]
|
||||
public static extern UInt32 FlushDNSResolverCache();
|
||||
public static Process GetProcess()
|
||||
{
|
||||
var process = new Process();
|
||||
process.StartInfo.WorkingDirectory = string.Format("{0}\\bin", Directory.GetCurrentDirectory());
|
||||
process.StartInfo.CreateNoWindow = true;
|
||||
process.StartInfo.RedirectStandardError = true;
|
||||
process.StartInfo.RedirectStandardInput = true;
|
||||
process.StartInfo.RedirectStandardOutput = true;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.EnableRaisingEvents = true;
|
||||
|
||||
return process;
|
||||
}
|
||||
public static extern uint FlushDNSResolverCache();
|
||||
|
||||
/// <summary>
|
||||
/// SS 控制器
|
||||
/// </summary>
|
||||
public SSController pSSController;
|
||||
|
||||
/// <summary>
|
||||
/// SSR 控制器
|
||||
/// </summary>
|
||||
public SSRController pSSRController;
|
||||
|
||||
/// <summary>
|
||||
/// V2Ray 控制器
|
||||
/// </summary>
|
||||
public VMessController pVMessController;
|
||||
|
||||
/// <summary>
|
||||
/// Trojan 控制器
|
||||
/// </summary>
|
||||
public TrojanController pTrojanController;
|
||||
|
||||
/// <summary>
|
||||
/// NF 控制器
|
||||
/// </summary>
|
||||
public NFController pNFController;
|
||||
|
||||
/// <summary>
|
||||
/// HTTP 控制器
|
||||
/// </summary>
|
||||
public HTTPController pHTTPController;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// TUN/TAP 控制器
|
||||
/// </summary>
|
||||
public TUNTAPController pTUNTAPController;
|
||||
|
||||
/// <summary>
|
||||
/// NTT 控制器
|
||||
/// </summary>
|
||||
public NTTController pNTTController;
|
||||
|
||||
/// <summary>
|
||||
/// 启动
|
||||
/// 启动
|
||||
/// </summary>
|
||||
/// <param name="server">服务器</param>
|
||||
/// <param name="mode">模式</param>
|
||||
/// <returns>是否启动成功</returns>
|
||||
public bool Start(Models.Server server, Models.Mode mode)
|
||||
public bool Start(Server server, Mode mode)
|
||||
{
|
||||
FlushDNSResolverCache();
|
||||
|
||||
var result = false;
|
||||
switch (server.Type)
|
||||
if (server.Type == "Socks5")
|
||||
{
|
||||
case "Socks5":
|
||||
if (mode.Type == 4)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
break;
|
||||
case "SS":
|
||||
KillProcess("Shadowsocks");
|
||||
if (pSSController == null)
|
||||
{
|
||||
pSSController = new SSController();
|
||||
}
|
||||
result = pSSController.Start(server, mode);
|
||||
break;
|
||||
case "SSR":
|
||||
KillProcess("ShadowsocksR");
|
||||
if (pSSRController == null)
|
||||
{
|
||||
pSSRController = new SSRController();
|
||||
}
|
||||
result = pSSRController.Start(server, mode);
|
||||
break;
|
||||
case "VMess":
|
||||
KillProcess("v2ray");
|
||||
if (pVMessController == null)
|
||||
{
|
||||
pVMessController = new VMessController();
|
||||
}
|
||||
result = pVMessController.Start(server, mode);
|
||||
break;
|
||||
case "Trojan":
|
||||
KillProcess("Trojan");
|
||||
if (pTrojanController == null)
|
||||
{
|
||||
pTrojanController = new TrojanController();
|
||||
}
|
||||
result = pTrojanController.Start(server, mode);
|
||||
break;
|
||||
result = mode.Type != 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (server.Type)
|
||||
{
|
||||
case "SS":
|
||||
pEncryptedProxyController = new SSController();
|
||||
break;
|
||||
case "SSR":
|
||||
pEncryptedProxyController = new SSRController();
|
||||
break;
|
||||
case "VMess":
|
||||
pEncryptedProxyController = new VMessController();
|
||||
break;
|
||||
case "Trojan":
|
||||
pEncryptedProxyController = new TrojanController();
|
||||
break;
|
||||
}
|
||||
|
||||
KillProcessByName(pEncryptedProxyController.MainFile);
|
||||
|
||||
// 检查端口是否被占用
|
||||
if (PortHelper.PortInUse(Global.Settings.Socks5LocalPort))
|
||||
{
|
||||
MessageBoxX.Show(i18N.TranslateFormat("The {0} port is in use.", "Socks5"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (PortHelper.PortInUse(Global.Settings.HTTPLocalPort))
|
||||
{
|
||||
MessageBoxX.Show(i18N.TranslateFormat("The {0} port is in use.", "HTTP"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (PortHelper.PortInUse(Global.Settings.RedirectorTCPPort, PortType.TCP))
|
||||
{
|
||||
MessageBoxX.Show(i18N.TranslateFormat("The {0} port is in use.", "Redirector TCP"));
|
||||
return false;
|
||||
}
|
||||
|
||||
Global.MainForm.StatusText(i18N.Translate("Starting ", pEncryptedProxyController.Name));
|
||||
result = pEncryptedProxyController.Start(server, mode);
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
if (mode.Type == 0)
|
||||
Logging.Info("加密代理已启动");
|
||||
switch (mode.Type)
|
||||
{
|
||||
if (pNFController == null)
|
||||
{
|
||||
pNFController = new NFController();
|
||||
}
|
||||
if (pNTTController == null)
|
||||
{
|
||||
pNTTController = new NTTController();
|
||||
}
|
||||
// 进程代理模式,启动 NF 控制器
|
||||
result = pNFController.Start(server, mode, false);
|
||||
if (!result)
|
||||
{
|
||||
MainForm.Instance.StatusText($"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("Restarting Redirector")}");
|
||||
Utils.Logging.Info("正常启动失败后尝试停止驱动服务再重新启动");
|
||||
//正常启动失败后尝试停止驱动服务再重新启动
|
||||
result = pNFController.Start(server, mode, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Task.Run(() => pNTTController.Start());
|
||||
}
|
||||
case 0: // 进程代理模式
|
||||
pModeController = new NFController();
|
||||
break;
|
||||
case 1: // TUN/TAP 黑名单代理模式
|
||||
case 2: // TUN/TAP 白名单代理模式
|
||||
pModeController = new TUNTAPController();
|
||||
break;
|
||||
case 3:
|
||||
case 5:
|
||||
pModeController = new HTTPController();
|
||||
break;
|
||||
case 4: // Socks5 代理模式,不需要启动额外的Server
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
else if (mode.Type == 1)
|
||||
|
||||
if (pModeController != null)
|
||||
{
|
||||
if (pTUNTAPController == null)
|
||||
{
|
||||
pTUNTAPController = new TUNTAPController();
|
||||
}
|
||||
if (pNTTController == null)
|
||||
{
|
||||
pNTTController = new NTTController();
|
||||
}
|
||||
// TUN/TAP 黑名单代理模式,启动 TUN/TAP 控制器
|
||||
result = pTUNTAPController.Start(server, mode);
|
||||
if (result)
|
||||
{
|
||||
Task.Run(() => pNTTController.Start());
|
||||
}
|
||||
Global.MainForm.StatusText(i18N.Translate("Starting ", pModeController.Name));
|
||||
result = pModeController.Start(server, mode);
|
||||
}
|
||||
else if (mode.Type == 2)
|
||||
|
||||
if (result)
|
||||
{
|
||||
if (pTUNTAPController == null)
|
||||
switch (mode.Type)
|
||||
{
|
||||
pTUNTAPController = new TUNTAPController();
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
Task.Run(() =>
|
||||
{
|
||||
Global.MainForm.NatTypeStatusText(i18N.Translate("Starting NatTester"));
|
||||
// Thread.Sleep(1000);
|
||||
var (nttResult, natType, localEnd, publicEnd) = pNTTController.Start();
|
||||
var country = Utils.Utils.GetCityCode(publicEnd);
|
||||
|
||||
if (nttResult) Global.MainForm.NatTypeStatusText(natType, country);
|
||||
});
|
||||
break;
|
||||
}
|
||||
if (pNTTController == null)
|
||||
{
|
||||
pNTTController = new NTTController();
|
||||
}
|
||||
// TUN/TAP 白名单代理模式,启动 TUN/TAP 控制器
|
||||
result = pTUNTAPController.Start(server, mode);
|
||||
if (result)
|
||||
{
|
||||
Task.Run(() => pNTTController.Start());
|
||||
}
|
||||
}
|
||||
else if (mode.Type == 3 || mode.Type == 5)
|
||||
{
|
||||
if (pHTTPController == null)
|
||||
{
|
||||
pHTTPController = new HTTPController();
|
||||
}
|
||||
// HTTP 系统代理和 Socks5 和 HTTP 代理模式,启动 HTTP 控制器
|
||||
result = pHTTPController.Start(server, mode);
|
||||
}
|
||||
else if (mode.Type == 4)
|
||||
{
|
||||
// Socks5 代理模式,不需要启动额外的控制器
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!result)
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
if (!result) Stop();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止
|
||||
/// 停止
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
if (pSSController != null)
|
||||
{
|
||||
pSSController.Stop();
|
||||
}
|
||||
else if (pSSRController != null)
|
||||
{
|
||||
pSSRController.Stop();
|
||||
}
|
||||
else if (pVMessController != null)
|
||||
{
|
||||
pVMessController.Stop();
|
||||
}
|
||||
else if (pTrojanController != null)
|
||||
{
|
||||
pTrojanController.Stop();
|
||||
}
|
||||
|
||||
if (pNFController != null)
|
||||
{
|
||||
pNFController.Stop();
|
||||
}
|
||||
else if (pTUNTAPController != null)
|
||||
{
|
||||
pTUNTAPController.Stop();
|
||||
}
|
||||
else if (pHTTPController != null)
|
||||
{
|
||||
pHTTPController.Stop();
|
||||
}
|
||||
|
||||
if (pNTTController != null)
|
||||
{
|
||||
pNTTController.Stop();
|
||||
}
|
||||
Task.Run(() => pEncryptedProxyController?.Stop());
|
||||
Task.Run(() => UsingPorts.Clear());
|
||||
pModeController?.Stop();
|
||||
}
|
||||
|
||||
public void KillProcess(string name)
|
||||
public static void KillProcessByName(string name)
|
||||
{
|
||||
var processes = Process.GetProcessesByName(name);
|
||||
foreach (var p in processes)
|
||||
{
|
||||
if (IsChildProcess(p, name))
|
||||
{
|
||||
p.Kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsChildProcess(Process process, string name)
|
||||
{
|
||||
bool result;
|
||||
try
|
||||
{
|
||||
var FileName = (Directory.GetCurrentDirectory() + "\\bin\\" + name + ".exe").ToLower();
|
||||
var procFileName = process.MainModule.FileName.ToLower();
|
||||
result = FileName.Equals(procFileName, StringComparison.Ordinal);
|
||||
foreach (var p in Process.GetProcessesByName(name))
|
||||
if (p.MainModule != null && p.MainModule.FileName.StartsWith(Global.NetchDir))
|
||||
p.Kill();
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (Win32Exception e)
|
||||
{
|
||||
Utils.Logging.Info(e.Message);
|
||||
result = false;
|
||||
Logging.Error($"结束进程 {name} 错误:\n" + e);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
99
Netch/Controllers/Mode/HTTPController.cs
Normal file
99
Netch/Controllers/Mode/HTTPController.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Forms;
|
||||
using Microsoft.Win32;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class HTTPController : ModeController
|
||||
{
|
||||
/// <summary>
|
||||
/// 实例
|
||||
/// </summary>
|
||||
public PrivoxyController pPrivoxyController = new PrivoxyController();
|
||||
|
||||
private string prevBypass, prevHTTP, prevPAC;
|
||||
private bool prevEnabled;
|
||||
|
||||
public HTTPController()
|
||||
{
|
||||
Name = "HTTP";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启动
|
||||
/// </summary>
|
||||
/// <param name="server">服务器</param>
|
||||
/// <param name="mode">模式</param>
|
||||
/// <returns>是否启动成功</returns>
|
||||
public override bool Start(Server server, Mode mode)
|
||||
{
|
||||
RecordPrevious();
|
||||
try
|
||||
{
|
||||
if (server.Type == "Socks5")
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(server.Username) && !string.IsNullOrWhiteSpace(server.Password)) return false;
|
||||
|
||||
pPrivoxyController.Start(server, mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
pPrivoxyController.Start(server, mode);
|
||||
}
|
||||
|
||||
if (mode.Type != 5) NativeMethods.SetGlobal($"127.0.0.1:{Global.Settings.HTTPLocalPort}", "<local>");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (MessageBoxX.Show(i18N.Translate("Failed to set the system proxy, it may be caused by the lack of dependent programs. Do you want to jump to Netch's official website to download dependent programs?"), confirm: true) == DialogResult.OK) Process.Start("https://netch.org/#/?id=%e4%be%9d%e8%b5%96");
|
||||
|
||||
Logging.Error("设置系统代理失败" + e);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void RecordPrevious()
|
||||
{
|
||||
var registry = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings");
|
||||
if (registry == null)
|
||||
{
|
||||
prevEnabled = false;
|
||||
prevPAC = prevHTTP = prevBypass = "";
|
||||
return;
|
||||
}
|
||||
|
||||
prevPAC = registry.GetValue("AutoConfigURL")?.ToString() ?? "";
|
||||
if ((registry.GetValue("ProxyEnable")?.Equals(1) ?? false) || prevPAC != "") prevEnabled = true;
|
||||
|
||||
prevHTTP = registry.GetValue("ProxyServer")?.ToString() ?? "";
|
||||
prevBypass = registry.GetValue("ProxyOverride")?.ToString() ?? "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止
|
||||
/// </summary>
|
||||
public override void Stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
pPrivoxyController.Stop();
|
||||
|
||||
NativeMethods.SetGlobal(prevHTTP, prevBypass);
|
||||
if (prevPAC != "")
|
||||
NativeMethods.SetURL(prevPAC);
|
||||
if (!prevEnabled)
|
||||
NativeMethods.SetDIRECT();
|
||||
prevEnabled = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Error("停止HTTP控制器错误:\n" + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
286
Netch/Controllers/Mode/NFController.cs
Normal file
286
Netch/Controllers/Mode/NFController.cs
Normal file
@@ -0,0 +1,286 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.ServiceProcess;
|
||||
using System.Threading;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
using nfapinet;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class NFController : ModeController
|
||||
{
|
||||
private static readonly ServiceController NFService = new ServiceController("netfilter2");
|
||||
|
||||
private static readonly string BinDriver = string.Empty;
|
||||
private static readonly string SystemDriver = $"{Environment.SystemDirectory}\\drivers\\netfilter2.sys";
|
||||
private static string[] _sysDns = { };
|
||||
|
||||
static NFController()
|
||||
{
|
||||
switch ($"{Environment.OSVersion.Version.Major}.{Environment.OSVersion.Version.Minor}")
|
||||
{
|
||||
case "10.0":
|
||||
BinDriver = "Win-10.sys";
|
||||
break;
|
||||
case "6.3":
|
||||
case "6.2":
|
||||
BinDriver = "Win-8.sys";
|
||||
break;
|
||||
case "6.1":
|
||||
case "6.0":
|
||||
BinDriver = "Win-7.sys";
|
||||
break;
|
||||
default:
|
||||
Logging.Error($"不支持的系统版本:{Environment.OSVersion.Version}");
|
||||
return;
|
||||
}
|
||||
|
||||
BinDriver = "bin\\" + BinDriver;
|
||||
}
|
||||
|
||||
public NFController()
|
||||
{
|
||||
Name = "Redirector";
|
||||
MainFile = "Redirector.exe";
|
||||
StartedKeywords("Started");
|
||||
StoppedKeywords("Failed", "Unable");
|
||||
}
|
||||
|
||||
public override bool Start(Server server, Mode mode)
|
||||
{
|
||||
Logging.Info("内置驱动版本: " + DriverVersion(BinDriver));
|
||||
if (DriverVersion(SystemDriver) != DriverVersion(BinDriver))
|
||||
{
|
||||
if (File.Exists(SystemDriver))
|
||||
{
|
||||
Logging.Info("系统驱动版本: " + DriverVersion(SystemDriver));
|
||||
Logging.Info("更新驱动");
|
||||
UninstallDriver();
|
||||
}
|
||||
|
||||
if (!InstallDriver())
|
||||
return false;
|
||||
}
|
||||
|
||||
var processList = "";
|
||||
foreach (var proc in mode.Rule)
|
||||
processList += proc + ",";
|
||||
processList += "NTT.exe";
|
||||
|
||||
Instance = GetProcess();
|
||||
if (server.Type != "Socks5")
|
||||
{
|
||||
Instance.StartInfo.Arguments += $"-r 127.0.0.1:{Global.Settings.Socks5LocalPort} -p \"{processList}\"";
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
var result = DNS.Lookup(server.Hostname);
|
||||
if (result == null)
|
||||
{
|
||||
Logging.Info("无法解析服务器 IP 地址");
|
||||
return false;
|
||||
}
|
||||
|
||||
Instance.StartInfo.Arguments += $"-r {result}:{server.Port} -p \"{processList}\"";
|
||||
if (!string.IsNullOrWhiteSpace(server.Username) && !string.IsNullOrWhiteSpace(server.Password)) Instance.StartInfo.Arguments += $" -username \"{server.Username}\" -password \"{server.Password}\"";
|
||||
}
|
||||
|
||||
Instance.StartInfo.Arguments += $" -t {Global.Settings.RedirectorTCPPort}";
|
||||
Instance.OutputDataReceived += OnOutputDataReceived;
|
||||
Instance.ErrorDataReceived += OnOutputDataReceived;
|
||||
|
||||
for (var i = 0; i < 2; i++)
|
||||
{
|
||||
State = State.Starting;
|
||||
Instance.Start();
|
||||
Instance.BeginOutputReadLine();
|
||||
Instance.BeginErrorReadLine();
|
||||
|
||||
for (var j = 0; j < 40; j++)
|
||||
{
|
||||
Thread.Sleep(250);
|
||||
|
||||
if (State == State.Started)
|
||||
{
|
||||
|
||||
//备份并替换系统DNS
|
||||
_sysDns = DNS.getSystemDns();
|
||||
string[] dns = {"1.1.1.1", "8.8.8.8"};
|
||||
DNS.SetDNS(dns);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Logging.Error(Name + " 启动超时");
|
||||
Stop();
|
||||
if (!RestartService()) return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool RestartService()
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (NFService.Status)
|
||||
{
|
||||
// 启动驱动服务
|
||||
case ServiceControllerStatus.Running:
|
||||
// 防止其他程序占用 重置 NF 百万连接数限制
|
||||
NFService.Stop();
|
||||
NFService.WaitForStatus(ServiceControllerStatus.Stopped);
|
||||
Global.MainForm.StatusText(i18N.Translate("Starting netfilter2 Service"));
|
||||
NFService.Start();
|
||||
break;
|
||||
case ServiceControllerStatus.Stopped:
|
||||
Global.MainForm.StatusText(i18N.Translate("Starting netfilter2 Service"));
|
||||
NFService.Start();
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Error("启动驱动服务失败:\n" + e);
|
||||
|
||||
var result = NFAPI.nf_registerDriver("netfilter2");
|
||||
if (result != NF_STATUS.NF_STATUS_SUCCESS)
|
||||
{
|
||||
Logging.Error($"注册驱动失败,返回值:{result}");
|
||||
return false;
|
||||
}
|
||||
|
||||
Logging.Info("注册驱动成功");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static string DriverVersion(string file)
|
||||
{
|
||||
return File.Exists(file) ? FileVersionInfo.GetVersionInfo(file).FileVersion : string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 卸载 NF 驱动
|
||||
/// </summary>
|
||||
/// <returns>是否成功卸载</returns>
|
||||
public static bool UninstallDriver()
|
||||
{
|
||||
Global.MainForm.StatusText("Uninstall netfilter2");
|
||||
Logging.Info("卸载NF驱动");
|
||||
try
|
||||
{
|
||||
if (NFService.Status == ServiceControllerStatus.Running)
|
||||
{
|
||||
NFService.Stop();
|
||||
NFService.WaitForStatus(ServiceControllerStatus.Stopped);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
if (!File.Exists(SystemDriver)) return true;
|
||||
|
||||
try
|
||||
{
|
||||
NFAPI.nf_unRegisterDriver("netfilter2");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Error(e.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
File.Delete(SystemDriver);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安装 NF 驱动
|
||||
/// </summary>
|
||||
/// <returns>驱动是否安装成功</returns>
|
||||
public static bool InstallDriver()
|
||||
{
|
||||
Logging.Info("安装NF驱动");
|
||||
try
|
||||
{
|
||||
File.Copy(BinDriver, SystemDriver);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Error("驱动复制失败\n" + e);
|
||||
return false;
|
||||
}
|
||||
|
||||
Global.MainForm.StatusText(i18N.Translate("Register driver"));
|
||||
// 注册驱动文件
|
||||
var result = NFAPI.nf_registerDriver("netfilter2");
|
||||
if (result == NF_STATUS.NF_STATUS_SUCCESS)
|
||||
{
|
||||
Logging.Info($"驱动安装成功,当前驱动版本:{DriverVersion(SystemDriver)}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Error($"注册驱动失败,返回值:{result}");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// private new void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
|
||||
// {
|
||||
// if (!Write(e.Data)) return;
|
||||
// if (State == State.Starting)
|
||||
// {
|
||||
// if (Instance.HasExited)
|
||||
// State = State.Stopped;
|
||||
// else if (e.Data.Contains("Started"))
|
||||
// State = State.Started;
|
||||
// else if (e.Data.Contains("Failed") || e.Data.Contains("Unable")) State = State.Stopped;
|
||||
// }
|
||||
// else if (State == State.Started)
|
||||
// {
|
||||
// if (e.Data.StartsWith("[APP][Bandwidth]"))
|
||||
// {
|
||||
// var splited = e.Data.Replace("[APP][Bandwidth]", "").Trim().Split(',');
|
||||
// if (splited.Length == 2)
|
||||
// {
|
||||
// var uploadSplited = splited[0].Split(':');
|
||||
// var downloadSplited = splited[1].Split(':');
|
||||
//
|
||||
// if (uploadSplited.Length == 2 && downloadSplited.Length == 2)
|
||||
// if (long.TryParse(uploadSplited[1], out var upload) && long.TryParse(downloadSplited[1], out var download))
|
||||
// Task.Run(() => OnBandwidthUpdated(upload, download));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
StopInstance();
|
||||
//恢复系统DNS
|
||||
DNS.SetDNS(_sysDns);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 流量变动事件
|
||||
/// </summary>
|
||||
public event BandwidthUpdateHandler OnBandwidthUpdated;
|
||||
|
||||
/// <summary>
|
||||
/// 流量变动处理器
|
||||
/// </summary>
|
||||
/// <param name="upload">上传</param>
|
||||
/// <param name="download">下载</param>
|
||||
public delegate void BandwidthUpdateHandler(long upload, long download);
|
||||
}
|
||||
}
|
||||
@@ -1,88 +1,80 @@
|
||||
using Netch.Forms;
|
||||
using Netch.Utils;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Models;
|
||||
using Netch.Properties;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class TUNTAPController
|
||||
public class TUNTAPController : ModeController
|
||||
{
|
||||
/// <summary>
|
||||
/// 进程实例(tun2socks)
|
||||
/// </summary>
|
||||
public Process Instance;
|
||||
// ByPassLan IP
|
||||
private readonly List<string> _bypassLanIPs = new List<string> {"10.0.0.0/8", "172.16.0.0/16", "192.168.0.0/16"};
|
||||
|
||||
private Mode _savedMode = new Mode();
|
||||
private Server _savedServer = new Server();
|
||||
|
||||
/// <summary>
|
||||
/// 当前状态
|
||||
/// 服务器 IP 地址
|
||||
/// </summary>
|
||||
public Models.State State = Models.State.Waiting;
|
||||
private IPAddress[] _serverAddresses = new IPAddress[0];
|
||||
|
||||
/// <summary>
|
||||
/// 服务器 IP 地址
|
||||
/// </summary>
|
||||
public IPAddress[] ServerAddresses = new IPAddress[0];
|
||||
|
||||
/// <summary>
|
||||
/// 保存传入的规则
|
||||
/// </summary>
|
||||
public Models.Server SavedServer = new Models.Server();
|
||||
public Models.Mode SavedMode = new Models.Mode();
|
||||
|
||||
/// <summary>
|
||||
/// 本地 DNS 服务控制器
|
||||
/// 本地 DNS 服务控制器
|
||||
/// </summary>
|
||||
public DNSController pDNSController = new DNSController();
|
||||
|
||||
// ByPassLan IP
|
||||
List<string> BypassLanIPs = new List<string>() { "10.0.0.0/8", "172.16.0.0/16", "192.168.0.0/16" };
|
||||
public TUNTAPController()
|
||||
{
|
||||
Name = "Tap";
|
||||
MainFile = "tun2socks.exe";
|
||||
StartedKeywords("Running");
|
||||
StoppedKeywords("failed","invalid vconfig file");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 配置 TUNTAP 适配器
|
||||
/// </summary>
|
||||
public bool Configure()
|
||||
private bool Configure()
|
||||
{
|
||||
// 查询服务器 IP 地址
|
||||
var destination = Dns.GetHostAddressesAsync(SavedServer.Hostname);
|
||||
var destination = Dns.GetHostAddressesAsync(_savedServer.Hostname);
|
||||
if (destination.Wait(1000))
|
||||
{
|
||||
if (destination.Result.Length == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (destination.Result.Length == 0) return false;
|
||||
|
||||
ServerAddresses = destination.Result;
|
||||
_serverAddresses = destination.Result;
|
||||
}
|
||||
|
||||
// 搜索出口
|
||||
return Utils.Configuration.SearchOutbounds();
|
||||
return SearchOutbounds();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置绕行规则
|
||||
/// </summary>
|
||||
public bool SetupBypass()
|
||||
private bool SetupBypass()
|
||||
{
|
||||
MainForm.Instance.StatusText($"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("SetupBypass")}");
|
||||
Global.MainForm.StatusText(i18N.Translate("SetupBypass"));
|
||||
Logging.Info("设置绕行规则 → 设置让服务器 IP 走直连");
|
||||
// 让服务器 IP 走直连
|
||||
foreach (var address in ServerAddresses)
|
||||
{
|
||||
foreach (var address in _serverAddresses)
|
||||
if (!IPAddress.IsLoopback(address))
|
||||
{
|
||||
NativeMethods.CreateRoute(address.ToString(), 32, Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理模式的绕过中国
|
||||
if (SavedMode.BypassChina)
|
||||
if (_savedMode.BypassChina)
|
||||
{
|
||||
Logging.Info("设置绕行规则 → 处理模式的绕过中国");
|
||||
using (var sr = new StringReader(Encoding.UTF8.GetString(Properties.Resources.CNIP)))
|
||||
using (var sr = new StringReader(Encoding.UTF8.GetString(Resources.CNIP)))
|
||||
{
|
||||
string text;
|
||||
|
||||
@@ -102,26 +94,20 @@ namespace Netch.Controllers
|
||||
var info = ip.Split('/');
|
||||
var address = IPAddress.Parse(info[0]);
|
||||
|
||||
if (!IPAddress.IsLoopback(address))
|
||||
{
|
||||
NativeMethods.CreateRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
|
||||
}
|
||||
if (!IPAddress.IsLoopback(address)) NativeMethods.CreateRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
|
||||
}
|
||||
|
||||
Logging.Info("设置绕行规则 → 处理绕过局域网 IP");
|
||||
// 处理绕过局域网 IP
|
||||
foreach (var ip in BypassLanIPs)
|
||||
foreach (var ip in _bypassLanIPs)
|
||||
{
|
||||
var info = ip.Split('/');
|
||||
var address = IPAddress.Parse(info[0]);
|
||||
|
||||
if (!IPAddress.IsLoopback(address))
|
||||
{
|
||||
NativeMethods.CreateRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
|
||||
}
|
||||
if (!IPAddress.IsLoopback(address)) NativeMethods.CreateRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
|
||||
}
|
||||
|
||||
if (SavedMode.Type == 2) // 处理仅规则内走直连
|
||||
if (_savedMode.Type == 2) // 处理仅规则内走直连
|
||||
{
|
||||
Logging.Info("设置绕行规则 → 处理仅规则内走直连");
|
||||
// 将 TUN/TAP 网卡权重放到最高
|
||||
@@ -142,74 +128,58 @@ namespace Netch.Controllers
|
||||
// 创建默认路由
|
||||
if (!NativeMethods.CreateRoute("0.0.0.0", 0, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index, 10))
|
||||
{
|
||||
State = Models.State.Stopped;
|
||||
State = State.Stopped;
|
||||
|
||||
foreach (var address in ServerAddresses)
|
||||
{
|
||||
NativeMethods.DeleteRoute(address.ToString(), 32, Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
|
||||
}
|
||||
foreach (var address in _serverAddresses) NativeMethods.DeleteRoute(address.ToString(), 32, Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Logging.Info("设置绕行规则 → 创建规则路由");
|
||||
// 创建规则路由
|
||||
foreach (var ip in SavedMode.Rule)
|
||||
foreach (var ip in _savedMode.Rule)
|
||||
{
|
||||
var info = ip.Split('/');
|
||||
|
||||
if (info.Length == 2)
|
||||
{
|
||||
if (int.TryParse(info[1], out var prefix))
|
||||
{
|
||||
NativeMethods.CreateRoute(info[0], prefix, Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (SavedMode.Type == 1) // 处理仅规则内走代理
|
||||
else if (_savedMode.Type == 1) // 处理仅规则内走代理
|
||||
{
|
||||
Logging.Info("设置绕行规则->处理仅规则内走代理");
|
||||
foreach (var ip in SavedMode.Rule)
|
||||
foreach (var ip in _savedMode.Rule)
|
||||
{
|
||||
var info = ip.Split('/');
|
||||
|
||||
if (info.Length == 2)
|
||||
{
|
||||
if (int.TryParse(info[1], out var prefix))
|
||||
{
|
||||
NativeMethods.CreateRoute(info[0], prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//处理 NAT 类型检测,由于协议的原因,无法仅通过域名确定需要代理的 IP,自己记录解析了返回的 IP,仅支持默认检测服务器
|
||||
if (Global.Settings.STUN_Server == "stun.stunprotocol.org")
|
||||
{
|
||||
try
|
||||
{
|
||||
var nttAddress = Dns.GetHostAddresses(Global.Settings.STUN_Server)[0];
|
||||
if (int.TryParse("32", out var prefix))
|
||||
{
|
||||
NativeMethods.CreateRoute(nttAddress.ToString(), prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
}
|
||||
if (int.TryParse("32", out var prefix)) NativeMethods.CreateRoute(nttAddress.ToString(), prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
|
||||
var nttrAddress = Dns.GetHostAddresses("stunresponse.coldthunder11.com")[0];
|
||||
if (int.TryParse("32", out var prefixr))
|
||||
{
|
||||
NativeMethods.CreateRoute(nttrAddress.ToString(), prefixr, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
}
|
||||
if (int.TryParse("32", out var prefixr)) NativeMethods.CreateRoute(nttrAddress.ToString(), prefixr, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Logging.Info("NAT 类型测试域名解析失败,将不会被添加到代理列表");
|
||||
}
|
||||
}
|
||||
|
||||
//处理DNS代理
|
||||
if (Global.Settings.TUNTAP.ProxyDNS)
|
||||
{
|
||||
Logging.Info("设置绕行规则 → 处理自定义 DNS 代理");
|
||||
if (Global.Settings.TUNTAP.UseCustomDNS)
|
||||
{
|
||||
string dns = "";
|
||||
var dns = string.Empty;
|
||||
foreach (var value in Global.Settings.TUNTAP.DNS)
|
||||
{
|
||||
dns += value;
|
||||
@@ -218,10 +188,7 @@ namespace Netch.Controllers
|
||||
|
||||
dns = dns.Trim();
|
||||
dns = dns.Substring(0, dns.Length - 1);
|
||||
if (int.TryParse("32", out var prefix))
|
||||
{
|
||||
NativeMethods.CreateRoute(dns, prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
}
|
||||
if (int.TryParse("32", out var prefix)) NativeMethods.CreateRoute(dns, prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -235,6 +202,7 @@ namespace Netch.Controllers
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -244,59 +212,48 @@ namespace Netch.Controllers
|
||||
/// </summary>
|
||||
public bool ClearBypass()
|
||||
{
|
||||
if (SavedMode.Type == 2)
|
||||
if (_savedMode.Type == 2)
|
||||
{
|
||||
NativeMethods.DeleteRoute("0.0.0.0", 0, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index, 10);
|
||||
|
||||
foreach (var ip in SavedMode.Rule)
|
||||
foreach (var ip in _savedMode.Rule)
|
||||
{
|
||||
var info = ip.Split('/');
|
||||
|
||||
if (info.Length == 2)
|
||||
{
|
||||
if (int.TryParse(info[1], out var prefix))
|
||||
{
|
||||
NativeMethods.DeleteRoute(info[0], prefix, Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (SavedMode.Type == 1)
|
||||
else if (_savedMode.Type == 1)
|
||||
{
|
||||
foreach (var ip in SavedMode.Rule)
|
||||
foreach (var ip in _savedMode.Rule)
|
||||
{
|
||||
var info = ip.Split('/');
|
||||
|
||||
if (info.Length == 2)
|
||||
{
|
||||
if (int.TryParse(info[1], out var prefix))
|
||||
{
|
||||
NativeMethods.DeleteRoute(info[0], prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Global.Settings.STUN_Server == "stun.stunprotocol.org")
|
||||
{
|
||||
try
|
||||
{
|
||||
var nttAddress = Dns.GetHostAddresses(Global.Settings.STUN_Server)[0];
|
||||
if (int.TryParse("32", out var prefix))
|
||||
{
|
||||
NativeMethods.DeleteRoute(nttAddress.ToString(), prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
}
|
||||
if (int.TryParse("32", out var prefix)) NativeMethods.DeleteRoute(nttAddress.ToString(), prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
|
||||
var nttrAddress = Dns.GetHostAddresses("stunresponse.coldthunder11.com")[0];
|
||||
if (int.TryParse("32", out var prefixr))
|
||||
{
|
||||
NativeMethods.DeleteRoute(nttrAddress.ToString(), prefixr, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
}
|
||||
if (int.TryParse("32", out var prefixr)) NativeMethods.DeleteRoute(nttrAddress.ToString(), prefixr, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
if (Global.Settings.TUNTAP.ProxyDNS)
|
||||
{
|
||||
if (Global.Settings.TUNTAP.UseCustomDNS)
|
||||
{
|
||||
string dns = "";
|
||||
var dns = string.Empty;
|
||||
foreach (var value in Global.Settings.TUNTAP.DNS)
|
||||
{
|
||||
dns += value;
|
||||
@@ -305,17 +262,11 @@ namespace Netch.Controllers
|
||||
|
||||
dns = dns.Trim();
|
||||
dns = dns.Substring(0, dns.Length - 1);
|
||||
if (int.TryParse("32", out var prefix))
|
||||
{
|
||||
NativeMethods.DeleteRoute(dns, prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
}
|
||||
if (int.TryParse("32", out var prefix)) NativeMethods.DeleteRoute(dns, prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (int.TryParse("32", out var prefix))
|
||||
{
|
||||
NativeMethods.DeleteRoute("1.1.1.1", prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
}
|
||||
if (int.TryParse("32", out var prefix)) NativeMethods.DeleteRoute("1.1.1.1", prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -325,25 +276,19 @@ namespace Netch.Controllers
|
||||
var info = ip.Split('/');
|
||||
var address = IPAddress.Parse(info[0]);
|
||||
|
||||
if (!IPAddress.IsLoopback(address))
|
||||
{
|
||||
NativeMethods.DeleteRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
|
||||
}
|
||||
if (!IPAddress.IsLoopback(address)) NativeMethods.DeleteRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
|
||||
}
|
||||
foreach (var ip in BypassLanIPs)
|
||||
|
||||
foreach (var ip in _bypassLanIPs)
|
||||
{
|
||||
var info = ip.Split('/');
|
||||
var address = IPAddress.Parse(info[0]);
|
||||
|
||||
if (!IPAddress.IsLoopback(address))
|
||||
{
|
||||
NativeMethods.DeleteRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
|
||||
}
|
||||
if (!IPAddress.IsLoopback(address)) NativeMethods.DeleteRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
|
||||
}
|
||||
|
||||
if (SavedMode.BypassChina)
|
||||
{
|
||||
using (var sr = new StringReader(Encoding.UTF8.GetString(Properties.Resources.CNIP)))
|
||||
if (_savedMode.BypassChina)
|
||||
using (var sr = new StringReader(Encoding.UTF8.GetString(Resources.CNIP)))
|
||||
{
|
||||
string text;
|
||||
|
||||
@@ -354,63 +299,29 @@ namespace Netch.Controllers
|
||||
NativeMethods.DeleteRoute(info[0], int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var address in ServerAddresses)
|
||||
{
|
||||
foreach (var address in _serverAddresses)
|
||||
if (!IPAddress.IsLoopback(address))
|
||||
{
|
||||
NativeMethods.DeleteRoute(address.ToString(), 32, Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启动
|
||||
/// </summary>
|
||||
/// <param name="server">配置</param>
|
||||
/// <returns>是否成功</returns>
|
||||
public bool Start(Models.Server server, Models.Mode mode)
|
||||
public override bool Start(Server server, Mode mode)
|
||||
{
|
||||
MainForm.Instance.StatusText($"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("Starting Tap")}");
|
||||
foreach (var proc in Process.GetProcessesByName("tun2socks"))
|
||||
{
|
||||
try
|
||||
{
|
||||
proc.Kill();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// 跳过
|
||||
}
|
||||
}
|
||||
Global.MainForm.StatusText(i18N.Translate("Starting Tap"));
|
||||
|
||||
if (!File.Exists("bin\\tun2socks.exe"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_savedMode = mode;
|
||||
_savedServer = server;
|
||||
|
||||
if (File.Exists("logging\\tun2socks.log"))
|
||||
{
|
||||
File.Delete("logging\\tun2socks.log");
|
||||
}
|
||||
|
||||
SavedMode = mode;
|
||||
SavedServer = server;
|
||||
|
||||
if (!Configure())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!Configure()) return false;
|
||||
|
||||
Logging.Info("设置绕行规则");
|
||||
SetupBypass();
|
||||
Logging.Info("设置绕行规则完毕");
|
||||
|
||||
Instance = new Process();
|
||||
Instance.StartInfo.WorkingDirectory = string.Format("{0}\\bin", Directory.GetCurrentDirectory());
|
||||
Instance.StartInfo.FileName = string.Format("{0}\\bin\\tun2socks.exe", Directory.GetCurrentDirectory());
|
||||
Instance = GetProcess();
|
||||
|
||||
var adapterName = TUNTAP.GetName(Global.TUNTAP.ComponentID);
|
||||
Logging.Info($"tun2sock使用适配器:{adapterName}");
|
||||
|
||||
@@ -419,7 +330,7 @@ namespace Netch.Controllers
|
||||
//if (Global.Settings.TUNTAP.UseCustomDNS || server.Type.Equals("VMess"))
|
||||
if (Global.Settings.TUNTAP.UseCustomDNS)
|
||||
{
|
||||
dns = "";
|
||||
dns = string.Empty;
|
||||
foreach (var value in Global.Settings.TUNTAP.DNS)
|
||||
{
|
||||
dns += value;
|
||||
@@ -434,32 +345,18 @@ namespace Netch.Controllers
|
||||
pDNSController.Start();
|
||||
dns = "127.0.0.1";
|
||||
}
|
||||
if (Global.Settings.TUNTAP.UseFakeDNS)
|
||||
{
|
||||
dns += " -fakeDns";
|
||||
}
|
||||
|
||||
if (Global.Settings.TUNTAP.UseFakeDNS) dns += " -fakeDns";
|
||||
|
||||
if (server.Type == "Socks5")
|
||||
{
|
||||
Instance.StartInfo.Arguments = string.Format("-proxyServer {0}:{1} -tunAddr {2} -tunMask {3} -tunGw {4} -tunDns {5} -tunName \"{6}\"", server.Hostname, server.Port, Global.Settings.TUNTAP.Address, Global.Settings.TUNTAP.Netmask, Global.Settings.TUNTAP.Gateway, dns, adapterName);
|
||||
}
|
||||
Instance.StartInfo.Arguments = $"-proxyServer {server.Hostname}:{server.Port} -tunAddr {Global.Settings.TUNTAP.Address} -tunMask {Global.Settings.TUNTAP.Netmask} -tunGw {Global.Settings.TUNTAP.Gateway} -tunDns {dns} -tunName \"{adapterName}\"";
|
||||
else
|
||||
{
|
||||
Instance.StartInfo.Arguments = string.Format("-proxyServer 127.0.0.1:{0} -tunAddr {1} -tunMask {2} -tunGw {3} -tunDns {4} -tunName \"{5}\"", Global.Settings.Socks5LocalPort, Global.Settings.TUNTAP.Address, Global.Settings.TUNTAP.Netmask, Global.Settings.TUNTAP.Gateway, dns, adapterName);
|
||||
}
|
||||
Instance.StartInfo.Arguments = $"-proxyServer 127.0.0.1:{Global.Settings.Socks5LocalPort} -tunAddr {Global.Settings.TUNTAP.Address} -tunMask {Global.Settings.TUNTAP.Netmask} -tunGw {Global.Settings.TUNTAP.Gateway} -tunDns {dns} -tunName \"{adapterName}\"";
|
||||
|
||||
Instance.StartInfo.CreateNoWindow = true;
|
||||
Instance.StartInfo.RedirectStandardError = true;
|
||||
Instance.StartInfo.RedirectStandardInput = true;
|
||||
Instance.StartInfo.RedirectStandardOutput = true;
|
||||
Instance.StartInfo.UseShellExecute = false;
|
||||
Instance.EnableRaisingEvents = true;
|
||||
Instance.ErrorDataReceived += OnOutputDataReceived;
|
||||
Instance.OutputDataReceived += OnOutputDataReceived;
|
||||
|
||||
Logging.Info(Instance.StartInfo.Arguments);
|
||||
|
||||
State = Models.State.Starting;
|
||||
State = State.Starting;
|
||||
Instance.Start();
|
||||
Instance.BeginErrorReadLine();
|
||||
Instance.BeginOutputReadLine();
|
||||
@@ -469,12 +366,9 @@ namespace Netch.Controllers
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
|
||||
if (State == Models.State.Started)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (State == State.Started) return true;
|
||||
|
||||
if (State == Models.State.Stopped)
|
||||
if (State == State.Stopped)
|
||||
{
|
||||
Stop();
|
||||
return false;
|
||||
@@ -485,46 +379,121 @@ namespace Netch.Controllers
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止
|
||||
/// TUN/TAP停止
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
public override void Stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Instance != null && !Instance.HasExited)
|
||||
{
|
||||
Instance.Kill();
|
||||
}
|
||||
|
||||
//pDNSController.Stop();
|
||||
//修复点击停止按钮后再启动,DNS服务没监听的BUG
|
||||
ClearBypass();
|
||||
pDNSController.Stop();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Utils.Logging.Info(e.ToString());
|
||||
}
|
||||
StopInstance();
|
||||
ClearBypass();
|
||||
pDNSController.Stop();
|
||||
}
|
||||
|
||||
public void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
|
||||
/// <summary>
|
||||
/// 搜索出口
|
||||
/// </summary>
|
||||
public static bool SearchOutbounds()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(e.Data))
|
||||
{
|
||||
File.AppendAllText("logging\\tun2socks.log", string.Format("{0}\r\n", e.Data.Trim()));
|
||||
Logging.Info("正在搜索出口中");
|
||||
|
||||
if (State == Models.State.Starting)
|
||||
if (Win32Native.GetBestRoute(BitConverter.ToUInt32(IPAddress.Parse("114.114.114.114").GetAddressBytes(), 0), 0, out var pRoute) == 0)
|
||||
{
|
||||
Global.Adapter.Index = pRoute.dwForwardIfIndex;
|
||||
Global.Adapter.Gateway = new IPAddress(pRoute.dwForwardNextHop);
|
||||
Logging.Info($"当前 网关 地址:{Global.Adapter.Gateway}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Error("GetBestRoute 搜索失败");
|
||||
return false;
|
||||
}
|
||||
|
||||
Logging.Info($"搜索适配器index:{Global.Adapter.Index}");
|
||||
var AddressGot = false;
|
||||
foreach (var adapter in NetworkInterface.GetAllNetworkInterfaces())
|
||||
try
|
||||
{
|
||||
if (e.Data.Contains("Running"))
|
||||
var adapterProperties = adapter.GetIPProperties();
|
||||
var p = adapterProperties.GetIPv4Properties();
|
||||
Logging.Info($"检测适配器:{adapter.Name} {adapter.Id} {adapter.Description}, index: {p.Index}");
|
||||
|
||||
// 通过索引查找对应适配器的 IPv4 地址
|
||||
if (p.Index == Global.Adapter.Index)
|
||||
{
|
||||
State = Models.State.Started;
|
||||
}
|
||||
else if (e.Data.Contains("failed") || e.Data.Contains("invalid vconfig file"))
|
||||
{
|
||||
State = Models.State.Stopped;
|
||||
var AdapterIPs = string.Empty;
|
||||
|
||||
foreach (var ip in adapterProperties.UnicastAddresses)
|
||||
{
|
||||
if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
AddressGot = true;
|
||||
Global.Adapter.Address = ip.Address;
|
||||
Logging.Info($"当前出口 IPv4 地址:{Global.Adapter.Address}");
|
||||
break;
|
||||
}
|
||||
|
||||
AdapterIPs = $"{ip.Address} | ";
|
||||
}
|
||||
|
||||
if (!AddressGot)
|
||||
{
|
||||
if (AdapterIPs.Length > 3)
|
||||
{
|
||||
AdapterIPs = AdapterIPs.Substring(0, AdapterIPs.Length - 3);
|
||||
Logging.Info($"所有出口地址:{AdapterIPs}");
|
||||
}
|
||||
|
||||
Logging.Error("出口无 IPv4 地址,当前只支持 IPv4 地址");
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
if (!AddressGot)
|
||||
{
|
||||
Logging.Error("无法找到当前使用适配器");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 搜索 TUN/TAP 适配器的索引
|
||||
Global.TUNTAP.ComponentID = TUNTAP.GetComponentID();
|
||||
if (string.IsNullOrEmpty(Global.TUNTAP.ComponentID))
|
||||
{
|
||||
Logging.Error("未找到可用 TUN/TAP 适配器");
|
||||
if (MessageBoxX.Show(i18N.Translate("TUN/TAP driver is not detected. Is it installed now?"), confirm: true) == DialogResult.OK)
|
||||
{
|
||||
Configuration.addtap();
|
||||
//给点时间,不然立马安装完毕就查找适配器可能会导致找不到适配器ID
|
||||
Thread.Sleep(1000);
|
||||
Global.TUNTAP.ComponentID = TUNTAP.GetComponentID();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//MessageBoxX.Show(i18N.Translate("Please install TAP-Windows and create an TUN/TAP adapter manually"));
|
||||
// return false;
|
||||
}
|
||||
|
||||
foreach (var adapter in NetworkInterface.GetAllNetworkInterfaces())
|
||||
if (adapter.Id == Global.TUNTAP.ComponentID)
|
||||
{
|
||||
Global.TUNTAP.Adapter = adapter;
|
||||
Global.TUNTAP.Index = adapter.GetIPProperties().GetIPv4Properties().Index;
|
||||
|
||||
Logging.Info($"找到适配器TUN/TAP:{adapter.Id}");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Logging.Error("无法找到出口");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,322 +0,0 @@
|
||||
using Netch.Forms;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.ServiceProcess;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class NFController
|
||||
{
|
||||
/// <summary>
|
||||
/// 流量变动事件
|
||||
/// </summary>
|
||||
public event BandwidthUpdateHandler OnBandwidthUpdated;
|
||||
|
||||
/// <summary>
|
||||
/// 流量变动处理器
|
||||
/// </summary>
|
||||
/// <param name="upload">上传</param>
|
||||
/// <param name="download">下载</param>
|
||||
public delegate void BandwidthUpdateHandler(long upload, long download);
|
||||
|
||||
/// <summary>
|
||||
/// 进程实例
|
||||
/// </summary>
|
||||
public Process Instance;
|
||||
|
||||
/// <summary>
|
||||
/// 当前状态
|
||||
/// </summary>
|
||||
public Models.State State = Models.State.Waiting;
|
||||
|
||||
// 生成驱动文件路径
|
||||
public string driverPath = string.Format("{0}\\drivers\\netfilter2.sys", Environment.SystemDirectory);
|
||||
|
||||
/// <summary>
|
||||
/// 启动
|
||||
/// </summary>
|
||||
/// <param name="server">服务器</param>
|
||||
/// <param name="mode">模式</param>
|
||||
/// <param name="StopServiceAndRestart">先停止驱动服务再重新启动</param>
|
||||
/// <returns>是否成功</returns>
|
||||
public bool Start(Models.Server server, Models.Mode mode, bool StopServiceAndRestart)
|
||||
{
|
||||
if (!StopServiceAndRestart)
|
||||
MainForm.Instance.StatusText($"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("Starting Redirector")}");
|
||||
|
||||
if (!File.Exists("bin\\Redirector.exe"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查驱动是否存在
|
||||
if (File.Exists(driverPath))
|
||||
{
|
||||
// 生成系统版本
|
||||
var version = $"{Environment.OSVersion.Version.Major.ToString()}.{Environment.OSVersion.Version.Minor.ToString()}";
|
||||
var driverName = "";
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case "10.0":
|
||||
driverName = "Win-10.sys";
|
||||
break;
|
||||
case "6.3":
|
||||
case "6.2":
|
||||
driverName = "Win-8.sys";
|
||||
break;
|
||||
case "6.1":
|
||||
case "6.0":
|
||||
driverName = "Win-7.sys";
|
||||
break;
|
||||
default:
|
||||
Utils.Logging.Info($"不支持的系统版本:{version}");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查驱动版本号
|
||||
FileVersionInfo SystemfileVerInfo = System.Diagnostics.FileVersionInfo.GetVersionInfo(driverPath);
|
||||
FileVersionInfo BinFileVerInfo = System.Diagnostics.FileVersionInfo.GetVersionInfo(string.Format("bin\\{0}", driverName));
|
||||
|
||||
if (!SystemfileVerInfo.FileVersion.Equals(BinFileVerInfo.FileVersion))
|
||||
{
|
||||
Utils.Logging.Info("开始更新驱动");
|
||||
// 需要更新驱动
|
||||
try
|
||||
{
|
||||
var service = new ServiceController("netfilter2");
|
||||
if (service.Status == ServiceControllerStatus.Running)
|
||||
{
|
||||
service.Stop();
|
||||
service.WaitForStatus(ServiceControllerStatus.Stopped);
|
||||
}
|
||||
nfapinet.NFAPI.nf_unRegisterDriver("netfilter2");
|
||||
|
||||
//删除老驱动
|
||||
File.Delete(driverPath);
|
||||
if (!InstallDriver())
|
||||
return false;
|
||||
|
||||
Utils.Logging.Info($"驱动更新完毕,当前驱动版本:{BinFileVerInfo.FileVersion}");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Utils.Logging.Info($"更新驱动出错");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!InstallDriver())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// 启动驱动服务
|
||||
var service = new ServiceController("netfilter2");
|
||||
if (service.Status == ServiceControllerStatus.Running && StopServiceAndRestart)
|
||||
{
|
||||
// 防止其他程序占用 重置 NF 百万连接数限制
|
||||
service.Stop();
|
||||
service.WaitForStatus(ServiceControllerStatus.Stopped);
|
||||
MainForm.Instance.StatusText($"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("Starting netfilter2 Service")}");
|
||||
service.Start();
|
||||
}
|
||||
else if (service.Status == ServiceControllerStatus.Stopped)
|
||||
{
|
||||
MainForm.Instance.StatusText($"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("Starting netfilter2 Service")}");
|
||||
service.Start();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Utils.Logging.Info(e.ToString());
|
||||
|
||||
var result = nfapinet.NFAPI.nf_registerDriver("netfilter2");
|
||||
if (result != nfapinet.NF_STATUS.NF_STATUS_SUCCESS)
|
||||
{
|
||||
Utils.Logging.Info($"注册驱动失败,返回值:{result}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var processes = "";
|
||||
foreach (var proc in mode.Rule)
|
||||
{
|
||||
processes += proc;
|
||||
processes += ",";
|
||||
}
|
||||
processes += "NTT.exe";
|
||||
|
||||
Instance = MainController.GetProcess();
|
||||
Instance.StartInfo.FileName = "bin\\Redirector.exe";
|
||||
Instance.StartInfo.Arguments = "";
|
||||
|
||||
if (server.Type != "Socks5")
|
||||
{
|
||||
Instance.StartInfo.Arguments += $"-r 127.0.0.1:{Global.Settings.Socks5LocalPort} -p \"{processes}\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = Utils.DNS.Lookup(server.Hostname);
|
||||
if (result == null)
|
||||
{
|
||||
Utils.Logging.Info("无法解析服务器 IP 地址");
|
||||
return false;
|
||||
}
|
||||
|
||||
Instance.StartInfo.Arguments += $"-r {result}:{server.Port} -p \"{processes}\"";
|
||||
if (!string.IsNullOrWhiteSpace(server.Username) && !string.IsNullOrWhiteSpace(server.Password))
|
||||
{
|
||||
Instance.StartInfo.Arguments += $" -username \"{server.Username}\" -password \"{server.Password}\"";
|
||||
}
|
||||
}
|
||||
|
||||
if (File.Exists("logging\\redirector.log"))
|
||||
{
|
||||
File.Delete("logging\\redirector.log");
|
||||
}
|
||||
|
||||
Instance.StartInfo.Arguments += $" -t {Global.Settings.RedirectorTCPPort}";
|
||||
Utils.Logging.Info(Instance.StartInfo.Arguments);
|
||||
Instance.OutputDataReceived += OnOutputDataReceived;
|
||||
Instance.ErrorDataReceived += OnOutputDataReceived;
|
||||
State = Models.State.Starting;
|
||||
Instance.Start();
|
||||
Instance.BeginOutputReadLine();
|
||||
Instance.BeginErrorReadLine();
|
||||
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
|
||||
if (State == Models.State.Started)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Utils.Logging.Info("NF 进程启动超时");
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Instance != null && !Instance.HasExited)
|
||||
{
|
||||
Instance.Kill();
|
||||
Instance.WaitForExit();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Utils.Logging.Info(e.ToString());
|
||||
}
|
||||
}
|
||||
public bool InstallDriver()
|
||||
{
|
||||
|
||||
Utils.Logging.Info("安装驱动中");
|
||||
// 生成系统版本
|
||||
var version = $"{Environment.OSVersion.Version.Major.ToString()}.{Environment.OSVersion.Version.Minor.ToString()}";
|
||||
|
||||
// 检查系统版本并复制对应驱动
|
||||
try
|
||||
{
|
||||
switch (version)
|
||||
{
|
||||
case "10.0":
|
||||
File.Copy("bin\\Win-10.sys", driverPath);
|
||||
Utils.Logging.Info("已复制 Win10 驱动");
|
||||
break;
|
||||
case "6.3":
|
||||
case "6.2":
|
||||
File.Copy("bin\\Win-8.sys", driverPath);
|
||||
Utils.Logging.Info("已复制 Win8 驱动");
|
||||
break;
|
||||
case "6.1":
|
||||
case "6.0":
|
||||
File.Copy("bin\\Win-7.sys", driverPath);
|
||||
Utils.Logging.Info("已复制 Win7 驱动");
|
||||
break;
|
||||
default:
|
||||
Utils.Logging.Info($"不支持的系统版本:{version}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Utils.Logging.Info("复制驱动文件失败");
|
||||
Utils.Logging.Info(e.ToString());
|
||||
return false;
|
||||
}
|
||||
MainForm.Instance.StatusText($"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("Register driver")}");
|
||||
// 注册驱动文件
|
||||
var result = nfapinet.NFAPI.nf_registerDriver("netfilter2");
|
||||
if (result != nfapinet.NF_STATUS.NF_STATUS_SUCCESS)
|
||||
{
|
||||
Utils.Logging.Info($"注册驱动失败,返回值:{result}");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(e.Data))
|
||||
{
|
||||
File.AppendAllText("logging\\redirector.log", string.Format("{0}\r\n", e.Data));
|
||||
|
||||
if (State == Models.State.Starting)
|
||||
{
|
||||
if (Instance.HasExited)
|
||||
{
|
||||
State = Models.State.Stopped;
|
||||
}
|
||||
else if (e.Data.Contains("Started"))
|
||||
{
|
||||
State = Models.State.Started;
|
||||
}
|
||||
else if (e.Data.Contains("Failed") || e.Data.Contains("Unable"))
|
||||
{
|
||||
State = Models.State.Stopped;
|
||||
}
|
||||
}
|
||||
else if (State == Models.State.Started)
|
||||
{
|
||||
if (e.Data.StartsWith("[APP][Bandwidth]"))
|
||||
{
|
||||
var splited = e.Data.Replace("[APP][Bandwidth]", "").Trim().Split(',');
|
||||
if (splited.Length == 2)
|
||||
{
|
||||
var uploadSplited = splited[0].Split(':');
|
||||
var downloadSplited = splited[1].Split(':');
|
||||
|
||||
if (uploadSplited.Length == 2 && downloadSplited.Length == 2)
|
||||
{
|
||||
if (long.TryParse(uploadSplited[1], out var upload) && long.TryParse(downloadSplited[1], out var download))
|
||||
{
|
||||
Task.Run(() => OnBandwidthUpdated(upload, download));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,98 +1,67 @@
|
||||
using Netch.Forms;
|
||||
using System;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class NTTController
|
||||
public class NTTController : Controller
|
||||
{
|
||||
/// <summary>
|
||||
/// 进程实例
|
||||
/// </summary>
|
||||
public Process Instance;
|
||||
private string _lastResult;
|
||||
|
||||
public NTTController()
|
||||
{
|
||||
Name = "NTT";
|
||||
MainFile = "NTT.exe";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前状态
|
||||
/// </summary>
|
||||
public Models.State State = Models.State.Waiting;
|
||||
|
||||
/// <summary>
|
||||
/// 启动NatTypeTester
|
||||
/// 启动 NatTypeTester
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public (bool, string, string, string) Start()
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
MainForm.Instance.NatTypeStatusText($"{Utils.i18N.Translate("Starting NatTester")}");
|
||||
try
|
||||
{
|
||||
if (!File.Exists("bin\\NTT.exe"))
|
||||
{
|
||||
return (false, null, null, null);
|
||||
}
|
||||
|
||||
Instance = MainController.GetProcess();
|
||||
Instance.StartInfo.FileName = "bin\\NTT.exe";
|
||||
Instance = GetProcess();
|
||||
|
||||
Instance.StartInfo.Arguments = $" {Global.Settings.STUN_Server} {Global.Settings.STUN_Server_Port}";
|
||||
|
||||
Instance.OutputDataReceived += OnOutputDataReceived;
|
||||
Instance.ErrorDataReceived += OnOutputDataReceived;
|
||||
|
||||
State = Models.State.Starting;
|
||||
State = State.Starting;
|
||||
Instance.Start();
|
||||
Instance.BeginOutputReadLine();
|
||||
Instance.BeginErrorReadLine();
|
||||
Instance.WaitForExit();
|
||||
|
||||
string[] result = File.ReadAllText("logging\\NTT.log").ToString().Split('#');
|
||||
var result = _lastResult.Split('#');
|
||||
var natType = result[0];
|
||||
var localEnd = result[1];
|
||||
var publicEnd = result[2];
|
||||
MainForm.Instance.NatTypeStatusText(natType);
|
||||
|
||||
return (true, natType, localEnd, publicEnd);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Utils.Logging.Info("NTT 进程出错");
|
||||
Logging.Error("NTT 进程出错");
|
||||
Stop();
|
||||
return (false, null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
private new void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Instance != null && !Instance.HasExited)
|
||||
{
|
||||
Instance.Kill();
|
||||
Instance.WaitForExit();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Utils.Logging.Info(e.ToString());
|
||||
}
|
||||
if (!string.IsNullOrEmpty(e.Data))
|
||||
_lastResult = e.Data;
|
||||
}
|
||||
|
||||
public void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
|
||||
/// <summary>
|
||||
/// 无用
|
||||
/// </summary>
|
||||
public override void Stop()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(e.Data))
|
||||
{
|
||||
if (File.Exists("logging\\NTT.log"))
|
||||
{
|
||||
File.Delete("logging\\NTT.log");
|
||||
}
|
||||
|
||||
File.AppendAllText("logging\\NTT.log", $"{e.Data}\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,85 +1,50 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using Netch.Models;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class PrivoxyController
|
||||
public class PrivoxyController : Controller
|
||||
{
|
||||
/// <summary>
|
||||
/// 进程实例
|
||||
/// </summary>
|
||||
public Process Instance;
|
||||
|
||||
/// <summary>
|
||||
/// 启动
|
||||
/// </summary>
|
||||
/// <param name="server">服务器</param>
|
||||
/// <param name="mode">模式</param>
|
||||
/// <returns>是否启动成功</returns>
|
||||
public bool Start(Models.Server server, Models.Mode mode)
|
||||
public PrivoxyController()
|
||||
{
|
||||
foreach (var proc in Process.GetProcessesByName("Privoxy"))
|
||||
{
|
||||
try
|
||||
{
|
||||
proc.Kill();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// 跳过
|
||||
}
|
||||
}
|
||||
Name = "Privoxy";
|
||||
MainFile = "Privoxy.exe";
|
||||
RedirectStd = false;
|
||||
}
|
||||
|
||||
if (!File.Exists("bin\\Privoxy.exe") || !File.Exists("bin\\default.conf"))
|
||||
public bool Start(Server server, Mode mode)
|
||||
{
|
||||
var isSocks5 = server.Type == "Socks5";
|
||||
var socks5Port = isSocks5 ? server.Port : Global.Settings.Socks5LocalPort;
|
||||
var text = File.ReadAllText("bin\\default.conf")
|
||||
.Replace("_BIND_PORT_", Global.Settings.HTTPLocalPort.ToString())
|
||||
.Replace("_DEST_PORT_", socks5Port.ToString())
|
||||
.Replace("0.0.0.0", Global.Settings.LocalAddress);
|
||||
if (isSocks5)
|
||||
text = text.Replace("/ 127.0.0.1", $"/ {server.Hostname}");
|
||||
File.WriteAllText("data\\privoxy.conf", text);
|
||||
|
||||
Instance = GetProcess();
|
||||
Instance.StartInfo.Arguments = "..\\data\\privoxy.conf";
|
||||
Instance.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
||||
Instance.StartInfo.UseShellExecute = true;
|
||||
try
|
||||
{
|
||||
Instance.Start();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (server.Type != "Socks5")
|
||||
{
|
||||
File.WriteAllText("data\\privoxy.conf", File.ReadAllText("bin\\default.conf").Replace("_BIND_PORT_", Global.Settings.HTTPLocalPort.ToString()).Replace("_DEST_PORT_", Global.Settings.Socks5LocalPort.ToString()).Replace("0.0.0.0", Global.Settings.LocalAddress));
|
||||
}
|
||||
else
|
||||
{
|
||||
File.WriteAllText("data\\privoxy.conf", File.ReadAllText("bin\\default.conf").Replace("_BIND_PORT_", Global.Settings.HTTPLocalPort.ToString()).Replace("_DEST_PORT_", server.Port.ToString()).Replace("s 0.0.0.0", $"s {Global.Settings.LocalAddress}").Replace("/ 127.0.0.1", $"/ {server.Hostname}"));
|
||||
}
|
||||
|
||||
|
||||
Instance = new Process
|
||||
{
|
||||
StartInfo =
|
||||
{
|
||||
FileName = string.Format("{0}\\bin\\Privoxy.exe", Directory.GetCurrentDirectory()),
|
||||
Arguments = "..\\data\\privoxy.conf",
|
||||
WorkingDirectory = string.Format("{0}\\bin", Directory.GetCurrentDirectory()),
|
||||
WindowStyle = ProcessWindowStyle.Hidden,
|
||||
UseShellExecute = true,
|
||||
CreateNoWindow = true
|
||||
}
|
||||
};
|
||||
Instance.Start();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
public override void Stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Instance != null && !Instance.HasExited)
|
||||
{
|
||||
Instance.Kill();
|
||||
Instance.WaitForExit();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// 跳过
|
||||
}
|
||||
StopInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
using Netch.Forms;
|
||||
using Netch.Utils;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class SSController
|
||||
{
|
||||
/// <summary>
|
||||
/// 进程实例
|
||||
/// </summary>
|
||||
public Process Instance;
|
||||
|
||||
/// <summary>
|
||||
/// 当前状态
|
||||
/// </summary>
|
||||
public Models.State State = Models.State.Waiting;
|
||||
|
||||
/// <summary>
|
||||
/// 启动
|
||||
/// </summary>
|
||||
/// <param name="server">服务器</param>
|
||||
/// <param name="mode">模式</param>
|
||||
/// <returns>是否启动成功</returns>
|
||||
public bool Start(Models.Server server, Models.Mode mode)
|
||||
{
|
||||
MainForm.Instance.StatusText($"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("Starting Shadowsocks")}");
|
||||
|
||||
File.Delete("logging\\shadowsocks.log");
|
||||
//从DLL启动Shaowsocks
|
||||
if (Global.Settings.BootShadowsocksFromDLL && (mode.Type == 0 || mode.Type == 1 || mode.Type == 2 || mode.Type == 3))
|
||||
{
|
||||
State = Models.State.Starting;
|
||||
var client = Encoding.UTF8.GetBytes($"0.0.0.0:{Global.Settings.Socks5LocalPort}");
|
||||
var remote = Encoding.UTF8.GetBytes($"{server.Hostname}:{server.Port}");
|
||||
var passwd = Encoding.UTF8.GetBytes($"{server.Password}");
|
||||
var method = Encoding.UTF8.GetBytes($"{server.EncryptMethod}");
|
||||
if (!NativeMethods.Shadowsocks.Info(client, remote, passwd, method))
|
||||
{
|
||||
State = Models.State.Stopped;
|
||||
Logging.Info("DLL SS INFO 设置失败!");
|
||||
return false;
|
||||
}
|
||||
Logging.Info("DLL SS INFO 设置成功!");
|
||||
|
||||
if (!NativeMethods.Shadowsocks.Start())
|
||||
{
|
||||
State = Models.State.Stopped;
|
||||
Logging.Info("DLL SS 启动失败!");
|
||||
return false;
|
||||
}
|
||||
Logging.Info("DLL SS 启动成功!");
|
||||
State = Models.State.Started;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!File.Exists("bin\\Shadowsocks.exe"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Instance = MainController.GetProcess();
|
||||
Instance.StartInfo.FileName = "bin\\Shadowsocks.exe";
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(server.Plugin) && !string.IsNullOrWhiteSpace(server.PluginOption))
|
||||
{
|
||||
Instance.StartInfo.Arguments = $"-s {server.Hostname} -p {server.Port} -b {Global.Settings.LocalAddress} -l {Global.Settings.Socks5LocalPort} -m {server.EncryptMethod} -k \"{server.Password}\" -u --plugin {server.Plugin} --plugin-opts \"{server.PluginOption}\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
Instance.StartInfo.Arguments = $"-s {server.Hostname} -p {server.Port} -b {Global.Settings.LocalAddress} -l {Global.Settings.Socks5LocalPort} -m {server.EncryptMethod} -k \"{server.Password}\" -u";
|
||||
}
|
||||
|
||||
if (mode.BypassChina)
|
||||
{
|
||||
Instance.StartInfo.Arguments += " --acl default.acl";
|
||||
}
|
||||
|
||||
Instance.OutputDataReceived += OnOutputDataReceived;
|
||||
Instance.ErrorDataReceived += OnOutputDataReceived;
|
||||
|
||||
State = Models.State.Starting;
|
||||
Instance.Start();
|
||||
Instance.BeginOutputReadLine();
|
||||
Instance.BeginErrorReadLine();
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
|
||||
if (State == Models.State.Started)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (State == Models.State.Stopped)
|
||||
{
|
||||
Utils.Logging.Info("SS 进程启动失败");
|
||||
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Utils.Logging.Info("SS 进程启动超时");
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Global.Settings.BootShadowsocksFromDLL)
|
||||
{
|
||||
NativeMethods.Shadowsocks.Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Instance != null && !Instance.HasExited)
|
||||
{
|
||||
Instance.Kill();
|
||||
Instance.WaitForExit();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Utils.Logging.Info(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(e.Data))
|
||||
{
|
||||
File.AppendAllText("logging\\shadowsocks.log", $"{e.Data}\r\n");
|
||||
|
||||
if (State == Models.State.Starting)
|
||||
{
|
||||
if (Instance.HasExited)
|
||||
{
|
||||
State = Models.State.Stopped;
|
||||
}
|
||||
else if (e.Data.Contains("listening at"))
|
||||
{
|
||||
State = Models.State.Started;
|
||||
}
|
||||
else if (e.Data.Contains("Invalid config path") || e.Data.Contains("usage") || e.Data.Contains("plugin service exit unexpectedly"))
|
||||
{
|
||||
State = Models.State.Stopped;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ec)
|
||||
{
|
||||
Logging.Info("写入Shadowsocks日志失败" + ec.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
using Netch.Forms;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class SSRController
|
||||
{
|
||||
/// <summary>
|
||||
/// 进程实例
|
||||
/// </summary>
|
||||
public Process Instance;
|
||||
|
||||
/// <summary>
|
||||
/// 当前状态
|
||||
/// </summary>
|
||||
public Models.State State = Models.State.Waiting;
|
||||
|
||||
/// <summary>
|
||||
/// 启动
|
||||
/// </summary>
|
||||
/// <param name="server">服务器</param>
|
||||
/// <param name="mode">模式</param>
|
||||
/// <returns>是否启动成功</returns>
|
||||
public bool Start(Models.Server server, Models.Mode mode)
|
||||
{
|
||||
MainForm.Instance.StatusText($"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("Starting ShadowsocksR")}");
|
||||
|
||||
File.Delete("logging\\shadowsocksr.log");
|
||||
|
||||
if (!File.Exists("bin\\ShadowsocksR.exe"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Instance = MainController.GetProcess();
|
||||
Instance.StartInfo.FileName = "bin\\ShadowsocksR.exe";
|
||||
Instance.StartInfo.Arguments = $"-s {server.Hostname} -p {server.Port} -k \"{server.Password}\" -m {server.EncryptMethod} -t 120";
|
||||
|
||||
if (!string.IsNullOrEmpty(server.Protocol))
|
||||
{
|
||||
Instance.StartInfo.Arguments += $" -O {server.Protocol}";
|
||||
|
||||
if (!string.IsNullOrEmpty(server.ProtocolParam))
|
||||
{
|
||||
Instance.StartInfo.Arguments += $" -G \"{server.ProtocolParam}\"";
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(server.OBFS))
|
||||
{
|
||||
Instance.StartInfo.Arguments += $" -o {server.OBFS}";
|
||||
|
||||
if (!string.IsNullOrEmpty(server.OBFSParam))
|
||||
{
|
||||
Instance.StartInfo.Arguments += $" -g \"{server.OBFSParam}\"";
|
||||
}
|
||||
}
|
||||
|
||||
Instance.StartInfo.Arguments += $" -b {Global.Settings.LocalAddress} -l {Global.Settings.Socks5LocalPort} -u";
|
||||
|
||||
if (mode.BypassChina)
|
||||
{
|
||||
Instance.StartInfo.Arguments += " --acl default.acl";
|
||||
}
|
||||
|
||||
Instance.OutputDataReceived += OnOutputDataReceived;
|
||||
Instance.ErrorDataReceived += OnOutputDataReceived;
|
||||
|
||||
State = Models.State.Starting;
|
||||
Instance.Start();
|
||||
Instance.BeginOutputReadLine();
|
||||
Instance.BeginErrorReadLine();
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
|
||||
if (State == Models.State.Started)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (State == Models.State.Stopped)
|
||||
{
|
||||
Utils.Logging.Info("SSR 进程启动失败");
|
||||
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Utils.Logging.Info("SSR 进程启动超时");
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Instance != null && !Instance.HasExited)
|
||||
{
|
||||
Instance.Kill();
|
||||
Instance.WaitForExit();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Utils.Logging.Info(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(e.Data))
|
||||
{
|
||||
File.AppendAllText("logging\\shadowsocksr.log", $"{e.Data}\r\n");
|
||||
|
||||
if (State == Models.State.Starting)
|
||||
{
|
||||
if (Instance.HasExited)
|
||||
{
|
||||
State = Models.State.Stopped;
|
||||
}
|
||||
else if (e.Data.Contains("listening at"))
|
||||
{
|
||||
State = Models.State.Started;
|
||||
}
|
||||
else if (e.Data.Contains("Invalid config path") || e.Data.Contains("usage"))
|
||||
{
|
||||
State = Models.State.Stopped;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class TrojanController
|
||||
{
|
||||
/// <summary>
|
||||
/// 进程实例
|
||||
/// </summary>
|
||||
public Process Instance;
|
||||
|
||||
/// <summary>
|
||||
/// 当前状态
|
||||
/// </summary>
|
||||
public Models.State State = Models.State.Waiting;
|
||||
|
||||
/// <summary>
|
||||
/// 启动
|
||||
/// </summary>
|
||||
/// <param name="server">服务器</param>
|
||||
/// <param name="mode">模式</param>
|
||||
/// <returns>是否启动成功</returns>
|
||||
public bool Start(Models.Server server, Models.Mode mode)
|
||||
{
|
||||
Forms.MainForm.Instance.StatusText($"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("Starting Trojan")}");
|
||||
|
||||
File.Delete("logging\\trojan.log");
|
||||
if (!File.Exists("bin\\Trojan.exe"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
File.WriteAllText("data\\last.json", Newtonsoft.Json.JsonConvert.SerializeObject(new Models.Trojan()
|
||||
{
|
||||
local_addr = Global.Settings.LocalAddress,
|
||||
local_port = Global.Settings.Socks5LocalPort,
|
||||
remote_addr = server.Hostname,
|
||||
remote_port = server.Port,
|
||||
password = new List<string>()
|
||||
{
|
||||
server.Password
|
||||
}
|
||||
}));
|
||||
|
||||
Instance = MainController.GetProcess();
|
||||
Instance.StartInfo.FileName = "bin\\Trojan.exe";
|
||||
Instance.StartInfo.Arguments = "-c ..\\data\\last.json";
|
||||
Instance.OutputDataReceived += OnOutputDataReceived;
|
||||
Instance.ErrorDataReceived += OnOutputDataReceived;
|
||||
|
||||
State = Models.State.Starting;
|
||||
Instance.Start();
|
||||
Instance.BeginOutputReadLine();
|
||||
Instance.BeginErrorReadLine();
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
|
||||
if (State == Models.State.Started)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (State == Models.State.Stopped)
|
||||
{
|
||||
Utils.Logging.Info("Trojan 进程启动失败");
|
||||
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Utils.Logging.Info("Trojan 进程启动超时");
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Instance != null && !Instance.HasExited)
|
||||
{
|
||||
Instance.Kill();
|
||||
Instance.WaitForExit();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Utils.Logging.Info(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(e.Data))
|
||||
{
|
||||
File.AppendAllText("logging\\trojan.log", $"{e.Data}\r\n");
|
||||
|
||||
if (State == Models.State.Starting)
|
||||
{
|
||||
if (Instance.HasExited)
|
||||
{
|
||||
State = Models.State.Stopped;
|
||||
}
|
||||
else if (e.Data.Contains("started"))
|
||||
{
|
||||
State = Models.State.Started;
|
||||
}
|
||||
else if (e.Data.Contains("exiting"))
|
||||
{
|
||||
State = Models.State.Stopped;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
using Netch.Models.GitHubRelease;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Models.GitHubRelease;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
@@ -14,8 +14,12 @@ namespace Netch.Controllers
|
||||
|
||||
private const int DefaultGetTimeout = 30000;
|
||||
|
||||
private const string Owner = @"NetchX";
|
||||
private const string Repo = @"Netch";
|
||||
public const string Owner = @"NetchX";
|
||||
public const string Repo = @"Netch";
|
||||
|
||||
public const string Name = @"Netch";
|
||||
public const string Copyright = @"Copyright © 2019 - 2020";
|
||||
public const string Version = @"1.4.12";
|
||||
|
||||
public string LatestVersionNumber;
|
||||
public string LatestVersionUrl;
|
||||
@@ -24,10 +28,6 @@ namespace Netch.Controllers
|
||||
public event EventHandler NewVersionFoundFailed;
|
||||
public event EventHandler NewVersionNotFound;
|
||||
|
||||
public const string Name = @"Netch";
|
||||
public const string Copyright = @"Copyright © 2019 - 2020";
|
||||
public const string Version = @"1.4.10";
|
||||
|
||||
public async void Check(bool notifyNoFound, bool isPreRelease)
|
||||
{
|
||||
try
|
||||
@@ -48,19 +48,13 @@ namespace Netch.Controllers
|
||||
else
|
||||
{
|
||||
LatestVersionNumber = latestRelease.tag_name;
|
||||
if (notifyNoFound)
|
||||
{
|
||||
NewVersionNotFound?.Invoke(this, new EventArgs());
|
||||
}
|
||||
if (notifyNoFound) NewVersionNotFound?.Invoke(this, new EventArgs());
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.WriteLine(e.Message);
|
||||
if (notifyNoFound)
|
||||
{
|
||||
NewVersionFoundFailed?.Invoke(this, new EventArgs());
|
||||
}
|
||||
Debug.WriteLine(e.ToString());
|
||||
if (notifyNoFound) NewVersionFoundFailed?.Invoke(this, new EventArgs());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,261 +0,0 @@
|
||||
using Netch.Forms;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class VMessController
|
||||
{
|
||||
/// <summary>
|
||||
/// 进程实例
|
||||
/// </summary>
|
||||
public Process Instance;
|
||||
|
||||
/// <summary>
|
||||
/// 当前状态
|
||||
/// </summary>
|
||||
public Models.State State = Models.State.Waiting;
|
||||
|
||||
/// <summary>
|
||||
/// 启动
|
||||
/// </summary>
|
||||
/// <param name="server">服务器</param>
|
||||
/// <param name="mode">模式</param>
|
||||
/// <returns>是否启动成功</returns>
|
||||
public bool Start(Models.Server server, Models.Mode mode)
|
||||
{
|
||||
MainForm.Instance.StatusText($"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("Starting V2ray")}");
|
||||
if (!File.Exists("bin\\v2ray.exe") || !File.Exists("bin\\v2ctl.exe"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
File.WriteAllText("data\\last.json", Newtonsoft.Json.JsonConvert.SerializeObject(new Models.Information.VMess.Config
|
||||
{
|
||||
inbounds = new List<Models.Information.VMess.Inbounds>
|
||||
{
|
||||
new Models.Information.VMess.Inbounds
|
||||
{
|
||||
settings = new Models.Information.VMess.InboundSettings(),
|
||||
port = Global.Settings.Socks5LocalPort,
|
||||
listen = Global.Settings.LocalAddress
|
||||
}
|
||||
},
|
||||
outbounds = new List<Models.Information.VMess.Outbounds>
|
||||
{
|
||||
new Models.Information.VMess.Outbounds
|
||||
{
|
||||
settings = new Models.Information.VMess.OutboundSettings
|
||||
{
|
||||
vnext = new List<Models.Information.VMess.VNext>
|
||||
{
|
||||
new Models.Information.VMess.VNext
|
||||
{
|
||||
address = server.Hostname,
|
||||
port = server.Port,
|
||||
users = new List<Models.Information.VMess.User>
|
||||
{
|
||||
new Models.Information.VMess.User
|
||||
{
|
||||
id = server.UserID,
|
||||
alterId = server.AlterID,
|
||||
security = server.EncryptMethod
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
streamSettings = new Models.Information.VMess.StreamSettings
|
||||
{
|
||||
network = server.TransferProtocol,
|
||||
security = server.TLSSecure ? "tls" : "",
|
||||
wsSettings = server.TransferProtocol == "ws" ? new Models.Information.VMess.WebSocketSettings
|
||||
{
|
||||
path = server.Path == "" ? "/" : server.Path,
|
||||
headers = new Models.Information.VMess.WSHeaders
|
||||
{
|
||||
Host = server.Host == "" ? server.Hostname : server.Host
|
||||
}
|
||||
} : null,
|
||||
tcpSettings = server.FakeType == "http" ? new Models.Information.VMess.TCPSettings
|
||||
{
|
||||
header = new Models.Information.VMess.TCPHeaders
|
||||
{
|
||||
type = server.FakeType,
|
||||
request = new Models.Information.VMess.TCPRequest
|
||||
{
|
||||
path = server.Path == "" ? "/" : server.Path,
|
||||
headers = new Models.Information.VMess.TCPRequestHeaders
|
||||
{
|
||||
Host = server.Host == "" ? server.Hostname : server.Host
|
||||
}
|
||||
}
|
||||
}
|
||||
} : null,
|
||||
kcpSettings = server.TransferProtocol == "kcp" ? new Models.Information.VMess.KCPSettings
|
||||
{
|
||||
header = new Models.Information.VMess.TCPHeaders
|
||||
{
|
||||
type = server.FakeType
|
||||
}
|
||||
} : null,
|
||||
quicSettings = server.TransferProtocol == "quic" ? new Models.Information.VMess.QUICSettings
|
||||
{
|
||||
security = server.QUICSecure,
|
||||
key = server.QUICSecret,
|
||||
header = new Models.Information.VMess.TCPHeaders
|
||||
{
|
||||
type = server.FakeType
|
||||
}
|
||||
} : null,
|
||||
httpSettings = server.TransferProtocol == "h2" ? new Models.Information.VMess.HTTPSettings
|
||||
{
|
||||
host = server.Host == "" ? server.Hostname : server.Host,
|
||||
path = server.Path == "" ? "/" : server.Path
|
||||
} : null,
|
||||
tlsSettings = new Models.Information.VMess.TLSSettings
|
||||
{
|
||||
allowInsecure = true,
|
||||
serverName = server.Host == "" ? server.Hostname : server.Host
|
||||
}
|
||||
},
|
||||
mux = new Models.Information.VMess.OutboundMux
|
||||
{
|
||||
enabled = server.UseMux
|
||||
}
|
||||
},
|
||||
(mode.Type==0||mode.Type==1||mode.Type==2) ? new Models.Information.VMess.Outbounds
|
||||
{
|
||||
tag = "TUNTAP",
|
||||
protocol = "freedom"
|
||||
}: new Models.Information.VMess.Outbounds
|
||||
{
|
||||
tag = "direct",
|
||||
protocol = "freedom"
|
||||
}
|
||||
},
|
||||
routing = new Models.Information.VMess.Routing
|
||||
{
|
||||
rules = new List<Models.Information.VMess.RoutingRules>
|
||||
{
|
||||
mode.BypassChina ? new Models.Information.VMess.RoutingRules
|
||||
{
|
||||
type = "field",
|
||||
ip = new List<string>
|
||||
{
|
||||
"geoip:cn",
|
||||
"geoip:private"
|
||||
|
||||
},
|
||||
domain = new List<string>
|
||||
{
|
||||
"geosite:cn"
|
||||
},
|
||||
outboundTag = "direct"
|
||||
} : new Models.Information.VMess.RoutingRules
|
||||
{
|
||||
type = "field",
|
||||
ip = new List<string>
|
||||
{
|
||||
"geoip:private"
|
||||
},
|
||||
outboundTag = "direct"
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
// 清理上一次的日志文件,防止淤积占用磁盘空间
|
||||
if (Directory.Exists("logging"))
|
||||
{
|
||||
if (File.Exists("logging\\v2ray.log"))
|
||||
{
|
||||
File.Delete("logging\\v2ray.log");
|
||||
}
|
||||
}
|
||||
|
||||
Instance = MainController.GetProcess();
|
||||
Instance.StartInfo.FileName = "bin\\v2ray.exe";
|
||||
Instance.StartInfo.Arguments = "-config ..\\data\\last.json";
|
||||
|
||||
Instance.OutputDataReceived += OnOutputDataReceived;
|
||||
Instance.ErrorDataReceived += OnOutputDataReceived;
|
||||
|
||||
State = Models.State.Starting;
|
||||
Instance.Start();
|
||||
Instance.BeginOutputReadLine();
|
||||
Instance.BeginErrorReadLine();
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
|
||||
if (State == Models.State.Started)
|
||||
{
|
||||
if (File.Exists("data\\last.json"))
|
||||
{
|
||||
File.Delete("data\\last.json");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (State == Models.State.Stopped)
|
||||
{
|
||||
Utils.Logging.Info("V2Ray 进程启动失败");
|
||||
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Utils.Logging.Info("V2Ray 进程启动超时");
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Instance != null && !Instance.HasExited)
|
||||
{
|
||||
Instance.Kill();
|
||||
Instance.WaitForExit();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Utils.Logging.Info(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(e.Data))
|
||||
{
|
||||
File.AppendAllText("logging\\v2ray.log", $"{e.Data}\r\n");
|
||||
|
||||
if (State == Models.State.Starting)
|
||||
{
|
||||
if (Instance.HasExited)
|
||||
{
|
||||
State = Models.State.Stopped;
|
||||
}
|
||||
else if (e.Data.Contains("started"))
|
||||
{
|
||||
State = Models.State.Started;
|
||||
}
|
||||
else if (e.Data.Contains("config file not readable") || e.Data.Contains("failed to"))
|
||||
{
|
||||
State = Models.State.Stopped;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Forms
|
||||
{
|
||||
@@ -13,9 +14,9 @@ namespace Netch.Forms
|
||||
|
||||
private void AboutForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
Text = Utils.i18N.Translate(Text);
|
||||
ChannelLabel.Text = Utils.i18N.Translate(ChannelLabel.Text);
|
||||
SponsorGroupBox.Text = Utils.i18N.Translate(SponsorGroupBox.Text);
|
||||
Text = i18N.Translate(Text);
|
||||
ChannelLabel.Text = i18N.Translate(ChannelLabel.Text);
|
||||
SponsorGroupBox.Text = i18N.Translate(SponsorGroupBox.Text);
|
||||
}
|
||||
|
||||
private void AboutForm_FormClosing(object sender, FormClosingEventArgs e)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Forms
|
||||
{
|
||||
@@ -13,10 +14,10 @@ namespace Netch.Forms
|
||||
|
||||
private void GlobalBypassIPForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
Text = Utils.i18N.Translate(Text);
|
||||
AddButton.Text = Utils.i18N.Translate(AddButton.Text);
|
||||
DeleteButton.Text = Utils.i18N.Translate(DeleteButton.Text);
|
||||
ControlButton.Text = Utils.i18N.Translate(ControlButton.Text);
|
||||
Text = i18N.Translate(Text);
|
||||
AddButton.Text = i18N.Translate(AddButton.Text);
|
||||
DeleteButton.Text = i18N.Translate(DeleteButton.Text);
|
||||
ControlButton.Text = i18N.Translate(ControlButton.Text);
|
||||
|
||||
IPListBox.Items.AddRange(Global.Settings.BypassIPs.ToArray());
|
||||
|
||||
@@ -42,12 +43,12 @@ namespace Netch.Forms
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show(Utils.i18N.Translate("Please enter a correct IP address"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBoxX.Show(i18N.Translate("Please enter a correct IP address"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show(Utils.i18N.Translate("Please enter an IP"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBoxX.Show(i18N.Translate("Please enter an IP"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +60,7 @@ namespace Netch.Forms
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show(Utils.i18N.Translate("Please select an IP"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBoxX.Show(i18N.Translate("Please select an IP"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,8 +72,8 @@ namespace Netch.Forms
|
||||
Global.Settings.BypassIPs.Add(ip as string);
|
||||
}
|
||||
|
||||
Utils.Configuration.Save();
|
||||
MessageBox.Show(Utils.i18N.Translate("Saved"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
Configuration.Save();
|
||||
MessageBoxX.Show(i18N.Translate("Saved"));
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
208
Netch/Forms/MainForm.Control.cs
Normal file
208
Netch/Forms/MainForm.Control.cs
Normal file
@@ -0,0 +1,208 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Controllers;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Forms
|
||||
{
|
||||
public partial class Dummy
|
||||
{
|
||||
}
|
||||
|
||||
partial class MainForm
|
||||
{
|
||||
private bool _isFirstCloseWindow = true;
|
||||
|
||||
private void ControlFun()
|
||||
{
|
||||
//防止模式选择框变成蓝色:D
|
||||
ModeComboBox.Select(0, 0);
|
||||
|
||||
if (State == State.Waiting || State == State.Stopped)
|
||||
{
|
||||
// 服务器、模式 需选择
|
||||
if (ServerComboBox.SelectedIndex == -1)
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Please select a server first"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (ModeComboBox.SelectedIndex == -1)
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Please select a mode first"));
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateStatus(State.Starting);
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
Task.Run(Firewall.AddNetchFwRules);
|
||||
|
||||
var server = ServerComboBox.SelectedItem as Models.Server;
|
||||
var mode = ModeComboBox.SelectedItem as Models.Mode;
|
||||
|
||||
if (_mainController.Start(server, mode))
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
UpdateStatus(State.Started,
|
||||
i18N.Translate(StateExtension.GetStatusString(State.Started)) + LocalPortText(server.Type, mode.Type));
|
||||
Bandwidth.NetTraffic(server, mode, _mainController);
|
||||
});
|
||||
// 如果勾选启动后最小化
|
||||
if (Global.Settings.MinimizeWhenStarted)
|
||||
{
|
||||
WindowState = FormWindowState.Minimized;
|
||||
NotifyIcon.Visible = true;
|
||||
|
||||
if (_isFirstCloseWindow)
|
||||
{
|
||||
// 显示提示语
|
||||
NotifyIcon.ShowBalloonTip(5,
|
||||
UpdateChecker.Name,
|
||||
i18N.Translate(
|
||||
"Netch is now minimized to the notification bar, double click this icon to restore."),
|
||||
ToolTipIcon.Info);
|
||||
|
||||
_isFirstCloseWindow = false;
|
||||
}
|
||||
|
||||
Hide();
|
||||
}
|
||||
|
||||
if (Global.Settings.StartedTcping)
|
||||
{
|
||||
// 自动检测延迟
|
||||
Task.Run(() =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (State == State.Started)
|
||||
{
|
||||
server.Test();
|
||||
// 重载服务器列表
|
||||
InitServer();
|
||||
|
||||
Thread.Sleep(Global.Settings.StartedTcping_Interval * 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateStatus(State.Stopped, i18N.Translate("Start failed"));
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// 停止
|
||||
UpdateStatus(State.Stopping);
|
||||
_mainController.Stop();
|
||||
UpdateStatus(State.Stopped);
|
||||
Task.Run(TestServer);
|
||||
}
|
||||
}
|
||||
|
||||
private static string LocalPortText(string serverType, int modeType)
|
||||
{
|
||||
var text = new StringBuilder(" (");
|
||||
if (Global.Settings.LocalAddress == "0.0.0.0")
|
||||
text.Append(i18N.Translate("Allow other Devices to connect") + " ");
|
||||
if (serverType == "Socks5")
|
||||
{
|
||||
// 不可控Socks5
|
||||
if (modeType == 3 || modeType == 5)
|
||||
{
|
||||
// 可控HTTP
|
||||
MainController.UsingPorts.Add(Global.Settings.HTTPLocalPort);
|
||||
text.Append($"HTTP {i18N.Translate("Local Port", ": ")}{Global.Settings.HTTPLocalPort}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 不可控HTTP
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 可控Socks5
|
||||
MainController.UsingPorts.Add(Global.Settings.Socks5LocalPort);
|
||||
text.Append($"Socks5 {i18N.Translate("Local Port", ": ")}{Global.Settings.Socks5LocalPort}");
|
||||
if (modeType == 3 || modeType == 5)
|
||||
{
|
||||
// 有HTTP
|
||||
MainController.UsingPorts.Add(Global.Settings.HTTPLocalPort);
|
||||
text.Append($" | HTTP {i18N.Translate("Local Port", ": ")}{Global.Settings.HTTPLocalPort}");
|
||||
}
|
||||
}
|
||||
|
||||
if (modeType == 0)
|
||||
MainController.UsingPorts.Add(Global.Settings.RedirectorTCPPort);
|
||||
|
||||
text.Append(")");
|
||||
return text.ToString();
|
||||
}
|
||||
|
||||
|
||||
public void OnBandwidthUpdated(long download)
|
||||
{
|
||||
try
|
||||
{
|
||||
UsedBandwidthLabel.Text = $"{i18N.Translate("Used", ": ")}{Bandwidth.Compute(download)}";
|
||||
//UploadSpeedLabel.Text = $"↑: {Utils.Bandwidth.Compute(upload - LastUploadBandwidth)}/s";
|
||||
DownloadSpeedLabel.Text = $"↑↓: {Bandwidth.Compute(download - LastDownloadBandwidth)}/s";
|
||||
|
||||
//LastUploadBandwidth = upload;
|
||||
LastDownloadBandwidth = download;
|
||||
Refresh();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public void OnBandwidthUpdated(long upload, long download)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (upload < 1 || download < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UsedBandwidthLabel.Text =
|
||||
$"{i18N.Translate("Used", ": ")}{Bandwidth.Compute(upload + download)}";
|
||||
UploadSpeedLabel.Text = $"↑: {Bandwidth.Compute(upload - LastUploadBandwidth)}/s";
|
||||
DownloadSpeedLabel.Text = $"↓: {Bandwidth.Compute(download - LastDownloadBandwidth)}/s";
|
||||
|
||||
LastUploadBandwidth = upload;
|
||||
LastDownloadBandwidth = download;
|
||||
Refresh();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上一次上传的流量
|
||||
/// </summary>
|
||||
public long LastUploadBandwidth;
|
||||
|
||||
/// <summary>
|
||||
/// 上一次下载的流量
|
||||
/// </summary>
|
||||
public long LastDownloadBandwidth;
|
||||
}
|
||||
}
|
||||
300
Netch/Forms/MainForm.Designer.cs
generated
300
Netch/Forms/MainForm.Designer.cs
generated
@@ -39,23 +39,24 @@ namespace Netch.Forms
|
||||
this.AddShadowsocksServerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.AddShadowsocksRServerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.AddVMessServerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.AddTrojanServerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.ModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.CreateProcessModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.ManageProcessModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.ReloadModesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.SubscribeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.ManageSubscribeLinksToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.UpdateServersFromSubscribeLinksToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.OptionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.ReloadModesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.RestartServiceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.UninstallServiceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.OpenDirectoryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.CleanDNSCacheToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.UpdateACLToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.updateACLWithProxyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.UninstallServiceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.reinstallTapDriverToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.AboutToolStripButton = new System.Windows.Forms.ToolStripButton();
|
||||
this.VersionLabel = new System.Windows.Forms.ToolStripLabel();
|
||||
this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.RelyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.ConfigurationGroupBox = new System.Windows.Forms.GroupBox();
|
||||
this.configLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.ProfileLabel = new System.Windows.Forms.Label();
|
||||
@@ -65,9 +66,9 @@ namespace Netch.Forms
|
||||
this.ModeComboBox = new System.Windows.Forms.SearchComboBox();
|
||||
this.ServerComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.EditPictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.EditServerPictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.CopyLinkPictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.DeletePictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.DeleteServerPictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.SpeedPictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.EditModePictureBox = new System.Windows.Forms.PictureBox();
|
||||
@@ -77,7 +78,9 @@ namespace Netch.Forms
|
||||
this.UsedBandwidthLabel = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.DownloadSpeedLabel = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.UploadSpeedLabel = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.blankToolStripStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.NatTypeStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.NatTypeStatusLightLabel = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.ControlButton = new System.Windows.Forms.Button();
|
||||
this.NotifyIcon = new System.Windows.Forms.NotifyIcon(this.components);
|
||||
this.NotifyMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
@@ -86,14 +89,13 @@ namespace Netch.Forms
|
||||
this.SettingsButton = new System.Windows.Forms.Button();
|
||||
this.ProfileGroupBox = new System.Windows.Forms.GroupBox();
|
||||
this.ProfileTable = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.AddTrojanServerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.MenuStrip.SuspendLayout();
|
||||
this.ConfigurationGroupBox.SuspendLayout();
|
||||
this.configLayoutPanel.SuspendLayout();
|
||||
this.tableLayoutPanel2.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.EditPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.EditServerPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.CopyLinkPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.DeletePictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.DeleteServerPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.SpeedPictureBox)).BeginInit();
|
||||
this.tableLayoutPanel3.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.EditModePictureBox)).BeginInit();
|
||||
@@ -114,11 +116,12 @@ namespace Netch.Forms
|
||||
this.OptionsToolStripMenuItem,
|
||||
this.AboutToolStripButton,
|
||||
this.VersionLabel,
|
||||
this.exitToolStripMenuItem});
|
||||
this.exitToolStripMenuItem,
|
||||
this.RelyToolStripMenuItem});
|
||||
this.MenuStrip.Location = new System.Drawing.Point(0, 0);
|
||||
this.MenuStrip.Name = "MenuStrip";
|
||||
this.MenuStrip.RenderMode = System.Windows.Forms.ToolStripRenderMode.Professional;
|
||||
this.MenuStrip.Size = new System.Drawing.Size(629, 26);
|
||||
this.MenuStrip.Size = new System.Drawing.Size(733, 26);
|
||||
this.MenuStrip.TabIndex = 0;
|
||||
//
|
||||
// ServerToolStripMenuItem
|
||||
@@ -170,11 +173,18 @@ namespace Netch.Forms
|
||||
this.AddVMessServerToolStripMenuItem.Text = "Add [VMess] Server";
|
||||
this.AddVMessServerToolStripMenuItem.Click += new System.EventHandler(this.AddVMessServerToolStripMenuItem_Click);
|
||||
//
|
||||
// AddTrojanServerToolStripMenuItem
|
||||
//
|
||||
this.AddTrojanServerToolStripMenuItem.Name = "AddTrojanServerToolStripMenuItem";
|
||||
this.AddTrojanServerToolStripMenuItem.Size = new System.Drawing.Size(259, 22);
|
||||
this.AddTrojanServerToolStripMenuItem.Text = "Add [Trojan] Server";
|
||||
this.AddTrojanServerToolStripMenuItem.Click += new System.EventHandler(this.AddTrojanServerToolStripMenuItem_Click);
|
||||
//
|
||||
// ModeToolStripMenuItem
|
||||
//
|
||||
this.ModeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.CreateProcessModeToolStripMenuItem,
|
||||
this.ManageProcessModeToolStripMenuItem});
|
||||
this.ReloadModesToolStripMenuItem});
|
||||
this.ModeToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
|
||||
this.ModeToolStripMenuItem.Name = "ModeToolStripMenuItem";
|
||||
this.ModeToolStripMenuItem.Size = new System.Drawing.Size(55, 21);
|
||||
@@ -183,16 +193,16 @@ namespace Netch.Forms
|
||||
// CreateProcessModeToolStripMenuItem
|
||||
//
|
||||
this.CreateProcessModeToolStripMenuItem.Name = "CreateProcessModeToolStripMenuItem";
|
||||
this.CreateProcessModeToolStripMenuItem.Size = new System.Drawing.Size(212, 22);
|
||||
this.CreateProcessModeToolStripMenuItem.Size = new System.Drawing.Size(202, 22);
|
||||
this.CreateProcessModeToolStripMenuItem.Text = "Create Process Mode";
|
||||
this.CreateProcessModeToolStripMenuItem.Click += new System.EventHandler(this.CreateProcessModeToolStripButton_Click);
|
||||
//
|
||||
// ManageProcessModeToolStripMenuItem
|
||||
// ReloadModesToolStripMenuItem
|
||||
//
|
||||
this.ManageProcessModeToolStripMenuItem.Name = "ManageProcessModeToolStripMenuItem";
|
||||
this.ManageProcessModeToolStripMenuItem.Size = new System.Drawing.Size(212, 22);
|
||||
this.ManageProcessModeToolStripMenuItem.Text = "Manage Process Mode";
|
||||
this.ManageProcessModeToolStripMenuItem.Click += new System.EventHandler(this.ManageProcessModeToolStripMenuItem_Click);
|
||||
this.ReloadModesToolStripMenuItem.Name = "ReloadModesToolStripMenuItem";
|
||||
this.ReloadModesToolStripMenuItem.Size = new System.Drawing.Size(202, 22);
|
||||
this.ReloadModesToolStripMenuItem.Text = "Reload Modes";
|
||||
this.ReloadModesToolStripMenuItem.Click += new System.EventHandler(this.ReloadModesToolStripMenuItem_Click);
|
||||
//
|
||||
// SubscribeToolStripMenuItem
|
||||
//
|
||||
@@ -221,64 +231,56 @@ namespace Netch.Forms
|
||||
// OptionsToolStripMenuItem
|
||||
//
|
||||
this.OptionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.ReloadModesToolStripMenuItem,
|
||||
this.RestartServiceToolStripMenuItem,
|
||||
this.UninstallServiceToolStripMenuItem,
|
||||
this.OpenDirectoryToolStripMenuItem,
|
||||
this.CleanDNSCacheToolStripMenuItem,
|
||||
this.UpdateACLToolStripMenuItem,
|
||||
this.updateACLWithProxyToolStripMenuItem,
|
||||
this.UninstallServiceToolStripMenuItem,
|
||||
this.reinstallTapDriverToolStripMenuItem});
|
||||
this.OptionsToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
|
||||
this.OptionsToolStripMenuItem.Name = "OptionsToolStripMenuItem";
|
||||
this.OptionsToolStripMenuItem.Size = new System.Drawing.Size(66, 21);
|
||||
this.OptionsToolStripMenuItem.Text = "Options";
|
||||
//
|
||||
// ReloadModesToolStripMenuItem
|
||||
// OpenDirectoryToolStripMenuItem
|
||||
//
|
||||
this.ReloadModesToolStripMenuItem.Name = "ReloadModesToolStripMenuItem";
|
||||
this.ReloadModesToolStripMenuItem.Size = new System.Drawing.Size(209, 22);
|
||||
this.ReloadModesToolStripMenuItem.Text = "Reload Modes";
|
||||
this.ReloadModesToolStripMenuItem.Click += new System.EventHandler(this.ReloadModesToolStripMenuItem_Click);
|
||||
//
|
||||
// RestartServiceToolStripMenuItem
|
||||
//
|
||||
this.RestartServiceToolStripMenuItem.Name = "RestartServiceToolStripMenuItem";
|
||||
this.RestartServiceToolStripMenuItem.Size = new System.Drawing.Size(209, 22);
|
||||
this.RestartServiceToolStripMenuItem.Text = "Restart Service";
|
||||
this.RestartServiceToolStripMenuItem.Click += new System.EventHandler(this.RestartServiceToolStripMenuItem_Click);
|
||||
//
|
||||
// UninstallServiceToolStripMenuItem
|
||||
//
|
||||
this.UninstallServiceToolStripMenuItem.Name = "UninstallServiceToolStripMenuItem";
|
||||
this.UninstallServiceToolStripMenuItem.Size = new System.Drawing.Size(209, 22);
|
||||
this.UninstallServiceToolStripMenuItem.Text = "Uninstall Service";
|
||||
this.UninstallServiceToolStripMenuItem.Click += new System.EventHandler(this.UninstallServiceToolStripMenuItem_Click);
|
||||
this.OpenDirectoryToolStripMenuItem.Name = "OpenDirectoryToolStripMenuItem";
|
||||
this.OpenDirectoryToolStripMenuItem.Size = new System.Drawing.Size(219, 22);
|
||||
this.OpenDirectoryToolStripMenuItem.Text = "Open Directory";
|
||||
this.OpenDirectoryToolStripMenuItem.Click += new System.EventHandler(this.OpenDirectoryToolStripMenuItem_Click);
|
||||
//
|
||||
// CleanDNSCacheToolStripMenuItem
|
||||
//
|
||||
this.CleanDNSCacheToolStripMenuItem.Name = "CleanDNSCacheToolStripMenuItem";
|
||||
this.CleanDNSCacheToolStripMenuItem.Size = new System.Drawing.Size(209, 22);
|
||||
this.CleanDNSCacheToolStripMenuItem.Size = new System.Drawing.Size(219, 22);
|
||||
this.CleanDNSCacheToolStripMenuItem.Text = "Clean DNS Cache";
|
||||
this.CleanDNSCacheToolStripMenuItem.Click += new System.EventHandler(this.CleanDNSCacheToolStripMenuItem_Click);
|
||||
//
|
||||
// UpdateACLToolStripMenuItem
|
||||
//
|
||||
this.UpdateACLToolStripMenuItem.Name = "UpdateACLToolStripMenuItem";
|
||||
this.UpdateACLToolStripMenuItem.Size = new System.Drawing.Size(209, 22);
|
||||
this.UpdateACLToolStripMenuItem.Size = new System.Drawing.Size(219, 22);
|
||||
this.UpdateACLToolStripMenuItem.Text = "Update ACL";
|
||||
this.UpdateACLToolStripMenuItem.Click += new System.EventHandler(this.updateACLToolStripMenuItem_Click);
|
||||
//
|
||||
// updateACLWithProxyToolStripMenuItem
|
||||
//
|
||||
this.updateACLWithProxyToolStripMenuItem.Name = "updateACLWithProxyToolStripMenuItem";
|
||||
this.updateACLWithProxyToolStripMenuItem.Size = new System.Drawing.Size(209, 22);
|
||||
this.updateACLWithProxyToolStripMenuItem.Size = new System.Drawing.Size(219, 22);
|
||||
this.updateACLWithProxyToolStripMenuItem.Text = "Update ACL with proxy";
|
||||
this.updateACLWithProxyToolStripMenuItem.Click += new System.EventHandler(this.updateACLWithProxyToolStripMenuItem_Click);
|
||||
//
|
||||
// UninstallServiceToolStripMenuItem
|
||||
//
|
||||
this.UninstallServiceToolStripMenuItem.Name = "UninstallServiceToolStripMenuItem";
|
||||
this.UninstallServiceToolStripMenuItem.Size = new System.Drawing.Size(219, 22);
|
||||
this.UninstallServiceToolStripMenuItem.Text = "Uninstall Service";
|
||||
this.UninstallServiceToolStripMenuItem.Click += new System.EventHandler(this.UninstallServiceToolStripMenuItem_Click);
|
||||
//
|
||||
// reinstallTapDriverToolStripMenuItem
|
||||
//
|
||||
this.reinstallTapDriverToolStripMenuItem.Name = "reinstallTapDriverToolStripMenuItem";
|
||||
this.reinstallTapDriverToolStripMenuItem.Size = new System.Drawing.Size(209, 22);
|
||||
this.reinstallTapDriverToolStripMenuItem.Size = new System.Drawing.Size(219, 22);
|
||||
this.reinstallTapDriverToolStripMenuItem.Text = "Reinstall TUN/TAP driver";
|
||||
this.reinstallTapDriverToolStripMenuItem.Click += new System.EventHandler(this.reinstallTapDriverToolStripMenuItem_Click);
|
||||
//
|
||||
@@ -300,8 +302,8 @@ namespace Netch.Forms
|
||||
this.VersionLabel.IsLink = true;
|
||||
this.VersionLabel.LinkBehavior = System.Windows.Forms.LinkBehavior.NeverUnderline;
|
||||
this.VersionLabel.Name = "VersionLabel";
|
||||
this.VersionLabel.Size = new System.Drawing.Size(32, 19);
|
||||
this.VersionLabel.Text = "x.x.x";
|
||||
this.VersionLabel.Size = new System.Drawing.Size(26, 19);
|
||||
this.VersionLabel.Text = "xxx";
|
||||
this.VersionLabel.Click += new System.EventHandler(this.VersionLabel_Click);
|
||||
//
|
||||
// exitToolStripMenuItem
|
||||
@@ -311,12 +313,21 @@ namespace Netch.Forms
|
||||
this.exitToolStripMenuItem.Text = "Exit";
|
||||
this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click);
|
||||
//
|
||||
// RelyToolStripMenuItem
|
||||
//
|
||||
this.RelyToolStripMenuItem.BackColor = System.Drawing.SystemColors.Control;
|
||||
this.RelyToolStripMenuItem.ForeColor = System.Drawing.Color.Red;
|
||||
this.RelyToolStripMenuItem.Name = "RelyToolStripMenuItem";
|
||||
this.RelyToolStripMenuItem.Size = new System.Drawing.Size(244, 22);
|
||||
this.RelyToolStripMenuItem.Text = "Unable to start? Click me to download";
|
||||
this.RelyToolStripMenuItem.Click += new System.EventHandler(this.RelyToolStripMenuItem_Click);
|
||||
//
|
||||
// ConfigurationGroupBox
|
||||
//
|
||||
this.ConfigurationGroupBox.Controls.Add(this.configLayoutPanel);
|
||||
this.ConfigurationGroupBox.Location = new System.Drawing.Point(12, 28);
|
||||
this.ConfigurationGroupBox.Name = "ConfigurationGroupBox";
|
||||
this.ConfigurationGroupBox.Size = new System.Drawing.Size(605, 115);
|
||||
this.ConfigurationGroupBox.Size = new System.Drawing.Size(709, 115);
|
||||
this.ConfigurationGroupBox.TabIndex = 1;
|
||||
this.ConfigurationGroupBox.TabStop = false;
|
||||
this.ConfigurationGroupBox.Text = "Configuration";
|
||||
@@ -325,7 +336,7 @@ namespace Netch.Forms
|
||||
//
|
||||
this.configLayoutPanel.ColumnCount = 3;
|
||||
this.configLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.configLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.configLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.configLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.configLayoutPanel.Controls.Add(this.ProfileLabel, 0, 2);
|
||||
this.configLayoutPanel.Controls.Add(this.ModeLabel, 0, 1);
|
||||
@@ -342,7 +353,7 @@ namespace Netch.Forms
|
||||
this.configLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
|
||||
this.configLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
|
||||
this.configLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
|
||||
this.configLayoutPanel.Size = new System.Drawing.Size(599, 93);
|
||||
this.configLayoutPanel.Size = new System.Drawing.Size(703, 93);
|
||||
this.configLayoutPanel.TabIndex = 15;
|
||||
//
|
||||
// ProfileLabel
|
||||
@@ -380,7 +391,7 @@ namespace Netch.Forms
|
||||
this.ProfileNameText.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.ProfileNameText.Location = new System.Drawing.Point(54, 65);
|
||||
this.ProfileNameText.Name = "ProfileNameText";
|
||||
this.ProfileNameText.Size = new System.Drawing.Size(442, 23);
|
||||
this.ProfileNameText.Size = new System.Drawing.Size(546, 23);
|
||||
this.ProfileNameText.TabIndex = 11;
|
||||
//
|
||||
// ModeComboBox
|
||||
@@ -392,7 +403,7 @@ namespace Netch.Forms
|
||||
this.ModeComboBox.IntegralHeight = false;
|
||||
this.ModeComboBox.Location = new System.Drawing.Point(54, 34);
|
||||
this.ModeComboBox.Name = "ModeComboBox";
|
||||
this.ModeComboBox.Size = new System.Drawing.Size(442, 24);
|
||||
this.ModeComboBox.Size = new System.Drawing.Size(546, 24);
|
||||
this.ModeComboBox.TabIndex = 2;
|
||||
this.ModeComboBox.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.ComboBox_DrawItem);
|
||||
//
|
||||
@@ -406,7 +417,7 @@ namespace Netch.Forms
|
||||
this.ServerComboBox.Location = new System.Drawing.Point(54, 3);
|
||||
this.ServerComboBox.MaxDropDownItems = 16;
|
||||
this.ServerComboBox.Name = "ServerComboBox";
|
||||
this.ServerComboBox.Size = new System.Drawing.Size(442, 24);
|
||||
this.ServerComboBox.Size = new System.Drawing.Size(546, 24);
|
||||
this.ServerComboBox.TabIndex = 1;
|
||||
this.ServerComboBox.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.ComboBox_DrawItem);
|
||||
//
|
||||
@@ -417,27 +428,28 @@ namespace Netch.Forms
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F));
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F));
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F));
|
||||
this.tableLayoutPanel2.Controls.Add(this.EditPictureBox, 0, 0);
|
||||
this.tableLayoutPanel2.Controls.Add(this.EditServerPictureBox, 0, 0);
|
||||
this.tableLayoutPanel2.Controls.Add(this.CopyLinkPictureBox, 3, 0);
|
||||
this.tableLayoutPanel2.Controls.Add(this.DeletePictureBox, 1, 0);
|
||||
this.tableLayoutPanel2.Controls.Add(this.DeleteServerPictureBox, 1, 0);
|
||||
this.tableLayoutPanel2.Controls.Add(this.SpeedPictureBox, 2, 0);
|
||||
this.tableLayoutPanel2.Location = new System.Drawing.Point(502, 3);
|
||||
this.tableLayoutPanel2.Location = new System.Drawing.Point(606, 3);
|
||||
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
|
||||
this.tableLayoutPanel2.RowCount = 1;
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel2.Size = new System.Drawing.Size(94, 24);
|
||||
this.tableLayoutPanel2.TabIndex = 12;
|
||||
//
|
||||
// EditPictureBox
|
||||
// EditServerPictureBox
|
||||
//
|
||||
this.EditPictureBox.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.EditPictureBox.Image = ((System.Drawing.Image)(resources.GetObject("EditPictureBox.Image")));
|
||||
this.EditPictureBox.Location = new System.Drawing.Point(3, 3);
|
||||
this.EditPictureBox.Name = "EditPictureBox";
|
||||
this.EditPictureBox.Size = new System.Drawing.Size(16, 16);
|
||||
this.EditPictureBox.TabIndex = 7;
|
||||
this.EditPictureBox.TabStop = false;
|
||||
this.EditPictureBox.Click += new System.EventHandler(this.EditPictureBox_Click);
|
||||
this.EditServerPictureBox.BackColor = System.Drawing.SystemColors.Control;
|
||||
this.EditServerPictureBox.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.EditServerPictureBox.Image = global::Netch.Properties.Resources.edit;
|
||||
this.EditServerPictureBox.Location = new System.Drawing.Point(3, 3);
|
||||
this.EditServerPictureBox.Name = "EditServerPictureBox";
|
||||
this.EditServerPictureBox.Size = new System.Drawing.Size(16, 16);
|
||||
this.EditServerPictureBox.TabIndex = 7;
|
||||
this.EditServerPictureBox.TabStop = false;
|
||||
this.EditServerPictureBox.Click += new System.EventHandler(this.EditServerPictureBox_Click);
|
||||
//
|
||||
// CopyLinkPictureBox
|
||||
//
|
||||
@@ -450,21 +462,21 @@ namespace Netch.Forms
|
||||
this.CopyLinkPictureBox.TabStop = false;
|
||||
this.CopyLinkPictureBox.Click += new System.EventHandler(this.CopyLinkPictureBox_Click);
|
||||
//
|
||||
// DeletePictureBox
|
||||
// DeleteServerPictureBox
|
||||
//
|
||||
this.DeletePictureBox.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.DeletePictureBox.Image = ((System.Drawing.Image)(resources.GetObject("DeletePictureBox.Image")));
|
||||
this.DeletePictureBox.Location = new System.Drawing.Point(26, 3);
|
||||
this.DeletePictureBox.Name = "DeletePictureBox";
|
||||
this.DeletePictureBox.Size = new System.Drawing.Size(16, 16);
|
||||
this.DeletePictureBox.TabIndex = 8;
|
||||
this.DeletePictureBox.TabStop = false;
|
||||
this.DeletePictureBox.Click += new System.EventHandler(this.DeletePictureBox_Click);
|
||||
this.DeleteServerPictureBox.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.DeleteServerPictureBox.Image = global::Netch.Properties.Resources.delete;
|
||||
this.DeleteServerPictureBox.Location = new System.Drawing.Point(26, 3);
|
||||
this.DeleteServerPictureBox.Name = "DeleteServerPictureBox";
|
||||
this.DeleteServerPictureBox.Size = new System.Drawing.Size(16, 16);
|
||||
this.DeleteServerPictureBox.TabIndex = 8;
|
||||
this.DeleteServerPictureBox.TabStop = false;
|
||||
this.DeleteServerPictureBox.Click += new System.EventHandler(this.DeleteServerPictureBox_Click);
|
||||
//
|
||||
// SpeedPictureBox
|
||||
//
|
||||
this.SpeedPictureBox.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.SpeedPictureBox.Image = ((System.Drawing.Image)(resources.GetObject("SpeedPictureBox.Image")));
|
||||
this.SpeedPictureBox.Image = global::Netch.Properties.Resources.speed;
|
||||
this.SpeedPictureBox.Location = new System.Drawing.Point(49, 3);
|
||||
this.SpeedPictureBox.Name = "SpeedPictureBox";
|
||||
this.SpeedPictureBox.Size = new System.Drawing.Size(16, 16);
|
||||
@@ -481,7 +493,7 @@ namespace Netch.Forms
|
||||
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F));
|
||||
this.tableLayoutPanel3.Controls.Add(this.EditModePictureBox, 0, 0);
|
||||
this.tableLayoutPanel3.Controls.Add(this.DeleteModePictureBox, 1, 0);
|
||||
this.tableLayoutPanel3.Location = new System.Drawing.Point(502, 34);
|
||||
this.tableLayoutPanel3.Location = new System.Drawing.Point(606, 34);
|
||||
this.tableLayoutPanel3.Name = "tableLayoutPanel3";
|
||||
this.tableLayoutPanel3.RowCount = 1;
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
@@ -491,9 +503,7 @@ namespace Netch.Forms
|
||||
// EditModePictureBox
|
||||
//
|
||||
this.EditModePictureBox.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.EditModePictureBox.ErrorImage = global::Netch.Properties.Resources.edit;
|
||||
this.EditModePictureBox.Image = global::Netch.Properties.Resources.edit;
|
||||
this.EditModePictureBox.InitialImage = global::Netch.Properties.Resources.edit;
|
||||
this.EditModePictureBox.Location = new System.Drawing.Point(3, 3);
|
||||
this.EditModePictureBox.Name = "EditModePictureBox";
|
||||
this.EditModePictureBox.Size = new System.Drawing.Size(16, 16);
|
||||
@@ -520,10 +530,12 @@ namespace Netch.Forms
|
||||
this.UsedBandwidthLabel,
|
||||
this.DownloadSpeedLabel,
|
||||
this.UploadSpeedLabel,
|
||||
this.NatTypeStatusLabel});
|
||||
this.blankToolStripStatusLabel,
|
||||
this.NatTypeStatusLabel,
|
||||
this.NatTypeStatusLightLabel});
|
||||
this.StatusStrip.Location = new System.Drawing.Point(0, 250);
|
||||
this.StatusStrip.Name = "StatusStrip";
|
||||
this.StatusStrip.Size = new System.Drawing.Size(629, 22);
|
||||
this.StatusStrip.Size = new System.Drawing.Size(733, 22);
|
||||
this.StatusStrip.SizingGrip = false;
|
||||
this.StatusStrip.TabIndex = 2;
|
||||
//
|
||||
@@ -555,15 +567,34 @@ namespace Netch.Forms
|
||||
this.UploadSpeedLabel.Text = "↑: 0 KB/s";
|
||||
this.UploadSpeedLabel.Visible = false;
|
||||
//
|
||||
// blankToolStripStatusLabel
|
||||
//
|
||||
this.blankToolStripStatusLabel.Name = "blankToolStripStatusLabel";
|
||||
this.blankToolStripStatusLabel.Size = new System.Drawing.Size(268, 17);
|
||||
this.blankToolStripStatusLabel.Spring = true;
|
||||
//
|
||||
// NatTypeStatusLabel
|
||||
//
|
||||
this.NatTypeStatusLabel.Name = "NatTypeStatusLabel";
|
||||
this.NatTypeStatusLabel.Size = new System.Drawing.Size(0, 17);
|
||||
this.NatTypeStatusLabel.Size = new System.Drawing.Size(36, 17);
|
||||
this.NatTypeStatusLabel.Text = "NAT:";
|
||||
this.NatTypeStatusLabel.TextAlign = System.Drawing.ContentAlignment.BottomLeft;
|
||||
//
|
||||
// NatTypeStatusLightLabel
|
||||
//
|
||||
this.NatTypeStatusLightLabel.ActiveLinkColor = System.Drawing.Color.Red;
|
||||
this.NatTypeStatusLightLabel.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||
this.NatTypeStatusLightLabel.ForeColor = System.Drawing.Color.Red;
|
||||
this.NatTypeStatusLightLabel.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
|
||||
this.NatTypeStatusLightLabel.Name = "NatTypeStatusLightLabel";
|
||||
this.NatTypeStatusLightLabel.Size = new System.Drawing.Size(18, 21);
|
||||
this.NatTypeStatusLightLabel.Text = "⬤";
|
||||
this.NatTypeStatusLightLabel.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
|
||||
//
|
||||
// ControlButton
|
||||
//
|
||||
this.ControlButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.ControlButton.Location = new System.Drawing.Point(542, 215);
|
||||
this.ControlButton.Location = new System.Drawing.Point(646, 214);
|
||||
this.ControlButton.Name = "ControlButton";
|
||||
this.ControlButton.Size = new System.Drawing.Size(75, 27);
|
||||
this.ControlButton.TabIndex = 3;
|
||||
@@ -619,7 +650,7 @@ namespace Netch.Forms
|
||||
this.ProfileGroupBox.Controls.Add(this.ProfileTable);
|
||||
this.ProfileGroupBox.Location = new System.Drawing.Point(12, 146);
|
||||
this.ProfileGroupBox.Name = "ProfileGroupBox";
|
||||
this.ProfileGroupBox.Size = new System.Drawing.Size(605, 65);
|
||||
this.ProfileGroupBox.Size = new System.Drawing.Size(709, 65);
|
||||
this.ProfileGroupBox.TabIndex = 13;
|
||||
this.ProfileGroupBox.TabStop = false;
|
||||
this.ProfileGroupBox.Text = "Profiles";
|
||||
@@ -637,21 +668,14 @@ namespace Netch.Forms
|
||||
this.ProfileTable.RowCount = 1;
|
||||
this.ProfileTable.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.ProfileTable.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.ProfileTable.Size = new System.Drawing.Size(599, 43);
|
||||
this.ProfileTable.Size = new System.Drawing.Size(703, 43);
|
||||
this.ProfileTable.TabIndex = 0;
|
||||
//
|
||||
// AddTrojanServerToolStripMenuItem
|
||||
//
|
||||
this.AddTrojanServerToolStripMenuItem.Name = "AddTrojanServerToolStripMenuItem";
|
||||
this.AddTrojanServerToolStripMenuItem.Size = new System.Drawing.Size(259, 22);
|
||||
this.AddTrojanServerToolStripMenuItem.Text = "Add [Trojan] Server";
|
||||
this.AddTrojanServerToolStripMenuItem.Click += new System.EventHandler(this.AddTrojanServerToolStripMenuItem_Click);
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
|
||||
this.ClientSize = new System.Drawing.Size(629, 272);
|
||||
this.ClientSize = new System.Drawing.Size(733, 272);
|
||||
this.Controls.Add(this.ProfileGroupBox);
|
||||
this.Controls.Add(this.SettingsButton);
|
||||
this.Controls.Add(this.ControlButton);
|
||||
@@ -668,15 +692,16 @@ namespace Netch.Forms
|
||||
this.Text = "Netch";
|
||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing);
|
||||
this.Load += new System.EventHandler(this.MainForm_Load);
|
||||
this.VisibleChanged += new System.EventHandler(this.MainForm_VisibleChanged);
|
||||
this.MenuStrip.ResumeLayout(false);
|
||||
this.MenuStrip.PerformLayout();
|
||||
this.ConfigurationGroupBox.ResumeLayout(false);
|
||||
this.configLayoutPanel.ResumeLayout(false);
|
||||
this.configLayoutPanel.PerformLayout();
|
||||
this.tableLayoutPanel2.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.EditPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.EditServerPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.CopyLinkPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.DeletePictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.DeleteServerPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.SpeedPictureBox)).EndInit();
|
||||
this.tableLayoutPanel3.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.EditModePictureBox)).EndInit();
|
||||
@@ -691,62 +716,65 @@ namespace Netch.Forms
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.MenuStrip MenuStrip;
|
||||
private System.Windows.Forms.ToolStripMenuItem ServerToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem SubscribeToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripLabel VersionLabel;
|
||||
private System.Windows.Forms.GroupBox ConfigurationGroupBox;
|
||||
private System.Windows.Forms.Label ServerLabel;
|
||||
private System.Windows.Forms.Label ModeLabel;
|
||||
private System.Windows.Forms.SearchComboBox ModeComboBox;
|
||||
private System.Windows.Forms.ComboBox ServerComboBox;
|
||||
private System.Windows.Forms.StatusStrip StatusStrip;
|
||||
private System.Windows.Forms.ToolStripStatusLabel StatusLabel;
|
||||
private System.Windows.Forms.Button ControlButton;
|
||||
private System.Windows.Forms.ToolStripMenuItem AddSocks5ServerToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem AddShadowsocksServerToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripButton AboutToolStripButton;
|
||||
private System.Windows.Forms.ToolStripMenuItem AddShadowsocksRServerToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem AddShadowsocksServerToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem AddSocks5ServerToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem AddTrojanServerToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem AddVMessServerToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem CleanDNSCacheToolStripMenuItem;
|
||||
private System.Windows.Forms.TableLayoutPanel configLayoutPanel;
|
||||
private System.Windows.Forms.GroupBox ConfigurationGroupBox;
|
||||
private System.Windows.Forms.Button ControlButton;
|
||||
private System.Windows.Forms.PictureBox CopyLinkPictureBox;
|
||||
private System.Windows.Forms.ToolStripMenuItem CreateProcessModeToolStripMenuItem;
|
||||
private System.Windows.Forms.PictureBox DeleteModePictureBox;
|
||||
private System.Windows.Forms.PictureBox DeleteServerPictureBox;
|
||||
private System.Windows.Forms.ToolStripStatusLabel DownloadSpeedLabel;
|
||||
private System.Windows.Forms.PictureBox EditModePictureBox;
|
||||
private System.Windows.Forms.PictureBox EditServerPictureBox;
|
||||
private System.Windows.Forms.ToolStripMenuItem ExitToolStripButton;
|
||||
private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem ImportServersFromClipboardToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem ManageSubscribeLinksToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem UpdateServersFromSubscribeLinksToolStripMenuItem;
|
||||
private System.Windows.Forms.PictureBox SpeedPictureBox;
|
||||
private System.Windows.Forms.PictureBox DeletePictureBox;
|
||||
private System.Windows.Forms.PictureBox EditPictureBox;
|
||||
private System.Windows.Forms.ToolStripMenuItem RestartServiceToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem UninstallServiceToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem OptionsToolStripMenuItem;
|
||||
private System.Windows.Forms.MenuStrip MenuStrip;
|
||||
private System.Windows.Forms.SearchComboBox ModeComboBox;
|
||||
private System.Windows.Forms.Label ModeLabel;
|
||||
private System.Windows.Forms.ToolStripMenuItem ModeToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem CreateProcessModeToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem ReloadModesToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripStatusLabel NatTypeStatusLabel;
|
||||
private System.Windows.Forms.NotifyIcon NotifyIcon;
|
||||
private System.Windows.Forms.ContextMenuStrip NotifyMenu;
|
||||
private System.Windows.Forms.ToolStripMenuItem ShowMainFormToolStripButton;
|
||||
private System.Windows.Forms.ToolStripMenuItem ExitToolStripButton;
|
||||
private System.Windows.Forms.Button SettingsButton;
|
||||
private System.Windows.Forms.ToolStripButton AboutToolStripButton;
|
||||
private System.Windows.Forms.ToolStripStatusLabel UsedBandwidthLabel;
|
||||
private System.Windows.Forms.ToolStripStatusLabel UploadSpeedLabel;
|
||||
private System.Windows.Forms.ToolStripStatusLabel DownloadSpeedLabel;
|
||||
private System.Windows.Forms.ToolStripMenuItem CleanDNSCacheToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem OpenDirectoryToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem OptionsToolStripMenuItem;
|
||||
private System.Windows.Forms.GroupBox ProfileGroupBox;
|
||||
private System.Windows.Forms.Label ProfileLabel;
|
||||
private System.Windows.Forms.TextBox ProfileNameText;
|
||||
private System.Windows.Forms.GroupBox ProfileGroupBox;
|
||||
private System.Windows.Forms.TableLayoutPanel ProfileTable;
|
||||
private System.Windows.Forms.ToolStripMenuItem ManageProcessModeToolStripMenuItem;
|
||||
private System.Windows.Forms.PictureBox EditModePictureBox;
|
||||
private System.Windows.Forms.PictureBox DeleteModePictureBox;
|
||||
private System.Windows.Forms.PictureBox CopyLinkPictureBox;
|
||||
private System.Windows.Forms.ToolStripStatusLabel NatTypeStatusLabel;
|
||||
private System.Windows.Forms.TableLayoutPanel configLayoutPanel;
|
||||
private System.Windows.Forms.ToolStripMenuItem reinstallTapDriverToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem ReloadModesToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem RelyToolStripMenuItem;
|
||||
private System.Windows.Forms.ComboBox ServerComboBox;
|
||||
private System.Windows.Forms.Label ServerLabel;
|
||||
private System.Windows.Forms.ToolStripMenuItem ServerToolStripMenuItem;
|
||||
private System.Windows.Forms.Button SettingsButton;
|
||||
private System.Windows.Forms.ToolStripMenuItem ShowMainFormToolStripButton;
|
||||
private System.Windows.Forms.PictureBox SpeedPictureBox;
|
||||
private System.Windows.Forms.ToolStripStatusLabel StatusLabel;
|
||||
private System.Windows.Forms.StatusStrip StatusStrip;
|
||||
private System.Windows.Forms.ToolStripMenuItem SubscribeToolStripMenuItem;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
|
||||
private System.Windows.Forms.ToolStripMenuItem UninstallServiceToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem UpdateACLToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem updateACLWithProxyToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem reinstallTapDriverToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem AddTrojanServerToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem UpdateServersFromSubscribeLinksToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripStatusLabel UploadSpeedLabel;
|
||||
private System.Windows.Forms.ToolStripStatusLabel UsedBandwidthLabel;
|
||||
private System.Windows.Forms.ToolStripLabel VersionLabel;
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.ToolStripStatusLabel NatTypeStatusLightLabel;
|
||||
private System.Windows.Forms.ToolStripStatusLabel blankToolStripStatusLabel;
|
||||
}
|
||||
}
|
||||
435
Netch/Forms/MainForm.MenuStrip.cs
Normal file
435
Netch/Forms/MainForm.MenuStrip.cs
Normal file
@@ -0,0 +1,435 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.ServiceProcess;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Controllers;
|
||||
using Netch.Forms.Mode;
|
||||
using Netch.Forms.Server;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
using nfapinet;
|
||||
using Trojan = Netch.Forms.Server.Trojan;
|
||||
using VMess = Netch.Forms.Server.VMess;
|
||||
using WebClient = Netch.Override.WebClient;
|
||||
|
||||
namespace Netch.Forms
|
||||
{
|
||||
partial class Dummy
|
||||
{
|
||||
}
|
||||
|
||||
partial class MainForm
|
||||
{
|
||||
#region MenuStrip
|
||||
|
||||
#region 服务器
|
||||
|
||||
private void ImportServersFromClipboardToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var texts = Clipboard.GetText();
|
||||
if (!string.IsNullOrWhiteSpace(texts))
|
||||
{
|
||||
var result = ShareLink.Parse(texts);
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
Global.Settings.Server.AddRange(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Import servers error!"), info: false);
|
||||
}
|
||||
|
||||
InitServer();
|
||||
Configuration.Save();
|
||||
}
|
||||
}
|
||||
|
||||
private void AddSocks5ServerToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
new Socks5().Show();
|
||||
Hide();
|
||||
}
|
||||
|
||||
private void AddShadowsocksServerToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
new Shadowsocks().Show();
|
||||
Hide();
|
||||
}
|
||||
|
||||
private void AddShadowsocksRServerToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
new ShadowsocksR().Show();
|
||||
Hide();
|
||||
}
|
||||
|
||||
private void AddVMessServerToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
new VMess().Show();
|
||||
Hide();
|
||||
}
|
||||
|
||||
private void AddTrojanServerToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
new Trojan().Show();
|
||||
Hide();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 模式
|
||||
|
||||
private void CreateProcessModeToolStripButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
new Process().Show();
|
||||
Hide();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 订阅
|
||||
|
||||
private void ManageSubscribeLinksToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
new SubscribeForm().Show();
|
||||
Hide();
|
||||
}
|
||||
|
||||
private void UpdateServersFromSubscribeLinksToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var bak_State = State;
|
||||
var bak_StateText = StatusLabel.Text;
|
||||
|
||||
if (Global.Settings.UseProxyToUpdateSubscription && ServerComboBox.SelectedIndex == -1)
|
||||
Global.Settings.UseProxyToUpdateSubscription = false;
|
||||
|
||||
if (Global.Settings.UseProxyToUpdateSubscription)
|
||||
{
|
||||
// 当前 ServerComboBox 中至少有一项
|
||||
if (ServerComboBox.SelectedIndex == -1)
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Please select a server first"));
|
||||
return;
|
||||
}
|
||||
|
||||
MenuStrip.Enabled = ConfigurationGroupBox.Enabled = ControlButton.Enabled = SettingsButton.Enabled = false;
|
||||
ControlButton.Text = "...";
|
||||
}
|
||||
|
||||
if (Global.Settings.SubscribeLink.Count > 0)
|
||||
{
|
||||
StatusText(i18N.Translate("Starting update subscription"));
|
||||
DeleteServerPictureBox.Enabled = false;
|
||||
|
||||
UpdateServersFromSubscribeLinksToolStripMenuItem.Enabled = false;
|
||||
Task.Run(() =>
|
||||
{
|
||||
if (Global.Settings.UseProxyToUpdateSubscription)
|
||||
{
|
||||
var mode = new Models.Mode
|
||||
{
|
||||
Remark = "ProxyUpdate",
|
||||
Type = 5
|
||||
};
|
||||
_mainController = new MainController();
|
||||
_mainController.Start(ServerComboBox.SelectedItem as Models.Server, mode);
|
||||
}
|
||||
|
||||
foreach (var item in Global.Settings.SubscribeLink)
|
||||
{
|
||||
using var client = new WebClient();
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(item.UserAgent))
|
||||
{
|
||||
client.Headers.Add("User-Agent", item.UserAgent);
|
||||
}
|
||||
else
|
||||
{
|
||||
client.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36");
|
||||
}
|
||||
|
||||
if (Global.Settings.UseProxyToUpdateSubscription)
|
||||
{
|
||||
client.Proxy = new WebProxy($"http://127.0.0.1:{Global.Settings.HTTPLocalPort}");
|
||||
}
|
||||
|
||||
var response = client.DownloadString(item.Link);
|
||||
|
||||
try
|
||||
{
|
||||
response = ShareLink.URLSafeBase64Decode(response);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
Global.Settings.Server = Global.Settings.Server.Where(server => server.Group != item.Remark).ToList();
|
||||
var result = ShareLink.Parse(response);
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
foreach (var x in result)
|
||||
{
|
||||
x.Group = item.Remark;
|
||||
}
|
||||
|
||||
Global.Settings.Server.AddRange(result);
|
||||
NotifyIcon.ShowBalloonTip(5,
|
||||
UpdateChecker.Name,
|
||||
string.Format(i18N.Translate("Update {1} server(s) from {0}"), item.Remark, result.Count),
|
||||
ToolTipIcon.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
NotifyIcon.ShowBalloonTip(5,
|
||||
UpdateChecker.Name,
|
||||
string.Format(i18N.Translate("Update servers error from {0}"), item.Remark),
|
||||
ToolTipIcon.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
InitServer();
|
||||
DeleteServerPictureBox.Enabled = true;
|
||||
if (Global.Settings.UseProxyToUpdateSubscription)
|
||||
{
|
||||
MenuStrip.Enabled = ConfigurationGroupBox.Enabled = ControlButton.Enabled = SettingsButton.Enabled = true;
|
||||
ControlButton.Text = i18N.Translate("Start");
|
||||
_mainController.Stop();
|
||||
NatTypeStatusLabel.Text = "";
|
||||
}
|
||||
|
||||
Configuration.Save();
|
||||
StatusText(i18N.Translate("Subscription updated"));
|
||||
|
||||
MenuStrip.Enabled = ConfigurationGroupBox.Enabled = ControlButton.Enabled = SettingsButton.Enabled = true;
|
||||
UpdateStatus(bak_State);
|
||||
StatusLabel.Text = bak_StateText;
|
||||
}).ContinueWith(task => { BeginInvoke(new Action(() => { UpdateServersFromSubscribeLinksToolStripMenuItem.Enabled = true; })); });
|
||||
|
||||
NotifyIcon.ShowBalloonTip(5,
|
||||
UpdateChecker.Name,
|
||||
i18N.Translate("Updating in the background"),
|
||||
ToolTipIcon.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("No subscription link"));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 选项
|
||||
|
||||
private void UninstallServiceToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Enabled = false;
|
||||
StatusText(i18N.Translate("Uninstalling Service"));
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (NFController.UninstallDriver())
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Service has been uninstalled"), owner: this);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MessageBoxX.Show(e.ToString(),info:false);
|
||||
Console.WriteLine(e);
|
||||
throw;
|
||||
}
|
||||
|
||||
StatusText(i18N.Translate(StateExtension.GetStatusString(State.Waiting)));
|
||||
Enabled = true;
|
||||
});
|
||||
}
|
||||
|
||||
private void ReloadModesToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Enabled = false;
|
||||
SaveConfigs();
|
||||
Task.Run(() =>
|
||||
{
|
||||
InitMode();
|
||||
|
||||
MessageBoxX.Show(i18N.Translate("Modes have been reload"), owner: this);
|
||||
Enabled = true;
|
||||
});
|
||||
}
|
||||
|
||||
private void CleanDNSCacheToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var bak_State = State;
|
||||
var bak_StateText = StatusLabel.Text;
|
||||
|
||||
try
|
||||
{
|
||||
Enabled = false;
|
||||
DNS.Cache.Clear();
|
||||
|
||||
MessageBoxX.Show(i18N.Translate("DNS cache cleanup succeeded"), owner: this);
|
||||
StatusText(i18N.Translate("DNS cache cleanup succeeded"));
|
||||
Enabled = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
UpdateStatus(bak_State);
|
||||
StatusLabel.Text = bak_StateText;
|
||||
}
|
||||
}
|
||||
|
||||
private void OpenDirectoryToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Utils.Utils.OpenDir(@".\");
|
||||
}
|
||||
|
||||
private void reinstallTapDriverToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
StatusText(i18N.Translate("Reinstalling TUN/TAP driver"));
|
||||
Enabled = false;
|
||||
try
|
||||
{
|
||||
Configuration.deltapall();
|
||||
Configuration.addtap();
|
||||
NotifyIcon.ShowBalloonTip(5,
|
||||
UpdateChecker.Name, i18N.Translate("Reinstall TUN/TAP driver successfully"),
|
||||
ToolTipIcon.Info);
|
||||
}
|
||||
catch
|
||||
{
|
||||
NotifyIcon.ShowBalloonTip(5,
|
||||
UpdateChecker.Name, i18N.Translate("Reinstall TUN/TAP driver failed"),
|
||||
ToolTipIcon.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
UpdateStatus(State.Waiting);
|
||||
Enabled = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateACLWithProxyToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
updateACLWithProxyToolStripMenuItem.Enabled = false;
|
||||
|
||||
// 当前 ServerComboBox 中至少有一项
|
||||
if (ServerComboBox.SelectedIndex == -1)
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Please select a server first"));
|
||||
return;
|
||||
}
|
||||
|
||||
MenuStrip.Enabled = ConfigurationGroupBox.Enabled = ControlButton.Enabled = SettingsButton.Enabled = false;
|
||||
ControlButton.Text = "...";
|
||||
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
var mode = new Models.Mode
|
||||
{
|
||||
Remark = "ProxyUpdate",
|
||||
Type = 5
|
||||
};
|
||||
_mainController = new MainController();
|
||||
_mainController.Start(ServerComboBox.SelectedItem as Models.Server, mode);
|
||||
|
||||
using var client = new WebClient();
|
||||
|
||||
client.Proxy = new WebProxy($"http://127.0.0.1:{Global.Settings.HTTPLocalPort}");
|
||||
|
||||
StatusText(i18N.Translate("Updating in the background"));
|
||||
try
|
||||
{
|
||||
client.DownloadFile(Global.Settings.ACL, "bin\\default.acl");
|
||||
NotifyIcon.ShowBalloonTip(5,
|
||||
UpdateChecker.Name, i18N.Translate("ACL updated successfully"),
|
||||
ToolTipIcon.Info);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Error("使用代理更新 ACL 失败!" + e);
|
||||
MessageBoxX.Show(i18N.Translate("ACL update failed") + "\n" + e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
UpdateStatus(State.Waiting);
|
||||
_mainController.Stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Exit(true);
|
||||
}
|
||||
|
||||
private void RelyToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
System.Diagnostics.Process.Start("https://mega.nz/file/9OQ1EazJ#0pjJ3xt57AVLr29vYEEv15GSACtXVQOGlEOPpi_2Ico");
|
||||
}
|
||||
|
||||
private void VersionLabel_Click(object sender, EventArgs e)
|
||||
{
|
||||
System.Diagnostics.Process.Start($"https://github.com/{UpdateChecker.Owner}/{UpdateChecker.Repo}/releases");
|
||||
}
|
||||
|
||||
private void AboutToolStripButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
new AboutForm().Show();
|
||||
Hide();
|
||||
}
|
||||
|
||||
private void updateACLToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var bak_State = State;
|
||||
var bak_StateText = StatusLabel.Text;
|
||||
|
||||
StatusText(i18N.Translate("Starting update ACL"));
|
||||
using var client = new WebClient();
|
||||
|
||||
client.DownloadFileTaskAsync(Global.Settings.ACL, "bin\\default.acl");
|
||||
client.DownloadFileCompleted += ((sender, args) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (args.Error == null)
|
||||
{
|
||||
NotifyIcon.ShowBalloonTip(5,
|
||||
UpdateChecker.Name, i18N.Translate("ACL updated successfully"),
|
||||
ToolTipIcon.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Error("ACL 更新失败!" + args.Error);
|
||||
MessageBoxX.Show(i18N.Translate("ACL update failed") + "\n" + args.Error);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
UpdateStatus(bak_State);
|
||||
StatusLabel.Text = bak_StateText;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
32
Netch/Forms/MainForm.Misc.cs
Normal file
32
Netch/Forms/MainForm.Misc.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Controllers;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Forms
|
||||
{
|
||||
/// <summary lang="en">
|
||||
/// this class is used to disable Designer <para />
|
||||
/// </summary>
|
||||
/// <summary lang="zh">
|
||||
/// 此类用于禁用设计器
|
||||
/// </summary>
|
||||
[DesignerCategory("")] public partial class Dummy { }
|
||||
partial class MainForm
|
||||
{
|
||||
private void CheckUpdate()
|
||||
{
|
||||
var updater = new UpdateChecker();
|
||||
updater.NewVersionFound += (o, args) =>
|
||||
{
|
||||
NotifyIcon.ShowBalloonTip(5,
|
||||
UpdateChecker.Name,
|
||||
$"{i18N.Translate(@"New version available",": ")}{updater.LatestVersionNumber}",
|
||||
ToolTipIcon.Info);
|
||||
};
|
||||
updater.Check(false, false);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
211
Netch/Forms/MainForm.Profile.cs
Normal file
211
Netch/Forms/MainForm.Profile.cs
Normal file
@@ -0,0 +1,211 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Forms
|
||||
{
|
||||
public partial class Dummy { }
|
||||
partial class MainForm
|
||||
{
|
||||
/// init at <see cref="MainForm_Load"/>
|
||||
private int _sizeHeight;
|
||||
|
||||
private int _profileConfigurationHeight;
|
||||
private int _profileGroupboxHeight;
|
||||
private int _configurationGroupBoxHeight;
|
||||
|
||||
private void InitProfile()
|
||||
{
|
||||
// Clear
|
||||
foreach (var button in ProfileButtons)
|
||||
button.Dispose();
|
||||
|
||||
ProfileButtons.Clear();
|
||||
ProfileTable.ColumnStyles.Clear();
|
||||
ProfileTable.RowStyles.Clear();
|
||||
|
||||
var numProfile = Global.Settings.ProfileCount;
|
||||
if (numProfile == 0)
|
||||
{
|
||||
// Hide Profile GroupBox, Change window size
|
||||
configLayoutPanel.RowStyles[2].SizeType = SizeType.Percent;
|
||||
configLayoutPanel.RowStyles[2].Height = 0;
|
||||
ProfileGroupBox.Visible = false;
|
||||
|
||||
ConfigurationGroupBox.Size = new Size(ConfigurationGroupBox.Size.Width, _configurationGroupBoxHeight - _profileConfigurationHeight);
|
||||
Size = new Size(Size.Width, _sizeHeight - (_profileConfigurationHeight + _profileGroupboxHeight));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load Profiles
|
||||
ProfileTable.ColumnCount = numProfile;
|
||||
|
||||
while (Global.Settings.Profiles.Count < numProfile)
|
||||
{
|
||||
Global.Settings.Profiles.Add(new Profile());
|
||||
}
|
||||
|
||||
for (var i = 0; i < numProfile; ++i)
|
||||
{
|
||||
var b = new Button();
|
||||
b.Click += ProfileButton_Click;
|
||||
b.Dock = DockStyle.Fill;
|
||||
b.Text = !Global.Settings.Profiles[i].IsDummy ? Global.Settings.Profiles[i].ProfileName : i18N.Translate("None");
|
||||
|
||||
ProfileTable.Controls.Add(b, i, 0);
|
||||
ProfileButtons.Add(b);
|
||||
}
|
||||
|
||||
// equal column
|
||||
for (var i = 1; i <= ProfileTable.RowCount; i++)
|
||||
{
|
||||
ProfileTable.RowStyles.Add(new RowStyle(SizeType.Percent, 1));
|
||||
}
|
||||
|
||||
for (var i = 1; i <= ProfileTable.ColumnCount; i++)
|
||||
{
|
||||
ProfileTable.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 1));
|
||||
}
|
||||
|
||||
if (Size.Height == _sizeHeight) return;
|
||||
configLayoutPanel.RowStyles[2].SizeType = SizeType.AutoSize;
|
||||
ProfileGroupBox.Visible = true;
|
||||
ConfigurationGroupBox.Size = new Size(ConfigurationGroupBox.Size.Width, _configurationGroupBoxHeight);
|
||||
Size = new Size(Size.Width, _sizeHeight);
|
||||
}
|
||||
}
|
||||
|
||||
private string LoadProfile(int index)
|
||||
{
|
||||
var p = Global.Settings.Profiles[index];
|
||||
|
||||
if (p.IsDummy)
|
||||
throw new Exception("Profile not found.");
|
||||
|
||||
var result = false;
|
||||
|
||||
foreach (Models.Server server in ServerComboBox.Items)
|
||||
{
|
||||
if (server.Remark.Equals(p.ServerRemark))
|
||||
{
|
||||
ServerComboBox.SelectedItem = server;
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!result)
|
||||
throw new Exception("Server not found.");
|
||||
|
||||
result = false;
|
||||
foreach (Models.Mode mode in ModeComboBox.Items)
|
||||
{
|
||||
if (mode.Remark.Equals(p.ModeRemark))
|
||||
{
|
||||
ModeComboBox.SelectedItem = mode;
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!result)
|
||||
throw new Exception("Mode not found.");
|
||||
|
||||
return p.ProfileName;
|
||||
}
|
||||
|
||||
private void SaveProfile(int index)
|
||||
{
|
||||
var selectedServer = (Models.Server) ServerComboBox.SelectedItem;
|
||||
var selectedMode = (Models.Mode) ModeComboBox.SelectedItem;
|
||||
var name = ProfileNameText.Text;
|
||||
|
||||
Global.Settings.Profiles[index] = new Profile(selectedServer, selectedMode, name);
|
||||
}
|
||||
|
||||
private void RemoveProfile(int index)
|
||||
{
|
||||
Global.Settings.Profiles[index] = new Profile();
|
||||
}
|
||||
|
||||
|
||||
private List<Button> ProfileButtons = new List<Button>();
|
||||
|
||||
private void ProfileButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
var index = ProfileButtons.IndexOf((Button) sender);
|
||||
|
||||
if (ModifierKeys == Keys.Control)
|
||||
{
|
||||
if (ServerComboBox.SelectedIndex == -1)
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Please select a server first"));
|
||||
}
|
||||
else if (ModeComboBox.SelectedIndex == -1)
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Please select a mode first"));
|
||||
}
|
||||
else if (ProfileNameText.Text == "")
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Please enter a profile name first"));
|
||||
}
|
||||
else
|
||||
{
|
||||
SaveProfile(index);
|
||||
ProfileButtons[index].Text = ProfileNameText.Text;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (Global.Settings.Profiles[index].IsDummy)
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("No saved profile here. Save a profile first by Ctrl+Click on the button"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (ModifierKeys == Keys.Shift)
|
||||
{
|
||||
if (MessageBoxX.Show(i18N.Translate("Remove this Profile?"), confirm: true) != DialogResult.OK) return;
|
||||
RemoveProfile(index);
|
||||
ProfileButtons[index].Text = i18N.Translate("None");
|
||||
MessageBoxX.Show(i18N.Translate("Profile Removed!"));
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ProfileNameText.Text = LoadProfile(index);
|
||||
|
||||
// start the profile
|
||||
ControlFun();
|
||||
if (State == State.Stopping || State == State.Stopped)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
while (State != State.Stopped)
|
||||
{
|
||||
Thread.Sleep(250);
|
||||
}
|
||||
|
||||
ControlFun();
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception ee)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
Logging.Info(ee.ToString());
|
||||
ProfileButtons[index].Text = i18N.Translate("Error");
|
||||
Thread.Sleep(1200);
|
||||
ProfileButtons[index].Text = i18N.Translate("None");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
249
Netch/Forms/MainForm.Server_Mode.cs
Normal file
249
Netch/Forms/MainForm.Server_Mode.cs
Normal file
@@ -0,0 +1,249 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Forms
|
||||
{
|
||||
public partial class Dummy
|
||||
{
|
||||
}
|
||||
|
||||
partial class MainForm
|
||||
{
|
||||
#region Server
|
||||
|
||||
private static void TestServer()
|
||||
{
|
||||
try
|
||||
{
|
||||
Parallel.ForEach(Global.Settings.Server, new ParallelOptions {MaxDegreeOfParallelism = 16},
|
||||
server => { server.Test(); });
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
public void InitServer()
|
||||
{
|
||||
ServerComboBox.Items.Clear();
|
||||
ServerComboBox.Items.AddRange(Global.Settings.Server.ToArray());
|
||||
|
||||
// 如果值合法,选中该位置
|
||||
if (Global.Settings.ServerComboBoxSelectedIndex > 0 &&
|
||||
Global.Settings.ServerComboBoxSelectedIndex < ServerComboBox.Items.Count)
|
||||
{
|
||||
ServerComboBox.SelectedIndex = Global.Settings.ServerComboBoxSelectedIndex;
|
||||
}
|
||||
// 如果值非法,且当前 ServerComboBox 中有元素,选择第一个位置
|
||||
else if (ServerComboBox.Items.Count > 0)
|
||||
{
|
||||
ServerComboBox.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
// 如果当前 ServerComboBox 中没元素,不做处理
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mode
|
||||
|
||||
private void InitMode()
|
||||
{
|
||||
ModeComboBox.Items.Clear();
|
||||
Global.ModeFiles.Clear();
|
||||
|
||||
if (Directory.Exists("mode"))
|
||||
{
|
||||
foreach (var name in Directory.GetFiles("mode", "*.txt"))
|
||||
{
|
||||
var ok = true;
|
||||
var mode = new Models.Mode();
|
||||
|
||||
using (var sr = new StringReader(File.ReadAllText(name)))
|
||||
{
|
||||
var i = 0;
|
||||
string text;
|
||||
|
||||
while ((text = sr.ReadLine()) != null)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
var splited = text.Trim().Substring(1).Split(',');
|
||||
|
||||
if (splited.Length == 0)
|
||||
{
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (splited.Length >= 1)
|
||||
{
|
||||
mode.Remark = i18N.Translate(splited[0].Trim());
|
||||
}
|
||||
|
||||
if (splited.Length >= 2)
|
||||
{
|
||||
if (int.TryParse(splited[1], out var result))
|
||||
{
|
||||
mode.Type = result;
|
||||
}
|
||||
else
|
||||
{
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (splited.Length >= 3)
|
||||
{
|
||||
if (int.TryParse(splited[2], out var result))
|
||||
{
|
||||
mode.BypassChina = result == 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!text.StartsWith("#") && !string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
mode.Rule.Add(text.Trim());
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (ok)
|
||||
{
|
||||
mode.FileName = Path.GetFileNameWithoutExtension(name);
|
||||
Global.ModeFiles.Add(mode);
|
||||
}
|
||||
}
|
||||
|
||||
var array = Global.ModeFiles.ToArray();
|
||||
Array.Sort(array, (a, b) => string.Compare(a.Remark, b.Remark, StringComparison.Ordinal));
|
||||
|
||||
ModeComboBox.Items.AddRange(array);
|
||||
|
||||
SelectLastMode();
|
||||
}
|
||||
}
|
||||
|
||||
private void SelectLastMode()
|
||||
{
|
||||
// 如果值合法,选中该位置
|
||||
if (Global.Settings.ModeComboBoxSelectedIndex > 0 &&
|
||||
Global.Settings.ModeComboBoxSelectedIndex < ModeComboBox.Items.Count)
|
||||
{
|
||||
ModeComboBox.SelectedIndex = Global.Settings.ModeComboBoxSelectedIndex;
|
||||
}
|
||||
// 如果值非法,且当前 ModeComboBox 中有元素,选择第一个位置
|
||||
else if (ModeComboBox.Items.Count > 0)
|
||||
{
|
||||
ModeComboBox.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
// 如果当前 ModeComboBox 中没元素,不做处理
|
||||
}
|
||||
|
||||
public void AddMode(Models.Mode mode)
|
||||
{
|
||||
ModeComboBox.Items.Clear();
|
||||
Global.ModeFiles.Add(mode);
|
||||
var array = Global.ModeFiles.ToArray();
|
||||
Array.Sort(array, (a, b) => string.Compare(a.Remark, b.Remark, StringComparison.Ordinal));
|
||||
ModeComboBox.Items.AddRange(array);
|
||||
|
||||
SelectLastMode();
|
||||
}
|
||||
|
||||
public void UpdateMode(Models.Mode NewMode, Models.Mode OldMode)
|
||||
{
|
||||
ModeComboBox.Items.Clear();
|
||||
Global.ModeFiles.Remove(OldMode);
|
||||
Global.ModeFiles.Add(NewMode);
|
||||
var array = Global.ModeFiles.ToArray();
|
||||
Array.Sort(array, (a, b) => string.Compare(a.Remark, b.Remark, StringComparison.Ordinal));
|
||||
ModeComboBox.Items.AddRange(array);
|
||||
|
||||
SelectLastMode();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Init at <see cref="MainForm_Load"/>
|
||||
/// </summary>
|
||||
private int _eWidth;
|
||||
|
||||
private void ComboBox_DrawItem(object sender, DrawItemEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!(sender is ComboBox cbx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 绘制背景颜色
|
||||
e.Graphics.FillRectangle(new SolidBrush(Color.White), e.Bounds);
|
||||
|
||||
if (e.Index < 0) return;
|
||||
|
||||
// 绘制 备注/名称 字符串
|
||||
e.Graphics.DrawString(cbx.Items[e.Index].ToString(), cbx.Font, new SolidBrush(Color.Black), e.Bounds);
|
||||
|
||||
switch (cbx.Items[e.Index])
|
||||
{
|
||||
case Models.Server item:
|
||||
{
|
||||
// 计算延迟底色
|
||||
SolidBrush brush;
|
||||
if (item.Delay > 200)
|
||||
brush = new SolidBrush(Color.Red);
|
||||
else if (item.Delay > 80)
|
||||
brush = new SolidBrush(Color.Yellow);
|
||||
else if (item.Delay >= 0)
|
||||
brush = new SolidBrush(Color.FromArgb(50, 255, 56));
|
||||
else
|
||||
brush = new SolidBrush(Color.Gray);
|
||||
|
||||
// 绘制延迟底色
|
||||
e.Graphics.FillRectangle(brush, _eWidth * 9, e.Bounds.Y, _eWidth, e.Bounds.Height);
|
||||
|
||||
// 绘制延迟字符串
|
||||
e.Graphics.DrawString(item.Delay.ToString(), cbx.Font, new SolidBrush(Color.Black),
|
||||
_eWidth * 9 + _eWidth / 30, e.Bounds.Y);
|
||||
break;
|
||||
}
|
||||
case Models.Mode item:
|
||||
{
|
||||
// 绘制 模式Box 底色
|
||||
e.Graphics.FillRectangle(new SolidBrush(Color.Gray), _eWidth * 9, e.Bounds.Y, _eWidth,
|
||||
e.Bounds.Height);
|
||||
|
||||
// 绘制 模式行数 字符串
|
||||
e.Graphics.DrawString(item.Rule.Count.ToString(), cbx.Font, new SolidBrush(Color.Black),
|
||||
_eWidth * 9 + _eWidth / 30, e.Bounds.Y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
173
Netch/Forms/MainForm.Status.cs
Normal file
173
Netch/Forms/MainForm.Status.cs
Normal file
@@ -0,0 +1,173 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Forms
|
||||
{
|
||||
public partial class Dummy
|
||||
{
|
||||
}
|
||||
|
||||
partial class MainForm
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前状态
|
||||
/// </summary>
|
||||
public State State { get; private set; } = State.Waiting;
|
||||
|
||||
public void NatTypeStatusText(string text = "", string country = "")
|
||||
{
|
||||
if (State != State.Started)
|
||||
{
|
||||
NatTypeStatusLabel.Text = "";
|
||||
NatTypeStatusLabel.Visible = NatTypeStatusLightLabel.Visible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(text))
|
||||
{
|
||||
if (country != "")
|
||||
{
|
||||
NatTypeStatusLabel.Text = String.Format("NAT{0}{1}[{2}]", i18N.Translate(": "), text, country);
|
||||
}
|
||||
else
|
||||
{
|
||||
NatTypeStatusLabel.Text = String.Format("NAT{0}{1}", i18N.Translate(": "), text);
|
||||
}
|
||||
if (Enum.TryParse(text, false, out STUN_Client.NatType natType))
|
||||
{
|
||||
NatTypeStatusLightLabel.Visible = true;
|
||||
UpdateNatTypeLight(natType);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NatTypeStatusLabel.Text = $@"NAT{i18N.Translate(": ", "Test failed")}";
|
||||
}
|
||||
|
||||
NatTypeStatusLabel.Visible = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新 NAT指示灯颜色
|
||||
/// </summary>
|
||||
/// <param name="natType"></param>
|
||||
private void UpdateNatTypeLight(STUN_Client.NatType natType)
|
||||
{
|
||||
Color c;
|
||||
switch (natType)
|
||||
{
|
||||
case STUN_Client.NatType.UdpBlocked:
|
||||
case STUN_Client.NatType.SymmetricUdpFirewall:
|
||||
case STUN_Client.NatType.Symmetric:
|
||||
c = Color.Red;
|
||||
break;
|
||||
case STUN_Client.NatType.RestrictedCone:
|
||||
case STUN_Client.NatType.PortRestrictedCone:
|
||||
c = Color.Yellow;
|
||||
break;
|
||||
case STUN_Client.NatType.OpenInternet:
|
||||
case STUN_Client.NatType.FullCone:
|
||||
c = Color.LimeGreen;
|
||||
break;
|
||||
default:
|
||||
c = Color.Black;
|
||||
break;
|
||||
}
|
||||
|
||||
NatTypeStatusLightLabel.ForeColor = c;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 更新状态栏文本
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
public void StatusText(string text)
|
||||
{
|
||||
StatusLabel.Text = i18N.Translate("Status", ": ") + text;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新 UI, 状态栏文本, 状态
|
||||
/// </summary>
|
||||
/// <param name="state"></param>
|
||||
/// <param name="text"></param>
|
||||
private void UpdateStatus(State state, string text = "")
|
||||
{
|
||||
State = state;
|
||||
StatusText(text == "" ? i18N.Translate(StateExtension.GetStatusString(state)) : text);
|
||||
|
||||
void MenuStripsEnabled(bool enabled)
|
||||
{
|
||||
// 需要禁用的菜单项
|
||||
UninstallServiceToolStripMenuItem.Enabled =
|
||||
updateACLWithProxyToolStripMenuItem.Enabled =
|
||||
UpdateServersFromSubscribeLinksToolStripMenuItem.Enabled =
|
||||
reinstallTapDriverToolStripMenuItem.Enabled = enabled;
|
||||
}
|
||||
|
||||
// TODO 补充
|
||||
switch (state)
|
||||
{
|
||||
case State.Waiting:
|
||||
ControlButton.Enabled = true;
|
||||
ControlButton.Text = i18N.Translate("Start");
|
||||
|
||||
break;
|
||||
case State.Starting:
|
||||
ControlButton.Enabled = false;
|
||||
ControlButton.Text = "...";
|
||||
|
||||
ConfigurationGroupBox.Enabled = false;
|
||||
|
||||
MenuStripsEnabled(false);
|
||||
break;
|
||||
case State.Started:
|
||||
ControlButton.Enabled = true;
|
||||
ControlButton.Text = i18N.Translate("Stop");
|
||||
|
||||
LastUploadBandwidth = 0;
|
||||
//LastDownloadBandwidth = 0;
|
||||
//UploadSpeedLabel.Text = "↑: 0 KB/s";
|
||||
DownloadSpeedLabel.Text = @"↑↓: 0 KB/s";
|
||||
UsedBandwidthLabel.Text = $@"{i18N.Translate("Used", ": ")}0 KB";
|
||||
UsedBandwidthLabel.Visible /*= UploadSpeedLabel.Visible*/ = DownloadSpeedLabel.Visible = true;
|
||||
break;
|
||||
case State.Stopping:
|
||||
ControlButton.Enabled = false;
|
||||
ControlButton.Text = "...";
|
||||
|
||||
ProfileGroupBox.Enabled = false;
|
||||
|
||||
UsedBandwidthLabel.Visible /*= UploadSpeedLabel.Visible*/ = DownloadSpeedLabel.Visible = false;
|
||||
NatTypeStatusText();
|
||||
break;
|
||||
case State.Stopped:
|
||||
ControlButton.Enabled = true;
|
||||
ControlButton.Text = i18N.Translate("Start");
|
||||
|
||||
LastUploadBandwidth = 0;
|
||||
LastDownloadBandwidth = 0;
|
||||
|
||||
ProfileGroupBox.Enabled = true;
|
||||
ConfigurationGroupBox.Enabled = true;
|
||||
|
||||
MenuStripsEnabled(true);
|
||||
break;
|
||||
case State.Terminating:
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 刷新 UI
|
||||
/// </summary>
|
||||
private void UpdateStatus()
|
||||
{
|
||||
UpdateStatus(State);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -120,51 +120,6 @@
|
||||
<metadata name="MenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="EditPictureBox.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAg9JREFUOE+F
|
||||
U81uElEYnTdw58qFunBlYnwAE7e+QhMT38CNcefWxKWufADjiqqtmsZIW2gRulBTY4fGGGmLMFOGn5aB
|
||||
GYa5c+f4nTsINKF6kkPIxz3nO/f7Llas1IXXGyW8Wi9h+T/kmVx+C7WGA8F14S2LxR8HdfjDAMMwFI7O
|
||||
YQg/CI14pVDGKIoGYnDZomMgB4gk0VAqgUoWkxjHMd5t7eCkTz2uWIxGd601nHYPR66H+nH7LKXW9LrG
|
||||
JBrHeL+9g1N/gDRNl4wBoxHhKDJxmWierPG3lGeiaGrQ9DpPjMFADJjA7fSko4ff0nWerDntWQJegQbl
|
||||
XRsLEiweZMAEEoFn1opl9GXopa97sFaLlWmCY0nAjo2WdCYn3ednIGvHodPCSIw+2z9hrRQqZoWzBLOu
|
||||
jBvJ1MlYyARK+LGl8LCWYq+vsyvMttA17oduiwOaru4vEhGvdzSuVRUu2THu7KvJDCYJxrHKugr5XdZk
|
||||
6kSsgWJXo+pr7J5q3K7GeFoXA75EDuRfYOyCdLZFTDhhipyboDsIv2QGg6H5YREorvSyzgTFH7wEnh8g
|
||||
0frxdAbn4Vs/xYtmNguK10TcCXjF+JmUrlpvNj/lDxqu2cDZFxialb1sKly0FZYl8oZc4yRK+CYeiPie
|
||||
8IYlH3dz+W3zuub5Vv5x33/V8VwG9aimsCniMEl92dZN0SxRB+D+Hw2grtB8iuYFAAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
<data name="DeletePictureBox.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAglJREFUOE+V
|
||||
k81PE1EUxUcXunEFS02MJibsZGfc6L6iazGaGI07QXcaE+PClf+ECxP/CKWwUFJqpVNKodAPGgtiW2g7
|
||||
03am89WZ47mvTdwUhJv8mua9e+7cd995GoAL5Cq5SB42jQ7S+RIWf2TwNZFWxJM6fm4U0GgZN5kzQc6T
|
||||
KXJNCpwjb/1gMJMt7GBhJY217TJqhy2YPUtRb7aRK1WkULC6WTRdz/9IzQ1yWQqcpXhqJZvHdz2nBEeF
|
||||
1Xcged/S62CROJeuSIGYfFnEfhCoxONiEIZIskgqt40oimY1nvnzQmIVHcsepfw/+p6HOI+6f9D8oMnA
|
||||
9HJ1tHXyyFf3kVjbhCbT/tM0hqtOH1G9huigPh7uwR7OqNXpceA6tC/86crgAh/u+zew79+FPXtvPNxz
|
||||
X88j6nXhOC4WU9lhgV6P5+e53FdzsO7chj0zHit2C87cE0Qd81+BeDKDettUbcFoI9wpIayUx1MusvdD
|
||||
ldruWspkmjgsW9lTi6eJwl4Ny/oGNNpTXYnNlk4anh9gicPfrTU+aVGEGO2pHDYYhKOUo4Pm4Vspqiuk
|
||||
qd6JE5/SlsqeyfWtYzuRPBEvpTJi6xdcUlaeJPOO5/liT3l5W5VdtMyu8r5g8M6Lv34roXx5JH5MrkuB
|
||||
R+QMmWB7l2jP55IkExaBIP+X+VaqtcbLMAynmftgqMOzv61mlBRRiHFjAAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
<data name="SpeedPictureBox.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAk9JREFUOE9N
|
||||
k19ojWEcx8+xsRgzbSlaJouGRCNuXIyMXJ1LpVyYFAttqylEsdKQC1yZpF24oJQrN0q5UJKUlP3DWTPz
|
||||
pzmm2Tk753nf9+fzfd/3nJ2nPr3v8z7P7/d7nu/v+ybMbBUsA703wwk/sKcPJz07POzszOg8HXAKBr55
|
||||
bLMmWKOgxZCEBfH7zg9/fev55Gw8G9jUXGC/IFMI7HXGt7ZBZ9fGHNtsJVQogYIrQMFVOc8GLn5x4eby
|
||||
UWB6k8AXU75N5gJ9aoBkMYGqL4JLbHB9bFRA+Xj207Pr0fcbTNtgC1QWE1TC6t/5INvF0UdmwgqlkZ4N
|
||||
rJvvP3JBmul6OArSrloJ6mAz3H383bMHE6FApZFlqitpbcbZhTnfWrzA9rNUDfVKsAFSY1Q5+9mFopWP
|
||||
IU6TGnJ2nrXetCslY6hwnRLo/q1XWVTr/iHwdCECQS2PFpl81IUnBLZ+LNit8bALRyA8gTTY0f816vVl
|
||||
Klwh2UneH5GweJ53076d5pv04SrSQiLWKkEVbFUl9VtItPYRZ6/iVr7549sx5sORuP2wBw5BgxIsgY2w
|
||||
DVZAlwLVc21/GwdTWRfvhXp4Cbv1rgRrQRbeDge466xaplO8x5FxMEvWCctBRTpgH4RGWgdyoRZuSyiJ
|
||||
qcrSIQ5+DgtBCXQCuXAphFaWjfVsnMD752iX2tQ5b6g7sAv0w20CiV50b3gCuTDB1ub7mGjvYCF0XRzc
|
||||
B/rrGkGqK7BYVI5MaFILSdzVdI9WHuRvG42Cj4Mc2g4toEJKUAMZSJlZzX8eY2N9ZDKIEQAAAABJRU5E
|
||||
rkJggg==
|
||||
</value>
|
||||
</data>
|
||||
<metadata name="StatusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>122, 17</value>
|
||||
</metadata>
|
||||
@@ -174,6 +129,7 @@
|
||||
<metadata name="NotifyMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>393, 17</value>
|
||||
</metadata>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="NotifyIcon.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
AAABAAMAAAAAAAEAIAAoIAQANgAAAEBAAAABACAAKEIAAF4gBAAgIAAAAQAgAKgQAACGYgQAKAAAAAAB
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
using Microsoft.WindowsAPICodePack.Dialogs;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using Microsoft.WindowsAPICodePack.Dialogs;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Forms.Mode
|
||||
{
|
||||
public partial class Process : Form
|
||||
{
|
||||
//用于判断当前窗口是否为编辑模式
|
||||
private Boolean EditMode = false;
|
||||
private bool EditMode;
|
||||
//被编辑模式坐标
|
||||
private Models.Mode EditMode_Old = null;
|
||||
private Models.Mode EditMode_Old;
|
||||
/// <summary>
|
||||
/// 编辑模式
|
||||
/// </summary>
|
||||
@@ -23,7 +25,7 @@ namespace Netch.Forms.Mode
|
||||
CheckForIllegalCrossThreadCalls = false;
|
||||
|
||||
EditMode_Old = mode;
|
||||
this.Text = "Edit Process Mode";
|
||||
Text = "Edit Process Mode";
|
||||
//循环填充已有规则
|
||||
mode.Rule.ForEach(i => RuleListBox.Items.Add(i));
|
||||
|
||||
@@ -67,7 +69,7 @@ namespace Netch.Forms.Mode
|
||||
return;
|
||||
}
|
||||
|
||||
var DirStack = new System.Collections.Generic.Stack<string>();
|
||||
var DirStack = new Stack<string>();
|
||||
DirStack.Push(DirName);
|
||||
|
||||
while (DirStack.Count > 0)
|
||||
@@ -89,16 +91,16 @@ namespace Netch.Forms.Mode
|
||||
|
||||
private void ModeForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
Text = Utils.i18N.Translate(Text);
|
||||
ConfigurationGroupBox.Text = Utils.i18N.Translate(ConfigurationGroupBox.Text);
|
||||
RemarkLabel.Text = Utils.i18N.Translate(RemarkLabel.Text);
|
||||
FilenameLabel.Text = Utils.i18N.Translate(FilenameLabel.Text);
|
||||
UseCustomFilenameBox.Text = Utils.i18N.Translate(UseCustomFilenameBox.Text);
|
||||
StaySameButton.Text = Utils.i18N.Translate(StaySameButton.Text);
|
||||
TimeDataButton.Text = Utils.i18N.Translate(TimeDataButton.Text);
|
||||
AddButton.Text = Utils.i18N.Translate(AddButton.Text);
|
||||
ScanButton.Text = Utils.i18N.Translate(ScanButton.Text);
|
||||
ControlButton.Text = Utils.i18N.Translate(ControlButton.Text);
|
||||
Text = i18N.Translate(Text);
|
||||
ConfigurationGroupBox.Text = i18N.Translate(ConfigurationGroupBox.Text);
|
||||
RemarkLabel.Text = i18N.Translate(RemarkLabel.Text);
|
||||
FilenameLabel.Text = i18N.Translate(FilenameLabel.Text);
|
||||
UseCustomFilenameBox.Text = i18N.Translate(UseCustomFilenameBox.Text);
|
||||
StaySameButton.Text = i18N.Translate(StaySameButton.Text);
|
||||
TimeDataButton.Text = i18N.Translate(TimeDataButton.Text);
|
||||
AddButton.Text = i18N.Translate(AddButton.Text);
|
||||
ScanButton.Text = i18N.Translate(ScanButton.Text);
|
||||
ControlButton.Text = i18N.Translate(ControlButton.Text);
|
||||
|
||||
if (Global.Settings.ModeFileNameType == 0)
|
||||
{
|
||||
@@ -130,12 +132,12 @@ namespace Netch.Forms.Mode
|
||||
/// </summary>
|
||||
private void RuleListBox_MouseUp(object sender, MouseEventArgs e)
|
||||
{
|
||||
ContextMenuStrip strip = new ContextMenuStrip();
|
||||
strip.Items.Add(Utils.i18N.Translate("Delete"));
|
||||
var strip = new ContextMenuStrip();
|
||||
strip.Items.Add(i18N.Translate("Delete"));
|
||||
if (e.Button == MouseButtons.Right)
|
||||
{
|
||||
strip.Show(this.RuleListBox, e.Location);//鼠标右键按下弹出菜单
|
||||
strip.MouseClick += new MouseEventHandler(deleteRule_Click);
|
||||
strip.Show(RuleListBox, e.Location);//鼠标右键按下弹出菜单
|
||||
strip.MouseClick += deleteRule_Click;
|
||||
}
|
||||
}
|
||||
void deleteRule_Click(object sender, EventArgs e)
|
||||
@@ -165,7 +167,7 @@ namespace Netch.Forms.Mode
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show(Utils.i18N.Translate("Please enter an process name (xxx.exe)"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBoxX.Show(i18N.Translate("Please enter an process name (xxx.exe)"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,7 +177,7 @@ namespace Netch.Forms.Mode
|
||||
{
|
||||
IsFolderPicker = true,
|
||||
Multiselect = false,
|
||||
Title = Utils.i18N.Translate("Select a folder"),
|
||||
Title = i18N.Translate("Select a folder"),
|
||||
AddToMostRecentlyUsedList = false,
|
||||
EnsurePathExists = true,
|
||||
NavigateToShortcut = true
|
||||
@@ -183,7 +185,7 @@ namespace Netch.Forms.Mode
|
||||
if (dialog.ShowDialog(Win32Native.GetForegroundWindow()) == CommonFileDialogResult.Ok)
|
||||
{
|
||||
ScanDirectory(dialog.FileName);
|
||||
MessageBox.Show(Utils.i18N.Translate("Scan completed"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBoxX.Show(i18N.Translate("Scan completed"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,14 +222,14 @@ namespace Netch.Forms.Mode
|
||||
|
||||
File.WriteAllText(Path.Combine("mode", FilenameTextBox.Text) + ".txt", text);
|
||||
|
||||
MessageBox.Show(Utils.i18N.Translate("Mode updated successfully"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBoxX.Show(i18N.Translate("Mode updated successfully"));
|
||||
|
||||
Global.MainForm.UpdateMode(mode, EditMode_Old);
|
||||
Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show(Utils.i18N.Translate("Unable to add empty rule"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBoxX.Show(i18N.Translate("Unable to add empty rule"));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -250,13 +252,13 @@ namespace Netch.Forms.Mode
|
||||
FilenameTextBox.Text = ((long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds).ToString();
|
||||
}
|
||||
|
||||
Utils.Configuration.Save();
|
||||
Configuration.Save();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(RemarkTextBox.Text))
|
||||
{
|
||||
if (Global.Settings.ModeFileNameType == 0 && string.IsNullOrWhiteSpace(FilenameTextBox.Text))
|
||||
{
|
||||
MessageBox.Show(Utils.i18N.Translate("Please enter a mode filename"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBoxX.Show(i18N.Translate("Please enter a mode filename"));
|
||||
return;
|
||||
}
|
||||
var ModeFilename = Path.Combine("mode", FilenameTextBox.Text);
|
||||
@@ -264,7 +266,7 @@ namespace Netch.Forms.Mode
|
||||
// 如果文件已存在,返回
|
||||
if (File.Exists(ModeFilename + ".txt"))
|
||||
{
|
||||
MessageBox.Show(Utils.i18N.Translate("File already exists.\n Please Change the filename"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBoxX.Show(i18N.Translate("File already exists.\n Please Change the filename"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -273,7 +275,7 @@ namespace Netch.Forms.Mode
|
||||
var mode = new Models.Mode
|
||||
{
|
||||
BypassChina = false,
|
||||
FileName = ModeFilename,
|
||||
FileName = FilenameTextBox.Text,
|
||||
Type = 0,
|
||||
Remark = RemarkTextBox.Text
|
||||
};
|
||||
@@ -295,19 +297,19 @@ namespace Netch.Forms.Mode
|
||||
|
||||
File.WriteAllText(ModeFilename + ".txt", text);
|
||||
|
||||
MessageBox.Show(Utils.i18N.Translate("Mode added successfully"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBoxX.Show(i18N.Translate("Mode added successfully"));
|
||||
|
||||
Global.MainForm.AddMode(mode);
|
||||
Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show(Utils.i18N.Translate("Unable to add empty rule"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBoxX.Show(i18N.Translate("Unable to add empty rule"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show(Utils.i18N.Translate("Please enter a mode remark"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBoxX.Show(i18N.Translate("Please enter a mode remark"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Drawing;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Forms.Server
|
||||
{
|
||||
@@ -22,14 +23,14 @@ namespace Netch.Forms.Server
|
||||
|
||||
private void Shadowsocks_Load(object sender, EventArgs e)
|
||||
{
|
||||
ConfigurationGroupBox.Text = Utils.i18N.Translate(ConfigurationGroupBox.Text);
|
||||
RemarkLabel.Text = Utils.i18N.Translate(RemarkLabel.Text);
|
||||
AddressLabel.Text = Utils.i18N.Translate(AddressLabel.Text);
|
||||
PasswordLabel.Text = Utils.i18N.Translate(PasswordLabel.Text);
|
||||
EncryptMethodLabel.Text = Utils.i18N.Translate(EncryptMethodLabel.Text);
|
||||
PluginLabel.Text = Utils.i18N.Translate(PluginLabel.Text);
|
||||
PluginOptionsLabel.Text = Utils.i18N.Translate(PluginOptionsLabel.Text);
|
||||
ControlButton.Text = Utils.i18N.Translate(ControlButton.Text);
|
||||
ConfigurationGroupBox.Text = i18N.Translate(ConfigurationGroupBox.Text);
|
||||
RemarkLabel.Text = i18N.Translate(RemarkLabel.Text);
|
||||
AddressLabel.Text = i18N.Translate(AddressLabel.Text);
|
||||
PasswordLabel.Text = i18N.Translate(PasswordLabel.Text);
|
||||
EncryptMethodLabel.Text = i18N.Translate(EncryptMethodLabel.Text);
|
||||
PluginLabel.Text = i18N.Translate(PluginLabel.Text);
|
||||
PluginOptionsLabel.Text = i18N.Translate(PluginOptionsLabel.Text);
|
||||
ControlButton.Text = i18N.Translate(ControlButton.Text);
|
||||
|
||||
foreach (var encrypt in Global.EncryptMethods.SS)
|
||||
{
|
||||
@@ -119,8 +120,8 @@ namespace Netch.Forms.Server
|
||||
};
|
||||
}
|
||||
|
||||
Utils.Configuration.Save();
|
||||
MessageBox.Show(Utils.i18N.Translate("Saved"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
Configuration.Save();
|
||||
MessageBoxX.Show(i18N.Translate("Saved"));
|
||||
Global.MainForm.InitServer();
|
||||
Close();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Drawing;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Forms.Server
|
||||
{
|
||||
@@ -22,16 +23,16 @@ namespace Netch.Forms.Server
|
||||
|
||||
private void ShadowsocksR_Load(object sender, EventArgs e)
|
||||
{
|
||||
ConfigurationGroupBox.Text = Utils.i18N.Translate(ConfigurationGroupBox.Text);
|
||||
RemarkLabel.Text = Utils.i18N.Translate(RemarkLabel.Text);
|
||||
AddressLabel.Text = Utils.i18N.Translate(AddressLabel.Text);
|
||||
PasswordLabel.Text = Utils.i18N.Translate(PasswordLabel.Text);
|
||||
EncryptMethodLabel.Text = Utils.i18N.Translate(EncryptMethodLabel.Text);
|
||||
ProtocolLabel.Text = Utils.i18N.Translate(ProtocolLabel.Text);
|
||||
ProtocolParamLabel.Text = Utils.i18N.Translate(ProtocolParamLabel.Text);
|
||||
OBFSLabel.Text = Utils.i18N.Translate(OBFSLabel.Text);
|
||||
OBFSParamLabel.Text = Utils.i18N.Translate(OBFSParamLabel.Text);
|
||||
ControlButton.Text = Utils.i18N.Translate(ControlButton.Text);
|
||||
ConfigurationGroupBox.Text = i18N.Translate(ConfigurationGroupBox.Text);
|
||||
RemarkLabel.Text = i18N.Translate(RemarkLabel.Text);
|
||||
AddressLabel.Text = i18N.Translate(AddressLabel.Text);
|
||||
PasswordLabel.Text = i18N.Translate(PasswordLabel.Text);
|
||||
EncryptMethodLabel.Text = i18N.Translate(EncryptMethodLabel.Text);
|
||||
ProtocolLabel.Text = i18N.Translate(ProtocolLabel.Text);
|
||||
ProtocolParamLabel.Text = i18N.Translate(ProtocolParamLabel.Text);
|
||||
OBFSLabel.Text = i18N.Translate(OBFSLabel.Text);
|
||||
OBFSParamLabel.Text = i18N.Translate(OBFSParamLabel.Text);
|
||||
ControlButton.Text = i18N.Translate(ControlButton.Text);
|
||||
|
||||
foreach (var encrypt in Global.EncryptMethods.SSR)
|
||||
{
|
||||
@@ -139,8 +140,8 @@ namespace Netch.Forms.Server
|
||||
};
|
||||
}
|
||||
|
||||
Utils.Configuration.Save();
|
||||
MessageBox.Show(Utils.i18N.Translate("Saved"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
Configuration.Save();
|
||||
MessageBoxX.Show(i18N.Translate("Saved"));
|
||||
Global.MainForm.InitServer();
|
||||
Close();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Drawing;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Forms.Server
|
||||
{
|
||||
@@ -22,12 +23,12 @@ namespace Netch.Forms.Server
|
||||
|
||||
private void Shadowsocks_Load(object sender, EventArgs e)
|
||||
{
|
||||
ConfigurationGroupBox.Text = Utils.i18N.Translate(ConfigurationGroupBox.Text);
|
||||
RemarkLabel.Text = Utils.i18N.Translate(RemarkLabel.Text);
|
||||
AddressLabel.Text = Utils.i18N.Translate(AddressLabel.Text);
|
||||
UsernameLabel.Text = Utils.i18N.Translate(UsernameLabel.Text);
|
||||
PasswordLabel.Text = Utils.i18N.Translate(PasswordLabel.Text);
|
||||
ControlButton.Text = Utils.i18N.Translate(ControlButton.Text);
|
||||
ConfigurationGroupBox.Text = i18N.Translate(ConfigurationGroupBox.Text);
|
||||
RemarkLabel.Text = i18N.Translate(RemarkLabel.Text);
|
||||
AddressLabel.Text = i18N.Translate(AddressLabel.Text);
|
||||
UsernameLabel.Text = i18N.Translate(UsernameLabel.Text);
|
||||
PasswordLabel.Text = i18N.Translate(PasswordLabel.Text);
|
||||
ControlButton.Text = i18N.Translate(ControlButton.Text);
|
||||
|
||||
if (Index != -1)
|
||||
{
|
||||
@@ -102,8 +103,8 @@ namespace Netch.Forms.Server
|
||||
};
|
||||
}
|
||||
|
||||
Utils.Configuration.Save();
|
||||
MessageBox.Show(Utils.i18N.Translate("Saved"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
Configuration.Save();
|
||||
MessageBoxX.Show(i18N.Translate("Saved"));
|
||||
Global.MainForm.InitServer();
|
||||
Close();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Drawing;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Forms.Server
|
||||
{
|
||||
@@ -22,11 +23,11 @@ namespace Netch.Forms.Server
|
||||
|
||||
private void Trojan_Load(object sender, EventArgs e)
|
||||
{
|
||||
ConfigurationGroupBox.Text = Utils.i18N.Translate(ConfigurationGroupBox.Text);
|
||||
RemarkLabel.Text = Utils.i18N.Translate(RemarkLabel.Text);
|
||||
AddressLabel.Text = Utils.i18N.Translate(AddressLabel.Text);
|
||||
PasswordLabel.Text = Utils.i18N.Translate(PasswordLabel.Text);
|
||||
ControlButton.Text = Utils.i18N.Translate(ControlButton.Text);
|
||||
ConfigurationGroupBox.Text = i18N.Translate(ConfigurationGroupBox.Text);
|
||||
RemarkLabel.Text = i18N.Translate(RemarkLabel.Text);
|
||||
AddressLabel.Text = i18N.Translate(AddressLabel.Text);
|
||||
PasswordLabel.Text = i18N.Translate(PasswordLabel.Text);
|
||||
ControlButton.Text = i18N.Translate(ControlButton.Text);
|
||||
|
||||
if (Index != -1)
|
||||
{
|
||||
@@ -98,8 +99,8 @@ namespace Netch.Forms.Server
|
||||
};
|
||||
}
|
||||
|
||||
Utils.Configuration.Save();
|
||||
MessageBox.Show(Utils.i18N.Translate("Saved"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
Configuration.Save();
|
||||
MessageBoxX.Show(i18N.Translate("Saved"));
|
||||
Global.MainForm.InitServer();
|
||||
Close();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Drawing;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Forms.Server
|
||||
{
|
||||
@@ -43,21 +44,21 @@ namespace Netch.Forms.Server
|
||||
|
||||
private void VMess_Load(object sender, EventArgs e)
|
||||
{
|
||||
ConfigurationGroupBox.Text = Utils.i18N.Translate(ConfigurationGroupBox.Text);
|
||||
RemarkLabel.Text = Utils.i18N.Translate(RemarkLabel.Text);
|
||||
AddressLabel.Text = Utils.i18N.Translate(AddressLabel.Text);
|
||||
UserIDLabel.Text = Utils.i18N.Translate(UserIDLabel.Text);
|
||||
AlterIDLabel.Text = Utils.i18N.Translate(AlterIDLabel.Text);
|
||||
EncryptMethodLabel.Text = Utils.i18N.Translate(EncryptMethodLabel.Text);
|
||||
TransferProtocolLabel.Text = Utils.i18N.Translate(TransferProtocolLabel.Text);
|
||||
FakeTypeLabel.Text = Utils.i18N.Translate(FakeTypeLabel.Text);
|
||||
HostLabel.Text = Utils.i18N.Translate(HostLabel.Text);
|
||||
PathLabel.Text = Utils.i18N.Translate(PathLabel.Text);
|
||||
QUICSecurityLabel.Text = Utils.i18N.Translate(QUICSecurityLabel.Text);
|
||||
QUICSecretLabel.Text = Utils.i18N.Translate(QUICSecretLabel.Text);
|
||||
TLSSecureCheckBox.Text = Utils.i18N.Translate(TLSSecureCheckBox.Text);
|
||||
UseMuxCheckBox.Text = Utils.i18N.Translate(UseMuxCheckBox.Text);
|
||||
ControlButton.Text = Utils.i18N.Translate(ControlButton.Text);
|
||||
ConfigurationGroupBox.Text = i18N.Translate(ConfigurationGroupBox.Text);
|
||||
RemarkLabel.Text = i18N.Translate(RemarkLabel.Text);
|
||||
AddressLabel.Text = i18N.Translate(AddressLabel.Text);
|
||||
UserIDLabel.Text = i18N.Translate(UserIDLabel.Text);
|
||||
AlterIDLabel.Text = i18N.Translate(AlterIDLabel.Text);
|
||||
EncryptMethodLabel.Text = i18N.Translate(EncryptMethodLabel.Text);
|
||||
TransferProtocolLabel.Text = i18N.Translate(TransferProtocolLabel.Text);
|
||||
FakeTypeLabel.Text = i18N.Translate(FakeTypeLabel.Text);
|
||||
HostLabel.Text = i18N.Translate(HostLabel.Text);
|
||||
PathLabel.Text = i18N.Translate(PathLabel.Text);
|
||||
QUICSecurityLabel.Text = i18N.Translate(QUICSecurityLabel.Text);
|
||||
QUICSecretLabel.Text = i18N.Translate(QUICSecretLabel.Text);
|
||||
TLSSecureCheckBox.Text = i18N.Translate(TLSSecureCheckBox.Text);
|
||||
UseMuxCheckBox.Text = i18N.Translate(UseMuxCheckBox.Text);
|
||||
ControlButton.Text = i18N.Translate(ControlButton.Text);
|
||||
|
||||
foreach (var encrypt in Global.EncryptMethods.VMess)
|
||||
{
|
||||
@@ -118,7 +119,7 @@ namespace Netch.Forms.Server
|
||||
}
|
||||
if (AlterIDTextBox.Text == "")
|
||||
{
|
||||
MessageBox.Show(Utils.i18N.Translate("Please fill in alterID"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBoxX.Show(i18N.Translate("Please fill in alterID"));
|
||||
return;
|
||||
}
|
||||
if (Index == -1)
|
||||
@@ -165,8 +166,8 @@ namespace Netch.Forms.Server
|
||||
};
|
||||
}
|
||||
|
||||
Utils.Configuration.Save();
|
||||
MessageBox.Show(Utils.i18N.Translate("Saved"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
Configuration.Save();
|
||||
MessageBoxX.Show(i18N.Translate("Saved"));
|
||||
Global.MainForm.InitServer();
|
||||
Close();
|
||||
}
|
||||
|
||||
4
Netch/Forms/SettingForm.Designer.cs
generated
4
Netch/Forms/SettingForm.Designer.cs
generated
@@ -473,9 +473,9 @@
|
||||
//
|
||||
// ProfileCount_TextBox
|
||||
//
|
||||
this.ProfileCount_TextBox.Location = new System.Drawing.Point(209, 164);
|
||||
this.ProfileCount_TextBox.Location = new System.Drawing.Point(120, 164);
|
||||
this.ProfileCount_TextBox.Name = "ProfileCount_TextBox";
|
||||
this.ProfileCount_TextBox.Size = new System.Drawing.Size(226, 23);
|
||||
this.ProfileCount_TextBox.Size = new System.Drawing.Size(90, 23);
|
||||
this.ProfileCount_TextBox.TabIndex = 9;
|
||||
this.ProfileCount_TextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
using Netch.Models.SSD;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
using TaskScheduler;
|
||||
|
||||
namespace Netch.Forms
|
||||
@@ -35,6 +34,7 @@ namespace Netch.Forms
|
||||
dns += ip;
|
||||
dns += ',';
|
||||
}
|
||||
|
||||
dns = dns.Trim();
|
||||
TUNTAPDNSTextBox.Text = dns.Substring(0, dns.Length - 1);
|
||||
}
|
||||
@@ -46,20 +46,20 @@ namespace Netch.Forms
|
||||
}
|
||||
}
|
||||
|
||||
private void SettingForm_Load(object sender, EventArgs e)
|
||||
private void InitText()
|
||||
{
|
||||
Text = Utils.i18N.Translate(Text);
|
||||
PortGroupBox.Text = Utils.i18N.Translate(PortGroupBox.Text);
|
||||
AllowDevicesCheckBox.Text = Utils.i18N.Translate(AllowDevicesCheckBox.Text);
|
||||
TUNTAPAddressLabel.Text = Utils.i18N.Translate(TUNTAPAddressLabel.Text);
|
||||
TUNTAPNetmaskLabel.Text = Utils.i18N.Translate(TUNTAPNetmaskLabel.Text);
|
||||
TUNTAPGatewayLabel.Text = Utils.i18N.Translate(TUNTAPGatewayLabel.Text);
|
||||
UseCustomDNSCheckBox.Text = Utils.i18N.Translate(UseCustomDNSCheckBox.Text);
|
||||
ProxyDNSCheckBox.Text = Utils.i18N.Translate(ProxyDNSCheckBox.Text);
|
||||
UseFakeDNSCheckBox.Text = Utils.i18N.Translate(UseFakeDNSCheckBox.Text);
|
||||
GlobalBypassIPsButton.Text = Utils.i18N.Translate(GlobalBypassIPsButton.Text);
|
||||
ControlButton.Text = Utils.i18N.Translate(ControlButton.Text);
|
||||
BootShadowsocksFromDLLCheckBox.Text = Utils.i18N.Translate(BootShadowsocksFromDLLCheckBox.Text);
|
||||
Text = i18N.Translate(Text);
|
||||
PortGroupBox.Text = i18N.Translate(PortGroupBox.Text);
|
||||
AllowDevicesCheckBox.Text = i18N.Translate(AllowDevicesCheckBox.Text);
|
||||
TUNTAPAddressLabel.Text = i18N.Translate(TUNTAPAddressLabel.Text);
|
||||
TUNTAPNetmaskLabel.Text = i18N.Translate(TUNTAPNetmaskLabel.Text);
|
||||
TUNTAPGatewayLabel.Text = i18N.Translate(TUNTAPGatewayLabel.Text);
|
||||
UseCustomDNSCheckBox.Text = i18N.Translate(UseCustomDNSCheckBox.Text);
|
||||
ProxyDNSCheckBox.Text = i18N.Translate(ProxyDNSCheckBox.Text);
|
||||
UseFakeDNSCheckBox.Text = i18N.Translate(UseFakeDNSCheckBox.Text);
|
||||
GlobalBypassIPsButton.Text = i18N.Translate(GlobalBypassIPsButton.Text);
|
||||
ControlButton.Text = i18N.Translate(ControlButton.Text);
|
||||
BootShadowsocksFromDLLCheckBox.Text = i18N.Translate(BootShadowsocksFromDLLCheckBox.Text);
|
||||
|
||||
ExitWhenClosedCheckBox.Checked = Global.Settings.ExitWhenClosed;
|
||||
StopWhenExitedCheckBox.Checked = Global.Settings.StopWhenExited;
|
||||
@@ -83,31 +83,36 @@ namespace Netch.Forms
|
||||
ProxyDNSCheckBox.Checked = Global.Settings.TUNTAP.ProxyDNS;
|
||||
UseFakeDNSCheckBox.Checked = Global.Settings.TUNTAP.UseFakeDNS;
|
||||
|
||||
BehaviorGroupBox.Text = Utils.i18N.Translate(BehaviorGroupBox.Text);
|
||||
ExitWhenClosedCheckBox.Text = Utils.i18N.Translate(ExitWhenClosedCheckBox.Text);
|
||||
StopWhenExitedCheckBox.Text = Utils.i18N.Translate(StopWhenExitedCheckBox.Text);
|
||||
StartWhenOpenedCheckBox.Text = Utils.i18N.Translate(StartWhenOpenedCheckBox.Text);
|
||||
MinimizeWhenStartedCheckBox.Text = Utils.i18N.Translate(MinimizeWhenStartedCheckBox.Text);
|
||||
RunAtStartup.Text = Utils.i18N.Translate(RunAtStartup.Text);
|
||||
CheckUpdateWhenOpenedCheckBox.Text = Utils.i18N.Translate(CheckUpdateWhenOpenedCheckBox.Text);
|
||||
ProfileCount_Label.Text = Utils.i18N.Translate(ProfileCount_Label.Text);
|
||||
DelayTestAfterStartup_Label.Text = Utils.i18N.Translate(DelayTestAfterStartup_Label.Text);
|
||||
EnableStartedTcping_CheckBox.Text = Utils.i18N.Translate(EnableStartedTcping_CheckBox.Text);
|
||||
DetectionInterval_Label.Text = Utils.i18N.Translate(DetectionInterval_Label.Text);
|
||||
DelayTestAfterStartup_Label.Text = Utils.i18N.Translate(DelayTestAfterStartup_Label.Text);
|
||||
STUNServerLabel.Text = Utils.i18N.Translate(STUNServerLabel.Text);
|
||||
STUNServerPortLabel.Text = Utils.i18N.Translate(STUNServerPortLabel.Text);
|
||||
BehaviorGroupBox.Text = i18N.Translate(BehaviorGroupBox.Text);
|
||||
ExitWhenClosedCheckBox.Text = i18N.Translate(ExitWhenClosedCheckBox.Text);
|
||||
StopWhenExitedCheckBox.Text = i18N.Translate(StopWhenExitedCheckBox.Text);
|
||||
StartWhenOpenedCheckBox.Text = i18N.Translate(StartWhenOpenedCheckBox.Text);
|
||||
MinimizeWhenStartedCheckBox.Text = i18N.Translate(MinimizeWhenStartedCheckBox.Text);
|
||||
RunAtStartup.Text = i18N.Translate(RunAtStartup.Text);
|
||||
CheckUpdateWhenOpenedCheckBox.Text = i18N.Translate(CheckUpdateWhenOpenedCheckBox.Text);
|
||||
ProfileCount_Label.Text = i18N.Translate(ProfileCount_Label.Text);
|
||||
DelayTestAfterStartup_Label.Text = i18N.Translate(DelayTestAfterStartup_Label.Text);
|
||||
EnableStartedTcping_CheckBox.Text = i18N.Translate(EnableStartedTcping_CheckBox.Text);
|
||||
DetectionInterval_Label.Text = i18N.Translate(DetectionInterval_Label.Text);
|
||||
DelayTestAfterStartup_Label.Text = i18N.Translate(DelayTestAfterStartup_Label.Text);
|
||||
STUNServerLabel.Text = i18N.Translate(STUNServerLabel.Text);
|
||||
STUNServerPortLabel.Text = i18N.Translate(STUNServerPortLabel.Text);
|
||||
|
||||
ProfileCount_TextBox.Text = Global.Settings.ProfileCount.ToString();
|
||||
STUN_ServerTextBox.Text = Global.Settings.STUN_Server.ToString();
|
||||
STUN_ServerTextBox.Text = Global.Settings.STUN_Server;
|
||||
STUN_ServerPortTextBox.Text = Global.Settings.STUN_Server_Port.ToString();
|
||||
|
||||
AclLabel.Text = Utils.i18N.Translate(AclLabel.Text);
|
||||
AclAddr.Text = Global.Settings.ACL.ToString();
|
||||
AclLabel.Text = i18N.Translate(AclLabel.Text);
|
||||
AclAddr.Text = Global.Settings.ACL;
|
||||
|
||||
LanguageLabel.Text = Utils.i18N.Translate(LanguageLabel.Text);
|
||||
LanguageComboBox.Items.AddRange(Utils.i18N.GetTranslateList().ToArray());
|
||||
LanguageLabel.Text = i18N.Translate(LanguageLabel.Text);
|
||||
LanguageComboBox.Items.AddRange(i18N.GetTranslateList().ToArray());
|
||||
LanguageComboBox.SelectedItem = Global.Settings.Language;
|
||||
}
|
||||
|
||||
private void SettingForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
InitText();
|
||||
|
||||
if (Global.Settings.TUNTAP.DNS.Count > 0)
|
||||
{
|
||||
@@ -117,6 +122,7 @@ namespace Netch.Forms
|
||||
dns += ip;
|
||||
dns += ',';
|
||||
}
|
||||
|
||||
dns = dns.Trim();
|
||||
TUNTAPDNSTextBox.Text = dns.Substring(0, dns.Length - 1);
|
||||
}
|
||||
@@ -170,75 +176,41 @@ namespace Netch.Forms
|
||||
Global.Settings.BootShadowsocksFromDLL = BootShadowsocksFromDLLCheckBox.Checked;
|
||||
Global.Settings.Language = LanguageComboBox.SelectedItem.ToString();
|
||||
|
||||
// 加载系统语言
|
||||
if (Global.Settings.Language.Equals("System"))
|
||||
{
|
||||
// 得到当前线程语言代码
|
||||
var culture = CultureInfo.CurrentCulture.Name;
|
||||
|
||||
// 尝试加载内置中文语言
|
||||
if (culture == "zh-CN")
|
||||
{
|
||||
// 加载语言
|
||||
Utils.i18N.Load(Encoding.UTF8.GetString(Properties.Resources.zh_CN));
|
||||
}
|
||||
|
||||
// 从外置文件中加载语言
|
||||
if (File.Exists($"i18n\\{culture}"))
|
||||
{
|
||||
// 加载语言
|
||||
Utils.i18N.Load(File.ReadAllText($"i18n\\{culture}"));
|
||||
}
|
||||
}
|
||||
|
||||
if (Global.Settings.Language.Equals("zh-CN"))
|
||||
{
|
||||
// 加载内置中文
|
||||
Utils.i18N.Load(Encoding.UTF8.GetString(Properties.Resources.zh_CN));
|
||||
}
|
||||
else if (Global.Settings.Language.Equals("en-US"))
|
||||
{
|
||||
// 加载内置英文
|
||||
Utils.i18N.Load(Global.Settings.Language);
|
||||
}
|
||||
else if (File.Exists($"i18n\\{Global.Settings.Language}"))
|
||||
{
|
||||
// 从外置文件中加载语言
|
||||
Utils.i18N.Load(File.ReadAllText($"i18n\\{Global.Settings.Language}"));
|
||||
}
|
||||
|
||||
// 开机自启判断
|
||||
TaskSchedulerClass scheduler = new TaskSchedulerClass();
|
||||
scheduler.Connect(null, null, null, null);
|
||||
ITaskFolder folder = scheduler.GetFolder("\\");
|
||||
bool taskIsExists = false;
|
||||
var scheduler = new TaskSchedulerClass();
|
||||
scheduler.Connect();
|
||||
var folder = scheduler.GetFolder("\\");
|
||||
var taskIsExists = false;
|
||||
try
|
||||
{
|
||||
folder.GetTask("Netch Startup");
|
||||
taskIsExists = true;
|
||||
}
|
||||
catch (Exception) { }
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
if (RunAtStartup.Checked)
|
||||
{
|
||||
if (taskIsExists)
|
||||
folder.DeleteTask("Netch Startup", 0);
|
||||
|
||||
ITaskDefinition task = scheduler.NewTask(0);
|
||||
var task = scheduler.NewTask(0);
|
||||
task.RegistrationInfo.Author = "Netch";
|
||||
task.RegistrationInfo.Description = "Netch run at startup.";
|
||||
task.Principal.RunLevel = _TASK_RUNLEVEL.TASK_RUNLEVEL_HIGHEST;
|
||||
|
||||
task.Triggers.Create(_TASK_TRIGGER_TYPE2.TASK_TRIGGER_LOGON);
|
||||
IExecAction action = (IExecAction)task.Actions.Create(_TASK_ACTION_TYPE.TASK_ACTION_EXEC);
|
||||
action.Path = System.Windows.Forms.Application.ExecutablePath;
|
||||
var action = (IExecAction) task.Actions.Create(_TASK_ACTION_TYPE.TASK_ACTION_EXEC);
|
||||
action.Path = Application.ExecutablePath;
|
||||
|
||||
|
||||
task.Settings.ExecutionTimeLimit = "PT0S";
|
||||
task.Settings.DisallowStartIfOnBatteries = false;
|
||||
task.Settings.RunOnlyIfIdle = false;
|
||||
|
||||
folder.RegisterTaskDefinition("Netch Startup", task, (int)_TASK_CREATION.TASK_CREATE, null, null, _TASK_LOGON_TYPE.TASK_LOGON_INTERACTIVE_TOKEN, "");
|
||||
folder.RegisterTaskDefinition("Netch Startup", task, (int) _TASK_CREATION.TASK_CREATE, null, null, _TASK_LOGON_TYPE.TASK_LOGON_INTERACTIVE_TOKEN, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -246,77 +218,15 @@ namespace Netch.Forms
|
||||
folder.DeleteTask("Netch Startup", 0);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var Socks5Port = int.Parse(Socks5PortTextBox.Text);
|
||||
|
||||
if (Socks5Port > 0 && Socks5Port < 65536)
|
||||
{
|
||||
Global.Settings.Socks5LocalPort = Socks5Port;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new FormatException();
|
||||
}
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
Socks5PortTextBox.Text = Global.Settings.Socks5LocalPort.ToString();
|
||||
MessageBox.Show(Utils.i18N.Translate("Port value illegal. Try again."), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
|
||||
// 端口检查
|
||||
if (!CheckPortText("Socks5", ref Socks5PortTextBox, ref Global.Settings.Socks5LocalPort))
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var HTTPPort = int.Parse(HTTPPortTextBox.Text);
|
||||
|
||||
if (HTTPPort > 0 && HTTPPort < 65536)
|
||||
{
|
||||
Global.Settings.HTTPLocalPort = HTTPPort;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new FormatException();
|
||||
}
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
HTTPPortTextBox.Text = Global.Settings.HTTPLocalPort.ToString();
|
||||
MessageBox.Show(Utils.i18N.Translate("Port value illegal. Try again."), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
|
||||
if (!CheckPortText("HTTP", ref HTTPPortTextBox, ref Global.Settings.HTTPLocalPort))
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var RedirectorPort = int.Parse(RedirectorTextBox.Text);
|
||||
|
||||
if (RedirectorPort > 0 && RedirectorPort < 65536)
|
||||
{
|
||||
Global.Settings.RedirectorTCPPort = RedirectorPort;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new FormatException();
|
||||
}
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
RedirectorTextBox.Text = Global.Settings.RedirectorTCPPort.ToString();
|
||||
MessageBox.Show(Utils.i18N.Translate("Port value illegal. Try again."), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
|
||||
if (!CheckPortText("RedirectorTCP", ref RedirectorTextBox, ref Global.Settings.RedirectorTCPPort, PortType.TCP))
|
||||
return;
|
||||
}
|
||||
|
||||
if (AllowDevicesCheckBox.Checked)
|
||||
{
|
||||
Global.Settings.LocalAddress = "0.0.0.0";
|
||||
}
|
||||
else
|
||||
{
|
||||
Global.Settings.LocalAddress = "127.0.0.1";
|
||||
}
|
||||
Global.Settings.LocalAddress = AllowDevicesCheckBox.Checked ? "0.0.0.0" : "127.0.0.1";
|
||||
|
||||
try
|
||||
{
|
||||
@@ -324,7 +234,7 @@ namespace Netch.Forms
|
||||
var Netmask = IPAddress.Parse(TUNTAPNetmaskTextBox.Text);
|
||||
var Gateway = IPAddress.Parse(TUNTAPGatewayTextBox.Text);
|
||||
|
||||
var DNS = new System.Collections.Generic.List<IPAddress>();
|
||||
var DNS = new List<IPAddress>();
|
||||
foreach (var ip in TUNTAPDNSTextBox.Text.Split(','))
|
||||
{
|
||||
DNS.Add(IPAddress.Parse(ip));
|
||||
@@ -332,7 +242,7 @@ namespace Netch.Forms
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
MessageBox.Show(Utils.i18N.Translate("IP address format illegal. Try again."), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBoxX.Show(i18N.Translate("IP address format illegal. Try again."));
|
||||
|
||||
TUNTAPAddressTextBox.Text = Global.Settings.TUNTAP.Address;
|
||||
TUNTAPNetmaskTextBox.Text = Global.Settings.TUNTAP.Netmask;
|
||||
@@ -344,12 +254,14 @@ namespace Netch.Forms
|
||||
DNS += ip;
|
||||
DNS += ',';
|
||||
}
|
||||
|
||||
DNS = DNS.Trim();
|
||||
TUNTAPDNSTextBox.Text = DNS.Substring(0, DNS.Length - 1);
|
||||
UseCustomDNSCheckBox.Checked = Global.Settings.TUNTAP.UseCustomDNS;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var ProfileCount = int.Parse(ProfileCount_TextBox.Text);
|
||||
@@ -366,10 +278,11 @@ namespace Netch.Forms
|
||||
catch (FormatException)
|
||||
{
|
||||
ProfileCount_TextBox.Text = Global.Settings.ProfileCount.ToString();
|
||||
MessageBox.Show(Utils.i18N.Translate("ProfileCount value illegal. Try again."), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBoxX.Show(i18N.Translate("ProfileCount value illegal. Try again."));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var STUN_Server = STUN_ServerTextBox.Text;
|
||||
@@ -389,10 +302,11 @@ namespace Netch.Forms
|
||||
catch (FormatException)
|
||||
{
|
||||
ProfileCount_TextBox.Text = Global.Settings.ProfileCount.ToString();
|
||||
MessageBox.Show(Utils.i18N.Translate("STUN_ServerPort value illegal. Try again."), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBoxX.Show(i18N.Translate("STUN_ServerPort value illegal. Try again."));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Global.Settings.StartedTcping = EnableStartedTcping_CheckBox.Checked;
|
||||
@@ -411,7 +325,7 @@ namespace Netch.Forms
|
||||
catch (FormatException)
|
||||
{
|
||||
ProfileCount_TextBox.Text = Global.Settings.ProfileCount.ToString();
|
||||
MessageBox.Show(Utils.i18N.Translate("Detection interval value illegal. Try again."), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBoxX.Show(i18N.Translate("Detection interval value illegal. Try again."));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -432,9 +346,47 @@ namespace Netch.Forms
|
||||
Global.Settings.TUNTAP.ProxyDNS = ProxyDNSCheckBox.Checked;
|
||||
Global.Settings.TUNTAP.UseFakeDNS = UseFakeDNSCheckBox.Checked;
|
||||
|
||||
Utils.Configuration.Save();
|
||||
MessageBox.Show(Utils.i18N.Translate("Saved. Modify some settings need to restart the software"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
Configuration.Save();
|
||||
MessageBoxX.Show(i18N.Translate("Saved"));
|
||||
Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="portName"></param>
|
||||
/// <param name="portTextBox"></param>
|
||||
/// <param name="originPort"></param>
|
||||
/// <param name="portType"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="FormatException"></exception>
|
||||
private bool CheckPortText(string portName, ref TextBox portTextBox, ref int originPort, PortType portType = PortType.Both)
|
||||
{
|
||||
// 端口检查
|
||||
try
|
||||
{
|
||||
var port = int.Parse(portTextBox.Text);
|
||||
|
||||
if (port <= 0 || port >= 65536)
|
||||
{
|
||||
throw new FormatException();
|
||||
}
|
||||
|
||||
if (PortHelper.PortInUse(port, portType))
|
||||
{
|
||||
MessageBoxX.Show(i18N.TranslateFormat("The {0} port is in use.", portName));
|
||||
return false;
|
||||
}
|
||||
|
||||
originPort = port;
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Port value illegal. Try again."));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
using Netch.Utils;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Forms
|
||||
{
|
||||
@@ -38,16 +38,16 @@ namespace Netch.Forms
|
||||
|
||||
private void SubscribeForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
Text = Utils.i18N.Translate(Text);
|
||||
RemarkColumnHeader.Text = Utils.i18N.Translate(RemarkColumnHeader.Text);
|
||||
LinkColumnHeader.Text = Utils.i18N.Translate(LinkColumnHeader.Text);
|
||||
UseSelectedServerCheckBox.Text = Utils.i18N.Translate(UseSelectedServerCheckBox.Text);
|
||||
DeleteToolStripMenuItem.Text = Utils.i18N.Translate(DeleteToolStripMenuItem.Text);
|
||||
CopyLinkToolStripMenuItem.Text = Utils.i18N.Translate(CopyLinkToolStripMenuItem.Text);
|
||||
RemarkLabel.Text = Utils.i18N.Translate(RemarkLabel.Text);
|
||||
LinkLabel.Text = Utils.i18N.Translate(LinkLabel.Text);
|
||||
AddButton.Text = Utils.i18N.Translate(AddButton.Text);
|
||||
ControlButton.Text = Utils.i18N.Translate(ControlButton.Text);
|
||||
Text = i18N.Translate(Text);
|
||||
RemarkColumnHeader.Text = i18N.Translate(RemarkColumnHeader.Text);
|
||||
LinkColumnHeader.Text = i18N.Translate(LinkColumnHeader.Text);
|
||||
UseSelectedServerCheckBox.Text = i18N.Translate(UseSelectedServerCheckBox.Text);
|
||||
DeleteToolStripMenuItem.Text = i18N.Translate(DeleteToolStripMenuItem.Text);
|
||||
CopyLinkToolStripMenuItem.Text = i18N.Translate(CopyLinkToolStripMenuItem.Text);
|
||||
RemarkLabel.Text = i18N.Translate(RemarkLabel.Text);
|
||||
LinkLabel.Text = i18N.Translate(LinkLabel.Text);
|
||||
AddButton.Text = i18N.Translate(AddButton.Text);
|
||||
ControlButton.Text = i18N.Translate(ControlButton.Text);
|
||||
|
||||
UserAgentTextBox.Text = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36";
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace Netch.Forms
|
||||
}
|
||||
private void DeleteToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (MessageBox.Show(Utils.i18N.Translate("Delete or not ? Will clean up the corresponding group of items in the server list"), Utils.i18N.Translate("Information"), MessageBoxButtons.OKCancel, MessageBoxIcon.Information) == DialogResult.OK)
|
||||
if (MessageBoxX.Show(i18N.Translate("Delete or not ? Will clean up the corresponding group of items in the server list"), confirm: true) == DialogResult.OK)
|
||||
{
|
||||
if (SubscribeLinkListView.SelectedItems.Count > 0)
|
||||
{
|
||||
@@ -128,14 +128,14 @@ namespace Netch.Forms
|
||||
{
|
||||
//是否为新增订阅
|
||||
var saveFlag = true;
|
||||
Global.Settings.SubscribeLink.ForEach((subitem) =>
|
||||
Global.Settings.SubscribeLink.ForEach(subitem =>
|
||||
{
|
||||
if (subitem.Link.Equals(LinkTextBox.Text))
|
||||
{
|
||||
if (!subitem.Remark.Equals(RemarkTextBox.Text))
|
||||
{
|
||||
//修改了订阅备注,修改旧订阅服务器
|
||||
Global.Settings.Server.ForEach((serverItem) =>
|
||||
Global.Settings.Server.ForEach(serverItem =>
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -159,16 +159,14 @@ namespace Netch.Forms
|
||||
subitem.UserAgent = UserAgentTextBox.Text;
|
||||
saveFlag = false;
|
||||
|
||||
Utils.Configuration.Save();
|
||||
Configuration.Save();
|
||||
Global.Settings.UseProxyToUpdateSubscription = UseSelectedServerCheckBox.Checked;
|
||||
MessageBox.Show(Utils.i18N.Translate("Successfully saved"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
|
||||
return;
|
||||
MessageBoxX.Show(i18N.Translate("Saved"));
|
||||
}
|
||||
});
|
||||
if (saveFlag)
|
||||
{
|
||||
Global.Settings.SubscribeLink.Add(new Models.SubscribeLink
|
||||
Global.Settings.SubscribeLink.Add(new SubscribeLink
|
||||
{
|
||||
Remark = RemarkTextBox.Text,
|
||||
Link = LinkTextBox.Text,
|
||||
@@ -184,25 +182,25 @@ namespace Netch.Forms
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show(Utils.i18N.Translate("Links must start with http:// or https://"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBoxX.Show(i18N.Translate("Links must start with http:// or https://"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show(Utils.i18N.Translate("Link can not be empty"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBoxX.Show(i18N.Translate("Link can not be empty"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show(Utils.i18N.Translate("Remark can not be empty"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBoxX.Show(i18N.Translate("Remark can not be empty"));
|
||||
}
|
||||
}
|
||||
|
||||
private void ControlButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
Utils.Configuration.Save();
|
||||
Configuration.Save();
|
||||
Global.Settings.UseProxyToUpdateSubscription = UseSelectedServerCheckBox.Checked;
|
||||
MessageBox.Show(Utils.i18N.Translate("Successfully saved"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBoxX.Show(i18N.Translate("Saved"));
|
||||
Close();
|
||||
}
|
||||
/// <summary>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
|
||||
@@ -6,8 +7,16 @@ namespace Netch
|
||||
{
|
||||
public static class Global
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 主窗体
|
||||
/// 换行
|
||||
/// </summary>
|
||||
public static string EOF = "\r\n";
|
||||
|
||||
public static readonly string NetchDir = (AppDomain.CurrentDomain.BaseDirectory).TrimEnd();
|
||||
|
||||
/// <summary>
|
||||
/// 主窗体的静态实例
|
||||
/// </summary>
|
||||
public static Forms.MainForm MainForm;
|
||||
|
||||
|
||||
16
Netch/Models/STUN.Client.cs
Normal file
16
Netch/Models/STUN.Client.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace Netch.Models
|
||||
{
|
||||
public class STUN_Client
|
||||
{
|
||||
public enum NatType
|
||||
{
|
||||
UdpBlocked,
|
||||
OpenInternet,
|
||||
SymmetricUdpFirewall,
|
||||
FullCone,
|
||||
RestrictedCone,
|
||||
PortRestrictedCone,
|
||||
Symmetric
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -156,32 +156,7 @@ namespace Netch.Models
|
||||
|
||||
if (Country == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var databaseReader = new DatabaseReader("bin\\GeoLite2-Country.mmdb");
|
||||
|
||||
if (IPAddress.TryParse(Hostname, out _) == true)
|
||||
{
|
||||
Country = databaseReader.Country(Hostname).Country.IsoCode;
|
||||
}
|
||||
else
|
||||
{
|
||||
var DnsResult = DNS.Lookup(Hostname);
|
||||
|
||||
if (DnsResult != null)
|
||||
{
|
||||
Country = databaseReader.Country(DnsResult).Country.IsoCode;
|
||||
}
|
||||
else
|
||||
{
|
||||
Country = "UN";
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Country = "UN";
|
||||
}
|
||||
Country = Utils.Utils.GetCityCode(Hostname);
|
||||
}
|
||||
|
||||
Group = Group.Equals("None") || Group.Equals("") ? "NONE" : Group;
|
||||
|
||||
@@ -142,7 +142,7 @@ namespace Netch.Models
|
||||
/// <summary>
|
||||
/// 已保存的快捷配置
|
||||
/// </summary>
|
||||
public List<Profile> profiles = new List<Profile>();
|
||||
public List<Profile> Profiles = new List<Profile>();
|
||||
|
||||
/// <summary>
|
||||
/// 快捷配置数量
|
||||
|
||||
@@ -36,4 +36,14 @@
|
||||
/// </summary>
|
||||
Terminating
|
||||
}
|
||||
}
|
||||
|
||||
public static class StateExtension
|
||||
{
|
||||
public static string GetStatusString(State state)
|
||||
{
|
||||
if (state == State.Waiting)
|
||||
return "Waiting for command";
|
||||
return state.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,7 @@ namespace Netch.Models
|
||||
public string cert;
|
||||
public string cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA";
|
||||
public string cipher_tls13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384";
|
||||
public string sni;
|
||||
public string sni = string.Empty;
|
||||
public List<string> alpn = new List<string>()
|
||||
{
|
||||
"h2",
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Controllers;
|
||||
using Netch.Forms;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch
|
||||
{
|
||||
@@ -24,14 +25,14 @@ namespace Netch
|
||||
// 清理上一次的日志文件,防止淤积占用磁盘空间
|
||||
if (Directory.Exists("logging"))
|
||||
{
|
||||
DirectoryInfo directory = new DirectoryInfo("logging");
|
||||
var directory = new DirectoryInfo("logging");
|
||||
|
||||
foreach (FileInfo file in directory.GetFiles())
|
||||
foreach (var file in directory.GetFiles())
|
||||
{
|
||||
file.Delete();
|
||||
}
|
||||
|
||||
foreach (DirectoryInfo dir in directory.GetDirectories())
|
||||
foreach (var dir in directory.GetDirectories())
|
||||
{
|
||||
dir.Delete(true);
|
||||
}
|
||||
@@ -50,67 +51,21 @@ namespace Netch
|
||||
}
|
||||
|
||||
// 加载配置
|
||||
Utils.Configuration.Load();
|
||||
Configuration.Load();
|
||||
|
||||
// 加载系统语言
|
||||
if (Global.Settings.Language.Equals("System"))
|
||||
{
|
||||
// 得到当前线程语言代码
|
||||
var culture = CultureInfo.CurrentCulture.Name;
|
||||
|
||||
// 尝试加载内置中文语言
|
||||
if (culture == "zh-CN")
|
||||
{
|
||||
// 加载语言
|
||||
Utils.i18N.Load(Encoding.UTF8.GetString(Properties.Resources.zh_CN));
|
||||
}
|
||||
|
||||
// 从外置文件中加载语言
|
||||
if (File.Exists($"i18n\\{culture}"))
|
||||
{
|
||||
// 加载语言
|
||||
Utils.i18N.Load(File.ReadAllText($"i18n\\{culture}"));
|
||||
}
|
||||
}
|
||||
|
||||
if (Global.Settings.Language.Equals("zh-CN"))
|
||||
{
|
||||
// 加载内置中文
|
||||
Utils.i18N.Load(Encoding.UTF8.GetString(Properties.Resources.zh_CN));
|
||||
}
|
||||
else if (Global.Settings.Language.Equals("en-US"))
|
||||
{
|
||||
// 加载内置英文
|
||||
Utils.i18N.Load(Global.Settings.Language);
|
||||
}
|
||||
else if (File.Exists($"i18n\\{Global.Settings.Language}"))
|
||||
{
|
||||
// 从外置文件中加载语言
|
||||
Utils.i18N.Load(File.ReadAllText($"i18n\\{Global.Settings.Language}"));
|
||||
}
|
||||
// 加载语言
|
||||
i18N.Load(Global.Settings.Language);
|
||||
|
||||
// 记录当前系统语言
|
||||
Utils.Logging.Info($"当前语言:{Global.Settings.Language}");
|
||||
Logging.Info($"当前语言:{Global.Settings.Language}");
|
||||
Logging.Info($"版本:{UpdateChecker.Owner}/{UpdateChecker.Repo} {UpdateChecker.Version}");
|
||||
Logging.Info($"主程序创建日期:{File.GetCreationTime(Global.NetchDir + "\\Netch.exe"):yyyy-M-d HH:mm}");
|
||||
|
||||
// 检查是否已经运行
|
||||
if (!mutex.WaitOne(0, false))
|
||||
{
|
||||
// 弹出提示
|
||||
MessageBox.Show(Utils.i18N.Translate("Netch is already running"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
|
||||
// 退出进程
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
var OS = Environment.Is64BitOperatingSystem ? "x64" : "x86";
|
||||
var PROC = Environment.Is64BitProcess ? "x64" : "x86";
|
||||
|
||||
// 如果系统位数与程序位数不一致
|
||||
if (OS != PROC)
|
||||
{
|
||||
|
||||
// 弹出提示
|
||||
MessageBox.Show($"{Utils.i18N.Translate("Netch is not compatible with your system.")}\n{Utils.i18N.Translate("Current arch of Netch:")} {PROC}\n{Utils.i18N.Translate("Current arch of system:")} {OS}", Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBoxX.Show(i18N.Translate("Netch is already running"));
|
||||
|
||||
// 退出进程
|
||||
Environment.Exit(1);
|
||||
@@ -122,7 +77,7 @@ namespace Netch
|
||||
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(Global.MainForm = new Forms.MainForm());
|
||||
Application.Run(Global.MainForm = new MainForm());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,11 +46,20 @@
|
||||
<Isolated>false</Isolated>
|
||||
<EmbedInteropTypes>false</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
<COMReference Include="NetFwTypeLib.dll">
|
||||
<Guid>58fbcf7c-e7a9-467c-80b3-fc65e8fcca08</Guid>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>0</VersionMinor>
|
||||
<Lcid>0</Lcid>
|
||||
<WrapperTool>tlbimp</WrapperTool>
|
||||
<Isolated>false</Isolated>
|
||||
</COMReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ini-parser" Version="2.5.2" />
|
||||
<PackageReference Include="MaxMind.GeoIP2" Version="3.2.0" />
|
||||
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.56" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="System.Buffers" Version="4.5.1" />
|
||||
<PackageReference Include="WindowsAPICodePack-Shell" Version="1.1.1" />
|
||||
@@ -61,6 +70,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="System.Management" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.ServiceProcess" />
|
||||
<Reference Include="System.Web" />
|
||||
@@ -97,6 +107,6 @@
|
||||
</ItemGroup>
|
||||
<ProjectExtensions><VisualStudio><UserProperties /></VisualStudio></ProjectExtensions>
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||
<Exec Command="@ECHO OFF
RD /S /Q $(TargetDir)bin > NUL 2>&1
RD /S /Q $(TargetDir)i18n > NUL 2>&1
RD /S /Q $(TargetDir)mode > NUL 2>&1

MKDIR $(TargetDir)bin > NUL 2>&1
MKDIR $(TargetDir)i18n > NUL 2>&1
MKDIR $(TargetDir)mode > NUL 2>&1

COPY /Y $(SolutionDir)binaries\* $(TargetDir)bin > NUL 2>&1
COPY /Y $(SolutionDir)translations\i18n\* $(TargetDir)i18n > NUL 2>&1
COPY /Y $(SolutionDir)modes\mode\* $(TargetDir)mode > NUL 2>&1
MKDIR $(TargetDir)bin\tap-driver > NUL 2>&1
COPY /Y $(SolutionDir)binaries\tap-driver\* $(TargetDir)bin\tap-driver > NUL 2>&1

DEL / f $(TargetDir)\*.config
DEL / f $(TargetDir)\*.pdb" />
|
||||
<Exec Command="@ECHO OFF
RD /S /Q $(TargetDir)bin > NUL 2>&1
RD /S /Q $(TargetDir)i18n > NUL 2>&1
RD /S /Q $(TargetDir)mode > NUL 2>&1

MKDIR $(TargetDir)bin > NUL 2>&1
MKDIR $(TargetDir)i18n > NUL 2>&1
MKDIR $(TargetDir)mode > NUL 2>&1

COPY /Y $(SolutionDir)binaries\* $(TargetDir)bin > NUL 2>&1
COPY /Y $(SolutionDir)translations\i18n\* $(TargetDir)i18n > NUL 2>&1
COPY /Y $(SolutionDir)modes\mode\* $(TargetDir)mode > NUL 2>&1
MKDIR $(TargetDir)bin\tap-driver > NUL 2>&1
COPY /Y $(SolutionDir)binaries\tap-driver\* $(TargetDir)bin\tap-driver > NUL 2>&1

DEL / f $(TargetDir)\*.config
DEL / f $(TargetDir)\*.pdb
RD /s /Q $(TargetDir)\x86" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
{
|
||||
protected override void OnRenderToolStripBorder(System.Windows.Forms.ToolStripRenderEventArgs e)
|
||||
{
|
||||
// 跳过
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,8 @@
|
||||
"Information": "信息",
|
||||
"Error": "错误",
|
||||
|
||||
"If this is your first time using this software,\n please check http://netch.org to install supports first,\n or the program may report errors.": "如果你是第一次使用本软件,\n请务必前往http://netch.org安装程序所需依赖,\n否则程序将无法正常运行!",
|
||||
"Netch is already running": "Netch 已经在运行中",
|
||||
"Netch is not compatible with your system.": "Netch 和你的系统不兼容",
|
||||
"Current arch of Netch:": "当前 Netch 架构:",
|
||||
"Current arch of system:": "当前系统架构:",
|
||||
|
||||
"Start": "启动",
|
||||
"Stop": "停止",
|
||||
@@ -16,15 +14,12 @@
|
||||
"Started": "已启动",
|
||||
"Stopping": "正在停止中",
|
||||
"Stopped": "已停止",
|
||||
"Starting Shadowsocks": "正在启动 Shadowsocks",
|
||||
"Starting ShadowsocksR": "正在启动 ShadowsocksR",
|
||||
"Starting V2ray": "正在启动 V2Ray",
|
||||
"Starting Trojan": "正在启动 Trojan",
|
||||
"Starting ": "正在启动 ",
|
||||
"Starting Tap": "正在启动 TUN/TAP",
|
||||
"Starting NatTester": "正在启动 NAT 测试",
|
||||
"Starting LocalDns service": "正在启动本地 DNS 服务",
|
||||
"Starting Redirector": "正在启动 Redirector",
|
||||
"ReStarting Redirector": "正常启动失败,正在尝试重新启动 Redirector",
|
||||
"Restarting Redirector": "正常启动失败,正在尝试重新启动 Redirector",
|
||||
"Starting netfilter2 Service": "正在启动 netfilter2 服务",
|
||||
"Starting dns Service": "正在启动 DNS 服务",
|
||||
"SetupBypass": "设置绕行规则",
|
||||
@@ -42,12 +37,10 @@
|
||||
"Add [ShadowsocksR] Server": "添加 [ShadowsocksR] 服务器",
|
||||
"Add [VMess] Server": "添加 [VMess] 服务器",
|
||||
"Add [Trojan] Server": "添加 [Trojan] 服务器",
|
||||
"VMess is currently not supported. For more information, please see our Github releases\n\nPress OK will redirect": "当前不支持 VMess 服务器。需要更多信息请查看我们的 Github 发布页\n\n点击 OK 将会跳转",
|
||||
"Netch is now minimized to the notification bar, double click this icon to restore.": "Netch 已最小化至通知栏,双击此图标恢复窗口。",
|
||||
"New version available": "发现新版本",
|
||||
"Mode": "模式",
|
||||
"Create Process Mode": "创建进程模式",
|
||||
"Manage Process Mode": "管理进程模式",
|
||||
"Edit Process Mode": "修改进程模式",
|
||||
|
||||
"Address": "地址",
|
||||
@@ -81,9 +74,6 @@
|
||||
"Update servers error from {0}": "从 {0} 更新服务器失败",
|
||||
|
||||
"Options": "选项",
|
||||
"Restart Service": "重启服务",
|
||||
"Restarting service": "正在重启服务中",
|
||||
"Service has been restarted": "服务已重启",
|
||||
"Uninstall Service": "卸载服务",
|
||||
"Uninstalling Service": "正在卸载服务中",
|
||||
"Service has been uninstalled": "服务已卸载",
|
||||
@@ -99,6 +89,7 @@
|
||||
"Reinstall TUN/TAP driver successfully": "重装 TUN/TAP 驱动成功",
|
||||
"Reinstall TUN/TAP driver failed": "重装 TUN/TAP 驱动失败",
|
||||
"Reinstalling TUN/TAP driver": "正在重装 TUN/TAP 驱动",
|
||||
"Open Directory": "打开目录",
|
||||
|
||||
"About": "关于",
|
||||
"Telegram Channel": "Telegram 频道",
|
||||
@@ -108,9 +99,11 @@
|
||||
|
||||
"Please press Stop button first": "请先点击停止按钮",
|
||||
"Please select a server first": "请先选择一个服务器",
|
||||
"Please select an mode first": "请先选择一个模式",
|
||||
"Please select a mode first": "请先选择一个模式",
|
||||
"Please enter a profile name first": "请先为该配置设置一个名称",
|
||||
"No saved profile here. Save a profile first by Ctrl+Click on the button": "当前按钮下没有保存配置,请先使用 CTRL + 左键 点击该按钮保存一个配置",
|
||||
"Remove this Profile?": "确认删除此配置?",
|
||||
"Profile Removed!": "配置已删除!",
|
||||
|
||||
"Used": "已使用",
|
||||
"Status": "状态",
|
||||
@@ -144,7 +137,6 @@
|
||||
"Remark can not be empty": "备注不可为空",
|
||||
"Link can not be empty": "链接不可为空",
|
||||
"Link must start with http:// or https://": "链接必须以 http:// 或 https:// 开头",
|
||||
"Successfully saved": "保存成功",
|
||||
"Please fill in alterID": "请填写额外ID",
|
||||
|
||||
"Settings": "设置",
|
||||
@@ -165,13 +157,12 @@
|
||||
"Port value illegal. Try again.": "端口值非法。请重试。",
|
||||
"Check update when opened": "打开软件时检查更新",
|
||||
"Start Shadowsocks from DLL (No support for ACL)": "SS DLL(推荐使用,不支持 ACL)",
|
||||
"ProfileCount": "快捷配置数量(重启软件生效)",
|
||||
"ProfileCount": "快捷配置数量",
|
||||
"ProfileCount value illegal. Try again.": "快捷配置数值非法。请重试。",
|
||||
"STUN_ServerPort value illegal. Try again.": "STUN 端口数值非法。请重试。",
|
||||
"Detection interval value illegal. Try again.": "检测间隔值非法。请重试。",
|
||||
"TUN/TAP driver is not detected. Is it installed now?": "未检测到 TUN/TAP 驱动,是否现在安装?",
|
||||
"Failed to set the system proxy, it may be caused by the lack of dependent programs. Do you want to jump to Netch's official website to download dependent programs?": "设置系统代理失败,可能是缺少依赖导致,是否跳转 Netch 官网下载依赖程序?",
|
||||
"Experimental function": "实验性功能",
|
||||
"Delay test after start": "启动后延迟测试",
|
||||
"Enable": "启用",
|
||||
"Detection interval(sec)": "检测间隔(秒)",
|
||||
@@ -179,7 +170,6 @@
|
||||
"STUN Server Port": "STUN 服务器端口",
|
||||
"Custom ACL": "自定义 ACL 规则",
|
||||
"Language": "语言",
|
||||
"Saved. Modify some settings need to restart the software": "保存成功,修改部分设置需重启软件",
|
||||
|
||||
"Profile": "配置名",
|
||||
"Profiles": "配置",
|
||||
@@ -187,6 +177,9 @@
|
||||
|
||||
"Show": "显示",
|
||||
"Exit": "退出",
|
||||
"Unable to start? Click me to download": "无法启动?点我下载依赖",
|
||||
|
||||
"The {0} port is in use.": "{0} 端口已被占用",
|
||||
|
||||
"Bypass LAN": "[网页代理] 绕过局域网",
|
||||
"Bypass LAN (Non System Proxy)": "[网页代理] 绕过局域网(不设置系统代理)",
|
||||
|
||||
@@ -1,15 +1,28 @@
|
||||
namespace Netch.Utils
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Diagnostics.Tracing.Parsers;
|
||||
using Microsoft.Diagnostics.Tracing.Session;
|
||||
using Netch.Controllers;
|
||||
using Netch.Forms;
|
||||
using Netch.Models;
|
||||
|
||||
namespace Netch.Utils
|
||||
{
|
||||
public static class Bandwidth
|
||||
{
|
||||
public static int received;
|
||||
|
||||
/// <summary>
|
||||
/// 计算流量
|
||||
/// </summary>
|
||||
/// <param name="bandwidth">流量</param>
|
||||
/// <returns>带单位的流量字符串</returns>
|
||||
public static string Compute(long bandwidth)
|
||||
/// 计算流量
|
||||
/// </summary>
|
||||
/// <param name="bandwidth">流量</param>
|
||||
/// <returns>带单位的流量字符串</returns>
|
||||
public static string Compute(long bandwidth)
|
||||
{
|
||||
string[] units = { "KB", "MB", "GB", "TB", "PB" };
|
||||
string[] units = {"KB", "MB", "GB", "TB", "PB"};
|
||||
double result = bandwidth;
|
||||
var i = -1;
|
||||
|
||||
@@ -18,7 +31,91 @@
|
||||
i++;
|
||||
} while ((result /= 1024) > 1024);
|
||||
|
||||
return string.Format("{0} {1}", System.Math.Round(result, 2), units[i]);
|
||||
if (result < 0)
|
||||
{
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return string.Format("{0} {1}", Math.Round(result, 2), units[i]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据程序名统计流量
|
||||
/// </summary>
|
||||
/// <param name="ProcessName"></param>
|
||||
public static void NetTraffic(Server server, Mode mode, MainController mainController)
|
||||
{
|
||||
var counterLock = new object();
|
||||
//int sent = 0;
|
||||
|
||||
//var processList = Process.GetProcessesByName(ProcessName).Select(p => p.Id).ToHashSet();
|
||||
var instances = new List<Process>();
|
||||
if (server.Type.Equals("Socks5") && mainController.pModeController.Name == "HTTP")
|
||||
{
|
||||
instances.Add(((HTTPController) mainController.pModeController).pPrivoxyController.Instance);
|
||||
}
|
||||
else if (server.Type.Equals("SS") && Global.Settings.BootShadowsocksFromDLL)
|
||||
{
|
||||
instances.Add(Process.GetCurrentProcess());
|
||||
}
|
||||
else if (mainController.pEncryptedProxyController != null)
|
||||
{
|
||||
instances.Add(mainController.pEncryptedProxyController.Instance);
|
||||
}
|
||||
else if (mainController.pModeController != null)
|
||||
{
|
||||
instances.Add(mainController.pModeController.Instance);
|
||||
}
|
||||
|
||||
var processList = instances.Select(instance => instance.Id).ToList();
|
||||
|
||||
Logging.Info("流量统计进程:" + string.Join(",", instances.Select(instance => $"({instance.Id})"+instance.ProcessName).ToArray()));
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
using (var session = new TraceEventSession("KernelAndClrEventsSession"))
|
||||
{
|
||||
session.EnableKernelProvider(KernelTraceEventParser.Keywords.NetworkTCPIP);
|
||||
|
||||
//这玩意儿上传和下载得到的data是一样的:)
|
||||
//所以暂时没办法区分上传下载流量
|
||||
session.Source.Kernel.TcpIpRecv += data =>
|
||||
{
|
||||
if (processList.Contains(data.ProcessID))
|
||||
{
|
||||
lock (counterLock)
|
||||
received += data.size;
|
||||
//Logging.Info($"TcpIpRecv: {Compute(data.size)}");
|
||||
}
|
||||
};
|
||||
session.Source.Kernel.UdpIpRecv += data =>
|
||||
{
|
||||
if (processList.Contains(data.ProcessID))
|
||||
{
|
||||
lock (counterLock)
|
||||
received += data.size;
|
||||
//Logging.Info($"UdpIpRecv: {Compute(data.size)}");
|
||||
}
|
||||
};
|
||||
|
||||
session.Source.Process();
|
||||
}
|
||||
});
|
||||
|
||||
if ((Convert.ToInt32(Global.MainForm.LastDownloadBandwidth) - Convert.ToInt32(received)) == 0)
|
||||
{
|
||||
Global.MainForm.OnBandwidthUpdated(0);
|
||||
received = 0;
|
||||
}
|
||||
|
||||
while (Global.MainForm.State != State.Stopped)
|
||||
{
|
||||
Task.Delay(1000).Wait();
|
||||
lock (counterLock)
|
||||
{
|
||||
Global.MainForm.OnBandwidthUpdated(Convert.ToInt64(received));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@ using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Models;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Netch.Utils
|
||||
{
|
||||
@@ -26,49 +28,50 @@ namespace Netch.Utils
|
||||
/// </summary>
|
||||
public static void Load()
|
||||
{
|
||||
if (Directory.Exists(DATA_DIR))
|
||||
if (Directory.Exists(DATA_DIR) && File.Exists(SETTINGS_JSON))
|
||||
{
|
||||
if (File.Exists(SETTINGS_JSON))
|
||||
try
|
||||
{
|
||||
try
|
||||
Global.Settings = JsonConvert.DeserializeObject<Setting>(File.ReadAllText(SETTINGS_JSON));
|
||||
if (Global.Settings.Server != null && Global.Settings.Server.Count > 0)
|
||||
{
|
||||
Global.Settings = Newtonsoft.Json.JsonConvert.DeserializeObject<Models.Setting>(File.ReadAllText(SETTINGS_JSON));
|
||||
if (Global.Settings.Server != null && Global.Settings.Server.Count > 0)
|
||||
// 如果是旧版 Server 类,使用旧版 Server 类进行读取
|
||||
if (Global.Settings.Server[0].Hostname == null)
|
||||
{
|
||||
// 如果是旧版 Server 类,使用旧版 Server 类进行读取
|
||||
if (Global.Settings.Server[0].Hostname == null)
|
||||
var LegacySettingConfig = JsonConvert.DeserializeObject<LegacySetting>(File.ReadAllText(SETTINGS_JSON));
|
||||
for (var i = 0; i < LegacySettingConfig.Server.Count; i++)
|
||||
{
|
||||
var LegacySettingConfig = Newtonsoft.Json.JsonConvert.DeserializeObject<Models.LegacySetting>(File.ReadAllText(SETTINGS_JSON));
|
||||
for (var i = 0; i < LegacySettingConfig.Server.Count; i++)
|
||||
Global.Settings.Server[i].Hostname = LegacySettingConfig.Server[i].Address;
|
||||
if (Global.Settings.Server[i].Type == "Shadowsocks")
|
||||
{
|
||||
Global.Settings.Server[i].Hostname = LegacySettingConfig.Server[i].Address;
|
||||
if (Global.Settings.Server[i].Type == "Shadowsocks")
|
||||
{
|
||||
Global.Settings.Server[i].Type = "SS";
|
||||
Global.Settings.Server[i].Plugin = LegacySettingConfig.Server[i].OBFS;
|
||||
Global.Settings.Server[i].PluginOption = LegacySettingConfig.Server[i].OBFSParam;
|
||||
}
|
||||
else if (Global.Settings.Server[i].Type == "ShadowsocksR")
|
||||
{
|
||||
Global.Settings.Server[i].Type = "SSR";
|
||||
}
|
||||
else if (Global.Settings.Server[i].Type == "VMess")
|
||||
{
|
||||
Global.Settings.Server[i].QUICSecure = LegacySettingConfig.Server[i].QUICSecurity;
|
||||
}
|
||||
Global.Settings.Server[i].Type = "SS";
|
||||
Global.Settings.Server[i].Plugin = LegacySettingConfig.Server[i].OBFS;
|
||||
Global.Settings.Server[i].PluginOption = LegacySettingConfig.Server[i].OBFSParam;
|
||||
}
|
||||
else if (Global.Settings.Server[i].Type == "ShadowsocksR")
|
||||
{
|
||||
Global.Settings.Server[i].Type = "SSR";
|
||||
}
|
||||
else if (Global.Settings.Server[i].Type == "VMess")
|
||||
{
|
||||
Global.Settings.Server[i].QUICSecure = LegacySettingConfig.Server[i].QUICSecurity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch (Newtonsoft.Json.JsonException)
|
||||
{
|
||||
catch (JsonException)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 弹出提示
|
||||
i18N.Load("System");
|
||||
MessageBoxX.Show(i18N.Translate("If this is your first time using this software,\n please check http://netch.org to install supports first,\n or the program may report errors."));
|
||||
|
||||
// 创建 data 文件夹并保存默认设置
|
||||
Save();
|
||||
}
|
||||
@@ -84,115 +87,9 @@ namespace Netch.Utils
|
||||
{
|
||||
Directory.CreateDirectory(DATA_DIR);
|
||||
}
|
||||
File.WriteAllText(SETTINGS_JSON, Newtonsoft.Json.JsonConvert.SerializeObject(Global.Settings, Newtonsoft.Json.Formatting.Indented));
|
||||
File.WriteAllText(SETTINGS_JSON, JsonConvert.SerializeObject(Global.Settings, Formatting.Indented));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 搜索出口
|
||||
/// </summary>
|
||||
public static bool SearchOutbounds()
|
||||
{
|
||||
Logging.Info("正在搜索出口中");
|
||||
|
||||
if (Win32Native.GetBestRoute(BitConverter.ToUInt32(IPAddress.Parse("114.114.114.114").GetAddressBytes(), 0), 0, out var pRoute) == 0)
|
||||
{
|
||||
Global.Adapter.Index = pRoute.dwForwardIfIndex;
|
||||
Global.Adapter.Gateway = new IPAddress(pRoute.dwForwardNextHop);
|
||||
Logging.Info($"当前 网关 地址:{Global.Adapter.Gateway}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Info("GetBestRoute 搜索失败");
|
||||
return false;
|
||||
}
|
||||
|
||||
Logging.Info($"搜索适配器index:{Global.Adapter.Index}");
|
||||
var AddressGot = false;
|
||||
foreach (var adapter in NetworkInterface.GetAllNetworkInterfaces())
|
||||
{
|
||||
try
|
||||
{
|
||||
var adapterProperties = adapter.GetIPProperties();
|
||||
var p = adapterProperties.GetIPv4Properties();
|
||||
Logging.Info($"检测适配器:{adapter.Name} {adapter.Id} {adapter.Description}, index: {p.Index}");
|
||||
|
||||
// 通过索引查找对应适配器的 IPv4 地址
|
||||
if (p.Index == Global.Adapter.Index)
|
||||
{
|
||||
var AdapterIPs = "";
|
||||
|
||||
foreach (var ip in adapterProperties.UnicastAddresses)
|
||||
{
|
||||
if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
AddressGot = true;
|
||||
Global.Adapter.Address = ip.Address;
|
||||
Logging.Info($"当前出口 IPv4 地址:{Global.Adapter.Address}");
|
||||
break;
|
||||
}
|
||||
AdapterIPs = $"{ip.Address} | ";
|
||||
}
|
||||
|
||||
if (!AddressGot)
|
||||
{
|
||||
if (AdapterIPs.Length > 3)
|
||||
{
|
||||
AdapterIPs = AdapterIPs.Substring(0, AdapterIPs.Length - 3);
|
||||
Logging.Info($"所有出口地址:{AdapterIPs}");
|
||||
}
|
||||
Logging.Info("出口无 IPv4 地址,当前只支持 IPv4 地址");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception)
|
||||
{ }
|
||||
}
|
||||
|
||||
if (!AddressGot)
|
||||
{
|
||||
Logging.Info("无法找到当前使用适配器");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 搜索 TUN/TAP 适配器的索引
|
||||
Global.TUNTAP.ComponentID = TUNTAP.GetComponentID();
|
||||
if (string.IsNullOrEmpty(Global.TUNTAP.ComponentID))
|
||||
{
|
||||
Logging.Info("未找到可用 TUN/TAP 适配器");
|
||||
if (MessageBox.Show(i18N.Translate("TUN/TAP driver is not detected. Is it installed now?"), i18N.Translate("Information"), MessageBoxButtons.OKCancel, MessageBoxIcon.Information) == DialogResult.OK)
|
||||
{
|
||||
addtap();
|
||||
//给点时间,不然立马安装完毕就查找适配器可能会导致找不到适配器ID
|
||||
Thread.Sleep(1000);
|
||||
Global.TUNTAP.ComponentID = TUNTAP.GetComponentID();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//MessageBox.Show(i18N.Translate("Please install TAP-Windows and create an TUN/TAP adapter manually"), i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
// return false;
|
||||
}
|
||||
|
||||
foreach (var adapter in NetworkInterface.GetAllNetworkInterfaces())
|
||||
{
|
||||
if (adapter.Id == Global.TUNTAP.ComponentID)
|
||||
{
|
||||
Global.TUNTAP.Adapter = adapter;
|
||||
Global.TUNTAP.Index = adapter.GetIPProperties().GetIPv4Properties().Index;
|
||||
|
||||
Logging.Info($"找到适配器:{adapter.Id}");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Logging.Info("无法找到出口");
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 安装tap网卡
|
||||
/// </summary>
|
||||
@@ -200,7 +97,7 @@ namespace Netch.Utils
|
||||
{
|
||||
Logging.Info("正在安装 TUN/TAP 适配器");
|
||||
//安装Tap Driver
|
||||
Process installProcess = new Process();
|
||||
var installProcess = new Process();
|
||||
installProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
||||
installProcess.StartInfo.FileName = Path.Combine("bin/tap-driver", "addtap.bat");
|
||||
installProcess.Start();
|
||||
@@ -213,7 +110,7 @@ namespace Netch.Utils
|
||||
public static void deltapall()
|
||||
{
|
||||
Logging.Info("正在卸载 TUN/TAP 适配器");
|
||||
Process installProcess = new Process();
|
||||
var installProcess = new Process();
|
||||
installProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
||||
installProcess.StartInfo.FileName = Path.Combine("bin/tap-driver", "deltapall.bat");
|
||||
installProcess.Start();
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using System.Management;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
|
||||
namespace Netch.Utils
|
||||
{
|
||||
@@ -45,5 +48,51 @@ namespace Netch.Utils
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置DNS
|
||||
/// </summary>
|
||||
/// <param name="dns"></param>
|
||||
public static void SetDNS(string[] dns)
|
||||
{
|
||||
ManagementClass wmi = new ManagementClass("Win32_NetworkAdapterConfiguration");
|
||||
ManagementObjectCollection moc = wmi.GetInstances();
|
||||
ManagementBaseObject inPar = null;
|
||||
ManagementBaseObject outPar = null;
|
||||
foreach (ManagementObject mo in moc)
|
||||
{
|
||||
//如果没有启用IP设置的网络设备则跳过,如果是虚拟机网卡也跳过
|
||||
if (!(bool)mo["IPEnabled"] ||
|
||||
mo["Description"].ToString().Contains("Virtual") ||
|
||||
mo["Description"].ToString().Contains("VMware") ||
|
||||
mo["Description"].ToString().Contains("TAP"))
|
||||
continue;
|
||||
|
||||
//设置DNS地址
|
||||
if (dns != null)
|
||||
{
|
||||
inPar = mo.GetMethodParameters("SetDNSServerSearchOrder");
|
||||
inPar["DNSServerSearchOrder"] = dns;
|
||||
outPar = mo.InvokeMethod("SetDNSServerSearchOrder", inPar, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 从网卡获取ip设置信息
|
||||
/// </summary>
|
||||
public static string[] getSystemDns()
|
||||
{
|
||||
var systemDns = new[] { "223.5.5.5", "1.1.1.1" };
|
||||
foreach (var network in NetworkInterface.GetAllNetworkInterfaces())
|
||||
if (!network.Description.Contains("Virtual") &&
|
||||
!network.Description.Contains("VMware") &&
|
||||
!network.Description.Contains("TAP") &&
|
||||
network.OperationalStatus == OperationalStatus.Up &&
|
||||
network.GetIPProperties()?.GatewayAddresses.Count != 0)
|
||||
{
|
||||
systemDns = network.GetIPProperties().DnsAddresses.Select(dns => dns.ToString()).ToArray();
|
||||
}
|
||||
|
||||
return systemDns;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
146
Netch/Utils/Firewall.cs
Normal file
146
Netch/Utils/Firewall.cs
Normal file
@@ -0,0 +1,146 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NetFwTypeLib;
|
||||
|
||||
namespace Netch.Utils
|
||||
{
|
||||
public class Firewall
|
||||
{
|
||||
private static readonly string[] ProgramPath =
|
||||
{
|
||||
"bin/NTT.exe",
|
||||
"bin/Privoxy.exe",
|
||||
"bin/Redirector.exe",
|
||||
"bin/Shadowsocks.exe",
|
||||
"bin/ShadowsocksR.exe",
|
||||
"bin/Trojan.exe",
|
||||
"bin/tun2socks.exe",
|
||||
"bin/unbound.exe",
|
||||
"bin/v2ray.exe",
|
||||
"Netch.exe"
|
||||
};
|
||||
|
||||
private const string Netch = "Netch";
|
||||
private const string NetchAutoRule = "NetchAutoRule";
|
||||
|
||||
/// <summary>
|
||||
/// 添加防火墙规则 (非 Netch 自带程序)
|
||||
/// </summary>
|
||||
/// <param name="exeFullPath"></param>
|
||||
public static void AddFwRule(string exeFullPath)
|
||||
{
|
||||
AddFwRule(NetchAutoRule, exeFullPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除防火墙规则 (非 Netch 自带程序)
|
||||
/// </summary>
|
||||
public static void RemoveFwRules()
|
||||
{
|
||||
try
|
||||
{
|
||||
RemoveFwRules(NetchAutoRule);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Warning("添加防火墙规则错误\n" + e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Netch 自带程序添加防火墙
|
||||
/// </summary>
|
||||
public static void AddNetchFwRules()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (GetFwRulePath(Netch).StartsWith(Global.NetchDir) && GetFwRulesNumber(Netch) >= ProgramPath.Length) return;
|
||||
RemoveNetchFwRules();
|
||||
foreach (var p in ProgramPath)
|
||||
{
|
||||
var path = Path.GetFullPath(p);
|
||||
if (File.Exists(path))
|
||||
{
|
||||
AddFwRule("Netch", path);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Warning("添加防火墙规则错误(如已关闭防火墙则可无视此错误)\n" + e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除防火墙规则 (Netch 自带程序)
|
||||
/// </summary>
|
||||
private static void RemoveNetchFwRules()
|
||||
{
|
||||
try
|
||||
{
|
||||
RemoveFwRules(Netch);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Warning("清除防火墙规则错误\n" + e);
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
#region 封装
|
||||
|
||||
private static readonly INetFwPolicy2 FwPolicy = (INetFwPolicy2) Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2"));
|
||||
|
||||
private static void AddFwRule(string ruleName, string exeFullPath)
|
||||
{
|
||||
var rule = NewFwRule();
|
||||
|
||||
rule.Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW;
|
||||
// ApplicationName 大小不敏感
|
||||
rule.ApplicationName = exeFullPath;
|
||||
// rule.Description = "";
|
||||
rule.Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN;
|
||||
rule.Enabled = true;
|
||||
rule.InterfaceTypes = "All";
|
||||
rule.Name = ruleName;
|
||||
|
||||
FwPolicy.Rules.Add(rule);
|
||||
}
|
||||
|
||||
private static void RemoveFwRules(string ruleName)
|
||||
{
|
||||
var c = GetFwRulesNumber(ruleName);
|
||||
foreach (var _ in new bool[c])
|
||||
{
|
||||
FwPolicy.Rules.Remove(ruleName);
|
||||
}
|
||||
}
|
||||
|
||||
private static INetFwRule NewFwRule()
|
||||
{
|
||||
return (INetFwRule) Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FWRule"));
|
||||
}
|
||||
|
||||
|
||||
private static string GetFwRulePath(string ruleName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var rule = (INetFwRule2) FwPolicy.Rules.Item(ruleName);
|
||||
return rule.ApplicationName;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private static int GetFwRulesNumber(string ruleName)
|
||||
{
|
||||
return FwPolicy.Rules.Cast<INetFwRule2>().Count(rule => rule.Name == ruleName);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -5,10 +5,7 @@ namespace Netch.Utils
|
||||
{
|
||||
public static class Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// 换行
|
||||
/// </summary>
|
||||
public static string EOF = "\r\n";
|
||||
private const string LogFile = "logging\\application.log";
|
||||
|
||||
/// <summary>
|
||||
/// 信息
|
||||
@@ -16,7 +13,25 @@ namespace Netch.Utils
|
||||
/// <param name="text">内容</param>
|
||||
public static void Info(string text)
|
||||
{
|
||||
File.AppendAllText("logging\\application.log", string.Format("[{0}] {1}{2}", DateTime.Now, text, EOF));
|
||||
File.AppendAllText(LogFile, $@"[{DateTime.Now}][INFO] {text}{Global.EOF}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 信息
|
||||
/// </summary>
|
||||
/// <param name="text">内容</param>
|
||||
public static void Warning(string text)
|
||||
{
|
||||
File.AppendAllText(LogFile, $@"[{DateTime.Now}][WARNING] {text}{Global.EOF}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 错误
|
||||
/// </summary>
|
||||
/// <param name="text">内容</param>
|
||||
public static void Error(string text)
|
||||
{
|
||||
File.AppendAllText(LogFile, $@"[{DateTime.Now}][ERROR] {text}{Global.EOF}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
24
Netch/Utils/MessageBoxX.cs
Normal file
24
Netch/Utils/MessageBoxX.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Netch.Utils
|
||||
{
|
||||
class MessageBoxX
|
||||
{
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <param name="text">内容</param>
|
||||
/// <param name="title">自定义标题</param>
|
||||
/// <param name="info">弹窗等级 (标题, 图标)</param>
|
||||
/// <param name="confirm">需要确认</param>
|
||||
/// <param name="owner">阻止 owner Focus() 直到 Messageox 被关闭</param>
|
||||
public static DialogResult Show(string text, string title = "", bool info = true, bool confirm = false,IWin32Window owner = null)
|
||||
{
|
||||
return MessageBox.Show(
|
||||
owner: owner,
|
||||
text: text,
|
||||
caption: i18N.Translate(string.IsNullOrWhiteSpace(title) ? (info ? "Information" : "Error") : title),
|
||||
buttons: confirm ? MessageBoxButtons.OKCancel : MessageBoxButtons.OK,
|
||||
icon: info ? MessageBoxIcon.Information : MessageBoxIcon.Exclamation);
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Netch/Utils/PortHelper.cs
Normal file
34
Netch/Utils/PortHelper.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System.Linq;
|
||||
using System.Net.NetworkInformation;
|
||||
using Netch.Controllers;
|
||||
|
||||
namespace Netch.Utils
|
||||
{
|
||||
public static class PortHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 指定类型的端口是否已经被使用了
|
||||
/// </summary>
|
||||
/// <param name="port">端口</param>
|
||||
/// <param name="type">检查端口类型</param>
|
||||
/// <returns>是否被占用</returns>
|
||||
public static bool PortInUse(int port, PortType type = PortType.Both)
|
||||
{
|
||||
var netInfo = IPGlobalProperties.GetIPGlobalProperties();
|
||||
var tcpResult = type != PortType.UDP && netInfo.GetActiveTcpListeners().Any(ipEndPoint => !MainController.UsingPorts.Contains(ipEndPoint.Port) && ipEndPoint.Port == port);
|
||||
var udpResult = type != PortType.TCP && netInfo.GetActiveUdpListeners().Any(ipEndPoint => !MainController.UsingPorts.Contains(ipEndPoint.Port) && ipEndPoint.Port == port);
|
||||
|
||||
return tcpResult || udpResult;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查端口类型
|
||||
/// </summary>
|
||||
public enum PortType
|
||||
{
|
||||
TCP,
|
||||
UDP,
|
||||
Both
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
using Netch.Models;
|
||||
using Netch.Models.SS;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using Netch.Models;
|
||||
using Netch.Models.SS;
|
||||
using Netch.Models.SSD;
|
||||
using Newtonsoft.Json;
|
||||
using Server = Netch.Models.Server;
|
||||
|
||||
namespace Netch.Utils
|
||||
{
|
||||
@@ -36,9 +38,9 @@ namespace Netch.Utils
|
||||
/// </summary>
|
||||
/// <param name="server">需要获取分享链接的服务器</param>
|
||||
/// <returns>解码后的字符串</returns>
|
||||
public static string GetShareLink(Models.Server server)
|
||||
public static string GetShareLink(Server server)
|
||||
{
|
||||
string retLinkStr = "";
|
||||
var retLinkStr = "";
|
||||
switch (server.Type)
|
||||
{
|
||||
case "Socks5":
|
||||
@@ -54,12 +56,12 @@ namespace Netch.Utils
|
||||
case "SSR":
|
||||
// https://github.com/shadowsocksr-backup/shadowsocks-rss/wiki/SSR-QRcode-scheme
|
||||
// ssr://base64(host:port:protocol:method:obfs:base64pass/?obfsparam=base64param&protoparam=base64param&remarks=base64remarks&group=base64group&udpport=0&uot=0)
|
||||
string paraStr = string.Format("/?obfsparam={0}&protoparam={1}&remarks={2}", URLSafeBase64Encode(server.OBFSParam), URLSafeBase64Encode(server.ProtocolParam), URLSafeBase64Encode(server.Remark));
|
||||
var paraStr = string.Format("/?obfsparam={0}&protoparam={1}&remarks={2}", URLSafeBase64Encode(server.OBFSParam), URLSafeBase64Encode(server.ProtocolParam), URLSafeBase64Encode(server.Remark));
|
||||
retLinkStr = "ssr://" + URLSafeBase64Encode(string.Format("{0}:{1}:{2}:{3}:{4}:{5}{6}", server.Hostname, server.Port, server.Protocol, server.EncryptMethod, server.OBFS, URLSafeBase64Encode(server.Password), paraStr));
|
||||
|
||||
break;
|
||||
case "VMess":
|
||||
string vmessJson = Newtonsoft.Json.JsonConvert.SerializeObject(new
|
||||
var vmessJson = JsonConvert.SerializeObject(new
|
||||
{
|
||||
v = "2",
|
||||
ps = server.Remark,
|
||||
@@ -121,7 +123,7 @@ namespace Netch.Utils
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Info(e.ToString());
|
||||
Logging.Error(e.ToString());
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -254,7 +256,7 @@ namespace Netch.Utils
|
||||
|
||||
if (!Global.EncryptMethods.SS.Contains(data.EncryptMethod))
|
||||
{
|
||||
Logging.Info(string.Format("不支持的 SS 加密方式:{0}", data.EncryptMethod));
|
||||
Logging.Error($"不支持的 SS 加密方式:{data.EncryptMethod}");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -267,7 +269,7 @@ namespace Netch.Utils
|
||||
}
|
||||
else if (text.StartsWith("ssd://"))
|
||||
{
|
||||
var json = JsonConvert.DeserializeObject<Models.SSD.Main>(URLSafeBase64Decode(text.Substring(6)));
|
||||
var json = JsonConvert.DeserializeObject<Main>(URLSafeBase64Decode(text.Substring(6)));
|
||||
|
||||
foreach (var server in json.servers)
|
||||
{
|
||||
@@ -293,85 +295,6 @@ namespace Netch.Utils
|
||||
|
||||
list.Add(SsrServerFromLink(text));
|
||||
|
||||
/* var data = new Server();
|
||||
data.Type = "SSR";
|
||||
|
||||
text = text.Substring(6);
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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.EncryptMethod = match.Groups["method"].Value;
|
||||
if (!Global.EncryptMethods.SSR.Contains(data.EncryptMethod))
|
||||
{
|
||||
Logging.Info(string.Format("不支持的 SSR 加密方式:{0}", data.EncryptMethod));
|
||||
return null;
|
||||
}
|
||||
|
||||
data.Protocol = match.Groups["protocol"].Value;
|
||||
if (!Global.Protocols.Contains(data.Protocol))
|
||||
{
|
||||
Logging.Info(string.Format("不支持的 SSR 协议:{0}", data.Protocol));
|
||||
return null;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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("remarks"))
|
||||
{
|
||||
data.Remark = URLSafeBase64Decode(dict["remarks"]);
|
||||
}
|
||||
|
||||
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);
|
||||
}*/
|
||||
|
||||
}
|
||||
else if (text.StartsWith("vmess://"))
|
||||
{
|
||||
@@ -390,14 +313,14 @@ namespace Netch.Utils
|
||||
data.TransferProtocol = vmess.net;
|
||||
if (!Global.TransferProtocols.Contains(data.TransferProtocol))
|
||||
{
|
||||
Logging.Info(string.Format("不支持的 VMess 传输协议:{0}", data.TransferProtocol));
|
||||
Logging.Error($"不支持的 VMess 传输协议:{data.TransferProtocol}");
|
||||
return null;
|
||||
}
|
||||
|
||||
data.FakeType = vmess.type;
|
||||
if (data.FakeType.Length != 0 && !Global.FakeTypes.Contains(data.FakeType))
|
||||
{
|
||||
Logging.Info(string.Format("不支持的 VMess 伪装类型:{0}", data.FakeType));
|
||||
Logging.Error($"不支持的 VMess 伪装类型:{data.FakeType}");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -414,7 +337,7 @@ namespace Netch.Utils
|
||||
{
|
||||
if (!Global.EncryptMethods.VMessQUIC.Contains(vmess.host))
|
||||
{
|
||||
Logging.Info(string.Format("不支持的 VMess QUIC 加密方式:{0}", vmess.host));
|
||||
Logging.Error($"不支持的 VMess QUIC 加密方式:{vmess.host}");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -470,43 +393,43 @@ namespace Netch.Utils
|
||||
case "SS":
|
||||
if (!Global.EncryptMethods.SS.Contains(NetchLink.EncryptMethod))
|
||||
{
|
||||
Logging.Info($"不支持的 SS 加密方式:{NetchLink.EncryptMethod}");
|
||||
Logging.Error($"不支持的 SS 加密方式:{NetchLink.EncryptMethod}");
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
case "SSR":
|
||||
if (!Global.EncryptMethods.SSR.Contains(NetchLink.EncryptMethod))
|
||||
{
|
||||
Logging.Info($"不支持的 SSR 加密方式:{NetchLink.EncryptMethod}");
|
||||
Logging.Error($"不支持的 SSR 加密方式:{NetchLink.EncryptMethod}");
|
||||
return null;
|
||||
}
|
||||
if (!Global.Protocols.Contains(NetchLink.Protocol))
|
||||
{
|
||||
Logging.Info($"不支持的 SSR 协议:{NetchLink.Protocol}");
|
||||
Logging.Error($"不支持的 SSR 协议:{NetchLink.Protocol}");
|
||||
return null;
|
||||
}
|
||||
if (!Global.OBFSs.Contains(NetchLink.OBFS))
|
||||
{
|
||||
Logging.Info($"不支持的 SSR 混淆:{NetchLink.OBFS}");
|
||||
Logging.Error($"不支持的 SSR 混淆:{NetchLink.OBFS}");
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
case "VMess":
|
||||
if (!Global.TransferProtocols.Contains(NetchLink.TransferProtocol))
|
||||
{
|
||||
Logging.Info($"不支持的 VMess 传输协议:{NetchLink.TransferProtocol}");
|
||||
Logging.Error($"不支持的 VMess 传输协议:{NetchLink.TransferProtocol}");
|
||||
return null;
|
||||
}
|
||||
if (!Global.FakeTypes.Contains(NetchLink.FakeType))
|
||||
{
|
||||
Logging.Info($"不支持的 VMess 伪装类型:{NetchLink.FakeType}");
|
||||
Logging.Error($"不支持的 VMess 伪装类型:{NetchLink.FakeType}");
|
||||
return null;
|
||||
}
|
||||
if (NetchLink.TransferProtocol == "quic")
|
||||
{
|
||||
if (!Global.EncryptMethods.VMessQUIC.Contains(NetchLink.QUICSecure))
|
||||
{
|
||||
Logging.Info($"不支持的 VMess QUIC 加密方式:{NetchLink.QUICSecure}");
|
||||
Logging.Error($"不支持的 VMess QUIC 加密方式:{NetchLink.QUICSecure}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -569,15 +492,15 @@ namespace Netch.Utils
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Info(e.ToString());
|
||||
Logging.Error(e.ToString());
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] emoji_bytes = { 240, 159 };
|
||||
foreach (Server node in list)
|
||||
foreach (var node in list)
|
||||
{
|
||||
var remark = Encoding.UTF8.GetBytes(node.Remark);
|
||||
int start_index = 0;
|
||||
var start_index = 0;
|
||||
while (remark.Length > start_index + 1 && remark[start_index] == emoji_bytes[0] && remark[start_index + 1] == emoji_bytes[1])
|
||||
start_index += 4;
|
||||
node.Remark = Encoding.UTF8.GetString(remark.Skip(start_index).ToArray()).Trim();
|
||||
@@ -591,7 +514,7 @@ namespace Netch.Utils
|
||||
{
|
||||
return "";
|
||||
}
|
||||
byte[] bytes = Convert.FromBase64String(value);
|
||||
var bytes = Convert.FromBase64String(value);
|
||||
return Encoding.UTF8.GetString(bytes);
|
||||
}
|
||||
public static string ToBase64String(string value)
|
||||
@@ -600,7 +523,7 @@ namespace Netch.Utils
|
||||
{
|
||||
return "";
|
||||
}
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(value);
|
||||
var bytes = Encoding.UTF8.GetBytes(value);
|
||||
return Convert.ToBase64String(bytes);
|
||||
}
|
||||
|
||||
@@ -673,7 +596,7 @@ namespace Netch.Utils
|
||||
{
|
||||
Server_Udp_Port = ushort.Parse(params_dict["udpport"]);
|
||||
}*/
|
||||
Server server = new Server();
|
||||
var server = new Server();
|
||||
server.Type = "SSR";
|
||||
server.Hostname = serverAddr;
|
||||
server.Port = Server_Port;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using MaxMind.GeoIP2;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
@@ -64,5 +65,41 @@ namespace Netch.Utils
|
||||
}
|
||||
return timeout;
|
||||
}
|
||||
|
||||
public static string GetCityCode(string Hostname)
|
||||
{
|
||||
if (Hostname.Contains(":"))
|
||||
{
|
||||
Hostname = Hostname.Split(':')[0];
|
||||
}
|
||||
string Country;
|
||||
try
|
||||
{
|
||||
var databaseReader = new DatabaseReader("bin\\GeoLite2-Country.mmdb");
|
||||
|
||||
if (IPAddress.TryParse(Hostname, out _) == true)
|
||||
{
|
||||
Country = databaseReader.Country(Hostname).Country.IsoCode;
|
||||
}
|
||||
else
|
||||
{
|
||||
var DnsResult = DNS.Lookup(Hostname);
|
||||
|
||||
if (DnsResult != null)
|
||||
{
|
||||
Country = databaseReader.Country(DnsResult).Country.IsoCode;
|
||||
}
|
||||
else
|
||||
{
|
||||
Country = "Unknown";
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Country = "Unknown";
|
||||
}
|
||||
return Country == null ? "Unknown" : Country;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +1,64 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Netch.Properties;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Netch.Utils
|
||||
{
|
||||
public static class i18N
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 数据
|
||||
/// </summary>
|
||||
public static Hashtable Data = new Hashtable();
|
||||
|
||||
public static string LangCode { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 加载
|
||||
/// </summary>
|
||||
/// <param name="text">语言文件</param>
|
||||
public static void Load(string text)
|
||||
/// <param name="langCode">语言代码</param>
|
||||
public static void Load(string langCode)
|
||||
{
|
||||
if (text.Equals("en-US"))
|
||||
LangCode = langCode;
|
||||
|
||||
var text = "";
|
||||
if (langCode.Equals("System"))
|
||||
{
|
||||
// 加载系统语言
|
||||
langCode = CultureInfo.CurrentCulture.Name;
|
||||
}
|
||||
|
||||
if (langCode == "zh-CN")
|
||||
{
|
||||
// 尝试加载内置中文语言
|
||||
text = Encoding.UTF8.GetString(Resources.zh_CN);
|
||||
}
|
||||
else if (langCode.Equals("en-US"))
|
||||
{
|
||||
// 清除得到英文
|
||||
Data.Clear();
|
||||
return;
|
||||
}
|
||||
var data = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(text);
|
||||
|
||||
if (data != null)
|
||||
else if (File.Exists($"i18n\\{langCode}"))
|
||||
{
|
||||
Data = new Hashtable();
|
||||
foreach (var v in data)
|
||||
{
|
||||
Data.Add(v.Key, v.Value);
|
||||
}
|
||||
// 从外置文件中加载语言
|
||||
text = File.ReadAllText($"i18n\\{langCode}");
|
||||
}
|
||||
|
||||
var data = JsonConvert.DeserializeObject<Dictionary<string, string>>(text);
|
||||
|
||||
if (data == null) return;
|
||||
|
||||
Data = new Hashtable();
|
||||
foreach (var v in data)
|
||||
{
|
||||
Data.Add(v.Key, v.Value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,35 +67,37 @@ namespace Netch.Utils
|
||||
/// </summary>
|
||||
/// <param name="text">需要翻译的文本</param>
|
||||
/// <returns>翻译完毕的文本</returns>
|
||||
public static string Translate(string text)
|
||||
public static string Translate(params object[] text)
|
||||
{
|
||||
if (Data.Contains(text))
|
||||
{
|
||||
return Data[text].ToString();
|
||||
}
|
||||
|
||||
return text;
|
||||
var a = new StringBuilder();
|
||||
foreach (var t in text)
|
||||
if (t is string)
|
||||
a.Append(Data.Contains(t) ? Data[t].ToString() : t);
|
||||
else
|
||||
a.Append(t);
|
||||
return a.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取可使用的语言
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static List<string> GetTranslateList()
|
||||
public static string TranslateFormat(string format, params object[] args)
|
||||
{
|
||||
List<string> TranslateFile = new List<string>();
|
||||
TranslateFile.Add("System");
|
||||
TranslateFile.Add("zh-CN");
|
||||
TranslateFile.Add("en-US");
|
||||
|
||||
if (Directory.Exists("i18n"))
|
||||
for (var i = 0; i < args.Length; i++)
|
||||
{
|
||||
foreach (var fileName in Directory.GetFiles("i18n", "*"))
|
||||
if (args[i] is string)
|
||||
{
|
||||
TranslateFile.Add(fileName.Substring(5));
|
||||
args[i] = Translate((string) args[i]);
|
||||
}
|
||||
}
|
||||
return TranslateFile;
|
||||
|
||||
return string.Format(Translate(format), args);
|
||||
}
|
||||
|
||||
public static List<string> GetTranslateList()
|
||||
{
|
||||
var translateFile = new List<string> {"System", "zh-CN", "en-US"};
|
||||
|
||||
if (!Directory.Exists("i18n")) return translateFile;
|
||||
translateFile.AddRange(Directory.GetFiles("i18n", "*").Select(fileName => fileName.Substring(5)));
|
||||
return translateFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -281,7 +281,7 @@ namespace Netch
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// 跳过
|
||||
// ignored
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
[中文说明](/docs/README.zh-CN.md)
|
||||
|
||||
[FAQ/常见问题](https://netch.org/#/docs/zh-CN/faq)
|
||||
|
||||
Game accelerator
|
||||
|
||||
## TOC
|
||||
|
||||
2
binaries
2
binaries
Submodule binaries updated: 385188a7b6...2adb17a398
@@ -1,5 +1,5 @@
|
||||
# 新手入门
|
||||
**Version : 1.3.7**
|
||||
**Version : 1.4.10**
|
||||
|
||||
[下载地址](https://github.com/NetchX/Netch/releases)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
## 添加服务器
|
||||
|
||||
> Netch 目前仅支持以下代理协议:Shadowsocks,VMess,Socks5,ShadowsockR。
|
||||
> Netch 目前仅支持以下代理协议:Shadowsocks,VMess,Socks5,ShadowsockR,Trojan。
|
||||
|
||||
首先,点击`服务器`增加所需服务器
|
||||
|
||||
|
||||
2
modes
2
modes
Submodule modes updated: 5ed034a88b...f0327e9399
Submodule translations updated: db0c5ae291...e7c5263f75
Reference in New Issue
Block a user