diff --git a/ProxySU.sln b/ProxySU.sln index 78ce6b6..a38b700 100644 --- a/ProxySU.sln +++ b/ProxySU.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31005.135 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31606.5 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libs", "Libs", "{CE908112-DB46-4B91-8236-9139A19D66E9}" EndProject diff --git a/ProxySuper.Core/App.cs b/ProxySuper.Core/App.cs index 6c745f8..919fd05 100644 --- a/ProxySuper.Core/App.cs +++ b/ProxySuper.Core/App.cs @@ -1,10 +1,5 @@ using MvvmCross.ViewModels; using ProxySuper.Core.ViewModels; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace ProxySuper.Core { diff --git a/ProxySuper.Core/Converters/LoginSecretTypeConverter.cs b/ProxySuper.Core/Converters/LoginSecretTypeConverter.cs index 07b11e9..56cd875 100644 --- a/ProxySuper.Core/Converters/LoginSecretTypeConverter.cs +++ b/ProxySuper.Core/Converters/LoginSecretTypeConverter.cs @@ -1,11 +1,6 @@ -using MvvmCross.Converters; -using ProxySuper.Core.Models.Hosts; +using ProxySuper.Core.Models.Hosts; using System; -using System.Collections.Generic; using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Windows.Data; namespace ProxySuper.Core.Converters diff --git a/ProxySuper.Core/Converters/ProxyTypeConverter.cs b/ProxySuper.Core/Converters/ProxyTypeConverter.cs index 4d36d15..560c5f1 100644 --- a/ProxySuper.Core/Converters/ProxyTypeConverter.cs +++ b/ProxySuper.Core/Converters/ProxyTypeConverter.cs @@ -1,9 +1,5 @@ using System; -using System.Collections.Generic; using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Windows.Data; namespace ProxySuper.Core.Converters diff --git a/ProxySuper.Core/Converters/VisibleConverter.cs b/ProxySuper.Core/Converters/VisibleConverter.cs index 70eeaa6..ffcdaba 100644 --- a/ProxySuper.Core/Converters/VisibleConverter.cs +++ b/ProxySuper.Core/Converters/VisibleConverter.cs @@ -1,9 +1,5 @@ using System; -using System.Collections.Generic; using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Windows; using System.Windows.Data; diff --git a/ProxySuper.Core/Helpers/DateTimeUtils.cs b/ProxySuper.Core/Helpers/DateTimeUtils.cs index 9d1673e..4625b81 100644 --- a/ProxySuper.Core/Helpers/DateTimeUtils.cs +++ b/ProxySuper.Core/Helpers/DateTimeUtils.cs @@ -1,12 +1,8 @@  using System; -using System.Collections.Generic; using System.Globalization; -using System.Linq; using System.Net; using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; namespace ProxySuper.Core.Helpers { diff --git a/ProxySuper.Core/Helpers/Utils.cs b/ProxySuper.Core/Helpers/Utils.cs index 6d5d0ff..76e41b1 100644 --- a/ProxySuper.Core/Helpers/Utils.cs +++ b/ProxySuper.Core/Helpers/Utils.cs @@ -1,11 +1,6 @@ using Newtonsoft.Json; using System; -using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Runtime.Serialization.Formatters.Binary; -using System.Text; -using System.Threading.Tasks; namespace ProxySuper.Core.Services { @@ -33,5 +28,13 @@ namespace ProxySuper.Core.Services { return DateTime.Now.Ticks.ToString(); } + + private static Random random = new Random(); + public static string RandomString(int length) + { + const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + return new string(Enumerable.Repeat(chars, length) + .Select(s => s[random.Next(s.Length)]).ToArray()); + } } } diff --git a/ProxySuper.Core/Models/Caddy.cs b/ProxySuper.Core/Models/Caddy.cs new file mode 100644 index 0000000..93e3c22 --- /dev/null +++ b/ProxySuper.Core/Models/Caddy.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ProxySuper.Core.Models +{ + public static class Caddy + { + public static string Service = @" +[Unit] +Description=Caddy +Documentation=https://caddyserver.com/docs/ +After=network.target network-online.target +Requires=network-online.target + +[Service] +#User=caddy +#Group=caddy +User=root +Group=root +ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile +ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile +TimeoutStopSec=5s +#LimitNOFILE=1048576 +#LimitNPROC=512 +PrivateTmp=true +ProtectSystem=full +#AmbientCapabilities=CAP_NET_BIND_SERVICE + +[Install] +WantedBy=multi-user.target +"; + + public static string DefaultCaddyFile = @" +:80 { + respond ""Hello world!""; +} +"; + } +} diff --git a/ProxySuper.Core/Models/Hosts/Host.cs b/ProxySuper.Core/Models/Hosts/Host.cs index 26a11a3..20baa6d 100644 --- a/ProxySuper.Core/Models/Hosts/Host.cs +++ b/ProxySuper.Core/Models/Hosts/Host.cs @@ -1,10 +1,6 @@ using Microsoft.Win32; using MvvmCross.Commands; -using System; -using System.Collections.Generic; using System.ComponentModel; -using System.Linq; -using System.Text; using System.Threading.Tasks; using System.Windows; diff --git a/ProxySuper.Core/Models/Hosts/LocalProxy.cs b/ProxySuper.Core/Models/Hosts/LocalProxy.cs index 38f300a..c382bbe 100644 --- a/ProxySuper.Core/Models/Hosts/LocalProxy.cs +++ b/ProxySuper.Core/Models/Hosts/LocalProxy.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Renci.SshNet; namespace ProxySuper.Core.Models.Hosts { @@ -12,7 +8,7 @@ namespace ProxySuper.Core.Models.Hosts public int Port { get; set; } = 1080; - public LocalProxyType Type { get; set; } + public ProxyTypes Type { get; set; } public string UserName { get; set; } @@ -20,5 +16,5 @@ namespace ProxySuper.Core.Models.Hosts } - + } diff --git a/ProxySuper.Core/Models/Hosts/LocalProxyType.cs b/ProxySuper.Core/Models/Hosts/LocalProxyType.cs deleted file mode 100644 index 88c3d9d..0000000 --- a/ProxySuper.Core/Models/Hosts/LocalProxyType.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace ProxySuper.Core.Models.Hosts -{ - public enum LocalProxyType - { - None = 0, - // - // 摘要: - // A SOCKS4 proxy server. - Socks4 = 1, - // - // 摘要: - // A SOCKS5 proxy server. - Socks5 = 2, - // - // 摘要: - // A HTTP proxy server. - Http = 3 - } -} diff --git a/ProxySuper.Core/Models/Hosts/LoginSecretType.cs b/ProxySuper.Core/Models/Hosts/LoginSecretType.cs index 1791823..8ba540a 100644 --- a/ProxySuper.Core/Models/Hosts/LoginSecretType.cs +++ b/ProxySuper.Core/Models/Hosts/LoginSecretType.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace ProxySuper.Core.Models.Hosts +namespace ProxySuper.Core.Models.Hosts { public enum LoginSecretType { diff --git a/ProxySuper.Core/Models/ProjectProgress.cs b/ProxySuper.Core/Models/ProjectProgress.cs new file mode 100644 index 0000000..dad33a3 --- /dev/null +++ b/ProxySuper.Core/Models/ProjectProgress.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ProxySuper.Core.Models +{ + public class ProjectProgress + { + private string _step; + + private string _desc; + + private int _percentage; + + private string _logs; + + public ProjectProgress() + { + _step = "步骤"; + + _desc = "步骤描述"; + + _percentage = 0; + + _logs = string.Empty; + + StepUpdate = () => { }; + } + + + public Action StepUpdate { get; set; } + + public Action LogsUpdate { get; set; } + + public string Desc + { + get { return _desc; } + set + { + _desc = value; + StepUpdate(); + + _logs += _desc + "\n"; + LogsUpdate(); + } + } + + public string Step + { + get { return _step; } + set + { + _step = value; + StepUpdate(); + + _logs += Step + "\n"; + LogsUpdate(); + } + } + + public int Percentage + { + get { return _percentage; } + set + { + _percentage = value; + StepUpdate(); + } + } + + public string Logs + { + get { return _logs; } + set + { + _logs = value; + LogsUpdate(); + } + } + } +} \ No newline at end of file diff --git a/ProxySuper.Core/Models/Projects/BrookSettings.cs b/ProxySuper.Core/Models/Projects/BrookSettings.cs new file mode 100644 index 0000000..7bf1adb --- /dev/null +++ b/ProxySuper.Core/Models/Projects/BrookSettings.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; + +namespace ProxySuper.Core.Models.Projects +{ + public class BrookSettings : IProjectSettings + { + public string Domain { get; set; } + + public string IP { get; set; } + + public string Password { get; set; } + + public BrookType BrookType { get; set; } + + public int Port { get; set; } = 443; + + public List FreePorts + { + get + { + if (Port == 443) + { + return new List { 80, 443 }; + } + return new List { Port }; + } + } + + public string Email => "server@brook.com"; + + public ProjectType Type { get; set; } = ProjectType.Brook; + + } +} diff --git a/ProxySuper.Core/Models/Projects/BrookType.cs b/ProxySuper.Core/Models/Projects/BrookType.cs new file mode 100644 index 0000000..6f5fc1d --- /dev/null +++ b/ProxySuper.Core/Models/Projects/BrookType.cs @@ -0,0 +1,10 @@ +namespace ProxySuper.Core.Models.Projects +{ + public enum BrookType + { + server, + wsserver, + wssserver, + socks5 + } +} diff --git a/ProxySuper.Core/Models/Projects/IProjectSettings.cs b/ProxySuper.Core/Models/Projects/IProjectSettings.cs index 6bd2874..1570c4e 100644 --- a/ProxySuper.Core/Models/Projects/IProjectSettings.cs +++ b/ProxySuper.Core/Models/Projects/IProjectSettings.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Collections.Generic; namespace ProxySuper.Core.Models.Projects { @@ -27,5 +23,10 @@ namespace ProxySuper.Core.Models.Projects /// 类型 /// ProjectType Type { get; set; } + + /// + /// 邮箱 + /// + string Email { get; } } } diff --git a/ProxySuper.Core/Models/Projects/NaiveProxySettings.cs b/ProxySuper.Core/Models/Projects/NaiveProxySettings.cs index 76fb1c4..f6c457f 100644 --- a/ProxySuper.Core/Models/Projects/NaiveProxySettings.cs +++ b/ProxySuper.Core/Models/Projects/NaiveProxySettings.cs @@ -1,8 +1,6 @@ -using System; +using Newtonsoft.Json; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace ProxySuper.Core.Models.Projects { @@ -13,7 +11,13 @@ namespace ProxySuper.Core.Models.Projects Port = 443; } - public List FreePorts => new List(); + public List FreePorts + { + get + { + return new List { 80, 443, Port }.Distinct().ToList(); + } + } public ProjectType Type { get; set; } = ProjectType.NaiveProxy; @@ -26,5 +30,24 @@ namespace ProxySuper.Core.Models.Projects public string Password { get; set; } public string MaskDomain { get; set; } + + [JsonIgnore] + public string Email + { + get + { + if (!string.IsNullOrEmpty(Domain)) + { + var arr = Domain.Split('.'); + if (arr.Length == 3) + { + return $"{arr[0]}@{arr[1]}.{arr[2]}"; + } + } + + + return $"{UserName + Port.ToString()}@gmail.com"; + } + } } } diff --git a/ProxySuper.Core/Models/Projects/ProjectType.cs b/ProxySuper.Core/Models/Projects/ProjectType.cs index 16b82b2..7216689 100644 --- a/ProxySuper.Core/Models/Projects/ProjectType.cs +++ b/ProxySuper.Core/Models/Projects/ProjectType.cs @@ -1,15 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace ProxySuper.Core.Models.Projects +namespace ProxySuper.Core.Models.Projects { public enum ProjectType { Xray = 0, TrojanGo = 1, - NaiveProxy = 2 + NaiveProxy = 2, + Brook = 3, } } diff --git a/ProxySuper.Core/Models/Projects/TrojanGoSettings.cs b/ProxySuper.Core/Models/Projects/TrojanGoSettings.cs index cf84518..17055fa 100644 --- a/ProxySuper.Core/Models/Projects/TrojanGoSettings.cs +++ b/ProxySuper.Core/Models/Projects/TrojanGoSettings.cs @@ -1,10 +1,7 @@ using Newtonsoft.Json; -using ProxySuper.Core.Services; using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace ProxySuper.Core.Models.Projects { @@ -14,13 +11,14 @@ namespace ProxySuper.Core.Models.Projects { Port = 443; WebSocketPath = "/ws"; + Password = Guid.NewGuid().ToString(); } public List FreePorts { get { - return new List(); + return new List { 80, 443, Port }.Distinct().ToList(); } } @@ -63,5 +61,25 @@ namespace ProxySuper.Core.Models.Projects /// public string WebSocketPath { get; set; } + + [JsonIgnore] + public string Email + { + get + { + if (!string.IsNullOrEmpty(Domain)) + { + var arr = Domain.Split('.'); + if (arr.Length == 3) + { + return $"{arr[0]}@{arr[1]}.{arr[2]}"; + } + } + + var prefix = Password.Length > 7 ? Password.Substring(0, 7) : Password; + return $"{prefix}@gmail.com"; + } + } + } } diff --git a/ProxySuper.Core/Models/Projects/XraySettings.cs b/ProxySuper.Core/Models/Projects/XraySettings.cs index d9fe96f..709da3f 100644 --- a/ProxySuper.Core/Models/Projects/XraySettings.cs +++ b/ProxySuper.Core/Models/Projects/XraySettings.cs @@ -1,8 +1,9 @@ -using System; +using Newtonsoft.Json; +using ProxySuper.Core.Services; +using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Net; namespace ProxySuper.Core.Models.Projects { @@ -20,13 +21,13 @@ namespace ProxySuper.Core.Models.Projects UUID = guid; Types = new List(); - VLESS_WS_Path = "/vlessws"; + VLESS_WS_Path = "/" + Utils.RandomString(6); VLESS_KCP_Type = "none"; VLESS_KCP_Seed = guid; - VLESS_gRPC_ServiceName = "xray_gRPC"; + VLESS_gRPC_ServiceName = "/" + Utils.RandomString(7); - VMESS_WS_Path = "/vmessws"; - VMESS_TCP_Path = "/vmesstcp"; + VMESS_WS_Path = "/" + Utils.RandomString(8); + VMESS_TCP_Path = "/" + Utils.RandomString(9); VMESS_KCP_Seed = guid; VMESS_KCP_Type = "none"; @@ -36,16 +37,45 @@ namespace ProxySuper.Core.Models.Projects ShadowSocksMethod = "aes-128-gcm"; } + [JsonIgnore] + public bool IsIPAddress + { + get + { + return IPAddress.TryParse(Domain, out _); + } + } + + [JsonIgnore] public List FreePorts { get { - return new List + var list = new List(); + list.Add(80); + list.Add(Port); + + if (Types.Contains(XrayType.VLESS_KCP)) { - VLESS_KCP_Port, - VMESS_KCP_Port, - ShadowSocksPort, - }; + list.Add(VLESS_KCP_Port); + } + + if (Types.Contains(XrayType.VMESS_KCP)) + { + list.Add(VMESS_KCP_Port); + } + + if (Types.Contains(XrayType.ShadowsocksAEAD)) + { + list.Add(ShadowSocksPort); + } + + if (Types.Contains(XrayType.VLESS_gRPC)) + { + list.Add(VLESS_gRPC_Port); + } + + return list.Distinct().ToList(); } } @@ -66,11 +96,34 @@ namespace ProxySuper.Core.Models.Projects /// public string UUID { get; set; } + /// + /// 多用户 + /// + public List MulitUUID { get; set; } = new List(); + /// /// 伪装域名 /// public string MaskDomain { get; set; } + [JsonIgnore] + public string Email + { + get + { + if (!string.IsNullOrEmpty(Domain)) + { + var arr = Domain.Split('.'); + if (arr.Length == 3) + { + return $"{arr[0]}@{arr[1]}.{arr[2]}"; + } + } + + return $"{UUID.Substring(2, 6)}@gmail.com"; + } + } + /// /// 安装类型 /// diff --git a/ProxySuper.Core/Models/Projects/XraySettings_SS.cs b/ProxySuper.Core/Models/Projects/XraySettings_SS.cs index debe70a..71936dd 100644 --- a/ProxySuper.Core/Models/Projects/XraySettings_SS.cs +++ b/ProxySuper.Core/Models/Projects/XraySettings_SS.cs @@ -1,9 +1,4 @@ using ProxySuper.Core.Services; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace ProxySuper.Core.Models.Projects { diff --git a/ProxySuper.Core/Models/Projects/XraySettings_Trojan.cs b/ProxySuper.Core/Models/Projects/XraySettings_Trojan.cs index 301032e..6d110a7 100644 --- a/ProxySuper.Core/Models/Projects/XraySettings_Trojan.cs +++ b/ProxySuper.Core/Models/Projects/XraySettings_Trojan.cs @@ -1,9 +1,4 @@ using ProxySuper.Core.Services; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace ProxySuper.Core.Models.Projects { diff --git a/ProxySuper.Core/Models/Projects/XraySettings_VLESS.cs b/ProxySuper.Core/Models/Projects/XraySettings_VLESS.cs index 63d8574..e2b959e 100644 --- a/ProxySuper.Core/Models/Projects/XraySettings_VLESS.cs +++ b/ProxySuper.Core/Models/Projects/XraySettings_VLESS.cs @@ -1,9 +1,4 @@ using ProxySuper.Core.Services; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace ProxySuper.Core.Models.Projects { diff --git a/ProxySuper.Core/Models/Projects/XraySettings_VMESS.cs b/ProxySuper.Core/Models/Projects/XraySettings_VMESS.cs index b9c0664..61fce95 100644 --- a/ProxySuper.Core/Models/Projects/XraySettings_VMESS.cs +++ b/ProxySuper.Core/Models/Projects/XraySettings_VMESS.cs @@ -1,9 +1,4 @@ using ProxySuper.Core.Services; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace ProxySuper.Core.Models.Projects { diff --git a/ProxySuper.Core/Models/Projects/XrayType.cs b/ProxySuper.Core/Models/Projects/XrayType.cs index 304cd6e..337e220 100644 --- a/ProxySuper.Core/Models/Projects/XrayType.cs +++ b/ProxySuper.Core/Models/Projects/XrayType.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace ProxySuper.Core.Models.Projects +namespace ProxySuper.Core.Models.Projects { public enum XrayType { diff --git a/ProxySuper.Core/Models/Record.cs b/ProxySuper.Core/Models/Record.cs index f4a6a67..b032781 100644 --- a/ProxySuper.Core/Models/Record.cs +++ b/ProxySuper.Core/Models/Record.cs @@ -1,21 +1,9 @@ -using Microsoft.Win32; -using MvvmCross; -using MvvmCross.Commands; -using MvvmCross.Navigation; -using MvvmCross.ViewModels; +using MvvmCross.ViewModels; using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using ProxySuper.Core.Models.Hosts; using ProxySuper.Core.Models.Projects; using ProxySuper.Core.Services; -using ProxySuper.Core.ViewModels; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.IO; -using System.Linq; using System.Text; -using System.Threading.Tasks; namespace ProxySuper.Core.Models { @@ -53,6 +41,9 @@ namespace ProxySuper.Core.Models [JsonProperty("naiveProxySettings")] public NaiveProxySettings NaiveProxySettings { get; set; } + [JsonProperty("brook")] + public BrookSettings BrookSettings { get; set; } + [JsonIgnore] public ProjectType Type @@ -63,7 +54,9 @@ namespace ProxySuper.Core.Models if (TrojanGoSettings != null) return ProjectType.TrojanGo; - return ProjectType.NaiveProxy; + if (NaiveProxySettings != null) return ProjectType.NaiveProxy; + + return ProjectType.Brook; } } diff --git a/ProxySuper.Core/Properties/AssemblyInfo.cs b/ProxySuper.Core/Properties/AssemblyInfo.cs index 6a26f9f..b26cc8e 100644 --- a/ProxySuper.Core/Properties/AssemblyInfo.cs +++ b/ProxySuper.Core/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // 有关程序集的一般信息由以下 diff --git a/ProxySuper.Core/ProxySuper.Core.csproj b/ProxySuper.Core/ProxySuper.Core.csproj index db1bc85..02c6703 100644 --- a/ProxySuper.Core/ProxySuper.Core.csproj +++ b/ProxySuper.Core/ProxySuper.Core.csproj @@ -67,9 +67,12 @@ + - + + + @@ -84,13 +87,20 @@ + + + + + + + @@ -102,6 +112,7 @@ + diff --git a/ProxySuper.Core/Services/BrookProject.cs b/ProxySuper.Core/Services/BrookProject.cs new file mode 100644 index 0000000..2672d84 --- /dev/null +++ b/ProxySuper.Core/Services/BrookProject.cs @@ -0,0 +1,128 @@ +using ProxySuper.Core.Models.Projects; +using Renci.SshNet; +using System; + +namespace ProxySuper.Core.Services +{ + public class BrookProject : ProjectBase + { + private string brookServiceTemp = @" + [Unit] + Description=brook service + After=network.target syslog.target + Wants=network.target + + [Service] + Type=simple + ExecStart=##run_cmd## + + [Install] + WantedBy=multi-user.target"; + + public BrookProject(SshClient sshClient, BrookSettings parameters, Action writeOutput) : base(sshClient, parameters, writeOutput) + { + } + + public override void Install() + { + + WriteOutput("检测安装系统环境..."); + EnsureSystemEnv(); + WriteOutput("检测安装系统环境完成"); + + WriteOutput("配置服务器端口..."); + ConfigFirewalld(); + WriteOutput("端口配置完成"); + + WriteOutput("安装必要的系统工具..."); + ConfigureSoftware(); + WriteOutput("系统工具安装完成"); + + WriteOutput("检测网络环境"); + EnsureIP(); + WriteOutput("检测网络环境完成"); + + if (Parameters.BrookType == BrookType.wssserver) + { + WriteOutput("检测域名是否绑定本机IP..."); + ValidateDomain(); + WriteOutput("域名检测完成"); + } + + InstallBrook(); + + + Console.WriteLine("*************安装完成,尽情享用吧**********"); + } + + public void InstallBrook() + { + Console.WriteLine("安装Brook"); + + string url = "https://github.com/txthinking/brook/releases/latest/download/brook_linux_amd64"; + if (ArchType == ArchType.arm) + { + url = url.Replace("brook_linux_amd64", "brook_linux_arm7"); + } + + RunCmd($"curl -L {url} -o /usr/bin/brook"); + RunCmd("chmod +x /usr/bin/brook"); + Console.WriteLine("安装Brook完成"); + + var brookService = brookServiceTemp.Replace("##run_cmd##", GetRunBrookCommand()); + + RunCmd("rm -rf /etc/systemd/system/brook.service"); + RunCmd("touch /etc/systemd/system/brook.service"); + RunCmd($"echo \"{brookService}\" > /etc/systemd/system/brook.service"); + RunCmd("sudo chmod 777 /etc/systemd/system/brook.service"); + + RunCmd("systemctl enable brook"); + RunCmd("systemctl restart brook"); + + WriteOutput("********************"); + WriteOutput("安装完成,尽情想用吧~ "); + WriteOutput("*********************"); + } + + private string GetRunBrookCommand() + { + var runBrookCmd = string.Empty; + + if (Parameters.BrookType == BrookType.server) + { + return $"/usr/bin/brook server --listen :{Parameters.Port} --password {Parameters.Password}"; + } + + if (Parameters.BrookType == BrookType.wsserver) + { + return $"/usr/bin/brook wsserver --listen :{Parameters.Port} --password {Parameters.Password}"; + } + + if (Parameters.BrookType == BrookType.wssserver) + { + return $"/usr/bin/brook wssserver --domain {Parameters.Domain} --password {Parameters.Password}"; + } + + if (Parameters.BrookType == BrookType.socks5) + { + var ip = OnlyIpv6 ? IPv6 : IPv4; + return $"/usr/bin/brook socks5 --socks5 {ip}:{Parameters.Port}"; + } + + return runBrookCmd; + } + + public void Uninstall() + { + RunCmd("systemctl stop brook"); + RunCmd("systemctl disable brook"); + RunCmd("rm -rf /etc/systemd/system/brook.service"); + RunCmd("rm -rf /usr/bin/brook"); + + Console.WriteLine("关闭端口"); + ResetFirewalld(); + + WriteOutput("******卸载完成******"); + } + } +} diff --git a/ProxySuper.Core/Services/NaiveProxyProject.cs b/ProxySuper.Core/Services/NaiveProxyProject.cs index 0d25b6b..0f9f7d9 100644 --- a/ProxySuper.Core/Services/NaiveProxyProject.cs +++ b/ProxySuper.Core/Services/NaiveProxyProject.cs @@ -1,13 +1,8 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using ProxySuper.Core.Models.Projects; +using ProxySuper.Core.Models.Projects; using Renci.SshNet; using System; -using System.Collections.Generic; using System.IO; -using System.Linq; using System.Text; -using System.Threading.Tasks; using System.Windows; namespace ProxySuper.Core.Services @@ -20,7 +15,10 @@ namespace ProxySuper.Core.Services public void Uninstall() { - UninstallCaddy(); + RunCmd("rm -rf caddy_install.sh"); + RunCmd("curl -o caddy_install.sh https://raw.githubusercontent.com/proxysu/shellscript/master/Caddy-Naive/caddy-naive-install.sh"); + RunCmd("yes | bash caddy_install.sh uninstall"); + RunCmd("rm -rf caddy_install.sh"); WriteOutput("ProxyNaive卸载完成"); } @@ -51,22 +49,18 @@ namespace ProxySuper.Core.Services EnsureSystemEnv(); WriteOutput("检测安装系统环境完成"); - WriteOutput("配置服务器端口..."); - ConfigurePort(); - WriteOutput("端口配置完成"); - WriteOutput("安装必要的系统工具..."); ConfigureSoftware(); WriteOutput("系统工具安装完成"); - WriteOutput("检测IP6..."); - ConfigureIPv6(); - WriteOutput("检测IP6完成"); - WriteOutput("配置防火墙..."); - ConfigureFirewall(); + ConfigFirewalld(); WriteOutput("防火墙配置完成"); + WriteOutput("检测网络环境"); + EnsureIP(); + WriteOutput("检测网络环境完成"); + WriteOutput("同步系统和本地时间..."); SyncTimeDiff(); WriteOutput("时间同步完成"); @@ -90,7 +84,7 @@ namespace ProxySuper.Core.Services { var errorLog = "安装终止," + ex.Message; WriteOutput(errorLog); - MessageBox.Show(errorLog); + MessageBox.Show("安装失败,请联系开发者或上传日志文件(Logs文件夹下)到github提问。"); } } @@ -98,6 +92,8 @@ namespace ProxySuper.Core.Services { WriteOutput("安装 NaiveProxy"); RunCmd(@"curl https://raw.githubusercontent.com/proxysu/shellscript/master/Caddy-Naive/caddy-naive-install.sh yes | bash"); + // 允许开机启动 + RunCmd("systemctl enable caddy"); UploadCaddyFile(false); ConfigNetwork(); WriteOutput("NaiveProxy 安装完成"); @@ -131,13 +127,13 @@ namespace ProxySuper.Core.Services private void UploadCaddyFile(bool useCustomWeb = false) { var caddyStr = BuildConfig(useCustomWeb); - var stream = new MemoryStream(Encoding.UTF8.GetBytes(caddyStr)); if (FileExists("/etc/caddy/Caddyfile")) { RunCmd("mv /etc/caddy/Caddyfile /etc/caddy/Caddyfile.back"); } - UploadFile(stream, "/etc/caddy/Caddyfile"); + + RunCmd($"echo {caddyStr} > /etc/caddy/Caddyfile"); RunCmd("systemctl restart caddy"); } diff --git a/ProxySuper.Core/Services/ProjectBase.cs b/ProxySuper.Core/Services/ProjectBase.cs index 3e525b3..983fcf2 100644 --- a/ProxySuper.Core/Services/ProjectBase.cs +++ b/ProxySuper.Core/Services/ProjectBase.cs @@ -1,5 +1,6 @@ using ProxySuper.Core.Helpers; using ProxySuper.Core.Models; +using ProxySuper.Core.Models.Hosts; using ProxySuper.Core.Models.Projects; using Renci.SshNet; using System; @@ -7,7 +8,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; -using System.Threading.Tasks; using System.Windows; namespace ProxySuper.Core.Services @@ -20,14 +20,24 @@ namespace ProxySuper.Core.Services Yum } + public enum ArchType + { + x86, + arm, + } + public abstract class ProjectBase where TSettings : IProjectSettings { + + private SshClient _sshClient; protected Action WriteOutput; protected CmdType CmdType { get; set; } + protected ArchType ArchType { get; set; } + protected bool IsSELinux { get; set; } protected bool OnlyIpv6 { get; set; } @@ -50,7 +60,9 @@ namespace ProxySuper.Core.Services var cmd = _sshClient.CreateCommand(cmdStr); WriteOutput(cmdStr); - var result = cmd.Execute(); + var exe = cmd.BeginExecute(); + var result = cmd.EndExecute(exe); + //var result = cmd.Execute(); WriteOutput(result); return result; } @@ -67,10 +79,25 @@ namespace ProxySuper.Core.Services { string cmd; + // cpu架构 + var result = RunCmd("uname -m"); + if (result.Contains("x86")) + { + ArchType = ArchType.x86; + } + else if (result.Contains("arm") || result.Contains("arch")) + { + ArchType = ArchType.arm; + } + else + { + throw new Exception($"未识别的架构处理器架构:{result}"); + } + // 确认安装命令 if (CmdType == CmdType.None) { - cmd = RunCmd("command -v apt-get"); + cmd = RunCmd("command -v apt"); if (!string.IsNullOrEmpty(cmd)) { CmdType = CmdType.Apt; @@ -83,6 +110,8 @@ namespace ProxySuper.Core.Services if (!string.IsNullOrEmpty(cmd)) { CmdType = CmdType.Dnf; + //RunCmd("echo \"export LC_ALL=en_US.UTF-8\" >> /etc/profile"); + //RunCmd("source /etc/profile"); } } @@ -105,7 +134,7 @@ namespace ProxySuper.Core.Services if (CmdType == CmdType.None || !hasSystemCtl) { - throw new Exception("系统缺乏必要的安装组件如:apt-get||dnf||yum||Syetemd,主机系统推荐使用:CentOS 7/8,Debian 8/9/10,Ubuntu 16.04及以上版本"); + throw new Exception("系统缺乏必要的安装组件如:apt||dnf||yum||Syetemd,主机系统推荐使用:CentOS 7/8,Debian 8/9/10,Ubuntu 16.04及以上版本"); } @@ -144,7 +173,7 @@ namespace ProxySuper.Core.Services /// /// 配置IPV6环境 /// - protected void ConfigureIPv6() + protected void EnsureIP() { if (IsOnlyIpv6()) { @@ -157,6 +186,8 @@ namespace ProxySuper.Core.Services /// protected void ConfigureSoftware() { + RunCmd(GetUpdateCmd()); + string cmd = RunCmd("command -v sudo"); if (string.IsNullOrEmpty(cmd)) { @@ -188,17 +219,14 @@ namespace ProxySuper.Core.Services { if (CmdType == CmdType.Apt) { - RunCmd(GetUpdateCmd()); RunCmd(GetInstallCmd("dnsutils")); } else if (CmdType == CmdType.Dnf) { - RunCmd(GetUpdateCmd()); RunCmd(GetInstallCmd("bind-utils")); } else if (CmdType == CmdType.Yum) { - RunCmd(GetUpdateCmd()); RunCmd(GetInstallCmd("bind-utils")); } } @@ -214,6 +242,13 @@ namespace ProxySuper.Core.Services RunCmd(GetInstallCmd("xz-devel")); } + // 检测是否安装cron + cmd = RunCmd("command -v cron"); + if (string.IsNullOrEmpty(cmd)) + { + RunCmd(GetInstallCmd("cron")); + } + // 检测是否安装lsof cmd = RunCmd("command -v lsof"); if (string.IsNullOrEmpty(cmd)) @@ -222,100 +257,30 @@ namespace ProxySuper.Core.Services } } - /// - /// 关闭端口 - /// - /// - protected void ClosePort(params int[] portList) - { - string cmd; - - cmd = RunCmd("command -v firewall-cmd"); - if (!string.IsNullOrEmpty(cmd)) - { - //有很奇怪的vps主机,在firewalld未运行时,端口是关闭的,无法访问。所以要先启动firewalld - //用于保证acme.sh申请证书成功 - cmd = RunCmd("firewall-cmd --state"); - if (cmd.Trim() != "running") - { - RunCmd("systemctl restart firewalld"); - } - - foreach (var port in portList) - { - RunCmd($"firewall-cmd --zone=public --remove-port={port}/tcp --permanent"); - RunCmd($"firewall-cmd --zone=public --remove-port={port}/udp --permanent"); - } - RunCmd("yes | firewall-cmd --reload"); - } - else - { - cmd = RunCmd("command -v ufw"); - if (!string.IsNullOrEmpty(cmd)) - { - foreach (var port in portList) - { - RunCmd($"ufw delete allow {port}/tcp"); - RunCmd($"ufw delete allow {port}/udp"); - } - RunCmd("yes | ufw reload"); - } - } - } - - /// - /// 开放端口 - /// - /// - protected void OpenPort(params int[] portList) - { - - string cmd; - - cmd = RunCmd("command -v firewall-cmd"); - if (!string.IsNullOrEmpty(cmd)) - { - //有很奇怪的vps主机,在firewalld未运行时,端口是关闭的,无法访问。所以要先启动firewalld - //用于保证acme.sh申请证书成功 - cmd = RunCmd("firewall-cmd --state"); - if (cmd.Trim() != "running") - { - RunCmd("systemctl restart firewalld"); - } - - foreach (var port in portList) - { - RunCmd($"firewall-cmd --zone=public --add-port={port}/tcp --permanent"); - RunCmd($"firewall-cmd --zone=public --add-port={port}/udp --permanent"); - } - RunCmd("yes | firewall-cmd --reload"); - } - else - { - cmd = RunCmd("command -v ufw"); - if (!string.IsNullOrEmpty(cmd)) - { - foreach (var port in portList) - { - RunCmd($"ufw allow {port}/tcp"); - RunCmd($"ufw allow {port}/udp"); - } - RunCmd("yes | ufw reload"); - } - } - } - /// /// 配置防火墙 /// - protected void ConfigureFirewall() + protected void ConfigFirewalld() { - var portList = new List(); - portList.Add(80); - portList.Add(Parameters.Port); - portList.AddRange(Parameters.FreePorts); + Parameters.FreePorts.ForEach(port => + { + SetPortFree(port); + }); - OpenPort(portList.ToArray()); + OpenPort(_sshClient.ConnectionInfo.Port); + OpenPort(Parameters.FreePorts.ToArray()); + } + + /// + /// 重置防火墙 + /// + protected void ResetFirewalld() + { + Parameters.FreePorts.ForEach(port => + { + SetPortFree(port); + }); + ClosePort(Parameters.FreePorts.ToArray()); } /// @@ -395,11 +360,60 @@ namespace ProxySuper.Core.Services /// protected void InstallCaddy() { - RunCmd("rm -rf caddy_install.sh"); - RunCmd("curl -o caddy_install.sh https://raw.githubusercontent.com/proxysu/shellscript/master/Caddy-Naive/caddy-naive-install.sh"); - RunCmd("yes | bash caddy_install.sh"); - RunCmd("rm -rf caddy_install.sh"); - RunCmd("systemctl enable caddy.service"); + #region 二进制文件安装 + RunCmd("rm -rf caddy.tar.gz"); + RunCmd("rm -rf /etc/caddy"); + RunCmd("rm -rf /usr/share/caddy"); + + var url = "https://github.com/caddyserver/caddy/releases/download/v2.4.3/caddy_2.4.3_linux_amd64.tar.gz"; + if (ArchType == ArchType.arm) + { + url = "https://github.com/caddyserver/caddy/releases/download/v2.4.3/caddy_2.4.3_linux_armv7.tar.gz"; + } + + RunCmd($"wget -O caddy.tar.gz {url}"); + RunCmd("mkdir /etc/caddy"); + RunCmd("tar -zxvf caddy.tar.gz -C /etc/caddy"); + RunCmd("cp -rf /etc/caddy/caddy /usr/bin"); + WriteToFile(Caddy.DefaultCaddyFile, "/etc/caddy/Caddyfile"); + WriteToFile(Caddy.Service, "/etc/systemd/system/caddy.service"); + RunCmd("systemctl daemon-reload"); + RunCmd("systemctl enable caddy"); + + RunCmd("mkdir /usr/share/caddy"); + + if (!FileExists("/usr/bin/caddy")) + { + throw new Exception("Caddy服务器安装失败,请联系开发者!"); + } + #endregion + + #region 官方安装步骤 + //if (CmdType == CmdType.Apt) + //{ + // RunCmd("apt install -y debian-keyring debian-archive-keyring apt-transport-https"); + // RunCmd("echo yes | curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo apt-key add -"); + // RunCmd("echo yes | curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list"); + // RunCmd("sudo apt -y update"); + // RunCmd("sudo apt install -y caddy"); + //} + + //if (CmdType == CmdType.Dnf) + //{ + // RunCmd("dnf install -y 'dnf-command(copr)'"); + // RunCmd("dnf copr -y enable @caddy/caddy"); + // RunCmd("dnf install -y caddy"); + //} + + //if (CmdType == CmdType.Yum) + //{ + // RunCmd("yum install -y yum-plugin-copr"); + // RunCmd("yum copr -y enable @caddy/caddy"); + // RunCmd("yum install -y caddy"); + //} + + //RunCmd("systemctl enable caddy.service"); + #endregion } /// @@ -407,11 +421,12 @@ namespace ProxySuper.Core.Services /// protected void UninstallCaddy() { - RunCmd("rm -rf caddy_install.sh"); - RunCmd("curl -o caddy_install.sh https://raw.githubusercontent.com/proxysu/shellscript/master/Caddy-Naive/caddy-naive-install.sh"); - RunCmd("yes | bash caddy_install.sh uninstall"); - RunCmd("rm -rf caddy_install.sh"); + RunCmd("systemctl stop caddy"); + RunCmd("systemctl disable caddy"); + RunCmd("rm -rf /etc/systemd/system/caddy.service"); + RunCmd("rm -rf /usr/bin/caddy"); RunCmd("rm -rf /usr/share/caddy"); + RunCmd("rm -rf /etc/caddy"); } @@ -435,62 +450,13 @@ namespace ProxySuper.Core.Services if (string.IsNullOrEmpty(IPv6)) { - throw new Exception("未检测可用的的IP地址"); + throw new Exception("未检测到可用的的IP地址,请重试安装"); } OnlyIpv6 = true; return OnlyIpv6; } - private bool SetPortFree(int port, bool force = true) - { - string result = RunCmd($"lsof -n -P -i :{port} | grep LISTEN"); - - if (!string.IsNullOrEmpty(result)) - { - if (force) - { - var btnResult = MessageBox.Show($"{port}端口被占用,将强制停止占用{port}端口的程序?", "提示", MessageBoxButton.YesNo); - if (btnResult == MessageBoxResult.No) - { - throw new Exception($"{port}端口被占用,安装停止!"); - } - - string[] process = result.Split(' '); - RunCmd($"systemctl stop {process[0]}"); - RunCmd($"systemctl disable {process[0]}"); - RunCmd($"pkill {process[0]}"); - return SetPortFree(port, force: false); - } - else - { - return false; - } - } - - return true; - } - - public void ConfigurePort() - { - if (Parameters.Port == 80 || Parameters.Port == 443) - { - SetPortFree(80); - SetPortFree(443); - } - else - { - SetPortFree(80); - SetPortFree(443); - SetPortFree(Parameters.Port); - - Parameters.FreePorts.ForEach(port => - { - SetPortFree(port); - }); - } - } - protected void SetNat64() { var dns64List = FilterFastestIP(); @@ -553,6 +519,121 @@ namespace ProxySuper.Core.Services return dns64List.Keys.ToList(); } + private bool SetPortFree(int port, bool force = true) + { + string result = RunCmd($"lsof -n -P -i :{port} | grep LISTEN"); + + if (!string.IsNullOrEmpty(result)) + { + if (force) + { + var btnResult = MessageBox.Show($"{port}端口被占用,将强制停止占用{port}端口的程序?", "提示", MessageBoxButton.YesNo); + if (btnResult == MessageBoxResult.No) + { + throw new Exception($"{port}端口被占用,安装停止!"); + } + + string[] process = result.Split(' '); + RunCmd($"systemctl stop {process[0]}"); + RunCmd($"systemctl disable {process[0]}"); + RunCmd($"pkill {process[0]}"); + return SetPortFree(port, force: false); + } + else + { + return false; + } + } + + return true; + } + + /// + /// 关闭端口 + /// + /// + private void ClosePort(params int[] portList) + { + string cmd; + + cmd = RunCmd("command -v firewall-cmd"); + if (!string.IsNullOrEmpty(cmd)) + { + //有很奇怪的vps主机,在firewalld未运行时,端口是关闭的,无法访问。所以要先启动firewalld + //用于保证acme.sh申请证书成功 + cmd = RunCmd("firewall-cmd --state"); + if (cmd.Trim() != "running") + { + RunCmd("systemctl restart firewalld"); + } + + foreach (var port in portList) + { + RunCmd($"firewall-cmd --zone=public --remove-port={port}/tcp --permanent"); + RunCmd($"firewall-cmd --zone=public --remove-port={port}/udp --permanent"); + } + RunCmd("yes | firewall-cmd --reload"); + } + else + { + cmd = RunCmd("command -v ufw"); + if (!string.IsNullOrEmpty(cmd)) + { + foreach (var port in portList) + { + RunCmd($"ufw delete allow {port}/tcp"); + RunCmd($"ufw delete allow {port}/udp"); + } + RunCmd("yes | ufw reload"); + } + } + } + + /// + /// 开放端口 + /// + /// + private void OpenPort(params int[] portList) + { + string cmd; + + cmd = RunCmd("command -v firewall-cmd"); + if (!string.IsNullOrEmpty(cmd)) + { + //有很奇怪的vps主机,在firewalld未运行时,端口是关闭的,无法访问。所以要先启动firewalld + //用于保证acme.sh申请证书成功 + cmd = RunCmd("firewall-cmd --state"); + if (cmd.Trim() != "running") + { + RunCmd("systemctl restart firewalld"); + } + + foreach (var port in portList) + { + RunCmd($"firewall-cmd --zone=public --add-port={port}/tcp --permanent"); + RunCmd($"firewall-cmd --zone=public --add-port={port}/udp --permanent"); + } + RunCmd("yes | firewall-cmd --reload"); + } + else + { + cmd = RunCmd("command -v ufw"); + if (string.IsNullOrEmpty(cmd)) + { + RunCmd(GetInstallCmd("ufw")); + RunCmd("echo y | ufw enable"); + } + + foreach (var port in portList) + { + RunCmd($"ufw allow {port}/tcp"); + RunCmd($"ufw allow {port}/udp"); + } + RunCmd("yes | ufw reload"); + + } + } + #endregion @@ -629,6 +710,7 @@ namespace ProxySuper.Core.Services RunCmd(GetInstallCmd("automake autoconf libtool")); // 安装Acme + var result = RunCmd($"curl https://get.acme.sh yes | sh"); if (result.Contains("Install success")) { @@ -640,18 +722,17 @@ namespace ProxySuper.Core.Services throw new Exception("安装 acme.sh 失败,请联系开发者!"); } - RunCmd("cd ~/.acme.sh/"); RunCmd("alias acme.sh=~/.acme.sh/acme.sh"); // 申请证书 if (OnlyIpv6) { - var cmd = $"/root/.acme.sh/acme.sh --force --debug --issue --standalone -d {Parameters.Domain} --listen-v6 --pre-hook \"service caddy stop\" --post-hook \"service caddy start\""; + var cmd = $"/root/.acme.sh/acme.sh --force --debug --issue --standalone -d {Parameters.Domain} --listen-v6 --pre-hook \"systemctl stop caddy\" --post-hook \"systemctl start caddy\" --server letsencrypt"; result = RunCmd(cmd); } else { - var cmd = $"/root/.acme.sh/acme.sh --force --debug --issue --standalone -d {Parameters.Domain} --pre-hook \"service caddy stop\" --post-hook \"service caddy start\""; + var cmd = $"/root/.acme.sh/acme.sh --force --debug --issue --standalone -d {Parameters.Domain} --pre-hook \"systemctl stop caddy\" --post-hook \"systemctl start caddy\" --server letsencrypt"; result = RunCmd(cmd); } @@ -684,6 +765,29 @@ namespace ProxySuper.Core.Services RunCmd($"chmod 755 {dirPath}"); } + protected void WriteToFile(string text, string path) + { + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(text))) + { + using (var sftp = new SftpClient(_sshClient.ConnectionInfo)) + { + try + { + sftp.Connect(); + sftp.UploadFile(stream, path, true); + } + catch (Exception ex) + { + throw ex; + } + finally + { + sftp.Disconnect(); + } + } + } + } + /// /// 上传文件 /// @@ -707,14 +811,18 @@ namespace ProxySuper.Core.Services { if (CmdType == CmdType.Apt) { - return "apt-get update"; + return "apt update"; } else if (CmdType == CmdType.Dnf) { + RunCmd("echo \"export LC_ALL=en_US.UTF-8\" >> /etc/profile"); + RunCmd("source /etc/profile"); return "dnf clean all;dnf makecache"; } else if (CmdType == CmdType.Yum) { + RunCmd("echo \"export LC_ALL=en_US.UTF-8\" >> /etc/profile"); + RunCmd("source /etc/profile"); return "yum clean all;yum makecache"; } @@ -730,15 +838,15 @@ namespace ProxySuper.Core.Services { if (CmdType == CmdType.Apt) { - return "echo y | apt-get install " + soft; + return "apt install -y " + soft; } else if (CmdType == CmdType.Dnf) { - return "echo y | dnf -y install " + soft; + return "dnf install -y " + soft; } else if (CmdType == CmdType.Yum) { - return "echo y | yum -y install " + soft; + return "yum install -y " + soft; } throw new Exception("未识别的系统"); diff --git a/ProxySuper.Core/Services/ServiceBase.cs b/ProxySuper.Core/Services/ServiceBase.cs new file mode 100644 index 0000000..3d9aad7 --- /dev/null +++ b/ProxySuper.Core/Services/ServiceBase.cs @@ -0,0 +1,740 @@ +using ProxySuper.Core.Helpers; +using ProxySuper.Core.Models; +using ProxySuper.Core.Models.Hosts; +using ProxySuper.Core.Models.Projects; +using Renci.SshNet; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ProxySuper.Core.Services +{ + public abstract class ServiceBase where TSettings : IProjectSettings + { + private Host _host; + + + private SshClient _sshClient; + + private ProjectProgress _progress; + + public ServiceBase(Host host, TSettings settings) + { + _host = host; + + Settings = settings; + + _sshClient = new SshClient(CreateConnectionInfo()); + + _progress = new ProjectProgress(); + + ArchType = ArchType.x86; + + CmdType = CmdType.None; + + IPv4 = string.Empty; + + IPv6 = string.Empty; + + IsOnlyIPv6 = false; + } + + public string RunCmd(string command) + { + AppendCommand(command); + + string result; + if (_sshClient.IsConnected) + { + result = _sshClient.CreateCommand(command).Execute(); + } + else + { + result = "连接已断开"; + } + + AppendCommand(result); + + return result; + } + + public ProjectProgress Progress => _progress; + + public TSettings Settings { get; set; } + + public ArchType ArchType { get; set; } + + public CmdType CmdType { get; set; } + + public string IPv4 { get; set; } + + public string IPv6 { get; set; } + + public bool IsOnlyIPv6 { get; set; } + + + #region 公用方法 + public void Connect() + { + Task.Run(() => + { + if (_sshClient.IsConnected == false) + { + Progress.Desc = ("正在与服务器建立连接"); + try + { + _sshClient.Connect(); + Progress.Desc = ("建立连接成功"); + } + catch (Exception e) + { + Progress.Desc = ("连接失败," + e.Message); + } + } + }); + } + + public void Disconnect() + { + Task.Run(() => + { + _sshClient.Disconnect(); + }); + } + + protected void WriteToFile(string text, string path) + { + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(text))) + { + using (var sftp = new SftpClient(_sshClient.ConnectionInfo)) + { + try + { + sftp.Connect(); + sftp.UploadFile(stream, path, true); + } + catch (Exception ex) + { + throw ex; + } + finally + { + sftp.Disconnect(); + } + } + } + } + + protected bool FileExists(string path) + { + var cmdStr = $"if [[ -f {path} ]];then echo '1';else echo '0'; fi"; + var cmd = RunCmd(cmdStr); + return cmd.Trim() == "1"; + } + + protected void SyncTimeDiff() + { + RunCmd("rm -f /etc/localtime"); + RunCmd("ln -s /usr/share/zoneinfo/UTC /etc/localtime"); + + var result = RunCmd("date +%s"); + var vpsSeconds = Convert.ToInt64(result); + var localSeconds = (int)(DateTime.Now.ToUniversalTime() - DateTime.Parse("1970-01-01")).TotalSeconds; + + if (Math.Abs(vpsSeconds - localSeconds) >= 90) + { + // 同步本地时间 + var netUtcTime = DateTimeUtils.GetUTCTime(); + DateTimeUtils.SetDate(netUtcTime.ToLocalTime()); + + // 同步VPS时间 + var utcTS = DateTimeUtils.GetUTCTime() - new DateTime(1970, 1, 1, 0, 0, 0, 0); + long timeStampVPS = Convert.ToInt64(utcTS.TotalSeconds); + RunCmd($"date --set=\"$(date \"+%Y-%m-%d %H:%M:%S\" -d @{timeStampVPS.ToString()})\""); + } + } + + protected void ValidateDomain() + { + var domainIP = RunCmd($"ping \"{Settings.Domain}\" -c 1" + @" | sed '1{s/[^(]*(//;s/).*//;q}'") + .Trim('\r', '\n'); + + if (IsOnlyIPv6) + { + Progress.Desc = ($"本机IP({IPv6})"); + if (IPv6 != domainIP) + { + throw new Exception("域名解析地址与服务器IP不匹配!"); + } + } + else + { + Progress.Desc = ($"本机IP({IPv4})"); + Progress.Desc = ($"域名IP({domainIP})"); + if (IPv4 != domainIP) + { + throw new Exception("域名解析地址与服务器IP不匹配!"); + } + } + } + + protected void EnableBBR() + { + Progress.Desc = ("检查系统是否满足启动BBR条件"); + var osVersion = RunCmd("uname -r"); + var canInstallBBR = CheckKernelVersionBBR(osVersion.Split('-')[0]); + + var bbrInfo = RunCmd("sysctl net.ipv4.tcp_congestion_control | grep bbr"); + var installed = bbrInfo.Contains("bbr"); + if (canInstallBBR && !installed) + { + RunCmd(@"bash -c 'echo ""net.core.default_qdisc=fq"" >> /etc/sysctl.conf'"); + RunCmd(@"bash -c 'echo ""net.ipv4.tcp_congestion_control=bbr"" >> /etc/sysctl.conf'"); + RunCmd(@"sysctl -p"); + + if (IsOnlyIPv6) + { + RemoveNat64(); + } + Progress.Desc = ("启动BBR成功"); + } + + if (!canInstallBBR) + { + Progress.Desc = ("系统不满足启用BBR条件,启动失败。"); + } + + } + + /// + /// 安装证书 + /// + /// + /// + protected void InstallCert(string dirPath, string certName, string keyName) + { + string certPath = dirPath + "/" + certName; + string keyPath = dirPath + "/" + keyName; + + Progress.Desc = ("安装Acme软件"); + #region 安装Acme + // 安装依赖 + RunCmd(GetInstallCmd("socat")); + + // 解决搬瓦工CentOS缺少问题 + RunCmd(GetInstallCmd("automake autoconf libtool")); + + // 安装Acme + var result = RunCmd($"curl https://get.acme.sh yes | sh"); + if (!result.Contains("nstall success")) + { + throw new Exception("安装 Acme 失败,请联系开发者!"); + } + + RunCmd("alias acme.sh=~/.acme.sh/acme.sh"); + + #endregion + + + #region 申请证书 + Progress.Desc = ("正在申请证书"); + // 申请证书 + var cmd = $"/root/.acme.sh/acme.sh --force --debug --issue --standalone -d {Settings.Domain} {(IsOnlyIPv6 ? "--listen-v6" : "")} --pre-hook \"systemctl stop caddy\" --post-hook \"systemctl start caddy\" --server letsencrypt"; + result = RunCmd(cmd); + + + if (result.Contains("success")) + { + Progress.Desc = ("申请证书成功"); + } + else + { + Progress.Desc = ("申请证书失败,如果申请次数过多请更换二级域名,或联系开发者!"); + throw new Exception("申请证书失败,如果申请次数过多请更换二级域名,或联系开发者!"); + } + #endregion + + // 安装证书 + Progress.Desc = ("安装Xray证书"); + RunCmd($"mkdir -p {dirPath}"); + RunCmd($"/root/.acme.sh/acme.sh --installcert -d {Settings.Domain} --certpath {certPath} --keypath {keyPath} --capath {certPath}"); + + result = RunCmd($@"if [ ! -f ""{keyPath}"" ]; then echo ""0""; else echo ""1""; fi | head -n 1"); + + if (result.Contains("1")) + { + Progress.Desc = ("安装证书成功"); + } + else + { + Progress.Desc = ("安装证书失败,请联系开发者!"); + throw new Exception("安装证书失败,请联系开发者!"); + } + + RunCmd($"chmod 755 {dirPath}"); + } + + + public bool IsRootUser() + { + // 禁止一些可能产生的干扰信息 + RunCmd(@"sed -i 's/echo/#echo/g' ~/.bashrc"); + RunCmd(@"sed -i 's/echo/#echo/g' ~/.profile"); + + var result = RunCmd("id -u"); + return result.Equals("0\n"); + } + + public void EnsureSystemEnv() + { + // cpu架构 + Progress.Desc = ("检测CPU架构"); + EnsureCPU(); + + // 安装命令类型 + Progress.Desc = ("检测系统安装命令"); + EnsureCmdType(); + + // systemctl + Progress.Desc = ("检测Systemctl"); + EnsureSystemctl(); + + // SELinux + Progress.Desc = ("检测SELinux"); + ConfigSELinux(); + } + + public void InstallSystemTools() + { + Progress.Desc = ("安装sudo工具"); + InstallSoftware("sudo"); + + Progress.Desc = ("安装curl工具"); + InstallSoftware("curl"); + + Progress.Desc = ("安装wget工具"); + InstallSoftware("wget"); + + Progress.Desc = ("安装ping工具"); + InstallSoftware("ping"); + + Progress.Desc = ("安装unzip工具"); + InstallSoftware("unzip"); + + Progress.Desc = ("安装cron工具"); + InstallSoftware("cron"); + + Progress.Desc = ("安装lsof工具"); + InstallSoftware("lsof"); + + Progress.Desc = ("安装systemd工具"); + InstallSoftware("systemd"); + } + + public void ConfigFirewalld() + { + Progress.Desc = ("释放被占用的端口"); + Settings.FreePorts.ForEach(port => SetPortFree(port)); + + Progress.Desc = ("开放需要的端口"); + OpenPort(Settings.FreePorts.ToArray()); + } + + public void EnsureNetwork() + { + string cmd; + + Progress.Desc = ("检测IPv4"); + cmd = RunCmd(@"curl -s https://api.ip.sb/ip --ipv4 --max-time 8"); + IPv4 = cmd.TrimEnd('\r', '\n'); + + Progress.Desc = ($"IPv4地址为{IPv4}"); + if (!string.IsNullOrEmpty(IPv4)) + { + IsOnlyIPv6 = false; + } + else + { + Progress.Desc = ("检测IPv6"); + cmd = RunCmd(@"curl -s https://api.ip.sb/ip --ipv6 --max-time 8"); + IPv6 = cmd.TrimEnd('\r', '\n'); + Progress.Desc = ($"IPv6地址为{IPv6}"); + + IsOnlyIPv6 = true; + SetNat64(); + } + + if (string.IsNullOrEmpty(IPv4) && string.IsNullOrEmpty(IPv6)) + { + throw new Exception("未检测到服务器公网IP,请检查网络或重试。"); + } + } + + public void InstallCaddy() + { + RunCmd("rm -rf caddy.tar.gz"); + RunCmd("rm -rf /etc/caddy"); + RunCmd("rm -rf /usr/share/caddy"); + + var url = "https://github.com/caddyserver/caddy/releases/download/v2.4.3/caddy_2.4.3_linux_amd64.tar.gz"; + if (ArchType == ArchType.arm) + { + url = "https://github.com/caddyserver/caddy/releases/download/v2.4.3/caddy_2.4.3_linux_armv7.tar.gz"; + } + + RunCmd($"wget -O caddy.tar.gz {url}"); + RunCmd("mkdir /etc/caddy"); + RunCmd("tar -zxvf caddy.tar.gz -C /etc/caddy"); + RunCmd("cp -rf /etc/caddy/caddy /usr/bin"); + WriteToFile(Caddy.DefaultCaddyFile, "/etc/caddy/Caddyfile"); + WriteToFile(Caddy.Service, "/etc/systemd/system/caddy.service"); + RunCmd("systemctl daemon-reload"); + RunCmd("systemctl enable caddy"); + + RunCmd("mkdir /usr/share/caddy"); + RunCmd("chmod 775 /usr/share/caddy"); + + if (!FileExists("/usr/bin/caddy")) + { + throw new Exception("Caddy服务器安装失败,请联系开发者!"); + } + } + #endregion + + + #region 检测System环境 + private void EnsureCPU() + { + var result = RunCmd("uname -m"); + if (result.Contains("x86")) + { + ArchType = ArchType.x86; + } + else if (result.Contains("arm") || result.Contains("arch")) + { + ArchType = ArchType.arm; + } + } + + private void EnsureCmdType() + { + var result = string.Empty; + + if (CmdType == CmdType.None) + { + result = RunCmd("command -v apt"); + if (!string.IsNullOrEmpty(result)) + { + CmdType = CmdType.Apt; + } + } + + if (CmdType == CmdType.None) + { + result = RunCmd("command -v dnf"); + if (!string.IsNullOrEmpty(result)) + { + CmdType = CmdType.Dnf; + } + } + + if (CmdType == CmdType.None) + { + result = RunCmd("command -v yum"); + if (!string.IsNullOrEmpty(result)) + { + CmdType = CmdType.Yum; + } + } + + if (CmdType == CmdType.None) + { + throw new Exception("未检测到正确的系统安装命令,请尝试使用ProxySU推荐的系统版本安装!"); + } + } + + private void EnsureSystemctl() + { + var result = RunCmd("command -v systemctl"); + if (string.IsNullOrEmpty(result)) + { + throw new Exception("系统缺少 systemctl 组件,请尝试使用ProxySU推荐的系统版本安装!"); + } + } + + private void ConfigSELinux() + { + // SELinux + var result = RunCmd("command -v getenforce"); + var isSELinux = !string.IsNullOrEmpty(result); + + // 判断是否启用了SELinux,如果启用了,并且工作在Enforcing模式下,则改为Permissive模式 + if (isSELinux) + { + result = RunCmd("getenforce"); + + // 检测到系统启用SELinux,且工作在严格模式下,需改为宽松模式 + if (result.Contains("Enforcing")) + { + RunCmd("setenforce 0"); + RunCmd(@"sed -i 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config"); + } + } + } + #endregion + + + #region 私有方法 + + protected void SetNat64() + { + var dns64List = FilterFastestIP(); + if (dns64List.Count == 0) + { + throw new Exception("未找到有效的Nat64网关"); + } + + var exists = FileExists("/etc/resolv.conf.proxysu"); + if (!exists) + { + var cmdStr = @"mv /etc/resolv.conf /etc/resolv.conf.proxysu"; + RunCmd(cmdStr); + } + + foreach (var gateip in dns64List) + { + RunCmd($"echo \"nameserver {gateip}\" > /etc/resolv.conf"); + } + } + + protected void RemoveNat64() + { + RunCmd("rm /etc/resolv.conf"); + RunCmd("mv /etc/resolv.conf.proxysu /etc/resolv.conf"); + } + + private List FilterFastestIP() + { + string[] gateNat64 = { + "2a01:4f9:c010:3f02::1", + "2001:67c:2b0::4", + "2001:67c:2b0::6", + "2a09:11c0:f1:bbf0::70", + "2a01:4f8:c2c:123f::1", + "2001:67c:27e4:15::6411", + "2001:67c:27e4::64", + "2001:67c:27e4:15::64", + "2001:67c:27e4::60", + "2a00:1098:2b::1", + "2a03:7900:2:0:31:3:104:161", + "2a00:1098:2c::1", + "2a09:11c0:100::53", + }; + + Dictionary dns64List = new Dictionary(); + foreach (var gateip in gateNat64) + { + var cmdStr = $"ping6 -c4 {gateip} | grep avg | awk '{{print $4}}'|cut -d/ -f2"; + var cmd = RunCmd(cmdStr); + if (!string.IsNullOrEmpty(cmd)) + { + if (float.TryParse(cmd, out float delay)) + { + dns64List.Add(gateip, delay); + } + } + } + + return dns64List.Keys.ToList(); + } + + private bool CheckKernelVersionBBR(string kernelVer) + { + string[] linuxKernelCompared = kernelVer.Split('.'); + if (int.Parse(linuxKernelCompared[0]) > 4) + { + return true; + } + else if (int.Parse(linuxKernelCompared[0]) < 4) + { + return false; + } + else if (int.Parse(linuxKernelCompared[0]) == 4) + { + if (int.Parse(linuxKernelCompared[1]) >= 9) + { + return true; + } + else if (int.Parse(linuxKernelCompared[1]) < 9) + { + return false; + } + + } + return false; + + } + + private void SetPortFree(int port) + { + string result = RunCmd($"lsof -n -P -i :{port} | grep LISTEN"); + + if (!string.IsNullOrEmpty(result)) + { + string[] process = result.Split(' '); + RunCmd($"systemctl stop {process[0]}"); + RunCmd($"systemctl disable {process[0]}"); + RunCmd($"pkill {process[0]}"); + } + } + + private void OpenPort(params int[] portList) + { + string cmd; + + cmd = RunCmd("command -v firewall-cmd"); + if (!string.IsNullOrEmpty(cmd)) + { + //有很奇怪的vps主机,在firewalld未运行时,端口是关闭的,无法访问。所以要先启动firewalld + //用于保证acme.sh申请证书成功 + cmd = RunCmd("firewall-cmd --state"); + if (cmd.Trim() != "running") + { + RunCmd("systemctl restart firewalld"); + } + + foreach (var port in portList) + { + RunCmd($"firewall-cmd --add-port={port}/tcp --permanent"); + RunCmd($"firewall-cmd --add-port={port}/udp --permanent"); + } + + RunCmd("yes | firewall-cmd --reload"); + } + else + { + cmd = RunCmd("command -v ufw"); + if (string.IsNullOrEmpty(cmd)) + { + RunCmd(GetInstallCmd("ufw")); + RunCmd("echo y | ufw enable"); + } + + foreach (var port in portList) + { + RunCmd($"ufw allow {port}/tcp"); + RunCmd($"ufw allow {port}/udp"); + } + RunCmd("yes | ufw reload"); + } + } + + private void ClosePort(params int[] portList) + { + string cmd; + + cmd = RunCmd("command -v firewall-cmd"); + if (!string.IsNullOrEmpty(cmd)) + { + //有很奇怪的vps主机,在firewalld未运行时,端口是关闭的,无法访问。所以要先启动firewalld + //用于保证acme.sh申请证书成功 + cmd = RunCmd("firewall-cmd --state"); + if (cmd.Trim() != "running") + { + RunCmd("systemctl restart firewalld"); + } + + foreach (var port in portList) + { + RunCmd($"firewall-cmd --remove-port={port}/tcp --permanent"); + RunCmd($"firewall-cmd --remove-port={port}/udp --permanent"); + } + RunCmd("yes | firewall-cmd --reload"); + } + else + { + cmd = RunCmd("command -v ufw"); + if (!string.IsNullOrEmpty(cmd)) + { + foreach (var port in portList) + { + RunCmd($"ufw delete allow {port}/tcp"); + RunCmd($"ufw delete allow {port}/udp"); + } + RunCmd("yes | ufw reload"); + } + } + } + + private void InstallSoftware(string software) + { + var result = RunCmd($"command -v {software}"); + if (string.IsNullOrEmpty(result)) + { + RunCmd(GetInstallCmd(software)); + } + } + + private string GetInstallCmd(string soft) + { + if (CmdType == CmdType.Apt) + { + return $"apt install -y {soft}"; + } + else if (CmdType == CmdType.Yum) + { + return $"yum install -y {soft}"; + } + else + { + return $"dnf install -y {soft}"; + } + } + + private void AppendCommand(string command) + { + if (!command.EndsWith("\n")) + { + command += "\n"; + } + Progress.Logs += command; + } + + private ConnectionInfo CreateConnectionInfo() + { + var authMethods = new List(); + + if (!string.IsNullOrEmpty(_host.Password)) + { + authMethods.Add(new PasswordAuthenticationMethod(_host.UserName, _host.Password)); + } + + if (_host.SecretType == LoginSecretType.PrivateKey) + { + authMethods.Add(new PrivateKeyAuthenticationMethod(_host.UserName, new PrivateKeyFile(_host.PrivateKeyPath))); + } + + if (_host.Proxy.Type == ProxyTypes.None) + { + return new ConnectionInfo( + host: _host.Address, + username: _host.Password, + authenticationMethods: authMethods.ToArray()); + } + + return new ConnectionInfo( + host: _host.Address, + port: _host.Port, + username: _host.UserName, + proxyType: _host.Proxy.Type, + proxyHost: _host.Proxy.Address, + proxyPort: _host.Proxy.Port, + proxyUsername: _host.Proxy.UserName, proxyPassword: _host.Proxy.Password, + authenticationMethods: authMethods.ToArray()); + } + #endregion + } +} diff --git a/ProxySuper.Core/Services/ShareLink.cs b/ProxySuper.Core/Services/ShareLink.cs index d669aaf..00992e1 100644 --- a/ProxySuper.Core/Services/ShareLink.cs +++ b/ProxySuper.Core/Services/ShareLink.cs @@ -1,16 +1,44 @@ using Newtonsoft.Json; using ProxySuper.Core.Models.Projects; using System; -using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading.Tasks; using System.Web; namespace ProxySuper.Core.Services { public class ShareLink { + public static string BuildBrook(BrookSettings settings) + { + var password = HttpUtility.UrlEncode(settings.Password); + + if (settings.BrookType == BrookType.server) + { + var address = HttpUtility.UrlEncode($"{settings.IP}:{settings.Port}"); + return $"brook://server?password={password}&server={address}"; + } + + if (settings.BrookType == BrookType.wsserver) + { + var address = HttpUtility.UrlEncode($"ws://{settings.IP}:{settings.Port}"); + return $"brook://wsserver?password={password}&wsserver={address}"; + } + + if (settings.BrookType == BrookType.wssserver) + { + var address = HttpUtility.UrlEncode($"wss://{settings.Domain}:{settings.Port}"); + return $"brook://wssserver?password={password}&wssserver={address}"; + } + + if (settings.BrookType == BrookType.socks5) + { + var address = HttpUtility.UrlEncode($"socks5://{settings.IP}:{settings.Port}"); + return $"brook://socks5?password={password}&socks5={address}"; + } + + return string.Empty; + } + public static string BuildNaiveProxy(NaiveProxySettings settings) { StringBuilder strBuilder = new StringBuilder(); @@ -28,10 +56,9 @@ namespace ProxySuper.Core.Services strBuilder.Append("trojan-go://"); strBuilder.Append($"{HttpUtility.UrlEncode(settings.Password)}@{settings.Domain}:{settings.Port}/?"); - strBuilder.Append($"sni={HttpUtility.UrlEncode(settings.Domain)}&"); if (settings.EnableWebSocket) { - strBuilder.Append($"type=ws&host={HttpUtility.UrlEncode(settings.Domain)}&path={HttpUtility.UrlEncode(settings.WebSocketPath)}&"); + strBuilder.Append($"type=ws&path={HttpUtility.UrlEncode(settings.WebSocketPath)}&"); } else { @@ -87,7 +114,7 @@ namespace ProxySuper.Core.Services aid = "0", net = "", type = "none", - host = settings.Domain, + host = "", path = "", tls = "tls", ps = "", @@ -169,7 +196,7 @@ namespace ProxySuper.Core.Services case XrayType.VLESS_gRPC: _protocol = "vless"; _type = "grpc"; - _path = settings.VLESS_gRPC_ServiceName; + _port = settings.VLESS_gRPC_Port; _descriptiveText = "vless-gRPC"; break; case XrayType.Trojan_TCP: @@ -199,6 +226,12 @@ namespace ProxySuper.Core.Services { parametersURL += "&flow=xtls-rprx-direct"; } + + + if (xrayType == XrayType.VLESS_gRPC) + { + parametersURL += $"&serviceName={settings.VLESS_gRPC_ServiceName}&mode=gun"; + } } diff --git a/ProxySuper.Core/Services/TrojanGoConfigBuilder.cs b/ProxySuper.Core/Services/TrojanGoConfigBuilder.cs index d9743c3..d4c467f 100644 --- a/ProxySuper.Core/Services/TrojanGoConfigBuilder.cs +++ b/ProxySuper.Core/Services/TrojanGoConfigBuilder.cs @@ -1,13 +1,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using ProxySuper.Core.Models; using ProxySuper.Core.Models.Projects; -using System; -using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace ProxySuper.Core.Services { diff --git a/ProxySuper.Core/Services/TrojanGoProject.cs b/ProxySuper.Core/Services/TrojanGoProject.cs index 4519f0d..bfa21e7 100644 --- a/ProxySuper.Core/Services/TrojanGoProject.cs +++ b/ProxySuper.Core/Services/TrojanGoProject.cs @@ -1,12 +1,8 @@ -using ProxySuper.Core.Models; -using ProxySuper.Core.Models.Projects; +using ProxySuper.Core.Models.Projects; using Renci.SshNet; using System; -using System.Collections.Generic; using System.IO; -using System.Linq; using System.Text; -using System.Threading.Tasks; using System.Windows; namespace ProxySuper.Core.Services @@ -48,8 +44,10 @@ namespace ProxySuper.Core.Services public void Uninstall() { + EnsureRootAuth(); + EnsureSystemEnv(); + RunCmd("systemctl stop trojan-go"); - RunCmd("systemctl stop caddy"); base.UninstallCaddy(); RunCmd("rm -rf /usr/local/bin/trojan-go"); @@ -79,24 +77,20 @@ namespace ProxySuper.Core.Services WriteOutput("检测安装系统环境..."); EnsureSystemEnv(); - WriteOutput("检测安装系统环境完成"); - - WriteOutput("配置服务器端口..."); - ConfigurePort(); - WriteOutput("端口配置完成"); + WriteOutput("检测安装系统环境完成"); WriteOutput("安装必要的系统工具..."); ConfigureSoftware(); WriteOutput("系统工具安装完成"); - WriteOutput("检测IP6..."); - ConfigureIPv6(); - WriteOutput("检测IP6完成"); - WriteOutput("配置防火墙..."); - ConfigureFirewall(); + ConfigFirewalld(); WriteOutput("防火墙配置完成"); + WriteOutput("检测网络环境"); + EnsureIP(); + WriteOutput("检测网络环境完成"); + WriteOutput("同步系统和本地时间..."); SyncTimeDiff(); WriteOutput("时间同步完成"); @@ -127,13 +121,12 @@ namespace ProxySuper.Core.Services { var errorLog = "安装终止," + ex.Message; WriteOutput(errorLog); - MessageBox.Show(errorLog); + MessageBox.Show("安装失败,请联系开发者或上传日志文件(Logs文件夹下)到github提问。"); } } private void InstallTrojanGo() { - WriteOutput("安装Trojan-Go"); RunCmd(@"curl https://raw.githubusercontent.com/proxysu/shellscript/master/trojan-go.sh yes | bash"); var success = FileExists("/usr/local/bin/trojan-go"); if (success == false) diff --git a/ProxySuper.Core/Services/XrayConfigBuilder.cs b/ProxySuper.Core/Services/XrayConfigBuilder.cs index 09f19b2..12226bc 100644 --- a/ProxySuper.Core/Services/XrayConfigBuilder.cs +++ b/ProxySuper.Core/Services/XrayConfigBuilder.cs @@ -1,13 +1,9 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using ProxySuper.Core.Models; using ProxySuper.Core.Models.Projects; -using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Text; -using System.Threading.Tasks; namespace ProxySuper.Core.Services { @@ -28,7 +24,6 @@ namespace ProxySuper.Core.Services public static int VLESS_TCP_Port = 1110; public static int VLESS_WS_Port = 1111; public static int VLESS_H2_Port = 1112; - public static int VLESS_mKCP_Port = 1113; public static int VMESS_TCP_Port = 1210; public static int VMESS_WS_Port = 1211; @@ -72,7 +67,7 @@ namespace ProxySuper.Core.Services public static string BuildCaddyConfig(XraySettings parameters, bool useCustomWeb = false) { var caddyStr = File.ReadAllText(Path.Combine(CaddyFileDir, "base.caddyfile")); - caddyStr = caddyStr.Replace("##domain##", parameters.Domain); + caddyStr = caddyStr.Replace("##domain##", parameters.IsIPAddress ? "" : parameters.Domain); caddyStr = caddyStr.Replace("##port##", FullbackPort.ToString()); if (!useCustomWeb && !string.IsNullOrEmpty(parameters.MaskDomain)) @@ -96,9 +91,33 @@ namespace ProxySuper.Core.Services return caddyStr; } + private static void SetClients(dynamic bound, List uuidList, bool withXtls = false) + { + bound.settings.clients.Clear(); + uuidList.ForEach(id => + { + object obj; + if (!withXtls) + { + obj = new { id = id }; + } + else + { + obj = new { id = id, flow = "xtls-rprx-direct" }; + } + + bound.settings.clients.Add(JToken.FromObject(obj)); + }); + } + + public static string BuildXrayConfig(XraySettings parameters) { + var uuidList = parameters.MulitUUID; + uuidList.Insert(0, parameters.UUID); + var xrayConfig = LoadXrayConfig(); + var baseBound = GetBound("VLESS_TCP_XTLS.json"); baseBound.port = parameters.Port; baseBound.settings.fallbacks.Add(JToken.FromObject(new @@ -106,13 +125,15 @@ namespace ProxySuper.Core.Services dest = FullbackPort })); xrayConfig.inbounds.Add(baseBound); - baseBound.settings.clients[0].id = parameters.UUID; + SetClients(baseBound, uuidList, withXtls: true); + + #region Fullbacks if (parameters.Types.Contains(XrayType.VLESS_WS)) { var wsInbound = GetBound("VLESS_WS.json"); wsInbound.port = VLESS_WS_Port; - wsInbound.settings.clients[0].id = parameters.UUID; + SetClients(wsInbound, uuidList); wsInbound.streamSettings.wsSettings.path = parameters.VLESS_WS_Path; baseBound.settings.fallbacks.Add(JToken.FromObject(new { @@ -123,30 +144,11 @@ namespace ProxySuper.Core.Services xrayConfig.inbounds.Add(JToken.FromObject(wsInbound)); } - if (parameters.Types.Contains(XrayType.VLESS_gRPC)) - { - var gRPCInBound = GetBound("VLESS_gRPC.json"); - gRPCInBound.port = parameters.VLESS_gRPC_Port; - gRPCInBound.settings.clients[0].id = parameters.UUID; - gRPCInBound.streamSettings.grpcSettings.serviceName = parameters.VLESS_gRPC_ServiceName; - xrayConfig.inbounds.Add(JToken.FromObject(gRPCInBound)); - } - - if (parameters.Types.Contains(XrayType.VLESS_KCP)) - { - var kcpBound = GetBound("VLESS_KCP.json"); - kcpBound.port = parameters.VLESS_KCP_Port; - kcpBound.settings.clients[0].id = parameters.UUID; - kcpBound.streamSettings.kcpSettings.header.type = parameters.VLESS_KCP_Type; - kcpBound.streamSettings.kcpSettings.seed = parameters.VLESS_KCP_Seed; - xrayConfig.inbounds.Add(JToken.FromObject(kcpBound)); - } - if (parameters.Types.Contains(XrayType.VMESS_TCP)) { var mtcpBound = GetBound("VMESS_TCP.json"); mtcpBound.port = VMESS_TCP_Port; - mtcpBound.settings.clients[0].id = parameters.UUID; + SetClients(mtcpBound, uuidList); mtcpBound.streamSettings.tcpSettings.header.request.path = parameters.VMESS_TCP_Path; baseBound.settings.fallbacks.Add(JToken.FromObject(new { @@ -161,7 +163,7 @@ namespace ProxySuper.Core.Services { var mwsBound = GetBound("VMESS_WS.json"); mwsBound.port = VMESS_WS_Port; - mwsBound.settings.clients[0].id = parameters.UUID; + SetClients(mwsBound, uuidList); mwsBound.streamSettings.wsSettings.path = parameters.VMESS_WS_Path; baseBound.settings.fallbacks.Add(JToken.FromObject(new { @@ -172,16 +174,6 @@ namespace ProxySuper.Core.Services xrayConfig.inbounds.Add(JToken.FromObject(mwsBound)); } - if (parameters.Types.Contains(XrayType.VMESS_KCP)) - { - var kcpBound = GetBound("VMESS_KCP.json"); - kcpBound.port = parameters.VMESS_KCP_Port; - kcpBound.settings.clients[0].id = parameters.UUID; - kcpBound.streamSettings.kcpSettings.header.type = parameters.VMESS_KCP_Type; - kcpBound.streamSettings.kcpSettings.seed = parameters.VMESS_KCP_Seed; - xrayConfig.inbounds.Add(JToken.FromObject(kcpBound)); - } - if (parameters.Types.Contains(XrayType.Trojan_TCP)) { var trojanTcpBound = GetBound("Trojan_TCP.json"); @@ -195,7 +187,37 @@ namespace ProxySuper.Core.Services }); xrayConfig.inbounds.Add(JToken.FromObject(trojanTcpBound)); } + #endregion + if (parameters.Types.Contains(XrayType.VLESS_gRPC)) + { + var gRPCInBound = GetBound("VLESS_gRPC.json"); + gRPCInBound.port = parameters.VLESS_gRPC_Port; + SetClients(gRPCInBound, uuidList); + gRPCInBound.streamSettings.grpcSettings.serviceName = parameters.VLESS_gRPC_ServiceName; + gRPCInBound.streamSettings.tlsSettings.serverName = parameters.Domain; + xrayConfig.inbounds.Add(JToken.FromObject(gRPCInBound)); + } + + if (parameters.Types.Contains(XrayType.VLESS_KCP)) + { + var kcpBound = GetBound("VLESS_KCP.json"); + kcpBound.port = parameters.VLESS_KCP_Port; + SetClients(kcpBound, uuidList); + kcpBound.streamSettings.kcpSettings.header.type = parameters.VLESS_KCP_Type; + kcpBound.streamSettings.kcpSettings.seed = parameters.VLESS_KCP_Seed; + xrayConfig.inbounds.Add(JToken.FromObject(kcpBound)); + } + + if (parameters.Types.Contains(XrayType.VMESS_KCP)) + { + var kcpBound = GetBound("VMESS_KCP.json"); + kcpBound.port = parameters.VMESS_KCP_Port; + SetClients(kcpBound, uuidList); + kcpBound.streamSettings.kcpSettings.header.type = parameters.VMESS_KCP_Type; + kcpBound.streamSettings.kcpSettings.seed = parameters.VMESS_KCP_Seed; + xrayConfig.inbounds.Add(JToken.FromObject(kcpBound)); + } if (parameters.Types.Contains(XrayType.ShadowsocksAEAD)) { diff --git a/ProxySuper.Core/Services/XrayProject.cs b/ProxySuper.Core/Services/XrayProject.cs index 4dd6043..4dc8146 100644 --- a/ProxySuper.Core/Services/XrayProject.cs +++ b/ProxySuper.Core/Services/XrayProject.cs @@ -1,13 +1,11 @@ using Newtonsoft.Json; -using ProxySuper.Core.Models; using ProxySuper.Core.Models.Projects; using Renci.SshNet; using System; -using System.Collections.Generic; using System.IO; using System.Linq; +using System.Net; using System.Text; -using System.Threading.Tasks; using System.Windows; namespace ProxySuper.Core.Services @@ -54,29 +52,28 @@ namespace ProxySuper.Core.Services EnsureSystemEnv(); WriteOutput("检测安装系统环境完成"); - WriteOutput("配置服务器端口..."); - ConfigurePort(); - WriteOutput("端口配置完成"); - WriteOutput("安装必要的系统工具..."); ConfigureSoftware(); WriteOutput("系统工具安装完成"); - WriteOutput("检测IP6..."); - ConfigureIPv6(); - WriteOutput("检测IP6完成"); - WriteOutput("配置防火墙..."); - ConfigureFirewall(); + ConfigFirewalld(); WriteOutput("防火墙配置完成"); + WriteOutput("检测网络环境"); + EnsureIP(); + WriteOutput("检测网络环境完成"); + WriteOutput("同步系统和本地时间..."); SyncTimeDiff(); WriteOutput("时间同步完成"); - WriteOutput("检测域名是否绑定本机IP..."); - ValidateDomain(); - WriteOutput("域名检测完成"); + if (!Parameters.IsIPAddress) + { + WriteOutput("检测域名是否绑定本机IP..."); + ValidateDomain(); + WriteOutput("域名检测完成"); + } WriteOutput("安装Caddy..."); InstallCaddy(); @@ -98,13 +95,14 @@ namespace ProxySuper.Core.Services { var errorLog = "安装终止," + ex.Message; WriteOutput(errorLog); - MessageBox.Show(errorLog); + MessageBox.Show("安装失败,请联系开发者或上传日志文件(Logs文件夹下)到github提问。"); } } public void UninstallProxy() { EnsureRootAuth(); + EnsureSystemEnv(); WriteOutput("卸载Caddy"); UninstallCaddy(); WriteOutput("卸载Xray"); @@ -112,7 +110,7 @@ namespace ProxySuper.Core.Services WriteOutput("卸载证书"); UninstallAcme(); WriteOutput("关闭端口"); - ClosePort(Parameters.ShadowSocksPort, Parameters.VMESS_KCP_Port); + ResetFirewalld(); WriteOutput("************ 卸载完成 ************"); } @@ -136,12 +134,16 @@ namespace ProxySuper.Core.Services { EnsureRootAuth(); EnsureSystemEnv(); - ConfigureFirewall(); + + RunCmd("systemctl stop caddy"); + RunCmd("systemctl stop xray"); + + ConfigFirewalld(); var configJson = XrayConfigBuilder.BuildXrayConfig(Parameters); var stream = new MemoryStream(Encoding.UTF8.GetBytes(configJson)); RunCmd("rm -rf /usr/local/etc/xray/config.json"); UploadFile(stream, "/usr/local/etc/xray/config.json"); - ConfigurePort(); + UploadCaddyFile(string.IsNullOrEmpty(Parameters.MaskDomain)); RunCmd("systemctl restart xray"); WriteOutput("************ 更新Xray配置成功,更新配置不包含域名,如果域名更换请重新安装。 ************"); @@ -153,6 +155,7 @@ namespace ProxySuper.Core.Services public void DoUninstallCaddy() { EnsureRootAuth(); + EnsureSystemEnv(); UninstallCaddy(); WriteOutput("************ 卸载Caddy完成 ************"); } @@ -160,7 +163,7 @@ namespace ProxySuper.Core.Services /// /// 安装证书 /// - public void InstallCertToXray() + public void InstallCertToXray(bool restartXray = false) { EnsureRootAuth(); EnsureSystemEnv(); @@ -169,8 +172,8 @@ namespace ProxySuper.Core.Services certName: "xray_ssl.crt", keyName: "xray_ssl.key"); - RunCmd("systemctl restart xray"); WriteOutput("************ 安装证书完成 ************"); + RunCmd("systemctl restart xray"); } /// @@ -252,12 +255,12 @@ namespace ProxySuper.Core.Services private void UploadCaddyFile(bool useCustomWeb = false) { var configJson = XrayConfigBuilder.BuildCaddyConfig(Parameters, useCustomWeb); - var stream = new MemoryStream(Encoding.UTF8.GetBytes(configJson)); + if (FileExists("/etc/caddy/Caddyfile")) { RunCmd("mv /etc/caddy/Caddyfile /etc/caddy/Caddyfile.back"); } - UploadFile(stream, "/etc/caddy/Caddyfile"); + WriteToFile(configJson, "/etc/caddy/Caddyfile"); RunCmd("systemctl restart caddy"); } @@ -294,14 +297,15 @@ namespace ProxySuper.Core.Services RunCmd(@"mv /usr/local/etc/xray/config.json /usr/local/etc/xray/config.json.1"); } - WriteOutput("安装TLS证书"); - InstallCertToXray(); - WriteOutput("TLS证书安装完成"); - + if (!Parameters.IsIPAddress) + { + WriteOutput("安装TLS证书"); + InstallCertToXray(); + WriteOutput("TLS证书安装完成"); + } var configJson = XrayConfigBuilder.BuildXrayConfig(Parameters); - var stream = new MemoryStream(Encoding.UTF8.GetBytes(configJson)); - UploadFile(stream, "/usr/local/etc/xray/config.json"); + WriteToFile(configJson, "/usr/local/etc/xray/config.json"); RunCmd("systemctl restart xray"); } diff --git a/ProxySuper.Core/Services/XrayService.cs b/ProxySuper.Core/Services/XrayService.cs new file mode 100644 index 0000000..68df0b5 --- /dev/null +++ b/ProxySuper.Core/Services/XrayService.cs @@ -0,0 +1,127 @@ +using ProxySuper.Core.Helpers; +using ProxySuper.Core.Models.Hosts; +using ProxySuper.Core.Models.Projects; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; + +namespace ProxySuper.Core.Services +{ + public class XrayService : ServiceBase + { + + public XrayService(Host host, XraySettings settings) : base(host, settings) + { + } + + public void Install() + { + Task.Run(() => + { + int index = 1; + if (!IsRootUser()) + { + MessageBox.Show("ProxySU需要使用Root用户进行安装!"); + return; + } + + Progress.Step = $"{index++}. 检测系统环境"; + EnsureSystemEnv(); + Progress.Percentage = 5; + + Progress.Step = $"{index++}. 安装必要的系统工具"; + InstallSystemTools(); + Progress.Percentage = 15; + + Progress.Step = $"{index++}. 配置防火墙"; + ConfigFirewalld(); + Progress.Percentage = 20; + + Progress.Step = $"{index++}. 检测网络环境"; + EnsureNetwork(); + if (Settings.IsIPAddress) + { + Progress.Desc = ("检查域名是否解析正确"); + ValidateDomain(); + } + Progress.Percentage = 25; + + Progress.Step = $"{index}. 同步系统和本地时间"; + SyncTimeDiff(); + Progress.Percentage = 30; + + Progress.Step = $"{index++}. 安装Caddy服务器"; + InstallCaddy(); + Progress.Percentage = 50; + + Progress.Step = $"{index++}. 安装Xray-Core"; + InstallXray(); + Progress.Percentage = 80; + + Progress.Step = $"{index++}. 上传Web服务器配置"; + UploadCaddyFile(); + Progress.Percentage = 90; + + Progress.Step = $"{index++}. 启动BBR"; + EnableBBR(); + Progress.Percentage = 100; + + Progress.Desc = ("!!!安装Xray完成!!!"); + }); + } + + public void InstallXray() + { + Progress.Desc = ("开始安装Xray-Core"); + RunCmd("bash -c \"$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)\" @ install"); + + if (!FileExists("/usr/local/bin/xray")) + { + Progress.Desc = ("Xray-Core安装失败,请联系开发者"); + throw new Exception("Xray-Core安装失败,请联系开发者"); + } + + Progress.Desc = ("设置Xray-core权限"); + RunCmd($"sed -i 's/User=nobody/User=root/g' /etc/systemd/system/xray.service"); + RunCmd($"sed -i 's/CapabilityBoundingSet=/#CapabilityBoundingSet=/g' /etc/systemd/system/xray.service"); + RunCmd($"sed -i 's/AmbientCapabilities=/#AmbientCapabilities=/g' /etc/systemd/system/xray.service"); + RunCmd($"systemctl daemon-reload"); + + if (FileExists("/usr/local/etc/xray/config.json")) + { + RunCmd(@"mv /usr/local/etc/xray/config.json /usr/local/etc/xray/config.json.1"); + } + Progress.Percentage = 60; + + if (!Settings.IsIPAddress) + { + Progress.Desc = ("安装TLS证书"); + InstallCert( + dirPath: "/usr/local/etc/xray/ssl", + certName: "xray_ssl.crt", + keyName: "xray_ssl.key"); + Progress.Percentage = 75; + } + + Progress.Desc = ("生成Xray服务器配置文件"); + var configJson = XrayConfigBuilder.BuildXrayConfig(Settings); + WriteToFile(configJson, "/usr/local/etc/xray/config.json"); + RunCmd("systemctl restart xray"); + } + + private void UploadCaddyFile(bool useCustomWeb = false) + { + var configJson = XrayConfigBuilder.BuildCaddyConfig(Settings, useCustomWeb); + + if (FileExists("/etc/caddy/Caddyfile")) + { + RunCmd("mv /etc/caddy/Caddyfile /etc/caddy/Caddyfile.back"); + } + WriteToFile(configJson, "/etc/caddy/Caddyfile"); + RunCmd("systemctl restart caddy"); + } + } +} diff --git a/ProxySuper.Core/ViewModels/BrookConfigViewModel.cs b/ProxySuper.Core/ViewModels/BrookConfigViewModel.cs new file mode 100644 index 0000000..99d9421 --- /dev/null +++ b/ProxySuper.Core/ViewModels/BrookConfigViewModel.cs @@ -0,0 +1,24 @@ +using MvvmCross.ViewModels; +using ProxySuper.Core.Models.Projects; +using ProxySuper.Core.Services; + +namespace ProxySuper.Core.ViewModels +{ + public class BrookConfigViewModel : MvxViewModel + { + public BrookSettings Settings { get; set; } + + public override void Prepare(BrookSettings parameter) + { + Settings = parameter; + } + + public string Link + { + get + { + return ShareLink.BuildBrook(Settings); + } + } + } +} diff --git a/ProxySuper.Core/ViewModels/BrookEditorViewModel.cs b/ProxySuper.Core/ViewModels/BrookEditorViewModel.cs new file mode 100644 index 0000000..9960068 --- /dev/null +++ b/ProxySuper.Core/ViewModels/BrookEditorViewModel.cs @@ -0,0 +1,88 @@ +using MvvmCross.Commands; +using MvvmCross.Navigation; +using MvvmCross.ViewModels; +using ProxySuper.Core.Models; +using ProxySuper.Core.Models.Hosts; +using ProxySuper.Core.Models.Projects; +using ProxySuper.Core.Services; +using System; +using System.Collections.Generic; + +namespace ProxySuper.Core.ViewModels +{ + public class BrookEditorViewModel : MvxViewModel + { + public BrookEditorViewModel(IMvxNavigationService navigationService) + { + NavigationService = navigationService; + } + + public IMvxNavigationService NavigationService { get; } + + public string Id { get; set; } + + public Host Host { get; set; } + + public BrookSettings Settings { get; set; } + + public List BrookTypes + { + get + { + return new List { + BrookType.server.ToString(), + BrookType.wsserver.ToString(), + BrookType.wssserver.ToString(), + BrookType.socks5.ToString(), + }; + } + } + + public string CheckedBrookType + { + get + { + return Settings.BrookType.ToString(); + } + set + { + Settings.BrookType = (BrookType)Enum.Parse(typeof(BrookType), value); + + if (Settings.BrookType == BrookType.wssserver) + { + Settings.Port = 443; + RaisePropertyChanged("Settings"); + } + RaisePropertyChanged("EnablePort"); + RaisePropertyChanged("EnableDomain"); + RaisePropertyChanged("EnableIP"); + } + } + + public bool EnablePort => Settings.BrookType != BrookType.wssserver; + + public bool EnableDomain => Settings.BrookType == BrookType.wssserver; + + public bool EnableIP => Settings.BrookType != BrookType.wssserver; + + public IMvxCommand SaveCommand => new MvxCommand(() => Save()); + + public override void Prepare(Record parameter) + { + var record = Utils.DeepClone(parameter); + Id = record.Id; + Host = record.Host; + Settings = record.BrookSettings; + } + + public void Save() + { + NavigationService.Close(this, new Record() + { + Id = Id, + Host = Host, + BrookSettings = Settings, + }); + } + } +} diff --git a/ProxySuper.Core/ViewModels/BrookInstallerViewModel.cs b/ProxySuper.Core/ViewModels/BrookInstallerViewModel.cs new file mode 100644 index 0000000..10e4084 --- /dev/null +++ b/ProxySuper.Core/ViewModels/BrookInstallerViewModel.cs @@ -0,0 +1,39 @@ +using MvvmCross.ViewModels; +using ProxySuper.Core.Models; +using ProxySuper.Core.Models.Hosts; +using ProxySuper.Core.Models.Projects; +using ProxySuper.Core.Services; + +namespace ProxySuper.Core.ViewModels +{ + public class BrookInstallerViewModel : MvxViewModel + { + + public Host Host { get; set; } + + public BrookSettings Settings { get; set; } + + public override void Prepare(Record parameter) + { + var record = Utils.DeepClone(parameter); + Host = record.Host; + Settings = record.BrookSettings; + } + + private bool _connected; + public bool Connected + { + get + { + return _connected; + } + set + { + _connected = value; + RaisePropertyChanged("Connected"); + } + } + + public string CommandText { get; set; } + } +} diff --git a/ProxySuper.Core/ViewModels/EnableRootViewModel.cs b/ProxySuper.Core/ViewModels/EnableRootViewModel.cs new file mode 100644 index 0000000..3ae228c --- /dev/null +++ b/ProxySuper.Core/ViewModels/EnableRootViewModel.cs @@ -0,0 +1,168 @@ +using MvvmCross.Commands; +using MvvmCross.ViewModels; +using ProxySuper.Core.Models.Hosts; +using Renci.SshNet; +using System; +using System.IO; +using System.Threading.Tasks; +using System.Windows; + +namespace ProxySuper.Core.ViewModels +{ + public class EnableRootViewModel : MvxViewModel + { + private SshClient _sshClient; + + public EnableRootViewModel() + { + Host = new Host(); + } + + public Host Host { get; set; } + + public string RootUserName { get; set; } + + public string RootPassword { get; set; } + + public string OutputText { get; set; } + + public IMvxCommand ExecuteCommand => new MvxCommand(Execute); + + public override void ViewDisappearing() + { + base.ViewDisappearing(); + if (_sshClient != null) + { + _sshClient.Disconnect(); + _sshClient.Dispose(); + } + } + + public void Execute() + { + Task.Factory.StartNew(() => + { + OpenConnect(); + if (!_sshClient.IsConnected) + { + MessageBox.Show("连接失败,请重试!"); + return; + } + + string result = string.Empty; + result = RunCmd("id -u"); + + if (result.TrimEnd('\r', '\n') == "0") + { + MessageBox.Show("当前账户已经具有root权限,无需再设置!"); + return; + } + + result = RunCmd($"echo {Host.Password} | sudo -S id -u"); + if (result.TrimEnd('\r', '\n') != "0") + { + MessageBox.Show("当前账户无法获取sudo权限,设置失败!"); + return; + } + + string cmdPre = $"echo {Host.Password} | sudo -S id -u" + ';'; + RunCmd(cmdPre + "sudo sed -i 's/PermitRootLogin /#PermitRootLogin /g' /etc/ssh/sshd_config"); + RunCmd(cmdPre + "sudo sed -i 's/PasswordAuthentication /#PasswordAuthentication /g' /etc/ssh/sshd_config"); + RunCmd(cmdPre + "sudo sed -i 's/PermitEmptyPasswords /#PermitEmptyPasswords /g' /etc/ssh/sshd_config"); + RunCmd(cmdPre + "echo 'PermitRootLogin yes' | sudo tee -a /etc/ssh/sshd_config"); + RunCmd(cmdPre + "echo 'PasswordAuthentication yes' | sudo tee -a /etc/ssh/sshd_config"); + RunCmd(cmdPre + "echo 'PermitEmptyPasswords no' | sudo tee -a /etc/ssh/sshd_config"); + RunCmd(cmdPre + "sudo systemctl restart sshd"); + + result = RunCmd(@"cat /dev/urandom | tr -dc '_A-Z#\-+=a-z(0-9%^>)]{<|' | head -c 20 ; echo ''"); + string setPassword = result.TrimEnd('\r', '\n') + '\n'; + RunCmd(cmdPre + $"echo \"{setPassword}{setPassword}\" | sudo passwd root"); + RunCmd("sudo systemctl restart sshd"); + + RootUserName = "root"; + RootPassword = setPassword.Trim('\n'); + RaisePropertyChanged("RootUserName"); + RaisePropertyChanged("RootPassword"); + + + var filePath = Host.Address.Replace(':', '_'); + using (StreamWriter sw = new StreamWriter("Logs\\host_password_info.txt")) + { + sw.WriteLine(Host.Address); + sw.WriteLine("root"); + sw.WriteLine(setPassword); + } + WriteOutput("设置成功,账号信息保存在Logs/host_password_info.txt"); + WriteOutput("账号:\nroot"); + WriteOutput($"密码:\n{setPassword}"); + }); + } + + protected string RunCmd(string cmdStr) + { + var cmd = _sshClient.CreateCommand(cmdStr); + WriteOutput(cmdStr); + + var result = cmd.Execute(); + WriteOutput(result); + return result; + } + + private void WriteOutput(string text) + { + OutputText += text + '\n'; + RaisePropertyChanged("OutputText"); + } + + + private void OpenConnect() + { + WriteOutput("正在建立连接..."); + var conneInfo = CreateConnectionInfo(Host); + _sshClient = new SshClient(conneInfo); + try + { + _sshClient.Connect(); + WriteOutput("Connected..."); + } + catch (Exception ex) + { + WriteOutput(ex.Message); + MessageBox.Show(ex.Message); + } + } + + private ConnectionInfo CreateConnectionInfo(Host host) + { + AuthenticationMethod auth = null; + + if (host.SecretType == LoginSecretType.Password) + { + auth = new PasswordAuthenticationMethod(host.UserName, host.Password); + } + else if (host.SecretType == LoginSecretType.PrivateKey) + { + auth = new PrivateKeyAuthenticationMethod(host.UserName, new PrivateKeyFile(host.PrivateKeyPath)); + } + + if (host.Proxy.Type == ProxyTypes.None) + { + return new ConnectionInfo(host.Address, host.Port, host.UserName, auth); + } + else + { + return new ConnectionInfo( + host: host.Address, + port: host.Port, + username: host.UserName, + proxyType: host.Proxy.Type, + proxyHost: host.Proxy.Address, + proxyPort: host.Proxy.Port, + proxyUsername: host.Proxy.UserName, + proxyPassword: host.Proxy.Password, + authenticationMethods: auth); + } + + } + } +} diff --git a/ProxySuper.Core/ViewModels/HomeViewModel.cs b/ProxySuper.Core/ViewModels/HomeViewModel.cs index 80c6bff..c20cd2a 100644 --- a/ProxySuper.Core/ViewModels/HomeViewModel.cs +++ b/ProxySuper.Core/ViewModels/HomeViewModel.cs @@ -11,8 +11,6 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; using System.Threading.Tasks; using System.Windows; @@ -66,6 +64,8 @@ namespace ProxySuper.Core.ViewModels public IMvxCommand AddNaiveProxyCommand => new MvxAsyncCommand(AddNaiveProxyRecord); + public IMvxCommand AddBrookCommand => new MvxAsyncCommand(AddBrookRecord); + public IMvxCommand RemoveCommand => new MvxAsyncCommand(DeleteRecord); public IMvxCommand EditCommand => new MvxAsyncCommand(EditRecord); @@ -118,6 +118,21 @@ namespace ProxySuper.Core.ViewModels SaveToJson(); } + public async Task AddBrookRecord() + { + Record record = new Record(); + record.Id = Utils.GetTickID(); + record.Host = new Host(); + record.BrookSettings = new BrookSettings(); + + var result = await _navigationService.Navigate(record); + if (result == null) return; + + Records.Add(result); + + SaveToJson(); + } + public async Task EditRecord(string id) { @@ -149,6 +164,14 @@ namespace ProxySuper.Core.ViewModels record.Host = result.Host; record.NaiveProxySettings = result.NaiveProxySettings; } + if (record.Type == ProjectType.Brook) + { + result = await _navigationService.Navigate(record); + if (result == null) return; + + record.Host = result.Host; + record.BrookSettings = result.BrookSettings; + } SaveToJson(); } @@ -185,6 +208,10 @@ namespace ProxySuper.Core.ViewModels { await _navigationService.Navigate(record.NaiveProxySettings); } + if (record.Type == ProjectType.Brook) + { + await _navigationService.Navigate(record.BrookSettings); + } } public async Task GoToInstall(string id) @@ -194,7 +221,7 @@ namespace ProxySuper.Core.ViewModels if (record.Type == ProjectType.Xray) { - await _navigationService.Navigate(record); + await _navigationService.Navigate(record); } if (record.Type == ProjectType.TrojanGo) { @@ -204,6 +231,10 @@ namespace ProxySuper.Core.ViewModels { await _navigationService.Navigate(record); } + if (record.Type == ProjectType.Brook) + { + await _navigationService.Navigate(record); + } } } } diff --git a/ProxySuper.Core/ViewModels/NaiveProxyConfigViewModel.cs b/ProxySuper.Core/ViewModels/NaiveProxyConfigViewModel.cs index ca22cd0..8e59f65 100644 --- a/ProxySuper.Core/ViewModels/NaiveProxyConfigViewModel.cs +++ b/ProxySuper.Core/ViewModels/NaiveProxyConfigViewModel.cs @@ -1,11 +1,6 @@ using MvvmCross.ViewModels; using ProxySuper.Core.Models.Projects; using ProxySuper.Core.Services; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace ProxySuper.Core.ViewModels { diff --git a/ProxySuper.Core/ViewModels/NaiveProxyEditorViewModel.cs b/ProxySuper.Core/ViewModels/NaiveProxyEditorViewModel.cs index e0e69e2..0dda929 100644 --- a/ProxySuper.Core/ViewModels/NaiveProxyEditorViewModel.cs +++ b/ProxySuper.Core/ViewModels/NaiveProxyEditorViewModel.cs @@ -1,17 +1,10 @@ -using Microsoft.Win32; -using MvvmCross.Commands; +using MvvmCross.Commands; using MvvmCross.Navigation; using MvvmCross.ViewModels; using ProxySuper.Core.Models; using ProxySuper.Core.Models.Hosts; using ProxySuper.Core.Models.Projects; using ProxySuper.Core.Services; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace ProxySuper.Core.ViewModels { diff --git a/ProxySuper.Core/ViewModels/NaiveProxyInstallerViewModel.cs b/ProxySuper.Core/ViewModels/NaiveProxyInstallerViewModel.cs index e21e425..35381cf 100644 --- a/ProxySuper.Core/ViewModels/NaiveProxyInstallerViewModel.cs +++ b/ProxySuper.Core/ViewModels/NaiveProxyInstallerViewModel.cs @@ -3,11 +3,6 @@ using ProxySuper.Core.Models; using ProxySuper.Core.Models.Hosts; using ProxySuper.Core.Models.Projects; using ProxySuper.Core.Services; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace ProxySuper.Core.ViewModels { diff --git a/ProxySuper.Core/ViewModels/ShareLinkViewModel.cs b/ProxySuper.Core/ViewModels/ShareLinkViewModel.cs index d9d79b0..749d86b 100644 --- a/ProxySuper.Core/ViewModels/ShareLinkViewModel.cs +++ b/ProxySuper.Core/ViewModels/ShareLinkViewModel.cs @@ -1,10 +1,7 @@ using MvvmCross.ViewModels; using ProxySuper.Core.Models; -using System; using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading.Tasks; namespace ProxySuper.Core.ViewModels { diff --git a/ProxySuper.Core/ViewModels/TrojanGoConfigViewModel.cs b/ProxySuper.Core/ViewModels/TrojanGoConfigViewModel.cs index 63e4fca..ff469e2 100644 --- a/ProxySuper.Core/ViewModels/TrojanGoConfigViewModel.cs +++ b/ProxySuper.Core/ViewModels/TrojanGoConfigViewModel.cs @@ -1,11 +1,6 @@ using MvvmCross.ViewModels; using ProxySuper.Core.Models.Projects; using ProxySuper.Core.Services; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace ProxySuper.Core.ViewModels { diff --git a/ProxySuper.Core/ViewModels/TrojanGoEditorViewModel.cs b/ProxySuper.Core/ViewModels/TrojanGoEditorViewModel.cs index 84b19f5..4e52497 100644 --- a/ProxySuper.Core/ViewModels/TrojanGoEditorViewModel.cs +++ b/ProxySuper.Core/ViewModels/TrojanGoEditorViewModel.cs @@ -5,11 +5,6 @@ using ProxySuper.Core.Models; using ProxySuper.Core.Models.Hosts; using ProxySuper.Core.Models.Projects; using ProxySuper.Core.Services; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace ProxySuper.Core.ViewModels { diff --git a/ProxySuper.Core/ViewModels/TrojanGoInstallerViewModel.cs b/ProxySuper.Core/ViewModels/TrojanGoInstallerViewModel.cs index 55c3d99..41ee15a 100644 --- a/ProxySuper.Core/ViewModels/TrojanGoInstallerViewModel.cs +++ b/ProxySuper.Core/ViewModels/TrojanGoInstallerViewModel.cs @@ -3,11 +3,6 @@ using ProxySuper.Core.Models; using ProxySuper.Core.Models.Hosts; using ProxySuper.Core.Models.Projects; using ProxySuper.Core.Services; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace ProxySuper.Core.ViewModels { diff --git a/ProxySuper.Core/ViewModels/XrayConfigViewModel.cs b/ProxySuper.Core/ViewModels/XrayConfigViewModel.cs index 3420b36..5988329 100644 --- a/ProxySuper.Core/ViewModels/XrayConfigViewModel.cs +++ b/ProxySuper.Core/ViewModels/XrayConfigViewModel.cs @@ -1,16 +1,5 @@ -using Microsoft.Win32; -using MvvmCross.ViewModels; +using MvvmCross.ViewModels; using ProxySuper.Core.Models.Projects; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media.Imaging; -using QRCoder; namespace ProxySuper.Core.ViewModels { @@ -56,6 +45,14 @@ namespace ProxySuper.Core.ViewModels } } + public bool Checked_VLESS_gRPC + { + get + { + return Settings.Types.Contains(XrayType.VLESS_gRPC); + } + } + public bool Checked_VMESS_TCP { get diff --git a/ProxySuper.Core/ViewModels/XrayEditorViewModel.cs b/ProxySuper.Core/ViewModels/XrayEditorViewModel.cs index 3a2c4c5..f34b1a4 100644 --- a/ProxySuper.Core/ViewModels/XrayEditorViewModel.cs +++ b/ProxySuper.Core/ViewModels/XrayEditorViewModel.cs @@ -1,8 +1,6 @@ -using MvvmCross; -using MvvmCross.Commands; +using MvvmCross.Commands; using MvvmCross.Navigation; using MvvmCross.ViewModels; -using Newtonsoft.Json; using ProxySuper.Core.Models; using ProxySuper.Core.Models.Hosts; using ProxySuper.Core.Models.Projects; @@ -10,10 +8,7 @@ using ProxySuper.Core.Services; using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Windows.Controls; -using System.Windows.Input; namespace ProxySuper.Core.ViewModels { @@ -94,7 +89,7 @@ namespace ProxySuper.Core.ViewModels get => Settings.ShadowSocksPort; set { - Settings.VMESS_KCP_Port = value; + Settings.ShadowSocksPort = value; RaisePropertyChanged("ShadowSocksPort"); } } @@ -110,6 +105,18 @@ namespace ProxySuper.Core.ViewModels } } + public string MultiUUID + { + get => string.Join(",", Settings.MulitUUID); + set + { + var input = value.Replace(',', ','); + var arr = input.Split(',').ToList(); + Settings.MulitUUID = arr; + RaisePropertyChanged("MultiUUID"); + } + } + public string Domain { get => Settings.Domain; @@ -135,6 +142,7 @@ namespace ProxySuper.Core.ViewModels get => Settings.TrojanPassword; set => Settings.TrojanPassword = value; } + public bool Checked_Trojan_TCP { get diff --git a/ProxySuper.Core/ViewModels/XrayInstallViewModel.cs b/ProxySuper.Core/ViewModels/XrayInstallViewModel.cs new file mode 100644 index 0000000..69ea300 --- /dev/null +++ b/ProxySuper.Core/ViewModels/XrayInstallViewModel.cs @@ -0,0 +1,68 @@ +using MvvmCross.Commands; +using MvvmCross.ViewModels; +using ProxySuper.Core.Models; +using ProxySuper.Core.Models.Hosts; +using ProxySuper.Core.Models.Projects; +using ProxySuper.Core.Services; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ProxySuper.Core.ViewModels +{ + public class XrayInstallViewModel : MvxViewModel + { + Host _host; + + XraySettings _settings; + + XrayService _xrayService; + + MvxInteraction _refreshLogInteraction = new MvxInteraction(); + + public override void ViewDestroy(bool viewFinishing = true) + { + _xrayService.Disconnect(); + base.ViewDestroy(viewFinishing); + } + + public override void Prepare(Record parameter) + { + this._host = parameter.Host; + this._settings = parameter.XraySettings; + } + + public override Task Initialize() + { + _xrayService = new XrayService(_host, _settings); + _xrayService.Progress.StepUpdate = () => RaisePropertyChanged("Progress"); + _xrayService.Progress.LogsUpdate = () => + { + RaisePropertyChanged("Logs"); + _refreshLogInteraction.Raise(); + }; + _xrayService.Connect(); + + return base.Initialize(); + } + + public ProjectProgress Progress + { + get => _xrayService.Progress; + } + + public string Logs + { + get => _xrayService.Progress.Logs; + } + + public IMvxInteraction LogsInteraction + { + get => _refreshLogInteraction; + } + + public IMvxCommand InstallCommand => new MvxCommand(_xrayService.Install); + } +} diff --git a/ProxySuper.Core/ViewModels/XrayInstallerViewModel.cs b/ProxySuper.Core/ViewModels/XrayInstallerViewModel.cs index 8074b25..48597cd 100644 --- a/ProxySuper.Core/ViewModels/XrayInstallerViewModel.cs +++ b/ProxySuper.Core/ViewModels/XrayInstallerViewModel.cs @@ -3,13 +3,6 @@ using ProxySuper.Core.Models; using ProxySuper.Core.Models.Hosts; using ProxySuper.Core.Models.Projects; using ProxySuper.Core.Services; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Renci.SshNet; -using System.Windows.Threading; namespace ProxySuper.Core.ViewModels { @@ -43,7 +36,5 @@ namespace ProxySuper.Core.ViewModels } public string CommandText { get; set; } - - public string OutputText { get; set; } } } diff --git a/ProxySuper.WPF/App.xaml.cs b/ProxySuper.WPF/App.xaml.cs index 7e3b001..52c5e57 100644 --- a/ProxySuper.WPF/App.xaml.cs +++ b/ProxySuper.WPF/App.xaml.cs @@ -1,13 +1,6 @@ -using MvvmCross.Platforms.Wpf.Views; +using MvvmCross.Core; using MvvmCross.Platforms.Wpf.Core; -using MvvmCross.Core; -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Data; -using System.Linq; -using System.Threading.Tasks; -using System.Windows; +using MvvmCross.Platforms.Wpf.Views; namespace ProxySuper.WPF { diff --git a/ProxySuper.WPF/Controls/HostControl.xaml b/ProxySuper.WPF/Controls/HostControl.xaml index 0a5397f..0825885 100644 --- a/ProxySuper.WPF/Controls/HostControl.xaml +++ b/ProxySuper.WPF/Controls/HostControl.xaml @@ -6,6 +6,7 @@ xmlns:local="clr-namespace:ProxySuper.WPF.Controls" xmlns:convert="clr-namespace:ProxySuper.Core.Converters;assembly=ProxySuper.Core" xmlns:host="clr-namespace:ProxySuper.Core.Models.Hosts;assembly=ProxySuper.Core" + xmlns:ssh="clr-namespace:Renci.SshNet;assembly=Renci.SshNet" mc:Ignorable="d"> @@ -16,8 +17,8 @@ - - + + @@ -129,21 +130,21 @@ IsChecked="{ Binding Host.Proxy.Type, Converter={StaticResource ProxyTypeConverter}, - ConverterParameter={x:Static host:LocalProxyType.None} + ConverterParameter={x:Static ssh:ProxyTypes.None} }"/> diff --git a/ProxySuper.WPF/Controls/HostControl.xaml.cs b/ProxySuper.WPF/Controls/HostControl.xaml.cs index f13ec61..e4a1959 100644 --- a/ProxySuper.WPF/Controls/HostControl.xaml.cs +++ b/ProxySuper.WPF/Controls/HostControl.xaml.cs @@ -1,17 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; +using System.Windows.Controls; namespace ProxySuper.WPF.Controls { diff --git a/ProxySuper.WPF/Controls/ProgressControl.xaml b/ProxySuper.WPF/Controls/ProgressControl.xaml new file mode 100644 index 0000000..a00c760 --- /dev/null +++ b/ProxySuper.WPF/Controls/ProgressControl.xaml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + diff --git a/ProxySuper.WPF/Controls/ProgressControl.xaml.cs b/ProxySuper.WPF/Controls/ProgressControl.xaml.cs new file mode 100644 index 0000000..f6fe564 --- /dev/null +++ b/ProxySuper.WPF/Controls/ProgressControl.xaml.cs @@ -0,0 +1,37 @@ +using MvvmCross.ViewModels; +using ProxySuper.Core.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace ProxySuper.WPF.Controls +{ + /// + /// ProgressControl.xaml 的交互逻辑 + /// + public partial class ProgressControl : UserControl + { + public ProgressControl() + { + InitializeComponent(); + + LogsTextBox.TextChanged += LogsTextBox_TextChanged; + } + + private void LogsTextBox_TextChanged(object sender, TextChangedEventArgs e) + { + LogsTextBox.ScrollToEnd(); + } + } +} diff --git a/ProxySuper.WPF/Controls/ShadowSocksControl.xaml b/ProxySuper.WPF/Controls/ShadowSocksControl.xaml index d0e6e75..b95d392 100644 --- a/ProxySuper.WPF/Controls/ShadowSocksControl.xaml +++ b/ProxySuper.WPF/Controls/ShadowSocksControl.xaml @@ -13,7 +13,7 @@ diff --git a/ProxySuper.WPF/Controls/ShadowSocksControl.xaml.cs b/ProxySuper.WPF/Controls/ShadowSocksControl.xaml.cs index f4d3175..f2e96b3 100644 --- a/ProxySuper.WPF/Controls/ShadowSocksControl.xaml.cs +++ b/ProxySuper.WPF/Controls/ShadowSocksControl.xaml.cs @@ -1,17 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; +using System.Windows.Controls; namespace ProxySuper.WPF.Controls { diff --git a/ProxySuper.WPF/Controls/Trojan_TCP_Control.xaml b/ProxySuper.WPF/Controls/Trojan_TCP_Control.xaml index 46f848e..39ae13f 100644 --- a/ProxySuper.WPF/Controls/Trojan_TCP_Control.xaml +++ b/ProxySuper.WPF/Controls/Trojan_TCP_Control.xaml @@ -13,7 +13,7 @@ diff --git a/ProxySuper.WPF/Controls/Trojan_TCP_Control.xaml.cs b/ProxySuper.WPF/Controls/Trojan_TCP_Control.xaml.cs index 3701ab9..72103e8 100644 --- a/ProxySuper.WPF/Controls/Trojan_TCP_Control.xaml.cs +++ b/ProxySuper.WPF/Controls/Trojan_TCP_Control.xaml.cs @@ -1,17 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; +using System.Windows.Controls; namespace ProxySuper.WPF.Controls { diff --git a/ProxySuper.WPF/Controls/VLESS_KCP_Control.xaml.cs b/ProxySuper.WPF/Controls/VLESS_KCP_Control.xaml.cs index 414c4b1..2173b7d 100644 --- a/ProxySuper.WPF/Controls/VLESS_KCP_Control.xaml.cs +++ b/ProxySuper.WPF/Controls/VLESS_KCP_Control.xaml.cs @@ -1,17 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; +using System.Windows.Controls; namespace ProxySuper.WPF.Controls { diff --git a/ProxySuper.WPF/Controls/VLESS_TCP_TLS_Control.xaml b/ProxySuper.WPF/Controls/VLESS_TCP_TLS_Control.xaml index f892b30..6328d5a 100644 --- a/ProxySuper.WPF/Controls/VLESS_TCP_TLS_Control.xaml +++ b/ProxySuper.WPF/Controls/VLESS_TCP_TLS_Control.xaml @@ -13,7 +13,7 @@ diff --git a/ProxySuper.WPF/Controls/VLESS_TCP_TLS_Control.xaml.cs b/ProxySuper.WPF/Controls/VLESS_TCP_TLS_Control.xaml.cs index c147188..fcebaef 100644 --- a/ProxySuper.WPF/Controls/VLESS_TCP_TLS_Control.xaml.cs +++ b/ProxySuper.WPF/Controls/VLESS_TCP_TLS_Control.xaml.cs @@ -1,17 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; +using System.Windows.Controls; namespace ProxySuper.WPF.Controls { diff --git a/ProxySuper.WPF/Controls/VLESS_WS_TLS_Control.xaml b/ProxySuper.WPF/Controls/VLESS_WS_TLS_Control.xaml index 0b28fba..1bde58e 100644 --- a/ProxySuper.WPF/Controls/VLESS_WS_TLS_Control.xaml +++ b/ProxySuper.WPF/Controls/VLESS_WS_TLS_Control.xaml @@ -13,7 +13,7 @@ diff --git a/ProxySuper.WPF/Controls/VLESS_WS_TLS_Control.xaml.cs b/ProxySuper.WPF/Controls/VLESS_WS_TLS_Control.xaml.cs index 7e3f8a9..5c434da 100644 --- a/ProxySuper.WPF/Controls/VLESS_WS_TLS_Control.xaml.cs +++ b/ProxySuper.WPF/Controls/VLESS_WS_TLS_Control.xaml.cs @@ -1,17 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; +using System.Windows.Controls; namespace ProxySuper.WPF.Controls { diff --git a/ProxySuper.WPF/Controls/VLESS_XTLS_Control.xaml b/ProxySuper.WPF/Controls/VLESS_XTLS_Control.xaml index b596ca2..971d8cd 100644 --- a/ProxySuper.WPF/Controls/VLESS_XTLS_Control.xaml +++ b/ProxySuper.WPF/Controls/VLESS_XTLS_Control.xaml @@ -13,7 +13,7 @@ diff --git a/ProxySuper.WPF/Controls/VLESS_XTLS_Control.xaml.cs b/ProxySuper.WPF/Controls/VLESS_XTLS_Control.xaml.cs index 185f6a1..4ee74c9 100644 --- a/ProxySuper.WPF/Controls/VLESS_XTLS_Control.xaml.cs +++ b/ProxySuper.WPF/Controls/VLESS_XTLS_Control.xaml.cs @@ -1,17 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; +using System.Windows.Controls; namespace ProxySuper.WPF.Controls { diff --git a/ProxySuper.WPF/Controls/VLESS_gRPC_Control.xaml.cs b/ProxySuper.WPF/Controls/VLESS_gRPC_Control.xaml.cs index 2b346ae..87ee670 100644 --- a/ProxySuper.WPF/Controls/VLESS_gRPC_Control.xaml.cs +++ b/ProxySuper.WPF/Controls/VLESS_gRPC_Control.xaml.cs @@ -1,17 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; +using System.Windows.Controls; namespace ProxySuper.WPF.Controls { diff --git a/ProxySuper.WPF/Controls/VMESS_KCP_Control.xaml.cs b/ProxySuper.WPF/Controls/VMESS_KCP_Control.xaml.cs index 0dccb5a..4183748 100644 --- a/ProxySuper.WPF/Controls/VMESS_KCP_Control.xaml.cs +++ b/ProxySuper.WPF/Controls/VMESS_KCP_Control.xaml.cs @@ -1,17 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; +using System.Windows.Controls; namespace ProxySuper.WPF.Controls { diff --git a/ProxySuper.WPF/Controls/VMESS_TCP_TLS_Control.xaml b/ProxySuper.WPF/Controls/VMESS_TCP_TLS_Control.xaml index e22f34f..1747181 100644 --- a/ProxySuper.WPF/Controls/VMESS_TCP_TLS_Control.xaml +++ b/ProxySuper.WPF/Controls/VMESS_TCP_TLS_Control.xaml @@ -13,7 +13,7 @@ diff --git a/ProxySuper.WPF/Controls/VMESS_TCP_TLS_Control.xaml.cs b/ProxySuper.WPF/Controls/VMESS_TCP_TLS_Control.xaml.cs index 12714fa..fe42054 100644 --- a/ProxySuper.WPF/Controls/VMESS_TCP_TLS_Control.xaml.cs +++ b/ProxySuper.WPF/Controls/VMESS_TCP_TLS_Control.xaml.cs @@ -1,17 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; +using System.Windows.Controls; namespace ProxySuper.WPF.Controls { diff --git a/ProxySuper.WPF/Controls/VMESS_WS_TLS_Control.xaml b/ProxySuper.WPF/Controls/VMESS_WS_TLS_Control.xaml index 4532868..7e885f7 100644 --- a/ProxySuper.WPF/Controls/VMESS_WS_TLS_Control.xaml +++ b/ProxySuper.WPF/Controls/VMESS_WS_TLS_Control.xaml @@ -13,7 +13,7 @@ diff --git a/ProxySuper.WPF/Controls/VMESS_WS_TLS_Control.xaml.cs b/ProxySuper.WPF/Controls/VMESS_WS_TLS_Control.xaml.cs index f8502d9..79887c2 100644 --- a/ProxySuper.WPF/Controls/VMESS_WS_TLS_Control.xaml.cs +++ b/ProxySuper.WPF/Controls/VMESS_WS_TLS_Control.xaml.cs @@ -1,17 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; +using System.Windows.Controls; namespace ProxySuper.WPF.Controls { diff --git a/ProxySuper.WPF/Controls/XraySettingsControl.xaml b/ProxySuper.WPF/Controls/XraySettingsControl.xaml index 4be4fad..baaeb96 100644 --- a/ProxySuper.WPF/Controls/XraySettingsControl.xaml +++ b/ProxySuper.WPF/Controls/XraySettingsControl.xaml @@ -10,179 +10,187 @@ - + - - + - + - - + - + - - + - + - - + - + - - + + + + + - - + - + - - + - + - - + - + - - + - + - - - - + - - + - + - - + - + - - + -