diff --git a/ProxySuper.Core/Models/Projects/TrojanGoSettings.cs b/ProxySuper.Core/Models/Projects/TrojanGoSettings.cs index 17055fa..4462cf8 100644 --- a/ProxySuper.Core/Models/Projects/TrojanGoSettings.cs +++ b/ProxySuper.Core/Models/Projects/TrojanGoSettings.cs @@ -9,6 +9,7 @@ namespace ProxySuper.Core.Models.Projects { public TrojanGoSettings() { + WithTLS = true; Port = 443; WebSocketPath = "/ws"; Password = Guid.NewGuid().ToString(); @@ -24,6 +25,11 @@ namespace ProxySuper.Core.Models.Projects public ProjectType Type { get; set; } = ProjectType.TrojanGo; + /// + /// 是否安装TLS证书 + /// + public bool WithTLS { get; set; } + /// /// 域名 /// diff --git a/ProxySuper.Core/Models/Projects/XraySettings.cs b/ProxySuper.Core/Models/Projects/XraySettings.cs index 709da3f..dc0ff65 100644 --- a/ProxySuper.Core/Models/Projects/XraySettings.cs +++ b/ProxySuper.Core/Models/Projects/XraySettings.cs @@ -11,6 +11,8 @@ namespace ProxySuper.Core.Models.Projects { public XraySettings() { + WithTLS = true; + var guid = Guid.NewGuid().ToString(); Port = 443; VLESS_KCP_Port = 2001; @@ -81,6 +83,12 @@ namespace ProxySuper.Core.Models.Projects public ProjectType Type { get; set; } = ProjectType.Xray; + /// + /// 是否安装证书, + /// 上传自有证书时选False,则不会自动安装证书。 + /// + public bool WithTLS { get; set; } + /// /// 端口 /// diff --git a/ProxySuper.Core/ProxySuper.Core.csproj b/ProxySuper.Core/ProxySuper.Core.csproj index ff82855..8e0b987 100644 --- a/ProxySuper.Core/ProxySuper.Core.csproj +++ b/ProxySuper.Core/ProxySuper.Core.csproj @@ -87,37 +87,28 @@ - - - - - - - - - diff --git a/ProxySuper.Core/Services/BrookProject.cs b/ProxySuper.Core/Services/BrookProject.cs deleted file mode 100644 index 2672d84..0000000 --- a/ProxySuper.Core/Services/BrookProject.cs +++ /dev/null @@ -1,128 +0,0 @@ -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 deleted file mode 100644 index 0f9f7d9..0000000 --- a/ProxySuper.Core/Services/NaiveProxyProject.cs +++ /dev/null @@ -1,168 +0,0 @@ -using ProxySuper.Core.Models.Projects; -using Renci.SshNet; -using System; -using System.IO; -using System.Text; -using System.Windows; - -namespace ProxySuper.Core.Services -{ - public class NaiveProxyProject : ProjectBase - { - public NaiveProxyProject(SshClient sshClient, NaiveProxySettings parameters, Action writeOutput) : base(sshClient, parameters, writeOutput) - { - } - - public void Uninstall() - { - 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卸载完成"); - } - - public void UploadWeb(Stream stream) - { - EnsureRootAuth(); - EnsureSystemEnv(); - - if (!FileExists("/usr/share/caddy")) - { - RunCmd("mkdir /usr/share/caddy"); - } - RunCmd("rm -rf /usr/share/caddy/*"); - UploadFile(stream, "/usr/share/caddy/caddy.zip"); - RunCmd("unzip /usr/share/caddy/caddy.zip -d /usr/share/caddy"); - RunCmd("chmod -R 777 /usr/share/caddy"); - UploadCaddyFile(useCustomWeb: true); - WriteOutput("************ 上传网站模板完成 ************"); - } - - public override void Install() - { - try - { - EnsureRootAuth(); - - WriteOutput("检测安装系统环境..."); - EnsureSystemEnv(); - WriteOutput("检测安装系统环境完成"); - - WriteOutput("安装必要的系统工具..."); - ConfigureSoftware(); - WriteOutput("系统工具安装完成"); - - WriteOutput("配置防火墙..."); - ConfigFirewalld(); - WriteOutput("防火墙配置完成"); - - WriteOutput("检测网络环境"); - EnsureIP(); - WriteOutput("检测网络环境完成"); - - WriteOutput("同步系统和本地时间..."); - SyncTimeDiff(); - WriteOutput("时间同步完成"); - - WriteOutput("检测域名是否绑定本机IP..."); - ValidateDomain(); - WriteOutput("域名检测完成"); - - WriteOutput("安装NaiveProxy..."); - InstallNaiveProxy(); - WriteOutput("NaiveProxy安装完成"); - - WriteOutput("启动BBR"); - EnableBBR(); - - WriteOutput("************"); - WriteOutput("安装完成,尽情享用吧......"); - WriteOutput("************"); - } - catch (Exception ex) - { - var errorLog = "安装终止," + ex.Message; - WriteOutput(errorLog); - MessageBox.Show("安装失败,请联系开发者或上传日志文件(Logs文件夹下)到github提问。"); - } - } - - private void InstallNaiveProxy() - { - 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 安装完成"); - } - - private void ConfigNetwork() - { - WriteOutput("优化网络参数"); - RunCmd(@"bash -c 'echo ""fs.file-max = 51200"" >> /etc/sysctl.conf'"); - RunCmd(@"bash -c 'echo ""net.core.rmem_max = 67108864"" >> /etc/sysctl.conf'"); - RunCmd(@"bash -c 'echo ""net.core.wmem_max = 67108864"" >> /etc/sysctl.conf'"); - RunCmd(@"bash -c 'echo ""net.core.rmem_default = 65536"" >> /etc/sysctl.conf'"); - RunCmd(@"bash -c 'echo ""net.core.wmem_default = 65536"" >> /etc/sysctl.conf'"); - RunCmd(@"bash -c 'echo ""net.core.netdev_max_backlog = 4096"" >> /etc/sysctl.conf'"); - RunCmd(@"bash -c 'echo ""net.core.somaxconn = 4096"" >> /etc/sysctl.conf'"); - RunCmd(@"bash -c 'echo ""net.ipv4.tcp_syncookies = 1"" >> /etc/sysctl.conf'"); - RunCmd(@"bash -c 'echo ""net.ipv4.tcp_tw_reuse = 1"" >> /etc/sysctl.conf'"); - RunCmd(@"bash -c 'echo ""net.ipv4.tcp_tw_recycle = 0"" >> /etc/sysctl.conf'"); - RunCmd(@"bash -c 'echo ""net.ipv4.tcp_fin_timeout = 30"" >> /etc/sysctl.conf'"); - RunCmd(@"bash -c 'echo ""net.ipv4.tcp_keepalive_time = 1200"" >> /etc/sysctl.conf'"); - RunCmd(@"bash -c 'echo ""net.ipv4.ip_local_port_range = 10000 65000"" >> /etc/sysctl.conf'"); - RunCmd(@"bash -c 'echo ""net.ipv4.tcp_max_syn_backlog = 4096"" >> /etc/sysctl.conf'"); - RunCmd(@"bash -c 'echo ""net.ipv4.tcp_max_tw_buckets = 5000"" >> /etc/sysctl.conf'"); - RunCmd(@"bash -c 'echo ""net.ipv4.tcp_rmem = 4096 87380 67108864"" >> /etc/sysctl.conf'"); - RunCmd(@"bash -c 'echo ""net.ipv4.tcp_wmem = 4096 65536 67108864"" >> /etc/sysctl.conf'"); - RunCmd(@"bash -c 'echo ""net.ipv4.tcp_mtu_probing = 1"" >> /etc/sysctl.conf'"); - RunCmd(@"sysctl -p"); - WriteOutput("网络参数优化完成"); - } - - private void UploadCaddyFile(bool useCustomWeb = false) - { - var caddyStr = BuildConfig(useCustomWeb); - - if (FileExists("/etc/caddy/Caddyfile")) - { - RunCmd("mv /etc/caddy/Caddyfile /etc/caddy/Caddyfile.back"); - } - - RunCmd($"echo {caddyStr} > /etc/caddy/Caddyfile"); - RunCmd("systemctl restart caddy"); - } - - private string BuildConfig(bool useCustomWeb = false) - { - var jsonStr = File.ReadAllText("Templates/NaiveProxy/naive_server.caddyfile"); - jsonStr = jsonStr.Replace("##port##", Parameters.Port.ToString()); - jsonStr = jsonStr.Replace("##domain##", Parameters.Domain); - jsonStr = jsonStr.Replace("##basicauth##", $"basic_auth {Parameters.UserName} {Parameters.Password}"); - - if (!useCustomWeb && !string.IsNullOrEmpty(Parameters.MaskDomain)) - { - var prefix = "http://"; - if (Parameters.MaskDomain.StartsWith("https://")) - { - prefix = "https://"; - } - var domain = Parameters.MaskDomain - .TrimStart("http://".ToCharArray()) - .TrimStart("https://".ToCharArray()); - - jsonStr = jsonStr.Replace("##reverse_proxy##", $"reverse_proxy {prefix}{domain} {{ \n header_up Host {domain} \n }}"); - } - else - { - jsonStr = jsonStr.Replace("##reverse_proxy##", ""); - jsonStr = jsonStr.Replace("#file_server", "file_server"); - } - return jsonStr; - } - } -} diff --git a/ProxySuper.Core/Services/NaiveProxyService.cs b/ProxySuper.Core/Services/NaiveProxyService.cs index 69724c9..939bf83 100644 --- a/ProxySuper.Core/Services/NaiveProxyService.cs +++ b/ProxySuper.Core/Services/NaiveProxyService.cs @@ -143,7 +143,7 @@ namespace ProxySuper.Core.Services } - #region 似有方法 + #region 私有方法 private void DoUploadWeb(object sender, CancelEventArgs e) { diff --git a/ProxySuper.Core/Services/ProjectBase.cs b/ProxySuper.Core/Services/ProjectBase.cs deleted file mode 100644 index 983fcf2..0000000 --- a/ProxySuper.Core/Services/ProjectBase.cs +++ /dev/null @@ -1,855 +0,0 @@ -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.Windows; - -namespace ProxySuper.Core.Services -{ - public enum CmdType - { - None, - Apt, - Dnf, - 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; } - - protected string IPv4 { get; set; } - - protected string IPv6 { get; set; } - - protected TSettings Parameters { get; set; } - - public ProjectBase(SshClient sshClient, TSettings parameters, Action writeOutput) - { - _sshClient = sshClient; - WriteOutput = writeOutput; - Parameters = parameters; - } - - protected string RunCmd(string cmdStr) - { - var cmd = _sshClient.CreateCommand(cmdStr); - WriteOutput(cmdStr); - - var exe = cmd.BeginExecute(); - var result = cmd.EndExecute(exe); - //var result = cmd.Execute(); - WriteOutput(result); - return result; - } - - /// - /// 执行安装命令 - /// - public abstract void Install(); - - /// - /// 配置系统基础环境 - /// - protected void EnsureSystemEnv() - { - 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"); - if (!string.IsNullOrEmpty(cmd)) - { - CmdType = CmdType.Apt; - } - } - - if (CmdType == CmdType.None) - { - cmd = RunCmd("command -v dnf"); - if (!string.IsNullOrEmpty(cmd)) - { - CmdType = CmdType.Dnf; - //RunCmd("echo \"export LC_ALL=en_US.UTF-8\" >> /etc/profile"); - //RunCmd("source /etc/profile"); - } - } - - if (CmdType == CmdType.None) - { - cmd = RunCmd("command -v yum"); - if (!string.IsNullOrEmpty(cmd)) - { - CmdType = CmdType.Yum; - } - } - - // systemctl - cmd = RunCmd("command -v systemctl"); - var hasSystemCtl = !string.IsNullOrEmpty(cmd); - - // SELinux - cmd = RunCmd("command -v getenforce"); - IsSELinux = !string.IsNullOrEmpty(cmd); - - if (CmdType == CmdType.None || !hasSystemCtl) - { - throw new Exception("系统缺乏必要的安装组件如:apt||dnf||yum||Syetemd,主机系统推荐使用:CentOS 7/8,Debian 8/9/10,Ubuntu 16.04及以上版本"); - } - - - // 判断是否启用了SELinux,如果启用了,并且工作在Enforcing模式下,则改为Permissive模式 - if (IsSELinux) - { - cmd = RunCmd("getenforce"); - - // 检测到系统启用SELinux,且工作在严格模式下,需改为宽松模式 - if (cmd.Contains("Enforcing")) - { - RunCmd("setenforce 0"); - RunCmd(@"sed -i 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config"); - } - } - } - - /// - /// 确保Root账户登陆 - /// - protected void EnsureRootAuth() - { - // 禁止一些可能产生的干扰信息 - RunCmd(@"sed -i 's/echo/#echo/g' ~/.bashrc"); - RunCmd(@"sed -i 's/echo/#echo/g' ~/.profile"); - - - // 检测是否运行在Root权限下 - var cmd = RunCmd("id -u"); - if (!cmd.Equals("0\n")) - { - throw new Exception("请使用Root账户登陆主机"); - } - } - - /// - /// 配置IPV6环境 - /// - protected void EnsureIP() - { - if (IsOnlyIpv6()) - { - SetNat64(); - } - } - - /// - /// 配置必要的软件 - /// - protected void ConfigureSoftware() - { - RunCmd(GetUpdateCmd()); - - string cmd = RunCmd("command -v sudo"); - if (string.IsNullOrEmpty(cmd)) - { - RunCmd(GetInstallCmd("sudo")); - } - - // 安装curl,wget,unzip - cmd = RunCmd("command -v curl"); - if (string.IsNullOrEmpty(cmd)) - { - RunCmd(GetInstallCmd("curl")); - } - - cmd = RunCmd("command -v wget"); - if (string.IsNullOrEmpty(cmd)) - { - RunCmd(GetInstallCmd("wget")); - } - - cmd = RunCmd("command -v unzip"); - if (string.IsNullOrEmpty(cmd)) - { - RunCmd(GetInstallCmd("unzip")); - } - - // 安装dig - cmd = RunCmd("command -v dig"); - if (string.IsNullOrEmpty(cmd)) - { - if (CmdType == CmdType.Apt) - { - RunCmd(GetInstallCmd("dnsutils")); - } - else if (CmdType == CmdType.Dnf) - { - RunCmd(GetInstallCmd("bind-utils")); - } - else if (CmdType == CmdType.Yum) - { - RunCmd(GetInstallCmd("bind-utils")); - } - } - - - // 处理极其少见的xz-utils未安装的情况 - if (CmdType == CmdType.Apt) - { - RunCmd(GetInstallCmd("xz-utils")); - } - else - { - 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)) - { - RunCmd(GetInstallCmd("lsof")); - } - } - - /// - /// 配置防火墙 - /// - protected void ConfigFirewalld() - { - Parameters.FreePorts.ForEach(port => - { - SetPortFree(port); - }); - - OpenPort(_sshClient.ConnectionInfo.Port); - OpenPort(Parameters.FreePorts.ToArray()); - } - - /// - /// 重置防火墙 - /// - protected void ResetFirewalld() - { - Parameters.FreePorts.ForEach(port => - { - SetPortFree(port); - }); - ClosePort(Parameters.FreePorts.ToArray()); - } - - /// - /// 配置同步时间差 - /// - 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() - { - if (OnlyIpv6) - { - string cmdFilter = @"| grep -oE '(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))' | head -n 1"; - var cmd = $"dig @resolver1.opendns.com AAAA {Parameters.Domain} +short -6 {cmdFilter}"; - var result = RunCmd(cmd).TrimEnd('\r', '\n'); - - if (result == IPv6) return; - } - - else - { - string cmdFilter = @"| grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | head -n 1"; - var cmd = $"dig @resolver1.opendns.com A {Parameters.Domain} +short -4 {cmdFilter}"; - var result = RunCmd(cmd).TrimEnd('\r', '\n'); - - if (result == IPv4) return; - - } - - - var btnResult = MessageBox.Show( - $"{Parameters.Domain}未能正常解析到服务器的IP,如果您使用了CDN请忽略,是否继续安装?", "提示", MessageBoxButton.YesNo); - - if (btnResult == MessageBoxResult.No) - { - throw new Exception($"域名解析失败,安装停止!"); - } - - } - - /// - /// 判断是否安装某个软件 - /// - /// - /// - 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"; - } - - /// - /// 安装 Caddy - /// - protected void InstallCaddy() - { - #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 - } - - /// - /// 卸载 Caddy - /// - protected void UninstallCaddy() - { - 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"); - } - - - #region 检测系统环境 - - private bool IsOnlyIpv6() - { - string cmd; - - cmd = RunCmd(@"curl -s https://api.ip.sb/ip --ipv4 --max-time 8"); - IPv4 = cmd.TrimEnd('\r', '\n'); - - if (!string.IsNullOrEmpty(IPv4)) - { - OnlyIpv6 = false; - return false; - } - - cmd = RunCmd(@"curl -s https://api.ip.sb/ip --ipv6 --max-time 8"); - IPv6 = cmd.TrimEnd('\r', '\n'); - - if (string.IsNullOrEmpty(IPv6)) - { - throw new Exception("未检测到可用的的IP地址,请重试安装"); - } - - OnlyIpv6 = true; - return OnlyIpv6; - } - - 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 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 - - - #region BBR - 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; - - } - - protected void EnableBBR() - { - 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 (OnlyIpv6) - { - RemoveNat64(); - } - WriteOutput("BBR启动成功"); - } - - if (!canInstallBBR) - { - WriteOutput("****** 系统不满足启用BBR条件,启动失败。 ******"); - } - - } - #endregion - - /// - /// 安装证书 - /// - /// - /// - protected void InstallCert(string dirPath, string certName, string keyName) - { - string certPath = dirPath + "/" + certName; - string keyPath = dirPath + "/" + keyName; - - // 安装依赖 - RunCmd(GetInstallCmd("socat")); - - // 解决搬瓦工CentOS缺少问题 - RunCmd(GetInstallCmd("automake autoconf libtool")); - - // 安装Acme - - var result = RunCmd($"curl https://get.acme.sh yes | sh"); - if (result.Contains("Install success")) - { - WriteOutput("安装 acme.sh 成功"); - } - else - { - WriteOutput("安装 acme.sh 失败,请联系开发者!"); - throw new Exception("安装 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 \"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 \"systemctl stop caddy\" --post-hook \"systemctl start caddy\" --server letsencrypt"; - result = RunCmd(cmd); - } - - if (result.Contains("success")) - { - WriteOutput("申请证书成功"); - } - else - { - WriteOutput("申请证书失败,如果申请次数过多请更换二级域名,或联系开发者!"); - throw new Exception("申请证书失败,如果申请次数过多请更换二级域名,或联系开发者!"); - } - - // 安装证书 - RunCmd($"mkdir -p {dirPath}"); - RunCmd($"/root/.acme.sh/acme.sh --installcert -d {Parameters.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")) - { - WriteOutput("安装证书成功"); - } - else - { - WriteOutput("安装证书失败,请联系开发者!"); - throw new Exception("安装证书失败,请联系开发者!"); - } - - 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(); - } - } - } - } - - /// - /// 上传文件 - /// - /// - /// - protected void UploadFile(Stream stream, string path) - { - using (var sftp = new SftpClient(_sshClient.ConnectionInfo)) - { - sftp.Connect(); - sftp.UploadFile(stream, path, true); - sftp.Disconnect(); - } - } - - /// - /// 根据系统环境匹配更新命令 - /// - /// - protected string GetUpdateCmd() - { - if (CmdType == CmdType.Apt) - { - 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"; - } - - throw new Exception("未识别的系统"); - } - - /// - /// 根据系统匹配安装命令 - /// - /// - /// - protected string GetInstallCmd(string soft) - { - if (CmdType == CmdType.Apt) - { - return "apt install -y " + soft; - } - else if (CmdType == CmdType.Dnf) - { - return "dnf install -y " + soft; - } - else if (CmdType == CmdType.Yum) - { - return "yum install -y " + soft; - } - - throw new Exception("未识别的系统"); - } - } -} diff --git a/ProxySuper.Core/Services/ServiceBase.cs b/ProxySuper.Core/Services/ServiceBase.cs index 9804184..3ac9721 100644 --- a/ProxySuper.Core/Services/ServiceBase.cs +++ b/ProxySuper.Core/Services/ServiceBase.cs @@ -12,6 +12,20 @@ using System.Threading.Tasks; namespace ProxySuper.Core.Services { + public enum ArchType + { + x86, + arm + } + + public enum CmdType + { + None, + Yum, + Apt, + Dnf + } + public abstract class ServiceBase where TSettings : IProjectSettings { private Host _host; diff --git a/ProxySuper.Core/Services/TrojanGoProject.cs b/ProxySuper.Core/Services/TrojanGoProject.cs deleted file mode 100644 index bfa21e7..0000000 --- a/ProxySuper.Core/Services/TrojanGoProject.cs +++ /dev/null @@ -1,181 +0,0 @@ -using ProxySuper.Core.Models.Projects; -using Renci.SshNet; -using System; -using System.IO; -using System.Text; -using System.Windows; - -namespace ProxySuper.Core.Services -{ - public class TrojanGoProject : ProjectBase - { - public TrojanGoProject(SshClient sshClient, TrojanGoSettings parameters, Action writeOutput) : base(sshClient, parameters, writeOutput) - { - } - - public void InstallCertToTrojanGo() - { - EnsureRootAuth(); - EnsureSystemEnv(); - InstallCert( - dirPath: "/usr/local/etc/trojan-go", - certName: "trojan-go.crt", - keyName: "trojan-go.key"); - - RunCmd("systemctl restart trojan-go"); - WriteOutput("************ 安装证书完成 ************"); - } - - public void UploadWeb(Stream stream) - { - EnsureRootAuth(); - EnsureSystemEnv(); - if (!FileExists("/usr/share/caddy")) - { - RunCmd("mkdir /usr/share/caddy"); - } - RunCmd("rm -rf /usr/share/caddy/*"); - UploadFile(stream, "/usr/share/caddy/caddy.zip"); - RunCmd("unzip /usr/share/caddy/caddy.zip -d /usr/share/caddy"); - RunCmd("chmod -R 777 /usr/share/caddy"); - UploadCaddyFile(useCustomWeb: true); - WriteOutput("************ 上传网站模板完成 ************"); - } - - public void Uninstall() - { - EnsureRootAuth(); - EnsureSystemEnv(); - - RunCmd("systemctl stop trojan-go"); - base.UninstallCaddy(); - - RunCmd("rm -rf /usr/local/bin/trojan-go"); - RunCmd("rm -rf /usr/local/etc/trojan-go"); - - RunCmd("acme.sh --uninstall"); - RunCmd("rm -r ~/.acme.sh"); - - WriteOutput("卸载Trojan-Go完成"); - } - - public override void Install() - { - try - { - EnsureRootAuth(); - - if (FileExists("/usr/local/bin/trojan-go")) - { - var btnResult = MessageBox.Show("已经安装Trojan-Go,是否需要重装?", "提示", MessageBoxButton.YesNo); - if (btnResult == MessageBoxResult.No) - { - MessageBox.Show("安装终止", "提示"); - return; - } - } - - WriteOutput("检测安装系统环境..."); - EnsureSystemEnv(); - WriteOutput("检测安装系统环境完成"); - - WriteOutput("安装必要的系统工具..."); - ConfigureSoftware(); - WriteOutput("系统工具安装完成"); - - WriteOutput("配置防火墙..."); - ConfigFirewalld(); - WriteOutput("防火墙配置完成"); - - WriteOutput("检测网络环境"); - EnsureIP(); - WriteOutput("检测网络环境完成"); - - WriteOutput("同步系统和本地时间..."); - SyncTimeDiff(); - WriteOutput("时间同步完成"); - - WriteOutput("检测域名是否绑定本机IP..."); - ValidateDomain(); - WriteOutput("域名检测完成"); - - WriteOutput("安装Caddy..."); - InstallCaddy(); - UploadCaddyFile(); - WriteOutput("Caddy安装完成"); - - WriteOutput("安装Trojan-Go..."); - InstallTrojanGo(); - WriteOutput("Trojan-Go安装完成"); - - - WriteOutput("启动BBR"); - EnableBBR(); - - RunCmd("systemctl restart trojan-go"); - WriteOutput("************"); - WriteOutput("安装完成,尽情享用吧......"); - WriteOutput("************"); - } - catch (Exception ex) - { - var errorLog = "安装终止," + ex.Message; - WriteOutput(errorLog); - MessageBox.Show("安装失败,请联系开发者或上传日志文件(Logs文件夹下)到github提问。"); - } - } - - private void InstallTrojanGo() - { - 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) - { - throw new Exception("trojan-go 安装失败,请联系开发者!"); - } - - RunCmd($"sed -i 's/User=nobody/User=root/g' /etc/systemd/system/trojan-go.service"); - RunCmd($"sed -i 's/CapabilityBoundingSet=/#CapabilityBoundingSet=/g' /etc/systemd/system/trojan-go.service"); - RunCmd($"sed -i 's/AmbientCapabilities=/#AmbientCapabilities=/g' /etc/systemd/system/trojan-go.service"); - RunCmd($"systemctl daemon-reload"); - - RunCmd("systemctl enable trojan-go"); - RunCmd("systemctl start trojan-go"); - WriteOutput("Trojan-Go 安装完成"); - - InstallCert( - dirPath: "/usr/local/etc/trojan-go", - certName: "trojan-go.crt", - keyName: "trojan-go.key"); - - if (FileExists("/usr/local/etc/trojan-go/config.json")) - { - RunCmd("mv /usr/local/etc/trojan-go/config.json config.json.old"); - } - - UploadTrojanGoSettings(); - } - - private void UploadTrojanGoSettings() - { - // 上传配置 - var settings = TrojanGoConfigBuilder.BuildTrojanGoConfig(Parameters); - var stream = new MemoryStream(Encoding.UTF8.GetBytes(settings)); - UploadFile(stream, "/usr/local/etc/trojan-go/config.json"); - RunCmd("systemctl restart trojan-go"); - } - - private void UploadCaddyFile(bool useCustomWeb = false) - { - var config = TrojanGoConfigBuilder.BuildCaddyConfig(Parameters, useCustomWeb); - var stream = new MemoryStream(Encoding.UTF8.GetBytes(config)); - if (FileExists("/etc/caddy/Caddyfile")) - { - RunCmd("mv /etc/caddy/Caddyfile /etc/caddy/Caddyfile.back"); - } - UploadFile(stream, "/etc/caddy/Caddyfile"); - RunCmd("systemctl restart caddy"); - } - } - -} diff --git a/ProxySuper.Core/Services/TrojanGoService.cs b/ProxySuper.Core/Services/TrojanGoService.cs index 9262565..5ac29ad 100644 --- a/ProxySuper.Core/Services/TrojanGoService.cs +++ b/ProxySuper.Core/Services/TrojanGoService.cs @@ -79,9 +79,15 @@ namespace ProxySuper.Core.Services RunCmd("systemctl enable trojan-go"); RunCmd("systemctl restart trojan-go"); + Progress.Percentage = 100; Progress.Step = "安装成功"; Progress.Desc = string.Empty; + + if (!Settings.WithTLS) + { + Progress.Step = "安装成功,请上传您的 TLS 证书。"; + } } catch (Exception ex) { @@ -136,22 +142,32 @@ namespace ProxySuper.Core.Services public void UpdateSettings() { - Progress.Step = "更新配置文件"; - Progress.Percentage = 0; + Task.Factory.StartNew(() => + { + try + { + Progress.Step = "更新配置文件"; + Progress.Percentage = 0; - Progress.Desc = "检测系统环境"; - EnsureRootUser(); - EnsureSystemEnv(); - Progress.Percentage = 30; + Progress.Desc = "检测系统环境"; + EnsureRootUser(); + EnsureSystemEnv(); + Progress.Percentage = 30; - Progress.Desc = "更新配置文件"; - UploadTrojanGoSettings(); + Progress.Desc = "更新配置文件"; + UploadTrojanGoSettings(); - Progress.Desc = "重启Trojan-Go服务器"; - RunCmd("systemctl restart trojan-go"); + Progress.Desc = "重启Trojan-Go服务器"; + RunCmd("systemctl restart trojan-go"); - Progress.Percentage = 100; - Progress.Desc = "更新配置成功"; + Progress.Percentage = 100; + Progress.Desc = "更新配置成功"; + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + } + }); } public void UploadWeb() @@ -336,14 +352,14 @@ namespace ProxySuper.Core.Services RunCmd($"sed -i 's/AmbientCapabilities=/#AmbientCapabilities=/g' /etc/systemd/system/trojan-go.service"); RunCmd($"systemctl daemon-reload"); - Progress.Desc = "Trojan-Go 安装完成"; - - Progress.Desc = "安装TLS证书"; - InstallCert( - dirPath: "/usr/local/etc/trojan-go", - certName: "trojan-go.crt", - keyName: "trojan-go.key"); - + if (Settings.WithTLS) + { + Progress.Desc = "安装TLS证书"; + InstallCert( + dirPath: "/usr/local/etc/trojan-go", + certName: "trojan-go.crt", + keyName: "trojan-go.key"); + } Progress.Desc = "上传Trojan-Go配置文件"; UploadTrojanGoSettings(); diff --git a/ProxySuper.Core/Services/XrayProject.cs b/ProxySuper.Core/Services/XrayProject.cs deleted file mode 100644 index 4dc8146..0000000 --- a/ProxySuper.Core/Services/XrayProject.cs +++ /dev/null @@ -1,329 +0,0 @@ -using Newtonsoft.Json; -using ProxySuper.Core.Models.Projects; -using Renci.SshNet; -using System; -using System.IO; -using System.Linq; -using System.Net; -using System.Text; -using System.Windows; - -namespace ProxySuper.Core.Services -{ - public class XrayProject : ProjectBase - { - - private const string ServerLogDir = @"Templates\xray\server\00_log"; - private const string ServerApiDir = @"Templates\xray\server\01_api"; - private const string ServerDnsDir = @"Templates\xray\server\02_dns"; - private const string ServerRoutingDir = @"Templates\xray\server\03_routing"; - private const string ServerPolicyDir = @"Templates\xray\server\04_policy"; - private const string ServerInboundsDir = @"Templates\xray\server\05_inbounds"; - private const string ServerOutboundsDir = @"Templates\xray\server\06_outbounds"; - private const string ServerTransportDir = @"Templates\xray\server\07_transport"; - private const string ServerStatsDir = @"Templates\xray\server\08_stats"; - private const string ServerReverseDir = @"Templates\xray\server\09_reverse"; - private const string CaddyFileDir = @"Templates\xray\caddy"; - - public XrayProject(SshClient sshClient, XraySettings parameters, Action writeOutput) : base(sshClient, parameters, writeOutput) - { - } - - /// - /// 安装Xray - /// - public override void Install() - { - try - { - EnsureRootAuth(); - - if (FileExists("/usr/local/bin/xray")) - { - var btnResult = MessageBox.Show("已经安装Xray,是否需要重装?", "提示", MessageBoxButton.YesNo); - if (btnResult == MessageBoxResult.No) - { - MessageBox.Show("安装终止", "提示"); - return; - } - } - - WriteOutput("检测安装系统环境..."); - EnsureSystemEnv(); - WriteOutput("检测安装系统环境完成"); - - WriteOutput("安装必要的系统工具..."); - ConfigureSoftware(); - WriteOutput("系统工具安装完成"); - - WriteOutput("配置防火墙..."); - ConfigFirewalld(); - WriteOutput("防火墙配置完成"); - - WriteOutput("检测网络环境"); - EnsureIP(); - WriteOutput("检测网络环境完成"); - - WriteOutput("同步系统和本地时间..."); - SyncTimeDiff(); - WriteOutput("时间同步完成"); - - if (!Parameters.IsIPAddress) - { - WriteOutput("检测域名是否绑定本机IP..."); - ValidateDomain(); - WriteOutput("域名检测完成"); - } - - WriteOutput("安装Caddy..."); - InstallCaddy(); - WriteOutput("Caddy安装完成"); - - WriteOutput("安装Xray-Core..."); - InstallXrayWithCert(); - WriteOutput("Xray-Core安装完成"); - - WriteOutput("启动BBR"); - EnableBBR(); - - UploadCaddyFile(); - WriteOutput("************"); - WriteOutput("安装完成,尽情享用吧......"); - WriteOutput("************"); - } - catch (Exception ex) - { - var errorLog = "安装终止," + ex.Message; - WriteOutput(errorLog); - MessageBox.Show("安装失败,请联系开发者或上传日志文件(Logs文件夹下)到github提问。"); - } - } - - public void UninstallProxy() - { - EnsureRootAuth(); - EnsureSystemEnv(); - WriteOutput("卸载Caddy"); - UninstallCaddy(); - WriteOutput("卸载Xray"); - UninstallXray(); - WriteOutput("卸载证书"); - UninstallAcme(); - WriteOutput("关闭端口"); - ResetFirewalld(); - - WriteOutput("************ 卸载完成 ************"); - } - - /// - /// 更新xray内核 - /// - public void UpdateXrayCore() - { - EnsureRootAuth(); - EnsureSystemEnv(); - RunCmd("bash -c \"$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)\" @ install"); - RunCmd("systemctl restart xray"); - WriteOutput("************ 更新xray内核完成 ************"); - } - - /// - /// 更新xray配置 - /// - public void UpdateXraySettings() - { - EnsureRootAuth(); - EnsureSystemEnv(); - - 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"); - - UploadCaddyFile(string.IsNullOrEmpty(Parameters.MaskDomain)); - RunCmd("systemctl restart xray"); - WriteOutput("************ 更新Xray配置成功,更新配置不包含域名,如果域名更换请重新安装。 ************"); - } - - /// - /// 重装Caddy - /// - public void DoUninstallCaddy() - { - EnsureRootAuth(); - EnsureSystemEnv(); - UninstallCaddy(); - WriteOutput("************ 卸载Caddy完成 ************"); - } - - /// - /// 安装证书 - /// - public void InstallCertToXray(bool restartXray = false) - { - EnsureRootAuth(); - EnsureSystemEnv(); - InstallCert( - dirPath: "/usr/local/etc/xray/ssl", - certName: "xray_ssl.crt", - keyName: "xray_ssl.key"); - - WriteOutput("************ 安装证书完成 ************"); - RunCmd("systemctl restart xray"); - } - - /// - /// 上传证书 - /// - /// - /// - public void UploadCert(Stream stream) - { - EnsureRootAuth(); - EnsureSystemEnv(); - - // 转移旧文件 - var oldFileName = $"ssl_{DateTime.Now.Ticks}"; - RunCmd($"mv /usr/local/etc/xray/ssl /usr/local/etc/xray/{oldFileName}"); - - // 上传新文件 - RunCmd("mkdir /usr/local/etc/xray/ssl"); - UploadFile(stream, "/usr/local/etc/xray/ssl/ssl.zip"); - RunCmd("unzip /usr/local/etc/xray/ssl/ssl.zip -d /usr/local/etc/xray/ssl"); - - // 改名 - var crtFiles = RunCmd("find /usr/local/etc/xray/ssl/*.crt").Split("\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); - if (crtFiles.Length > 0) - { - RunCmd($"mv {crtFiles[0]} /usr/local/etc/xray/ssl/xray_ssl.crt"); - } - else - { - WriteOutput("************ 上传证书失败,请联系开发者 ************"); - RunCmd("rm -rf /usr/local/etc/xray/ssl"); - RunCmd($"mv /usr/local/etc/xray/ssl{oldFileName} /usr/local/etc/xray/ssl"); - WriteOutput("操作已回滚"); - return; - } - - var keyFiles = RunCmd("find /usr/local/etc/xray/ssl/*.key").Split("\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); - if (keyFiles.Length > 0) - { - RunCmd($"mv {keyFiles[0]} /usr/local/etc/xray/ssl/xray_ssl.key"); - } - else - { - WriteOutput("************ 上传证书失败,请联系开发者 ************"); - RunCmd("rm -rf /usr/local/etc/xray/ssl"); - RunCmd($"mv /usr/local/etc/xray/ssl{oldFileName} /usr/local/etc/xray/ssl"); - WriteOutput("操作已回滚"); - return; - } - - RunCmd("systemctl restart xray"); - WriteOutput("************ 上传证书完成 ************"); - } - - /// - /// 上传静态网站 - /// - /// - public void UploadWeb(Stream stream) - { - EnsureRootAuth(); - EnsureSystemEnv(); - if (!FileExists("/usr/share/caddy")) - { - RunCmd("mkdir /usr/share/caddy"); - } - RunCmd("rm -rf /usr/share/caddy/*"); - UploadFile(stream, "/usr/share/caddy/caddy.zip"); - RunCmd("unzip /usr/share/caddy/caddy.zip -d /usr/share/caddy"); - RunCmd("chmod -R 777 /usr/share/caddy"); - UploadCaddyFile(useCustomWeb: true); - WriteOutput("************ 上传网站模板完成 ************"); - } - - /// - /// 上传Caddy文件 - /// - /// - private void UploadCaddyFile(bool useCustomWeb = false) - { - var configJson = XrayConfigBuilder.BuildCaddyConfig(Parameters, useCustomWeb); - - if (FileExists("/etc/caddy/Caddyfile")) - { - RunCmd("mv /etc/caddy/Caddyfile /etc/caddy/Caddyfile.back"); - } - WriteToFile(configJson, "/etc/caddy/Caddyfile"); - RunCmd("systemctl restart caddy"); - } - - - - private void UninstallXray() - { - RunCmd("bash -c \"$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)\" @ remove"); - } - - private void UninstallAcme() - { - RunCmd("acme.sh --uninstall"); - RunCmd("rm -r ~/.acme.sh"); - } - - private void InstallXrayWithCert() - { - RunCmd("bash -c \"$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)\" @ install"); - - if (!FileExists("/usr/local/bin/xray")) - { - WriteOutput("Xray-Core安装失败,请联系开发者"); - throw new Exception("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"); - } - - if (!Parameters.IsIPAddress) - { - WriteOutput("安装TLS证书"); - InstallCertToXray(); - WriteOutput("TLS证书安装完成"); - } - - var configJson = XrayConfigBuilder.BuildXrayConfig(Parameters); - WriteToFile(configJson, "/usr/local/etc/xray/config.json"); - RunCmd("systemctl restart xray"); - } - - private int GetRandomPort() - { - var random = new Random(); - return random.Next(10001, 60000); - } - - private dynamic LoadJsonObj(string path) - { - if (File.Exists(path)) - { - var jsonStr = File.ReadAllText(path, Encoding.UTF8); - return JsonConvert.DeserializeObject(jsonStr); - } - return null; - } - - } -} diff --git a/ProxySuper.Core/Services/XrayService.cs b/ProxySuper.Core/Services/XrayService.cs index 6a14ed1..7df4d7b 100644 --- a/ProxySuper.Core/Services/XrayService.cs +++ b/ProxySuper.Core/Services/XrayService.cs @@ -85,6 +85,11 @@ namespace ProxySuper.Core.Services Progress.Percentage = 100; Progress.Step = "安装成功"; Progress.Desc = string.Empty; + + if (!Settings.WithTLS) + { + Progress.Step = "安装成功,请上传您的 TLS 证书。"; + } } catch (Exception ex) { @@ -379,7 +384,7 @@ namespace ProxySuper.Core.Services } Progress.Percentage = 60; - if (!Settings.IsIPAddress) + if (Settings.WithTLS && !Settings.IsIPAddress) { Progress.Desc = ("安装TLS证书"); InstallCert( diff --git a/ProxySuper.Core/ViewModels/BrookEditorViewModel.cs b/ProxySuper.Core/ViewModels/BrookEditorViewModel.cs index 9960068..29ef9e5 100644 --- a/ProxySuper.Core/ViewModels/BrookEditorViewModel.cs +++ b/ProxySuper.Core/ViewModels/BrookEditorViewModel.cs @@ -67,6 +67,8 @@ namespace ProxySuper.Core.ViewModels public IMvxCommand SaveCommand => new MvxCommand(() => Save()); + public IMvxCommand SaveAndInstallCommand => new MvxCommand(SaveAndInstall); + public override void Prepare(Record parameter) { var record = Utils.DeepClone(parameter); @@ -84,5 +86,17 @@ namespace ProxySuper.Core.ViewModels BrookSettings = Settings, }); } + + private void SaveAndInstall() + { + var record = new Record + { + Id = this.Id, + Host = this.Host, + BrookSettings = Settings, + }; + NavigationService.Close(this, record); + NavigationService.Navigate(record); + } } } diff --git a/ProxySuper.Core/ViewModels/BrookInstallerViewModel.cs b/ProxySuper.Core/ViewModels/BrookInstallerViewModel.cs deleted file mode 100644 index 10e4084..0000000 --- a/ProxySuper.Core/ViewModels/BrookInstallerViewModel.cs +++ /dev/null @@ -1,39 +0,0 @@ -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/NaiveProxyEditorViewModel.cs b/ProxySuper.Core/ViewModels/NaiveProxyEditorViewModel.cs index 0dda929..cb131e4 100644 --- a/ProxySuper.Core/ViewModels/NaiveProxyEditorViewModel.cs +++ b/ProxySuper.Core/ViewModels/NaiveProxyEditorViewModel.cs @@ -35,6 +35,8 @@ namespace ProxySuper.Core.ViewModels public IMvxCommand SaveCommand => new MvxCommand(Save); + public IMvxCommand SaveAndInstallCommand => new MvxCommand(SaveAndInstall); + private void Save() { NavigationService.Close(this, new Record @@ -44,5 +46,18 @@ namespace ProxySuper.Core.ViewModels NaiveProxySettings = Settings }); } + + + private void SaveAndInstall() + { + var record = new Record + { + Id = this.Id, + Host = this.Host, + NaiveProxySettings = Settings, + }; + NavigationService.Close(this, record); + NavigationService.Navigate(record); + } } } diff --git a/ProxySuper.Core/ViewModels/NaiveProxyInstallerViewModel.cs b/ProxySuper.Core/ViewModels/NaiveProxyInstallerViewModel.cs deleted file mode 100644 index 35381cf..0000000 --- a/ProxySuper.Core/ViewModels/NaiveProxyInstallerViewModel.cs +++ /dev/null @@ -1,39 +0,0 @@ -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 NaiveProxyInstallerViewModel : MvxViewModel - { - public Host Host { get; set; } - - public NaiveProxySettings Settings { get; set; } - - public override void Prepare(Record parameter) - { - var record = Utils.DeepClone(parameter); - Host = record.Host; - Settings = record.NaiveProxySettings; - } - - 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/TrojanGoEditorViewModel.cs b/ProxySuper.Core/ViewModels/TrojanGoEditorViewModel.cs index 4e52497..737e9b0 100644 --- a/ProxySuper.Core/ViewModels/TrojanGoEditorViewModel.cs +++ b/ProxySuper.Core/ViewModels/TrojanGoEditorViewModel.cs @@ -19,6 +19,8 @@ namespace ProxySuper.Core.ViewModels public IMvxCommand SaveCommand => new MvxCommand(Save); + public IMvxCommand SaveAndInstallCommand => new MvxCommand(SaveAndInstall); + public string Id { get; set; } public Host Host { get; set; } @@ -43,6 +45,18 @@ namespace ProxySuper.Core.ViewModels TrojanGoSettings = Settings, }); } + + private void SaveAndInstall() + { + var record = new Record + { + Id = this.Id, + Host = this.Host, + TrojanGoSettings = Settings, + }; + NavigationService.Close(this, record); + NavigationService.Navigate(record); + } } diff --git a/ProxySuper.Core/ViewModels/TrojanGoInstallerViewModel.cs b/ProxySuper.Core/ViewModels/TrojanGoInstallerViewModel.cs deleted file mode 100644 index 41ee15a..0000000 --- a/ProxySuper.Core/ViewModels/TrojanGoInstallerViewModel.cs +++ /dev/null @@ -1,40 +0,0 @@ -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 TrojanGoInstallerViewModel : MvxViewModel - { - public Host Host { get; set; } - - public TrojanGoSettings Settings { get; set; } - - public override void Prepare(Record parameter) - { - var record = Utils.DeepClone(parameter); - Host = record.Host; - Settings = record.TrojanGoSettings; - } - - 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/XrayEditorViewModel.cs b/ProxySuper.Core/ViewModels/XrayEditorViewModel.cs index 66dab9b..b90580d 100644 --- a/ProxySuper.Core/ViewModels/XrayEditorViewModel.cs +++ b/ProxySuper.Core/ViewModels/XrayEditorViewModel.cs @@ -67,6 +67,15 @@ namespace ProxySuper.Core.ViewModels { public IMvxCommand RandomUuid => new MvxCommand(() => GetUuid()); + public bool WithTLS + { + get => Settings.WithTLS; + set + { + Settings.WithTLS = value; + RaisePropertyChanged("Port"); + } + } public int Port { diff --git a/ProxySuper.Core/ViewModels/XrayInstallerViewModel.cs b/ProxySuper.Core/ViewModels/XrayInstallerViewModel.cs deleted file mode 100644 index 48597cd..0000000 --- a/ProxySuper.Core/ViewModels/XrayInstallerViewModel.cs +++ /dev/null @@ -1,40 +0,0 @@ -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 XrayInstallerViewModel : MvxViewModel - { - - public Host Host { get; set; } - - public XraySettings Settings { get; set; } - - public override void Prepare(Record parameter) - { - var record = Utils.DeepClone(parameter); - Host = record.Host; - Settings = record.XraySettings; - } - - - private bool _connected; - public bool Connected - { - get - { - return _connected; - } - set - { - _connected = value; - RaisePropertyChanged("Connected"); - } - } - - public string CommandText { get; set; } - } -} diff --git a/ProxySuper.WPF/Controls/XraySettingsControl.xaml b/ProxySuper.WPF/Controls/XraySettingsControl.xaml index baaeb96..236503a 100644 --- a/ProxySuper.WPF/Controls/XraySettingsControl.xaml +++ b/ProxySuper.WPF/Controls/XraySettingsControl.xaml @@ -106,6 +106,15 @@ + + + diff --git a/ProxySuper.WPF/ProxySuper.WPF.csproj b/ProxySuper.WPF/ProxySuper.WPF.csproj index 3566273..09946b5 100644 --- a/ProxySuper.WPF/ProxySuper.WPF.csproj +++ b/ProxySuper.WPF/ProxySuper.WPF.csproj @@ -123,9 +123,6 @@ BrookEditorView.xaml - - BrookInstallerView.xaml - BrookInstallView.xaml @@ -141,9 +138,6 @@ NaiveProxyEditorView.xaml - - NaiveProxyInstallerView.xaml - NaiveProxyInstallView.xaml @@ -156,9 +150,6 @@ TrojanGoEditorView.xaml - - TrojanGoInstallerView.xaml - TrojanGoInstallView.xaml @@ -168,9 +159,6 @@ XrayConfigView.xaml - - XrayInstallerView.xaml - XrayInstallView.xaml @@ -243,10 +231,6 @@ Designer MSBuild:Compile - - Designer - MSBuild:Compile - Designer MSBuild:Compile @@ -286,10 +270,6 @@ Designer MSBuild:Compile - - Designer - MSBuild:Compile - Designer MSBuild:Compile @@ -306,10 +286,6 @@ Designer MSBuild:Compile - - Designer - MSBuild:Compile - Designer MSBuild:Compile @@ -322,10 +298,6 @@ Designer MSBuild:Compile - - Designer - MSBuild:Compile - Designer MSBuild:Compile diff --git a/ProxySuper.WPF/Resources/Languages/en.xaml b/ProxySuper.WPF/Resources/Languages/en.xaml index 72caa31..60e0d61 100644 --- a/ProxySuper.WPF/Resources/Languages/en.xaml +++ b/ProxySuper.WPF/Resources/Languages/en.xaml @@ -76,6 +76,8 @@ Domain/IP Redir Url + With TLS + Unchecked means upload your own TLS. UUID Multi User Multi Id split with "," @@ -105,8 +107,10 @@ InstallCert UploadWeb UploadCert - + + With TLS + Unchecked means upload your own TLS. Address Port Password diff --git a/ProxySuper.WPF/Resources/Languages/tw_cn.xaml b/ProxySuper.WPF/Resources/Languages/tw_cn.xaml index abc5371..5e150cf 100644 --- a/ProxySuper.WPF/Resources/Languages/tw_cn.xaml +++ b/ProxySuper.WPF/Resources/Languages/tw_cn.xaml @@ -75,6 +75,8 @@ 域名/IP 偽裝網址 + 自動申請證書 + 如上傳自有證書,則取消對勾。 UUID 多用戶 多個UUID用“,”分隔 @@ -107,6 +109,8 @@ + 自動申請證書 + 如上傳自有證書,則取消對勾。 域名 端口 密碼 diff --git a/ProxySuper.WPF/Resources/Languages/zh_cn.xaml b/ProxySuper.WPF/Resources/Languages/zh_cn.xaml index 7b39651..74886e7 100644 --- a/ProxySuper.WPF/Resources/Languages/zh_cn.xaml +++ b/ProxySuper.WPF/Resources/Languages/zh_cn.xaml @@ -76,6 +76,8 @@ 域名/IP 伪装网址 + 自动申请证书 + 如上传自有证书,则取消对勾。 UUID 多用户 多个UUID用“,”分隔 @@ -108,6 +110,8 @@ + 自动申请证书 + 如上传自有证书,则取消对勾。 域名 端口 密码 diff --git a/ProxySuper.WPF/Views/Brook/BrookEditorView.xaml b/ProxySuper.WPF/Views/Brook/BrookEditorView.xaml index 52862f2..dacf2ed 100644 --- a/ProxySuper.WPF/Views/Brook/BrookEditorView.xaml +++ b/ProxySuper.WPF/Views/Brook/BrookEditorView.xaml @@ -60,15 +60,24 @@