diff --git a/Netch/Resources/zh-CN b/Netch/Resources/zh-CN index 74a8f552..90ba5ceb 100644 --- a/Netch/Resources/zh-CN +++ b/Netch/Resources/zh-CN @@ -47,6 +47,7 @@ "Address": "地址", "Username": "用户名", + "User": "用户", "Password": "密码", "Version": "版本", "User ID": "用户 ID", @@ -71,7 +72,7 @@ "Plugin Options": "插件参数", "Remote Address": "远端地址", "Local Addresses": "本地地址(可多个)", - "Public Key": "节点公钥", + "Public Key": "公钥", "Private Key": "私钥", "PSK": "节点预共享密钥", diff --git a/Netch/Servers/SSH/SSHForm.cs b/Netch/Servers/SSH/SSHForm.cs new file mode 100644 index 00000000..928d3826 --- /dev/null +++ b/Netch/Servers/SSH/SSHForm.cs @@ -0,0 +1,19 @@ +using Netch.Forms; + +namespace Netch.Servers; + +[Fody.ConfigureAwait(true)] +public class SSHForm : ServerForm +{ + public SSHForm(SSHServer? server = default) + { + server ??= new SSHServer(); + Server = server; + CreateTextBox("User", "User", s => true, s => server.User = s, server.User); + CreateTextBox("Password", "Password", s => true, s => server.Password = s, server.Password); + CreateTextBox("PrivateKey", "Private Key", s => true, s => server.PrivateKey = s, server.PrivateKey); + CreateTextBox("PublicKey", "Public Key", s => true, s => server.PublicKey = s, server.PublicKey); + } + + protected override string TypeName { get; } = "SSH"; +} \ No newline at end of file diff --git a/Netch/Servers/SSH/SSHServer.cs b/Netch/Servers/SSH/SSHServer.cs new file mode 100644 index 00000000..404f14fb --- /dev/null +++ b/Netch/Servers/SSH/SSHServer.cs @@ -0,0 +1,33 @@ +using Netch.Models; + +namespace Netch.Servers; + +public class SSHServer : Server +{ + public override string Type { get; } = "SSH"; + + public override string MaskedData() + { + return $"{User}"; + } + + /// + /// 用户 + /// + public string User { get; set; } = "root"; + + /// + /// 密码 + /// + public string Password { get; set; } = string.Empty; + + /// + /// 私钥 + /// + public string PrivateKey { get; set; } + + /// + /// 主机公钥 + /// + public string? PublicKey { get; set; } +} diff --git a/Netch/Servers/SSH/SSHUtil.cs b/Netch/Servers/SSH/SSHUtil.cs new file mode 100644 index 00000000..166b0def --- /dev/null +++ b/Netch/Servers/SSH/SSHUtil.cs @@ -0,0 +1,53 @@ +using System.Text.Encodings.Web; +using System.Text.Json; +using System.Text.Json.Serialization; +using Netch.Interfaces; +using Netch.Models; +using Netch.Utils; + +namespace Netch.Servers; + +public class SSHUtil : IServerUtil +{ + public ushort Priority { get; } = 4; + + public string TypeName { get; } = "SSH"; + + public string FullName { get; } = "SSH"; + + public string ShortName { get; } = "SSH"; + + public string[] UriScheme { get; } = { "ssh" }; + + public Type ServerType { get; } = typeof(SSHServer); + + public void Edit(Server s) + { + new SSHForm((SSHServer)s).ShowDialog(); + } + + public void Create() + { + new SSHForm().ShowDialog(); + } + + public string GetShareLink(Server s) + { + return V2rayUtils.GetVShareLink(s, "ssh"); + } + + public IServerController GetController() + { + return new V2rayController(); + } + + public IEnumerable ParseUri(string text) + { + return V2rayUtils.ParseVUri(text); + } + + public bool CheckServer(Server s) + { + return true; + } +} \ No newline at end of file diff --git a/Netch/Servers/V2ray/V2rayConfig.cs b/Netch/Servers/V2ray/V2rayConfig.cs index 2d26668e..d1db9e04 100644 --- a/Netch/Servers/V2ray/V2rayConfig.cs +++ b/Netch/Servers/V2ray/V2rayConfig.cs @@ -44,8 +44,12 @@ public class OutboundConfiguration public string address { get; set; } + public string user { get; set; } + public ushort port { get; set; } + public string password { get; set; } + public string packetEncoding { get; set; } public string plugin { get; set; } @@ -58,6 +62,8 @@ public class OutboundConfiguration public string peerPublicKey { get; set; } + public string publicKey { get; set; } + public string privateKey { get; set; } public string preSharedKey { get; set; } diff --git a/Netch/Servers/V2ray/V2rayConfigUtils.cs b/Netch/Servers/V2ray/V2rayConfigUtils.cs index 94010b8e..5307e6de 100644 --- a/Netch/Servers/V2ray/V2rayConfigUtils.cs +++ b/Netch/Servers/V2ray/V2rayConfigUtils.cs @@ -145,21 +145,18 @@ public static class V2rayConfigUtils } case ShadowsocksServer ss: outbound.protocol = "shadowsocks"; - outbound.settings = new OutboundConfiguration + outbound.settings.servers = new[] { - servers = new[] + new ShadowsocksServerItem { - new ShadowsocksServerItem - { - address = await server.AutoResolveHostnameAsync(), - port = server.Port, - method = ss.EncryptMethod, - password = ss.Password, - } - }, - plugin = ss.Plugin ?? "", - pluginOpts = ss.PluginOption ?? "" + address = await server.AutoResolveHostnameAsync(), + port = server.Port, + method = ss.EncryptMethod, + password = ss.Password + } }; + outbound.settings.plugin = ss.Plugin ?? ""; + outbound.settings.pluginOpts = ss.PluginOption ?? ""; if (Global.Settings.V2RayConfig.TCPFastOpen) { @@ -174,27 +171,24 @@ public static class V2rayConfigUtils break; case ShadowsocksRServer ssr: outbound.protocol = "shadowsocks"; - outbound.settings = new OutboundConfiguration + outbound.settings.servers = new[] { - servers = new[] + new ShadowsocksServerItem { - new ShadowsocksServerItem - { - address = await server.AutoResolveHostnameAsync(), - port = server.Port, - method = ssr.EncryptMethod, - password = ssr.Password, - } - }, - plugin = "shadowsocksr", - pluginArgs = new string[] - { - "--obfs=" + ssr.OBFS, - "--obfs-param=" + ssr.OBFSParam ?? "", - "--protocol=" + ssr.Protocol, - "--protocol-param=" + ssr.ProtocolParam ?? "" + address = await server.AutoResolveHostnameAsync(), + port = server.Port, + method = ssr.EncryptMethod, + password = ssr.Password, } }; + outbound.settings.plugin = "shadowsocksr"; + outbound.settings.pluginArgs = new string[] + { + "--obfs=" + ssr.OBFS, + "--obfs-param=" + ssr.OBFSParam ?? "", + "--protocol=" + ssr.Protocol, + "--protocol-param=" + ssr.ProtocolParam ?? "" + }; if (Global.Settings.V2RayConfig.TCPFastOpen) { @@ -209,18 +203,15 @@ public static class V2rayConfigUtils break; case TrojanServer trojan: outbound.protocol = "trojan"; - outbound.settings = new OutboundConfiguration + outbound.settings.servers = new[] { - servers = new[] + new ShadowsocksServerItem // I'm not serious { - new ShadowsocksServerItem // I'm not serious - { - address = await server.AutoResolveHostnameAsync(), - port = server.Port, - method = "", - password = trojan.Password, - flow = trojan.TLSSecureType == "xtls" ? "xtls-rprx-direct" : "" - } + address = await server.AutoResolveHostnameAsync(), + port = server.Port, + method = "", + password = trojan.Password, + flow = trojan.TLSSecureType == "xtls" ? "xtls-rprx-direct" : "" } }; @@ -258,16 +249,13 @@ public static class V2rayConfigUtils break; case WireGuardServer wg: outbound.protocol = "wireguard"; - outbound.settings = new OutboundConfiguration - { - address = await server.AutoResolveHostnameAsync(), - port = server.Port, - localAddresses = wg.LocalAddresses.SplitOrDefault(), - peerPublicKey = wg.PeerPublicKey, - privateKey = wg.PrivateKey, - preSharedKey = wg.PreSharedKey, - mtu = wg.MTU - }; + outbound.settings.address = await server.AutoResolveHostnameAsync(); + outbound.settings.port = server.Port; + outbound.settings.localAddresses = wg.LocalAddresses.SplitOrDefault(); + outbound.settings.peerPublicKey = wg.PeerPublicKey; + outbound.settings.privateKey = wg.PrivateKey; + outbound.settings.preSharedKey = wg.PreSharedKey; + outbound.settings.mtu = wg.MTU; if (Global.Settings.V2RayConfig.TCPFastOpen) { @@ -281,6 +269,26 @@ public static class V2rayConfigUtils } break; + case SSHServer ssh: + outbound.protocol = "ssh"; + outbound.settings.address = await server.AutoResolveHostnameAsync(); + outbound.settings.port = server.Port; + outbound.settings.user = ssh.User; + outbound.settings.password = ssh.Password; + outbound.settings.privateKey = ssh.PrivateKey; + outbound.settings.publicKey = ssh.PublicKey; + + if (Global.Settings.V2RayConfig.TCPFastOpen) + { + outbound.streamSettings = new StreamSettings + { + sockopt = new Sockopt + { + tcpFastOpen = true + } + }; + } + break; } return outbound;