diff --git a/Netch/Controllers/TUNController.cs b/Netch/Controllers/TUNController.cs index 123d8f0b..f9a36959 100644 --- a/Netch/Controllers/TUNController.cs +++ b/Netch/Controllers/TUNController.cs @@ -44,8 +44,8 @@ public class TUNController : Guard, IModeController _mode = tunMode; _tunConfig = Global.Settings.TUNTAP; - if (server is Socks5LocalServer socks5Bridge) - _serverRemoteAddress = await DnsUtils.LookupAsync(socks5Bridge.RemoteHostname); + if (server.RemoteHostname.ValueOrDefault() != null) + _serverRemoteAddress = await DnsUtils.LookupAsync(server.RemoteHostname!); else _serverRemoteAddress = await DnsUtils.LookupAsync(server.Hostname); @@ -93,10 +93,9 @@ public class TUNController : Guard, IModeController Global.MainForm.StatusText(i18N.Translate("Assigning unicast IP")); if (!await Task.Run(() => RouteHelper.CreateUnicastIP(AddressFamily.InterNetwork, - _tunConfig.Address, - (byte)Utils.Utils.SubnetToCidr(_tunConfig.Netmask), - (ulong)tunIndex)) - ) + _tunConfig.Address, + (byte)Utils.Utils.SubnetToCidr(_tunConfig.Netmask), + (ulong)tunIndex))) { Log.Error("Create unicast IP failed"); throw new MessageException("Create unicast IP failed"); diff --git a/Netch/Forms/ServerForm.cs b/Netch/Forms/ServerForm.cs index 5c02a216..ba1b8fdd 100644 --- a/Netch/Forms/ServerForm.cs +++ b/Netch/Forms/ServerForm.cs @@ -78,7 +78,7 @@ public abstract class ServerForm : Form PerformLayout(); } - protected void CreateTextBox(string name, + protected (Label,TextBox) CreateTextBox(string name, string remark, Func check, Action save, @@ -98,18 +98,21 @@ public abstract class ServerForm : Form _checkActions.Add(textBox, check); _saveActions.Add(textBox, o => save.Invoke((string)o)); + var label = new Label + { + AutoSize = true, + Location = new Point(10, ControlLineHeight * _controlLines), + Name = $"{name}Label", + Size = new Size(56, 17), + Text = remark + }; + ConfigurationGroupBox.Controls.AddRange(new Control[] { - textBox, - new Label - { - AutoSize = true, - Location = new Point(10, ControlLineHeight * _controlLines), - Name = $"{name}Label", - Size = new Size(56, 17), - Text = remark - } + label, + textBox }); + return (label, textBox); } protected void CreateComboBox(string name, string remark, List values, Action save, string value, int width = InputBoxWidth) diff --git a/Netch/Interfaces/IServerController.cs b/Netch/Interfaces/IServerController.cs index 0a985665..6c0c8665 100644 --- a/Netch/Interfaces/IServerController.cs +++ b/Netch/Interfaces/IServerController.cs @@ -9,7 +9,7 @@ public interface IServerController : IController public string? LocalAddress { get; set; } - public Task StartAsync(Server s); + public Task StartAsync(Server s); } public static class ServerControllerExtension diff --git a/Netch/Models/Server.cs b/Netch/Models/Server.cs index f94e1b6c..5ff53de4 100644 --- a/Netch/Models/Server.cs +++ b/Netch/Models/Server.cs @@ -40,6 +40,7 @@ public abstract class Server : ICloneable /// /// 代理类型 /// + [JsonPropertyOrder(int.MinValue)] public abstract string Type { get; } public object Clone() diff --git a/Netch/Resources/zh-CN b/Netch/Resources/zh-CN index 266cac2a..9c90f9ef 100644 --- a/Netch/Resources/zh-CN +++ b/Netch/Resources/zh-CN @@ -68,6 +68,7 @@ "Saved": "保存成功", "Plugin": "插件", "Plugin Options": "插件参数", + "Remote Address": "远端地址", "Subscription": "订阅", "Manage Subscriptions": "管理订阅", diff --git a/Netch/Servers/Shadowsocks/ShadowsocksController.cs b/Netch/Servers/Shadowsocks/ShadowsocksController.cs index ff02224e..2909afa3 100644 --- a/Netch/Servers/Shadowsocks/ShadowsocksController.cs +++ b/Netch/Servers/Shadowsocks/ShadowsocksController.cs @@ -22,7 +22,7 @@ public class ShadowsocksController : Guard, IServerController public string? LocalAddress { get; set; } - public async Task StartAsync(Server s) + public async Task StartAsync(Server s) { var server = (ShadowsocksServer)s; @@ -38,6 +38,6 @@ public class ShadowsocksController : Guard, IServerController }; await StartGuardAsync(Arguments.Format(arguments)); - return new Socks5LocalServer(IPAddress.Loopback.ToString(), this.Socks5LocalPort(), server.Hostname); + return new Socks5Server(IPAddress.Loopback.ToString(), this.Socks5LocalPort(), server.Hostname); } } \ No newline at end of file diff --git a/Netch/Servers/ShadowsocksR/ShadowsocksRController.cs b/Netch/Servers/ShadowsocksR/ShadowsocksRController.cs index 8ea654f2..69064ca0 100644 --- a/Netch/Servers/ShadowsocksR/ShadowsocksRController.cs +++ b/Netch/Servers/ShadowsocksR/ShadowsocksRController.cs @@ -21,7 +21,7 @@ public class ShadowsocksRController : Guard, IServerController public string? LocalAddress { get; set; } - public async Task StartAsync(Server s) + public async Task StartAsync(Server s) { var server = (ShadowsocksRServer)s; @@ -42,6 +42,6 @@ public class ShadowsocksRController : Guard, IServerController }; await StartGuardAsync(Arguments.Format(arguments)); - return new Socks5LocalServer(IPAddress.Loopback.ToString(), this.Socks5LocalPort(), server.Hostname); + return new Socks5Server(IPAddress.Loopback.ToString(), this.Socks5LocalPort(), server.Hostname); } } \ No newline at end of file diff --git a/Netch/Servers/Socks5/Socks5Controller.cs b/Netch/Servers/Socks5/Socks5Controller.cs index f793dcce..9bd8110f 100644 --- a/Netch/Servers/Socks5/Socks5Controller.cs +++ b/Netch/Servers/Socks5/Socks5Controller.cs @@ -6,7 +6,7 @@ public class Socks5Controller : V2rayController { public override string Name { get; } = "Socks5"; - public override Task StartAsync(Server s) + public override Task StartAsync(Server s) { var server = (Socks5Server)s; if (!server.Auth()) diff --git a/Netch/Servers/Socks5/Socks5Form.cs b/Netch/Servers/Socks5/Socks5Form.cs index 21ba26b7..5b46d4b8 100644 --- a/Netch/Servers/Socks5/Socks5Form.cs +++ b/Netch/Servers/Socks5/Socks5Form.cs @@ -1,4 +1,5 @@ using Netch.Forms; +using Netch.Utils; namespace Netch.Servers; @@ -9,8 +10,30 @@ public class Socks5Form : ServerForm { server ??= new Socks5Server(); Server = server; - CreateTextBox("Username", "Username", s => true, s => server.Username = s, server.Username); - CreateTextBox("Password", "Password", s => true, s => server.Password = s, server.Password); + CreateTextBox("Username", "Username", s => true, s => server.Username = s, server.Username.ValueOrDefault()); + CreateTextBox("Password", "Password", s => true, s => server.Password = s, server.Password.ValueOrDefault()); + (_remoteHostnameLabel, _remoteHostnameTextBox) = CreateTextBox("RemoteHostname", + "Remote Address", + s => true, + s => server.RemoteHostname = s, + server.RemoteHostname.ValueOrDefault()); + + AddressTextBox.TextChanged += AddressTextBoxOnTextChanged; + AddressTextBoxOnTextChanged(null!, null!); + } + + private readonly Label _remoteHostnameLabel; + private readonly TextBox _remoteHostnameTextBox; + + private void AddressTextBoxOnTextChanged(object? sender, EventArgs e) + { + _remoteHostnameLabel.Visible = _remoteHostnameTextBox.Visible = IsPrivateAddress(AddressTextBox.Text); + } + + private bool IsPrivateAddress(string address) + { + // https://en.wikipedia.org/wiki/Private_network#Private_IPv4_addresses + return address.StartsWith("10.") || address.StartsWith("192.168.") || address.StartsWith("172.") || address.StartsWith("127."); } protected override string TypeName { get; } = "Socks5"; diff --git a/Netch/Servers/Socks5/Socks5LocalServer.cs b/Netch/Servers/Socks5/Socks5LocalServer.cs deleted file mode 100644 index 4eb360f9..00000000 --- a/Netch/Servers/Socks5/Socks5LocalServer.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Netch.Servers; - -// TODO migrate to Socks5Server class -/// -/// Encrypted proxy client's local socks5 server -/// ( property is used for saving remote address/hostname for special use) -/// -public class Socks5LocalServer : Socks5Server -{ - public Socks5LocalServer(string hostname, ushort port, string remoteHostname) - { - Hostname = hostname; - Port = port; - RemoteHostname = remoteHostname; - } - - public string RemoteHostname { get; set; } -} \ No newline at end of file diff --git a/Netch/Servers/Socks5/Socks5Server.cs b/Netch/Servers/Socks5/Socks5Server.cs index 14161aff..a6b50727 100644 --- a/Netch/Servers/Socks5/Socks5Server.cs +++ b/Netch/Servers/Socks5/Socks5Server.cs @@ -4,6 +4,8 @@ namespace Netch.Servers; public class Socks5Server : Server { + public override string Type { get; } = "Socks5"; + /// /// 密码 /// @@ -14,7 +16,7 @@ public class Socks5Server : Server /// public string? Username { get; set; } - public override string Type { get; } = "Socks5"; + public string? RemoteHostname { get; set; } public override string MaskedData() { @@ -37,6 +39,11 @@ public class Socks5Server : Server Password = password; } + public Socks5Server(string hostname, ushort port, string remoteHostname) : this(hostname, port) + { + RemoteHostname = remoteHostname; + } + public bool Auth() { return !string.IsNullOrWhiteSpace(Username) && !string.IsNullOrWhiteSpace(Password); diff --git a/Netch/Servers/Trojan/TrojanController.cs b/Netch/Servers/Trojan/TrojanController.cs index 398eac49..ef81e65d 100644 --- a/Netch/Servers/Trojan/TrojanController.cs +++ b/Netch/Servers/Trojan/TrojanController.cs @@ -23,7 +23,7 @@ public class TrojanController : Guard, IServerController public string? LocalAddress { get; set; } - public async Task StartAsync(Server s) + public async Task StartAsync(Server s) { var server = (TrojanServer)s; var trojanConfig = new TrojanConfig @@ -48,6 +48,6 @@ public class TrojanController : Guard, IServerController } await StartGuardAsync("-c ..\\data\\last.json"); - return new Socks5LocalServer(IPAddress.Loopback.ToString(), this.Socks5LocalPort(), server.Hostname); + return new Socks5Server(IPAddress.Loopback.ToString(), this.Socks5LocalPort(), server.Hostname); } } \ No newline at end of file diff --git a/Netch/Servers/V2ray/V2rayController.cs b/Netch/Servers/V2ray/V2rayController.cs index 0506f923..3d9fe9b3 100644 --- a/Netch/Servers/V2ray/V2rayController.cs +++ b/Netch/Servers/V2ray/V2rayController.cs @@ -24,7 +24,7 @@ public class V2rayController : Guard, IServerController public string? LocalAddress { get; set; } - public virtual async Task StartAsync(Server s) + public virtual async Task StartAsync(Server s) { await using (var fileStream = new FileStream(Constants.TempConfig, FileMode.Create, FileAccess.Write, FileShare.Read)) { @@ -32,6 +32,6 @@ public class V2rayController : Guard, IServerController } await StartGuardAsync("-config ..\\data\\last.json"); - return new Socks5LocalServer(IPAddress.Loopback.ToString(), this.Socks5LocalPort(), s.Hostname); + return new Socks5Server(IPAddress.Loopback.ToString(), this.Socks5LocalPort(), s.Hostname); } } \ No newline at end of file