From e18a6fbd0c3dfbf4eaaebd882f3b7959800cb2c4 Mon Sep 17 00:00:00 2001 From: ProxySU Date: Thu, 20 Aug 2020 20:07:37 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=BAV2Ray\Trojan\Trojan-go=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=AE=89=E8=A3=85=E8=BF=87=E7=A8=8B=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E7=AA=97=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ProxySU/MainWindow.xaml | 3 +- ProxySU/MainWindow.xaml.cs | 3874 +++++++++++++++---- ProxySU/Properties/AssemblyInfo.cs | 4 +- ProxySU/bin/Beta/Beta.zip | Bin 496729 -> 497795 bytes TemplateConfg/trojan_caddy_config.caddyfile | 5 +- TemplateConfg/trojan_server_config.json | 2 +- 6 files changed, 3188 insertions(+), 700 deletions(-) diff --git a/ProxySU/MainWindow.xaml b/ProxySU/MainWindow.xaml index 8605dea..c1a6a93 100644 --- a/ProxySU/MainWindow.xaml +++ b/ProxySU/MainWindow.xaml @@ -317,7 +317,6 @@ - @@ -412,7 +411,7 @@ - + diff --git a/ProxySU/MainWindow.xaml.cs b/ProxySU/MainWindow.xaml.cs index a0da549..7c28837 100644 --- a/ProxySU/MainWindow.xaml.cs +++ b/ProxySU/MainWindow.xaml.cs @@ -46,13 +46,9 @@ namespace ProxySU //public static ConnectionInfo ConnectionInfo; static bool testDomain = false; //设置标识--域名是否需要检测解析,初始化为不需要 static string sshShellCommand;//定义保存执行的命令 - //sshShellCommand = ; - //TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 - static string currentShellCommandResult;//定义Shell命令执行结果保存变量 - //currentShellCommandResult = ; - //TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - + static string sshCmdUpdate;//保存软件安装所用更新软件库命令 + static string sshCmdInstall;//保存软件安装所用命令格式 public MainWindow() { @@ -469,6 +465,8 @@ namespace ProxySU { string currentStatus = "正在登录远程主机......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 try { @@ -507,23 +505,54 @@ namespace ProxySU { currentStatus = "主机登录成功"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果在监视窗口 Thread.Sleep(1000); } //检测是否运行在root权限下 - string testRootAuthority = client.RunCommand(@"id -u").Result; - if (testRootAuthority.Equals("0\n")==false) + currentShellCommandResult = "检测是否运行在root权限下..."; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"id -u"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string testRootAuthority = currentShellCommandResult; + if (testRootAuthority.Equals("0\n") == false) { MessageBox.Show("请使用具有root权限的账户登录主机!!"); client.Disconnect(); return; } + else + { + currentShellCommandResult = "检测结果:OK!"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + //string testRootAuthority = client.RunCommand(@"id -u").Result; + //if (testRootAuthority.Equals("0\n")==false) + //{ + // MessageBox.Show("请使用具有root权限的账户登录主机!!"); + // client.Disconnect(); + // return; + //} //检测是否安装有V2ray currentStatus = "检测系统是否已经安装V2ray......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - string cmdTestV2rayInstalled = @"find / -name v2ray"; - string resultCmdTestV2rayInstalled = client.RunCommand(cmdTestV2rayInstalled).Result; + //string cmdTestV2rayInstalled = @"find / -name v2ray"; + sshShellCommand = @"find / -name v2ray"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string resultCmdTestV2rayInstalled = currentShellCommandResult; if (resultCmdTestV2rayInstalled.Contains("/usr/bin/v2ray") == true || resultCmdTestV2rayInstalled.Contains("/usr/local/bin/v2ray") == true) { MessageBoxResult messageBoxResult = MessageBox.Show("远程主机已安装V2ray,是否强制重新安装?", "", MessageBoxButton.YesNo, MessageBoxImage.Question); @@ -531,18 +560,45 @@ namespace ProxySU { currentStatus = "安装取消,退出"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); client.Disconnect(); return; } + else + { + currentStatus = "已选择强制安装V2Ray!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); + } + } + else + { + currentShellCommandResult = "检测结果:未安装V2Ray!"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } //检测远程主机系统环境是否符合要求 currentStatus = "检测系统是否符合安装要求......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - string result = client.RunCommand("uname -r").Result; + //string result = client.RunCommand("uname -r").Result; + sshShellCommand = @"uname -r"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + string result = currentShellCommandResult; string[] linuxKernelVerStr= result.Split('-'); bool detectResult = DetectKernelVersion(linuxKernelVerStr[0]); @@ -551,17 +607,57 @@ namespace ProxySU MessageBox.Show($"当前系统内核版本为{linuxKernelVerStr[0]},V2ray要求内核为2.6.23及以上。请升级内核再安装!"); currentStatus = "系统内核版本不符合要求,安装失败!!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); } //检测系统是否支持yum 或 apt-get或zypper,且支持Systemd //如果不存在组件,则命令结果为空,string.IsNullOrEmpty值为真, - bool getApt = String.IsNullOrEmpty(client.RunCommand("command -v apt").Result); - bool getDnf = String.IsNullOrEmpty(client.RunCommand("command -v dnf").Result); - bool getYum = String.IsNullOrEmpty(client.RunCommand("command -v yum").Result); - bool getZypper = String.IsNullOrEmpty(client.RunCommand("command -v zypper").Result); - bool getSystemd = String.IsNullOrEmpty(client.RunCommand("command -v systemctl").Result); - bool getGetenforce = String.IsNullOrEmpty(client.RunCommand("command -v getenforce").Result); + //bool getApt = String.IsNullOrEmpty(client.RunCommand("command -v apt").Result); + //bool getDnf = String.IsNullOrEmpty(client.RunCommand("command -v dnf").Result); + //bool getYum = String.IsNullOrEmpty(client.RunCommand("command -v yum").Result); + //bool getZypper = String.IsNullOrEmpty(client.RunCommand("command -v zypper").Result); + //bool getSystemd = String.IsNullOrEmpty(client.RunCommand("command -v systemctl").Result); + //bool getGetenforce = String.IsNullOrEmpty(client.RunCommand("command -v getenforce").Result); + + sshShellCommand = @"command -v apt"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + bool getApt = String.IsNullOrEmpty(currentShellCommandResult); + + sshShellCommand = @"command -v dnf"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + bool getDnf = String.IsNullOrEmpty(currentShellCommandResult); + + sshShellCommand = @"command -v yum"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + bool getYum = String.IsNullOrEmpty(currentShellCommandResult); + + sshShellCommand = @"command -v zypper"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + bool getZypper = String.IsNullOrEmpty(currentShellCommandResult); + + sshShellCommand = @"command -v systemctl"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + bool getSystemd = String.IsNullOrEmpty(currentShellCommandResult); + + sshShellCommand = @"command -v getenforce"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + bool getGetenforce = String.IsNullOrEmpty(currentShellCommandResult); + //没有安装apt,也没有安装dnf\yum,也没有安装zypper,或者没有安装systemd的,不满足安装条件 //也就是apt ,dnf\yum, zypper必须安装其中之一,且必须安装Systemd的系统才能安装。 @@ -570,50 +666,168 @@ namespace ProxySU MessageBox.Show($"系统缺乏必要的安装组件如:apt||dnf||yum||zypper||Syetemd,主机系统推荐使用:CentOS 7/8,Debian 8/9/10,Ubuntu 16.04及以上版本"); currentStatus = "系统环境不满足要求,安装失败!!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 Thread.Sleep(1000); client.Disconnect(); return; } - //在相应系统内安装curl(如果没有安装curl) + else + { + currentStatus = "检测结果:OK!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + + //设置安装软件所用的命令格式 + if (getApt == false) + { + //client.RunCommand("apt -qq update"); + //client.RunCommand("apt -y -qq install curl"); + sshCmdUpdate = @"apt -qq update"; + sshCmdInstall = @"apt -y -qq install "; + } + else if (getDnf == false) + { + //client.RunCommand("dnf -q makecache"); + //client.RunCommand("dnf -y -q install curl"); + sshCmdUpdate = @"dnf -q makecache"; + sshCmdInstall = @"dnf -y -q install "; + } + else if (getYum == false) + { + //client.RunCommand("yum -q makecache"); + //client.RunCommand("yum -y -q install curl"); + sshCmdUpdate = @"yum -q makecache"; + sshCmdInstall = @"yum -y -q install "; + } + else if (getZypper == false) + { + //client.RunCommand("zypper ref"); + //client.RunCommand("zypper -y install curl"); + sshCmdUpdate = @"zypper ref"; + sshCmdInstall = @"zypper -y install "; + } + + //判断是否启用了SELinux,如果启用了,并且工作在Enforcing模式下,则改为Permissive模式 + if (getGetenforce == false) + { + //string testSELinux = client.RunCommand("getenforce").Result; + sshShellCommand = @"getenforce"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string testSELinux = currentShellCommandResult; + + if (testSELinux.Contains("Enforcing") == true) + { + currentStatus = "检测到系统启用SELinux,且工作在严格模式下,需改为宽松模式!修改中..."; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + //MessageBox.Show("Enforcing"); + //client.RunCommand("setenforce 0");//不重启改为Permissive模式 + //client.RunCommand("sed -i 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config");//重启也工作在Permissive模式下 + sshShellCommand = @"setenforce 0"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + sshShellCommand = @"sed -i 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + currentStatus = "修改完毕!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + + } + //在相应系统内安装curl(如果没有安装curl)--此为依赖软件 if (string.IsNullOrEmpty(client.RunCommand("command -v curl").Result) == true) { + sshShellCommand = $"{sshCmdUpdate}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"{sshCmdInstall}curl"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + //为假则表示系统有相应的组件。 - if (getApt == false) - { - client.RunCommand("apt -qq update"); - client.RunCommand("apt -y -qq install curl"); - } - else if (getDnf == false) - { - client.RunCommand("dnf -q makecache"); - client.RunCommand("dnf -y -q install curl"); - } - else if (getYum == false) - { - client.RunCommand("yum -q makecache"); - client.RunCommand("yum -y -q install curl"); - } + //if (getApt == false) + //{ + // client.RunCommand("apt -qq update"); + // client.RunCommand("apt -y -qq install curl"); + //} + //else if (getDnf == false) + //{ + // client.RunCommand("dnf -q makecache"); + // client.RunCommand("dnf -y -q install curl"); + //} + //else if (getYum == false) + //{ + // client.RunCommand("yum -q makecache"); + // client.RunCommand("yum -y -q install curl"); + //} //else if (getZypper == false) //{ // client.RunCommand("zypper ref"); // client.RunCommand("zypper -y install curl"); //} } + ////在相应系统内安装curl(如果没有安装curl) + //if (string.IsNullOrEmpty(client.RunCommand("command -v curl").Result) == true) + //{ + // //为假则表示系统有相应的组件。 + // if (getApt == false) + // { + // client.RunCommand("apt -qq update"); + // client.RunCommand("apt -y -qq install curl"); + // } + // else if (getDnf == false) + // { + // client.RunCommand("dnf -q makecache"); + // client.RunCommand("dnf -y -q install curl"); + // } + // else if (getYum == false) + // { + // client.RunCommand("yum -q makecache"); + // client.RunCommand("yum -y -q install curl"); + // } + // //else if (getZypper == false) + // //{ + // // client.RunCommand("zypper ref"); + // // client.RunCommand("zypper -y install curl"); + // //} + //} - //判断是否启用了SELinux,如果启用了,并且工作在Enforcing模式下,则改为Permissive模式 - if (getGetenforce == false) - { - string testSELinux = client.RunCommand("getenforce").Result; - if (testSELinux.Contains("Enforcing")==true) - { - client.RunCommand("setenforce 0");//不重启改为Permissive模式 - client.RunCommand("sed -i 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config");//重启也工作在Permissive模式下 - } - } + ////判断是否启用了SELinux,如果启用了,并且工作在Enforcing模式下,则改为Permissive模式 + //if (getGetenforce == false) + //{ + // string testSELinux = client.RunCommand("getenforce").Result; + // if (testSELinux.Contains("Enforcing")==true) + // { + // client.RunCommand("setenforce 0");//不重启改为Permissive模式 + // client.RunCommand("sed -i 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config");//重启也工作在Permissive模式下 + // } + //} //校对时间 currentStatus = "校对时间......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); //获取远程主机的时间戳 long timeStampVPS = Convert.ToInt64(client.RunCommand("date +%s").Result.ToString()); @@ -627,78 +841,134 @@ namespace ProxySU MessageBox.Show("本地时间与远程主机时间相差超过限制(90秒),请先用\"系统工具-->时间校对\"校对时间后再设置"); currentStatus = "时间较对失败......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); client.Disconnect(); return; } + currentStatus = "时间差符合要求,OK!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + //如果使用是WebSocket + TLS + Web/http2/Http2Web/tcp_TLS/WebSocket_TLS模式,需要检测域名解析是否正确 if (testDomain == true) { currentStatus = "正在检测域名是否解析到当前VPS的IP上......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - - string nativeIp = client.RunCommand("curl -4 ip.sb").Result.ToString(); - string testDomainCmd = "ping " + ReceiveConfigurationParameters[4] + " -c 1 | grep -oE -m1 \"([0-9]{1,3}\\.){3}[0-9]{1,3}\""; - string resultCmd = client.RunCommand(testDomainCmd).Result.ToString(); + //string nativeIp = client.RunCommand("curl -4 ip.sb").Result.ToString(); + //string testDomainCmd = "ping " + ReceiveConfigurationParameters[4] + " -c 1 | grep -oE -m1 \"([0-9]{1,3}\\.){3}[0-9]{1,3}\""; + //string resultCmd = client.RunCommand(testDomainCmd).Result.ToString(); - if (String.Equals(nativeIp, resultCmd) == true) + sshShellCommand = @"curl -4 ip.sb"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string nativeIp = currentShellCommandResult; + + sshShellCommand = "ping " + ReceiveConfigurationParameters[4] + " -c 1 | grep -oE -m1 \"([0-9]{1,3}\\.){3}[0-9]{1,3}\""; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string resultTestDomainCmd = currentShellCommandResult; + + if (String.Equals(nativeIp, resultTestDomainCmd) == true) { currentStatus = "解析正确!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); } else { currentStatus = "域名未能正确解析到当前VPS的IP上!安装失败!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); MessageBox.Show("域名未能正确解析到当前VPS的IP上,请检查!若解析设置正确,请等待生效后再重试安装。如果域名使用了CDN,请先关闭!"); client.Disconnect(); return; } - - } - if (testDomain == true) { + //检测是否安装lsof if (string.IsNullOrEmpty(client.RunCommand("command -v lsof").Result) == true) { + sshShellCommand = $"{sshCmdUpdate}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"{sshCmdInstall}lsof"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + //为假则表示系统有相应的组件。 - if (getApt == false) - { - client.RunCommand("apt -qq update"); - client.RunCommand("apt -y -qq install lsof"); - } - else if (getDnf == false) - { - client.RunCommand("dnf -q makecache"); - client.RunCommand("dnf -y -q install lsof"); - } - else if (getYum == false) - { - client.RunCommand("yum -q makecache"); - client.RunCommand("yum -y -q install lsof"); - } - //else if (getZypper == false) - //{ - // client.RunCommand("zypper ref"); - // client.RunCommand("zypper -y install lsof"); - //} + //if (getApt == false) + // { + // client.RunCommand("apt -qq update"); + // client.RunCommand("apt -y -qq install lsof"); + // } + // else if (getDnf == false) + // { + // client.RunCommand("dnf -q makecache"); + // client.RunCommand("dnf -y -q install lsof"); + // } + // else if (getYum == false) + // { + // client.RunCommand("yum -q makecache"); + // client.RunCommand("yum -y -q install lsof"); + // } + //else if (getZypper == false) + //{ + // client.RunCommand("zypper ref"); + // client.RunCommand("zypper -y install lsof"); + //} } currentStatus = "正在检测端口占用情况......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - - if (String.IsNullOrEmpty(client.RunCommand(@"lsof -n -P -i :80 | grep LISTEN").Result) == false || String.IsNullOrEmpty(client.RunCommand(@"lsof -n -P -i :443 | grep LISTEN").Result) == false) + + sshShellCommand = @"lsof -n -P -i :80 | grep LISTEN"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + string testPort80 = currentShellCommandResult; + + sshShellCommand = @"lsof -n -P -i :443 | grep LISTEN"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + string testPort443 = currentShellCommandResult; + + + if (String.IsNullOrEmpty(testPort80) == false || String.IsNullOrEmpty(testPort443) == false) { - //MessageBox.Show("80/443端口之一,或全部被占用,请先用系统工具中的“释放80/443端口”工具,释放出,再重新安装"); MessageBoxResult dialogResult = MessageBox.Show("80/443端口之一,或全部被占用,将强制停止占用80/443端口的程序?", "Stop application", MessageBoxButton.YesNo); if (dialogResult == MessageBoxResult.No) { currentStatus = "端口被占用,安装失败......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); client.Disconnect(); return; @@ -706,42 +976,254 @@ namespace ProxySU currentStatus = "正在释放80/443端口......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - string cmdTestPort = @"lsof -n -P -i :443 | grep LISTEN"; - string cmdResult = client.RunCommand(cmdTestPort).Result; - if (String.IsNullOrEmpty(cmdResult) == false) + //string cmdTestPort = @"lsof -n -P -i :443 | grep LISTEN"; + //string cmdResult = client.RunCommand(cmdTestPort).Result; + + if (String.IsNullOrEmpty(testPort443) == false) { - string[] cmdResultArry443 = cmdResult.Split(' '); - client.RunCommand($"systemctl stop {cmdResultArry443[0]}"); - client.RunCommand($"systemctl disable {cmdResultArry443[0]}"); - client.RunCommand($"kill -9 {cmdResultArry443[3]}"); + string[] cmdResultArry443 = testPort443.Split(' '); + //client.RunCommand($"systemctl stop {cmdResultArry443[0]}"); + //client.RunCommand($"systemctl disable {cmdResultArry443[0]}"); + //client.RunCommand($"kill -9 {cmdResultArry443[3]}"); + sshShellCommand = $"systemctl stop {cmdResultArry443[0]}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"systemctl disable {cmdResultArry443[0]}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"kill -9 {cmdResultArry443[3]}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } - cmdTestPort = @"lsof -n -P -i :80 | grep LISTEN"; - cmdResult = client.RunCommand(cmdTestPort).Result; - if (String.IsNullOrEmpty(cmdResult) == false) + //cmdTestPort = @"lsof -n -P -i :80 | grep LISTEN"; + //cmdResult = client.RunCommand(cmdTestPort).Result; + if (String.IsNullOrEmpty(testPort80) == false) { - string[] cmdResultArry80 = cmdResult.Split(' '); - client.RunCommand($"systemctl stop {cmdResultArry80[0]}"); - client.RunCommand($"systemctl disable {cmdResultArry80[0]}"); - client.RunCommand($"kill -9 {cmdResultArry80[3]}"); + string[] cmdResultArry80 = testPort80.Split(' '); + //client.RunCommand($"systemctl stop {cmdResultArry80[0]}"); + //client.RunCommand($"systemctl disable {cmdResultArry80[0]}"); + //client.RunCommand($"kill -9 {cmdResultArry80[3]}"); + sshShellCommand = $"systemctl stop {cmdResultArry80[0]}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"systemctl disable {cmdResultArry80[0]}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"kill -9 {cmdResultArry80[3]}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } currentStatus = "80/443端口释放完毕!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); + } + else + { + currentStatus = "检测结果:未被占用!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + + //if (String.IsNullOrEmpty(client.RunCommand(@"lsof -n -P -i :80 | grep LISTEN").Result) == false || String.IsNullOrEmpty(client.RunCommand(@"lsof -n -P -i :443 | grep LISTEN").Result) == false) + //{ + // //MessageBox.Show("80/443端口之一,或全部被占用,请先用系统工具中的“释放80/443端口”工具,释放出,再重新安装"); + // MessageBoxResult dialogResult = MessageBox.Show("80/443端口之一,或全部被占用,将强制停止占用80/443端口的程序?", "Stop application", MessageBoxButton.YesNo); + // if (dialogResult == MessageBoxResult.No) + // { + // currentStatus = "端口被占用,安装失败......"; + // textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + // Thread.Sleep(1000); + // client.Disconnect(); + // return; + // } + + // currentStatus = "正在释放80/443端口......"; + // textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + // Thread.Sleep(1000); + + // string cmdTestPort = @"lsof -n -P -i :443 | grep LISTEN"; + // string cmdResult = client.RunCommand(cmdTestPort).Result; + // if (String.IsNullOrEmpty(cmdResult) == false) + // { + // string[] cmdResultArry443 = cmdResult.Split(' '); + // client.RunCommand($"systemctl stop {cmdResultArry443[0]}"); + // client.RunCommand($"systemctl disable {cmdResultArry443[0]}"); + // client.RunCommand($"kill -9 {cmdResultArry443[3]}"); + // } + + // cmdTestPort = @"lsof -n -P -i :80 | grep LISTEN"; + // cmdResult = client.RunCommand(cmdTestPort).Result; + // if (String.IsNullOrEmpty(cmdResult) == false) + // { + // string[] cmdResultArry80 = cmdResult.Split(' '); + // client.RunCommand($"systemctl stop {cmdResultArry80[0]}"); + // client.RunCommand($"systemctl disable {cmdResultArry80[0]}"); + // client.RunCommand($"kill -9 {cmdResultArry80[3]}"); + // } + // currentStatus = "80/443端口释放完毕!"; + // textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + // Thread.Sleep(1000); + + //} + + } + currentStatus = "系统环境检测完毕,符合安装要求,开始布署......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); + + //打开防火墙端口 + currentStatus = "开启防火墙相应端口......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string openFireWallPort = ReceiveConfigurationParameters[1]; + if (String.IsNullOrEmpty(client.RunCommand("command -v firewall-cmd").Result) == false) + { + if (String.Equals(openFireWallPort, "443")) + { + //client.RunCommand("firewall-cmd --zone=public --add-port=80/tcp --permanent"); + //client.RunCommand("firewall-cmd --zone=public --add-port=443/tcp --permanent"); + //client.RunCommand("firewall-cmd --reload"); + + sshShellCommand = @"firewall-cmd --zone=public --add-port=80/tcp --permanent"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"firewall-cmd --zone=public --add-port=443/tcp --permanent"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"yes | firewall-cmd --reload"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } + else + { + //client.RunCommand($"firewall-cmd --zone=public --add-port={openFireWallPort}/tcp --permanent"); + //client.RunCommand($"firewall-cmd --zone=public --add-port={openFireWallPort}/udp --permanent"); + //client.RunCommand("firewall-cmd --reload"); + + sshShellCommand = $"firewall-cmd --zone=public --add-port={openFireWallPort}/tcp --permanent"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"firewall-cmd --zone=public --add-port={openFireWallPort}/udp --permanent"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"yes | firewall-cmd --reload"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 } } - currentStatus = "符合安装要求,布署中......"; - textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); - Thread.Sleep(1000); - - //下载官方安装脚本安装 + if (String.IsNullOrEmpty(client.RunCommand("command -v ufw").Result) == false) + { + if (String.Equals(openFireWallPort, "443")) + { + //client.RunCommand("ufw allow 80"); + //client.RunCommand("ufw allow 443"); + //client.RunCommand("yes | ufw reload"); - client.RunCommand("curl -o /tmp/go.sh https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh"); - client.RunCommand("yes | bash /tmp/go.sh -f"); - string installResult = client.RunCommand("find / -name v2ray").Result.ToString(); + sshShellCommand = @"ufw allow 80"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"ufw allow 443"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"yes | ufw reload"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + else + { + //client.RunCommand($"ufw allow {openFireWallPort}/tcp"); + //client.RunCommand($"ufw allow {openFireWallPort}/udp"); + //client.RunCommand("yes | ufw reload"); + sshShellCommand = $"ufw allow {openFireWallPort}/tcp"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"ufw allow {openFireWallPort}/udp"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"yes | ufw reload"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + } + + //下载官方安装脚本安装 + currentStatus = "正在安装V2Ray......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); + + //client.RunCommand("curl -o /tmp/go.sh https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh"); + //client.RunCommand("yes | bash /tmp/go.sh -f"); + //string installResult = client.RunCommand("find / -name v2ray").Result.ToString(); + sshShellCommand = @"curl -o /tmp/go.sh https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"yes | bash /tmp/go.sh -f"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"find / -name trojan"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string installResult = currentShellCommandResult; if (!installResult.Contains("/usr/local/bin/v2ray")) { @@ -749,6 +1231,9 @@ namespace ProxySU currentStatus = "安装V2ray失败(官方脚本运行出错!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + client.Disconnect(); return; } @@ -756,18 +1241,34 @@ namespace ProxySU { currentStatus = "V2ray安装成功!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - client.RunCommand("systemctl enable v2ray; systemctl start v2ray"); + //client.RunCommand("systemctl enable v2ray; systemctl start v2ray"); + sshShellCommand = @"systemctl enable v2ray"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } - - client.RunCommand("mv /etc/v2ray/config.json /etc/v2ray/config.json.1"); + + //client.RunCommand("mv /usr/local/etc/v2ray/config.json /usr/local/etc/v2ray/config.json.1"); + sshShellCommand = @"mv /usr/local/etc/v2ray/config.json /usr/local/etc/v2ray/config.json.1"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 //上传配置文件 - currentStatus = "V2ray配置文件上传中......"; + currentStatus = "上传V2ray配置文件......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); //生成服务端配置 + //serverConfig = @""; using (StreamReader reader = File.OpenText(serverConfig)) { JObject serverJson = (JObject)JToken.ReadFrom(new JsonTextReader(reader)); @@ -827,75 +1328,132 @@ namespace ProxySU File.Delete(@"config.json"); - //打开防火墙端口 - string openFireWallPort = ReceiveConfigurationParameters[1]; - if (String.IsNullOrEmpty(client.RunCommand("command -v firewall-cmd").Result) == false) - { - if (String.Equals(openFireWallPort, "443")) - { - client.RunCommand("firewall-cmd --zone=public --add-port=80/tcp --permanent"); - client.RunCommand("firewall-cmd --zone=public --add-port=443/tcp --permanent"); - client.RunCommand("firewall-cmd --reload"); - } - else - { - client.RunCommand($"firewall-cmd --zone=public --add-port={openFireWallPort}/tcp --permanent"); - client.RunCommand($"firewall-cmd --zone=public --add-port={openFireWallPort}/udp --permanent"); - client.RunCommand("firewall-cmd --reload"); - } - } - if (String.IsNullOrEmpty(client.RunCommand("command -v ufw").Result) == false) - { - if (String.Equals(openFireWallPort, "443")) - { - client.RunCommand("ufw allow 80"); - client.RunCommand("ufw allow 443"); - client.RunCommand("yes | ufw reload"); - } - else - { - client.RunCommand($"ufw allow {openFireWallPort}/tcp"); - client.RunCommand($"ufw allow {openFireWallPort}/udp"); - client.RunCommand("yes | ufw reload"); - } - } - //如果是WebSocket + TLS + Web模式,需要安装Caddy if (ReceiveConfigurationParameters[0].Contains("WebSocketTLS2Web") ==true || ReceiveConfigurationParameters[0].Contains("http2Web") == true) { currentStatus = "使用WebSocket+TLS+Web/HTTP2+TLS+Web模式,正在安装Caddy......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); //安装Caddy //为假则表示系统有相应的组件。 if (getApt == false) { - client.RunCommand(@"echo ""deb [trusted=yes] https://apt.fury.io/caddy/ /"" | tee -a /etc/apt/sources.list.d/caddy-fury.list"); - client.RunCommand("apt install -y apt-transport-https"); - client.RunCommand("apt -qq update"); - client.RunCommand("apt -y -qq install caddy"); + //client.RunCommand(@"echo ""deb [trusted=yes] https://apt.fury.io/caddy/ /"" | tee -a /etc/apt/sources.list.d/caddy-fury.list"); + //client.RunCommand("apt install -y apt-transport-https"); + //client.RunCommand("apt -qq update"); + //client.RunCommand("apt -y -qq install caddy"); + sshShellCommand = @"echo ""deb [trusted=yes] https://apt.fury.io/caddy/ /"" | tee -a /etc/apt/sources.list.d/caddy-fury.list"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"apt install -y apt-transport-https"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"apt -qq update"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"apt -y -qq install caddy"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } else if (getDnf == false) { - client.RunCommand(@"dnf install 'dnf-command(copr)' -y"); - client.RunCommand(@"dnf copr enable @caddy/caddy -y"); - //client.RunCommand("dnf -q makecache"); - client.RunCommand("dnf -y -q install caddy"); + //client.RunCommand(@"dnf install 'dnf-command(copr)' -y"); + //client.RunCommand(@"dnf copr enable @caddy/caddy -y"); + ////client.RunCommand("dnf -q makecache"); + //client.RunCommand("dnf -y -q install caddy"); + sshShellCommand = @"dnf install 'dnf-command(copr)' -y"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"dnf copr enable @caddy/caddy -y"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + //sshShellCommand = @"dnf -q makecache"; + //TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + //currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + //TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"dnf -y -q install caddy"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } else if (getYum == false) { - client.RunCommand(@"yum install yum-plugin-copr -y"); - client.RunCommand(@"yum copr enable @caddy/caddy -y"); - //client.RunCommand("yum -q makecache"); - client.RunCommand("yum -y -q install caddy"); + //client.RunCommand(@"yum install yum-plugin-copr -y"); + //client.RunCommand(@"yum copr enable @caddy/caddy -y"); + ////client.RunCommand("yum -q makecache"); + //client.RunCommand("yum -y -q install caddy"); + sshShellCommand = @"yum install yum-plugin-copr -y"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"yum copr enable @caddy/caddy -y"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + //sshShellCommand = @"yum -q makecache"; + //TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + //currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + //TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"yum -y -q install caddy"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } + //if (getApt == false) + //{ + // client.RunCommand(@"echo ""deb [trusted=yes] https://apt.fury.io/caddy/ /"" | tee -a /etc/apt/sources.list.d/caddy-fury.list"); + // client.RunCommand("apt install -y apt-transport-https"); + // client.RunCommand("apt -qq update"); + // client.RunCommand("apt -y -qq install caddy"); + //} + //else if (getDnf == false) + //{ + // client.RunCommand(@"dnf install 'dnf-command(copr)' -y"); + // client.RunCommand(@"dnf copr enable @caddy/caddy -y"); + // //client.RunCommand("dnf -q makecache"); + // client.RunCommand("dnf -y -q install caddy"); + //} + //else if (getYum == false) + //{ + // client.RunCommand(@"yum install yum-plugin-copr -y"); + // client.RunCommand(@"yum copr enable @caddy/caddy -y"); + // //client.RunCommand("yum -q makecache"); + // client.RunCommand("yum -y -q install caddy"); + //} //else if (getZypper == false) //{ // client.RunCommand("zypper ref"); // client.RunCommand("zypper -y install curl"); //} - installResult = client.RunCommand("find / -name caddy").Result.ToString(); + + sshShellCommand = @"find / -name caddy"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + installResult = currentShellCommandResult; if (!installResult.Contains("/usr/bin/caddy")) { @@ -903,31 +1461,123 @@ namespace ProxySU currentStatus = "安装Caddy失败!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + client.Disconnect(); return; } - else { - currentStatus = "Caddy安装成功!"; - textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); - Thread.Sleep(1000); - client.RunCommand("systemctl enable caddy"); - } + + currentStatus = "Caddy安装成功!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); + //client.RunCommand("systemctl enable caddy"); + sshShellCommand = @"systemctl enable caddy"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + //if (getApt == false) + //{ + // client.RunCommand(@"echo ""deb [trusted=yes] https://apt.fury.io/caddy/ /"" | tee -a /etc/apt/sources.list.d/caddy-fury.list"); + // client.RunCommand("apt install -y apt-transport-https"); + // client.RunCommand("apt -qq update"); + // client.RunCommand("apt -y -qq install caddy"); + //} + //else if (getDnf == false) + //{ + // client.RunCommand(@"dnf install 'dnf-command(copr)' -y"); + // client.RunCommand(@"dnf copr enable @caddy/caddy -y"); + // //client.RunCommand("dnf -q makecache"); + // client.RunCommand("dnf -y -q install caddy"); + //} + //else if (getYum == false) + //{ + // client.RunCommand(@"yum install yum-plugin-copr -y"); + // client.RunCommand(@"yum copr enable @caddy/caddy -y"); + // //client.RunCommand("yum -q makecache"); + // client.RunCommand("yum -y -q install caddy"); + //} + ////else if (getZypper == false) + ////{ + //// client.RunCommand("zypper ref"); + //// client.RunCommand("zypper -y install curl"); + ////} + //installResult = client.RunCommand("find / -name caddy").Result.ToString(); + + //if (!installResult.Contains("/usr/bin/caddy")) + //{ + // MessageBox.Show("安装Caddy失败!"); + + // currentStatus = "安装Caddy失败!"; + // textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + // client.Disconnect(); + // return; + //} + //else { + // currentStatus = "Caddy安装成功!"; + // textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + // Thread.Sleep(1000); + // client.RunCommand("systemctl enable caddy"); + //} //在Caddy 2还未推出2.2.0的正式版之前,先用测试版替代 if (String.Equals(ReceiveConfigurationParameters[0], "http2Web")) { currentStatus = "正在为Http2Web模式升级Caddy v2.2.0测试版!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - client.RunCommand(@"curl -o /tmp/caddy.zip https://raw.githubusercontent.com/proxysu/Resources/master/Caddy2/caddy.zip"); - client.RunCommand(@"unzip /tmp/caddy.zip"); - client.RunCommand(@"chmod +x caddy"); - client.RunCommand(@"systemctl stop caddy;rm -f /usr/bin/caddy"); - client.RunCommand(@"cp /root/caddy /usr/bin/"); + //client.RunCommand(@"curl -o /tmp/caddy.zip https://raw.githubusercontent.com/proxysu/Resources/master/Caddy2/caddy.zip"); + //client.RunCommand(@"unzip /tmp/caddy.zip"); + //client.RunCommand(@"chmod +x caddy"); + //client.RunCommand(@"systemctl stop caddy;rm -f /usr/bin/caddy"); + //client.RunCommand(@"cp /root/caddy /usr/bin/"); + + sshShellCommand = @"curl -o /tmp/caddy.zip https://raw.githubusercontent.com/proxysu/Resources/master/Caddy2/caddy.zip"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"unzip /tmp/caddy.zip"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"chmod +x caddy"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"systemctl stop caddy;rm -f /usr/bin/caddy"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"cp /root/caddy /usr/bin/"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } + currentStatus = "上传Caddy配置文件......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); + + sshShellCommand = @"mv /etc/caddy/Caddyfile /etc/caddy/Caddyfile.bak"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + if (ReceiveConfigurationParameters[0].Contains("WebSocketTLS2Web") == true) { serverConfig = "TemplateConfg\\WebSocketTLSWeb_server_config.caddyfile"; @@ -948,97 +1598,269 @@ namespace ProxySU //client.RunCommand(sshCmd); //设置域名 - string sshCmd = $"sed -i 's/##domain##/{ReceiveConfigurationParameters[4]}/' {upLoadPath}"; - client.RunCommand(sshCmd); + //string sshCmd = $"sed -i 's/##domain##/{ReceiveConfigurationParameters[4]}/' {upLoadPath}"; + //client.RunCommand(sshCmd); + sshShellCommand = $"sed -i 's/##domain##/{ReceiveConfigurationParameters[4]}/' {upLoadPath}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + //设置Path - sshCmd = $"sed -i 's/##path##/\\{ReceiveConfigurationParameters[3]}/' {upLoadPath}"; - client.RunCommand(sshCmd); + //sshCmd = $"sed -i 's/##path##/\\{ReceiveConfigurationParameters[3]}/' {upLoadPath}"; + //client.RunCommand(sshCmd); + sshShellCommand = $"sed -i 's/##path##/\\{ReceiveConfigurationParameters[3]}/' {upLoadPath}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + - //设置伪装网站 if (String.IsNullOrEmpty(ReceiveConfigurationParameters[7])==false) { - sshCmd = $"sed -i 's/##sites##/reverse_proxy {ReceiveConfigurationParameters[7]}/' {upLoadPath}"; - client.RunCommand(sshCmd); + //sshCmd = $"sed -i 's/##sites##/reverse_proxy {ReceiveConfigurationParameters[7]}/' {upLoadPath}"; + //client.RunCommand(sshCmd); + sshShellCommand = $"sed -i 's/##sites##/proxy \\/ {ReceiveConfigurationParameters[7]}/' {upLoadPath}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } - Thread.Sleep(2000); - + currentStatus = "Caddy配置文件上传成功,OK!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); + //启动Caddy服务 - client.RunCommand("systemctl restart caddy"); + //client.RunCommand("systemctl restart caddy"); + currentStatus = "正在启动Caddy......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + // Thread.Sleep(1000); + //启动Caddy服务 + sshShellCommand = @"systemctl restart caddy"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + currentStatus = "Caddy启动成功!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); } if (String.Equals(ReceiveConfigurationParameters[0], "Http2") == true || String.Equals(ReceiveConfigurationParameters[0], "WebSocketTLS") == true|| String.Equals(ReceiveConfigurationParameters[0], "tcpTLS") == true) { currentStatus = "使用Http2/WebSocket+TLS/tcp+TLS模式,正在安装acme.sh......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - if (getApt == false) - { - //client.RunCommand("apt-get -qq update"); - client.RunCommand("apt -y -qq install socat"); - } - else if (getDnf == false) - { - //client.RunCommand("yum -q makecache"); - client.RunCommand("dnf -y -q install socat"); - } - else if (getYum == false) - { - //client.RunCommand("yum -q makecache"); - client.RunCommand("yum -y -q install socat"); - } + //安装所依赖的软件 + sshShellCommand = $"{sshCmdUpdate}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"{sshCmdInstall}socat"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + //if (getApt == false) + //{ + // //client.RunCommand("apt-get -qq update"); + // client.RunCommand("apt -y -qq install socat"); + //} + //else if (getDnf == false) + //{ + // //client.RunCommand("yum -q makecache"); + // client.RunCommand("dnf -y -q install socat"); + //} + //else if (getYum == false) + //{ + // //client.RunCommand("yum -q makecache"); + // client.RunCommand("yum -y -q install socat"); + //} //if (getZypper == false) //{ // // client.RunCommand("zypper ref"); // client.RunCommand("zypper -y install socat"); //} - client.RunCommand("curl https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | INSTALLONLINE=1 sh"); - client.RunCommand("cd ~/.acme.sh/"); - client.RunCommand("alias acme.sh=~/.acme.sh/acme.sh"); + //client.RunCommand("curl https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | INSTALLONLINE=1 sh"); + //client.RunCommand("cd ~/.acme.sh/"); + //client.RunCommand("alias acme.sh=~/.acme.sh/acme.sh"); + sshShellCommand = @"curl https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | INSTALLONLINE=1 sh"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"cd ~/.acme.sh/"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"alias acme.sh=~/.acme.sh/acme.sh"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + currentStatus = "申请域名证书......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - client.RunCommand("mkdir -p /usr/local/etc/v2ray/ssl"); - client.RunCommand($"/root/.acme.sh/acme.sh --issue --standalone -d {ReceiveConfigurationParameters[4]}"); + //client.RunCommand("mkdir -p /etc/v2ray/ssl"); + //client.RunCommand($"/root/.acme.sh/acme.sh --issue --standalone -d {ReceiveConfigurationParameters[4]}"); + sshShellCommand = $"/root/.acme.sh/acme.sh --issue --standalone -d {ReceiveConfigurationParameters[4]}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + + //currentStatus = "申请域名证书......"; + //textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + //Thread.Sleep(1000); + + //client.RunCommand("mkdir -p /usr/local/etc/v2ray/ssl"); + //client.RunCommand($"/root/.acme.sh/acme.sh --issue --standalone -d {ReceiveConfigurationParameters[4]}"); currentStatus = "安装证书到V2ray......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - client.RunCommand($"/root/.acme.sh/acme.sh --installcert -d {ReceiveConfigurationParameters[4]} --certpath /usr/local/etc/v2ray/ssl/v2ray_ssl.crt --keypath /usr/local/etc/v2ray/ssl/v2ray_ssl.key --capath /usr/local/etc/v2ray/ssl/v2ray_ssl.crt --reloadcmd \"systemctl restart v2ray\""); + // client.RunCommand($"/root/.acme.sh/acme.sh --installcert -d {ReceiveConfigurationParameters[4]} --certpath /usr/local/etc/v2ray/ssl/v2ray_ssl.crt --keypath /usr/local/etc/v2ray/ssl/v2ray_ssl.key --capath /usr/local/etc/v2ray/ssl/v2ray_ssl.crt --reloadcmd \"systemctl restart v2ray\""); + sshShellCommand = $"/root/.acme.sh/acme.sh --installcert -d {ReceiveConfigurationParameters[4]} --certpath /usr/local/etc/v2ray/ssl/v2ray_ssl.crt --keypath /usr/local/etc/v2ray/ssl/v2ray_ssl.key --capath /usr/local/etc/v2ray/ssl/v2ray_ssl.crt --reloadcmd \"systemctl restart v2ray\""; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } currentStatus = "正在启动V2ray......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); //启动V2ray服务 - client.RunCommand("systemctl restart v2ray"); + //client.RunCommand("systemctl restart v2ray"); + sshShellCommand = @"systemctl restart v2ray"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + currentStatus = "V2ray启动成功!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); //测试BBR条件,若满足提示是否启用 - result = client.RunCommand("uname -r").Result; - //var result = client.RunCommand("cat /root/test.ver"); - linuxKernelVerStr = result.Split('-'); + currentStatus = "BBR测试......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - detectResult = DetectKernelVersionBBR(linuxKernelVerStr[0]); - string resultCmdTestBBR = client.RunCommand(@"sysctl net.ipv4.tcp_congestion_control | grep bbr").Result; + Thread.Sleep(1000); + + //var result = client.RunCommand("uname -r"); + sshShellCommand = @"uname -r"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string[] linuxKernelVerStrBBR = currentShellCommandResult.Split('-'); + + bool detectResultBBR = DetectKernelVersionBBR(linuxKernelVerStrBBR[0]); + //client.RunCommand(@"sysctl net.ipv4.tcp_congestion_control | grep bbr").Result; + sshShellCommand = @"sysctl net.ipv4.tcp_congestion_control | grep bbr"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + string resultCmdTestBBR = currentShellCommandResult; //如果内核满足大于等于4.9,且还未启用BBR,则启用BBR - if (detectResult == true && resultCmdTestBBR.Contains("bbr") == false) + if (detectResultBBR == true && resultCmdTestBBR.Contains("bbr") == false) { - client.RunCommand(@"bash -c 'echo ""net.core.default_qdisc=fq"" >> /etc/sysctl.conf'"); - client.RunCommand(@"bash -c 'echo ""net.ipv4.tcp_congestion_control=bbr"" >> /etc/sysctl.conf'"); - client.RunCommand(@"sysctl -p"); + currentStatus = "正在启用BBR......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); + + //client.RunCommand(@"bash -c 'echo ""net.core.default_qdisc=fq"" >> /etc/sysctl.conf'"); + //client.RunCommand(@"bash -c 'echo ""net.ipv4.tcp_congestion_control=bbr"" >> /etc/sysctl.conf'"); + //client.RunCommand(@"sysctl -p"); + sshShellCommand = @"bash -c 'echo ""net.core.default_qdisc=fq"" >> /etc/sysctl.conf'"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"bash -c 'echo ""net.ipv4.tcp_congestion_control=bbr"" >> /etc/sysctl.conf'"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"sysctl -p"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } + else if (resultCmdTestBBR.Contains("bbr") == true) + { + currentStatus = "BBR已经启用了!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + else + { + currentStatus = "系统不满足启用BBR的条件,启用失败!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + client.Disconnect();//断开服务器ssh连接 + //result = client.RunCommand("uname -r").Result; + ////var result = client.RunCommand("cat /root/test.ver"); + //linuxKernelVerStr = result.Split('-'); + + //detectResult = DetectKernelVersionBBR(linuxKernelVerStr[0]); + //string resultCmdTestBBR = client.RunCommand(@"sysctl net.ipv4.tcp_congestion_control | grep bbr").Result; + ////如果内核满足大于等于4.9,且还未启用BBR,则启用BBR + //if (detectResult == true && resultCmdTestBBR.Contains("bbr") == false) + //{ + // client.RunCommand(@"bash -c 'echo ""net.core.default_qdisc=fq"" >> /etc/sysctl.conf'"); + // client.RunCommand(@"bash -c 'echo ""net.ipv4.tcp_congestion_control=bbr"" >> /etc/sysctl.conf'"); + // client.RunCommand(@"sysctl -p"); + //} //生成客户端配置 currentStatus = "生成客户端配置......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); if (!Directory.Exists("v2ray_config"))//如果不存在就创建file文件夹      { @@ -1088,10 +1910,12 @@ namespace ProxySU } } - client.Disconnect(); + //client.Disconnect(); - currentStatus = "安装成功"; + currentStatus = "V2Ray安装成功,祝您使用愉快!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 Thread.Sleep(1000); //显示服务端连接参数 @@ -1134,6 +1958,8 @@ namespace ProxySU } currentStatus = "主机登录失败"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 } #endregion @@ -1159,8 +1985,10 @@ namespace ProxySU private void UpdateV2ray(ConnectionInfo connectionInfo, TextBlock textBlockName, ProgressBar progressBar) { string currentStatus = "正在登录远程主机......"; - Action updateAction = new Action(UpdateTextBlock); + //Action updateAction = new Action(UpdateTextBlock); textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 try { @@ -1199,22 +2027,54 @@ namespace ProxySU { currentStatus = "主机登录成功"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果在监视窗口 + Thread.Sleep(1000); } //检测是否运行在root权限下 - string testRootAuthority = client.RunCommand(@"id -u").Result; + currentShellCommandResult = "检测是否运行在root权限下..."; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"id -u"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string testRootAuthority = currentShellCommandResult; if (testRootAuthority.Equals("0\n") == false) { MessageBox.Show("请使用具有root权限的账户登录主机!!"); client.Disconnect(); return; } + else + { + currentShellCommandResult = "检测结果:OK!"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + //string testRootAuthority = client.RunCommand(@"id -u").Result; + //if (testRootAuthority.Equals("0\n") == false) + //{ + // MessageBox.Show("请使用具有root权限的账户登录主机!!"); + // client.Disconnect(); + // return; + //} //检测远程主机V2ray版本 currentStatus = "检测远程主机V2ray版本......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); //检测是否安装V2Ray - string resultCmdTestV2rayInstalled = client.RunCommand(@"find / -name v2ray").Result; + sshShellCommand = @"find / -name v2ray"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string resultCmdTestV2rayInstalled = currentShellCommandResult; if (resultCmdTestV2rayInstalled.Contains("/usr/bin/v2ray") == false && resultCmdTestV2rayInstalled.Contains("/usr/local/bin/v2ray") == false) { @@ -1222,6 +2082,9 @@ namespace ProxySU currentStatus = "未安装V2ray,退出"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); client.Disconnect(); return; @@ -1229,47 +2092,142 @@ namespace ProxySU } else if (resultCmdTestV2rayInstalled.Contains("/usr/bin/v2ray") == true) { - client.RunCommand("curl -o /tmp/go.sh https://raw.githubusercontent.com/proxysu/shellscript/master/v2ray/go.sh"); - client.RunCommand("yes | bash /tmp/go.sh --remove"); - string installResult = client.RunCommand("find / -name v2ray").Result.ToString(); + currentStatus = "检测到使用旧安装脚本的V2Ray......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + MessageBoxResult messageBoxResult = MessageBox.Show("检测到使用旧安装脚本的V2Ray,是否卸载旧版本并使用新安装脚本重新安装?", "", MessageBoxButton.YesNo, MessageBoxImage.Question); + if (messageBoxResult == MessageBoxResult.No) + { + currentStatus = "安装取消,退出"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); + client.Disconnect(); + return; + } + else + { + currentStatus = "正在卸载旧版本......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); + } + + + //client.RunCommand("curl -o /tmp/go.sh https://raw.githubusercontent.com/proxysu/shellscript/master/v2ray/go.sh"); + //client.RunCommand("yes | bash /tmp/go.sh --remove"); + + sshShellCommand = @"curl -o /tmp/go.sh https://raw.githubusercontent.com/proxysu/shellscript/master/v2ray/go.sh"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"yes | bash /tmp/go.sh --remove"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"find / -name v2ray"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string installResult = currentShellCommandResult; if (!installResult.Contains("/usr/bin/v2ray")) { - currentStatus = "删除旧版本,OK"; + currentStatus = "卸载旧版本,OK"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); } - currentStatus = "安装新版本。。。。。。"; + currentStatus = "安装新版本......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - client.RunCommand("curl -o /tmp/go.sh https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh"); - client.RunCommand("yes | bash /tmp/go.sh -f"); - installResult = client.RunCommand("find / -name v2ray").Result.ToString(); + //client.RunCommand("curl -o /tmp/go.sh https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh"); + //client.RunCommand("yes | bash /tmp/go.sh -f"); + //installResult = client.RunCommand("find / -name v2ray").Result.ToString(); + sshShellCommand = @"curl -o /tmp/go.sh https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + sshShellCommand = @"yes | bash /tmp/go.sh -f"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"find / -name v2ray"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + installResult = currentShellCommandResult; if (!installResult.Contains("/usr/local/bin/v2ray")) { MessageBox.Show("安装V2ray失败(官方脚本运行出错!"); currentStatus = "安装V2ray失败(官方脚本运行出错!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + client.Disconnect(); return; } - client.RunCommand(@"mv /etc/v2ray/config.json /usr/local/etc/v2ray/"); - client.RunCommand(@"systemctl restart v2ray"); + + currentStatus = "迁移原配置文件。"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + //client.RunCommand(@"mv /etc/v2ray/config.json /usr/local/etc/v2ray/"); + //client.RunCommand(@"systemctl restart v2ray"); + sshShellCommand = @"mv /etc/v2ray/config.json /usr/local/etc/v2ray/"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"systemctl restart v2ray"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + currentStatus = "已更新到最新版本。"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); } - string sshcmd; - sshcmd = @"/usr/local/bin/v2ray -version | head -n 1 | cut -d "" "" -f2"; + //string sshcmd; + //sshcmd = @"/usr/local/bin/v2ray -version | head -n 1 | cut -d "" "" -f2"; + sshShellCommand = @"/usr/local/bin/v2ray -version | head -n 1 | cut -d "" "" -f2"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - string v2rayCurrentVersion = client.RunCommand(sshcmd).Result;//不含字母v + string v2rayCurrentVersion = currentShellCommandResult;//不含字母v - sshcmd = @"curl -H ""Accept: application/json"" -H ""User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:74.0) Gecko/20100101 Firefox/74.0"" -s ""https://api.github.com/repos/v2fly/v2ray-core/releases/latest"" --connect-timeout 10| grep 'tag_name' | cut -d\"" -f4"; - string v2rayNewVersion = client.RunCommand(sshcmd).Result;//包含字母v + //sshcmd = @"curl -H ""Accept: application/json"" -H ""User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:74.0) Gecko/20100101 Firefox/74.0"" -s ""https://api.github.com/repos/v2fly/v2ray-core/releases/latest"" --connect-timeout 10| grep 'tag_name' | cut -d\"" -f4"; + sshShellCommand = @"curl -H ""Accept: application/json"" -H ""User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:74.0) Gecko/20100101 Firefox/74.0"" -s ""https://api.github.com/repos/v2fly/v2ray-core/releases/latest"" --connect-timeout 10 | grep 'tag_name' | cut -d\"" -f4"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string v2rayNewVersion = currentShellCommandResult;//包含字母v if (v2rayNewVersion.Contains(v2rayCurrentVersion) == false) { @@ -1278,16 +2236,32 @@ namespace ProxySU { currentStatus = "正在升级V2ray到最新版本......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); - Thread.Sleep(1000); - client.RunCommand(@"bash <(curl -L -s https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh)"); - sshcmd = @"/usr/local/bin/v2ray -version | head -n 1 | cut -d "" "" -f2"; + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - v2rayCurrentVersion = client.RunCommand(sshcmd).Result;//不含字母v + Thread.Sleep(1000); + //client.RunCommand(@"bash <(curl -L -s https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh)"); + sshShellCommand = @"bash <(curl -L -s https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh)"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + //sshcmd = @"/usr/local/bin/v2ray -version | head -n 1 | cut -d "" "" -f2"; + sshShellCommand = @"/usr/local/bin/v2ray -version | head -n 1 | cut -d "" "" -f2"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + + v2rayCurrentVersion = currentShellCommandResult;//不含字母v if (v2rayNewVersion.Contains(v2rayCurrentVersion) == true) { MessageBox.Show($"升级成功!!\n当前版本为:v{v2rayCurrentVersion}\n最新版本为:{v2rayNewVersion}"); currentStatus = "升级成功!当前已是最新版本!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); } else @@ -1295,6 +2269,9 @@ namespace ProxySU MessageBox.Show("升级失败,原因未知,请向开发者提问,以寻求支持!"); currentStatus = "升级失败!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); } } @@ -1302,6 +2279,9 @@ namespace ProxySU { currentStatus = "升级取消,退出"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); client.Disconnect(); return; @@ -1312,6 +2292,9 @@ namespace ProxySU MessageBox.Show($"远程主机当前已是最新版本:{v2rayNewVersion}\n无需升级!"); currentStatus = "已是最新版本,无需升级,退出"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); } @@ -1351,6 +2334,8 @@ namespace ProxySU } currentStatus = "主机登录失败"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 } #endregion @@ -1409,6 +2394,8 @@ namespace ProxySU string currentStatus = "正在登录远程主机......"; Action updateAction = new Action(UpdateTextBlock); textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 try { @@ -1447,37 +2434,57 @@ namespace ProxySU { currentStatus = "主机登录成功"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果在监视窗口 + Thread.Sleep(1000); } - //检测是否运行在root权限下 - string testRootAuthority = client.RunCommand(@"id -u").Result; + currentShellCommandResult = "检测是否运行在root权限下..."; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"id -u"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string testRootAuthority = currentShellCommandResult; if (testRootAuthority.Equals("0\n") == false) { MessageBox.Show("请使用具有root权限的账户登录主机!!"); client.Disconnect(); return; } - //检测远程主机系统环境是否符合要求 - currentStatus = "检测系统是否符合安装要求......"; - textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); - Thread.Sleep(1000); - - string resultCmd = client.RunCommand("uname -m").Result; - - if (resultCmd.Contains("x86_64") == false) + else { - MessageBox.Show($"请在x86_64系统中安装Trojan"); - currentStatus = "系统不符合要求,安装失败!!"; - textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); - Thread.Sleep(1000); + currentShellCommandResult = "检测结果:OK!"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } + ////检测是否运行在root权限下 + //string testRootAuthority = client.RunCommand(@"id -u").Result; + //if (testRootAuthority.Equals("0\n") == false) + //{ + // MessageBox.Show("请使用具有root权限的账户登录主机!!"); + // client.Disconnect(); + // return; + //} + //检测是否安装有Trojan currentStatus = "检测系统是否已经安装Trojan......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - string resultCmdTestTrojanInstalled = client.RunCommand(@"find / -name trojan").Result; + //string resultCmdTestTrojanInstalled = client.RunCommand(@"find / -name trojan").Result; + sshShellCommand = @"find / -name trojan"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string resultCmdTestTrojanInstalled = currentShellCommandResult; if (resultCmdTestTrojanInstalled.Contains("/usr/local/bin/trojan") == true) { @@ -1486,20 +2493,103 @@ namespace ProxySU { currentStatus = "安装取消,退出"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); client.Disconnect(); return; } + else + { + currentStatus = "已选择强制安装Trojan!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); + } } + else + { + currentShellCommandResult = "检测结果:未安装Trojan!"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + //检测远程主机系统环境是否符合要求 + currentStatus = "检测系统是否符合安装要求......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); + + //string resultCmd = client.RunCommand("uname -m").Result; + sshShellCommand = @"uname -m"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string resultCmd = currentShellCommandResult; + if (resultCmd.Contains("x86_64") == false) + { + MessageBox.Show($"请在x86_64系统中安装Trojan"); + currentStatus = "系统不符合要求,安装失败!!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); + } + //检测系统是否支持yum 或 apt或zypper,且支持Systemd - //如果不存在组件,则命令结果为空,string.IsNullOrEmpty值为真, - bool getApt = String.IsNullOrEmpty(client.RunCommand("command -v apt").Result); - bool getDnf = String.IsNullOrEmpty(client.RunCommand("command -v dnf").Result); - bool getYum = String.IsNullOrEmpty(client.RunCommand("command -v yum").Result); - bool getZypper = String.IsNullOrEmpty(client.RunCommand("command -v zypper").Result); - bool getSystemd = String.IsNullOrEmpty(client.RunCommand("command -v systemctl").Result); - bool getGetenforce = String.IsNullOrEmpty(client.RunCommand("command -v getenforce").Result); + //如果不存在组件,则命令结果为空,string.IsNullOrEmpty值为真 + + //bool getApt = String.IsNullOrEmpty(client.RunCommand("command -v apt").Result); + //bool getDnf = String.IsNullOrEmpty(client.RunCommand("command -v dnf").Result); + //bool getYum = String.IsNullOrEmpty(client.RunCommand("command -v yum").Result); + //bool getZypper = String.IsNullOrEmpty(client.RunCommand("command -v zypper").Result); + //bool getSystemd = String.IsNullOrEmpty(client.RunCommand("command -v systemctl").Result); + //bool getGetenforce = String.IsNullOrEmpty(client.RunCommand("command -v getenforce").Result); + + sshShellCommand = @"command -v apt"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + bool getApt = String.IsNullOrEmpty(currentShellCommandResult); + + sshShellCommand = @"command -v dnf"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + bool getDnf = String.IsNullOrEmpty(currentShellCommandResult); + + sshShellCommand = @"command -v yum"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + bool getYum = String.IsNullOrEmpty(currentShellCommandResult); + + sshShellCommand = @"command -v zypper"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + bool getZypper = String.IsNullOrEmpty(currentShellCommandResult); + + sshShellCommand = @"command -v systemctl"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + bool getSystemd = String.IsNullOrEmpty(currentShellCommandResult); + + sshShellCommand = @"command -v getenforce"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + bool getGetenforce = String.IsNullOrEmpty(currentShellCommandResult); + //没有安装apt,也没有安装dnf\yum,也没有安装zypper,或者没有安装systemd的,不满足安装条件 //也就是apt ,dnf\yum, zypper必须安装其中之一,且必须安装Systemd的系统才能安装。 @@ -1508,42 +2598,129 @@ namespace ProxySU MessageBox.Show($"系统缺乏必要的安装组件如:apt-get||yum||zypper||Syetemd,主机系统推荐使用:CentOS 7/8,Debian 8/9/10,Ubuntu 16.04及以上版本"); currentStatus = "系统环境不满足要求,安装失败!!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); client.Disconnect(); return; } + else + { + currentStatus = "检测结果:OK!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + //设置安装软件所用的命令格式 + //为假则表示系统有相应的组件。 + + if (getApt == false) + { + //client.RunCommand("apt -qq update"); + //client.RunCommand("apt -y -qq install curl"); + sshCmdUpdate = @"apt -qq update"; + sshCmdInstall = @"apt -y -qq install "; + } + else if (getDnf == false) + { + //client.RunCommand("dnf -q makecache"); + //client.RunCommand("dnf -y -q install curl"); + sshCmdUpdate = @"dnf -q makecache"; + sshCmdInstall = @"dnf -y -q install "; + } + else if (getYum == false) + { + //client.RunCommand("yum -q makecache"); + //client.RunCommand("yum -y -q install curl"); + sshCmdUpdate = @"yum -q makecache"; + sshCmdInstall = @"yum -y -q install "; + } + else if (getZypper == false) + { + //client.RunCommand("zypper ref"); + //client.RunCommand("zypper -y install curl"); + sshCmdUpdate = @"zypper ref"; + sshCmdInstall = @"zypper -y install "; + } + //判断是否启用了SELinux,如果启用了,并且工作在Enforcing模式下,则改为Permissive模式 if (getGetenforce == false) { - string testSELinux = client.RunCommand("getenforce").Result; - //MessageBox.Show(testSELinux); + //string testSELinux = client.RunCommand("getenforce").Result; + sshShellCommand = @"getenforce"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string testSELinux = currentShellCommandResult; + if (testSELinux.Contains("Enforcing") == true) { + currentStatus = "检测到系统启用SELinux,且工作在严格模式下,需改为宽松模式!修改中..."; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + //MessageBox.Show("Enforcing"); - client.RunCommand("setenforce 0");//不重启改为Permissive模式 - client.RunCommand("sed -i 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config");//重启也工作在Permissive模式下 + //client.RunCommand("setenforce 0");//不重启改为Permissive模式 + //client.RunCommand("sed -i 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config");//重启也工作在Permissive模式下 + sshShellCommand = @"setenforce 0"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + sshShellCommand = @"sed -i 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + currentStatus = "修改完毕!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } - + } + + //检测域名解析是否正确 + + currentStatus = "正在检测域名是否解析到当前VPS的IP上......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); //在相应系统内安装curl(如果没有安装curl) if (string.IsNullOrEmpty(client.RunCommand("command -v curl").Result) == true) { + sshShellCommand = $"{sshCmdUpdate}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"{sshCmdInstall}curl"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + //为假则表示系统有相应的组件。 - if (getApt == false) - { - client.RunCommand("apt -qq update"); - client.RunCommand("apt -y -qq install curl"); - } - else if (getDnf == false) - { - client.RunCommand("dnf -q makecache"); - client.RunCommand("dnf -y -q install curl"); - } - else if (getYum == false) - { - client.RunCommand("yum -q makecache"); - client.RunCommand("yum -y -q install curl"); - } + //if (getApt == false) + //{ + // client.RunCommand("apt -qq update"); + // client.RunCommand("apt -y -qq install curl"); + //} + //else if (getDnf == false) + //{ + // client.RunCommand("dnf -q makecache"); + // client.RunCommand("dnf -y -q install curl"); + //} + //else if (getYum == false) + //{ + // client.RunCommand("yum -q makecache"); + // client.RunCommand("yum -y -q install curl"); + //} //else if (getZypper == false) //{ // client.RunCommand("zypper ref"); @@ -1551,22 +2728,42 @@ namespace ProxySU //} } //检测域名是否解析正确 - currentStatus = "正在检测域名是否解析到当前VPS的IP上......"; - textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); - Thread.Sleep(1000); - string nativeIp = client.RunCommand("curl -4 ip.sb").Result.ToString(); - string testDomainCmd = "ping " + ReceiveConfigurationParameters[4] + " -c 1 | grep -oE -m1 \"([0-9]{1,3}\\.){3}[0-9]{1,3}\""; - string resultTestDomainCmd = client.RunCommand(testDomainCmd).Result.ToString(); + //currentStatus = "正在检测域名是否解析到当前VPS的IP上......"; + //textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + //Thread.Sleep(1000); + //string nativeIp = client.RunCommand("curl -4 ip.sb").Result.ToString(); + //string testDomainCmd = "ping " + ReceiveConfigurationParameters[4] + " -c 1 | grep -oE -m1 \"([0-9]{1,3}\\.){3}[0-9]{1,3}\""; + //string resultTestDomainCmd = client.RunCommand(testDomainCmd).Result.ToString(); + sshShellCommand = @"curl -4 ip.sb"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string nativeIp = currentShellCommandResult; + + sshShellCommand = "ping " + ReceiveConfigurationParameters[4] + " -c 1 | grep -oE -m1 \"([0-9]{1,3}\\.){3}[0-9]{1,3}\""; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + //string testDomainCmd = "ping " + ReceiveConfigurationParameters[4] + " -c 1 | grep -oE -m1 \"([0-9]{1,3}\\.){3}[0-9]{1,3}\""; + string resultTestDomainCmd = currentShellCommandResult; if (String.Equals(nativeIp, resultTestDomainCmd) == true) { currentStatus = "解析正确!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); } else { currentStatus = "域名未能正确解析到当前VPS的IP上!安装失败!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); MessageBox.Show("域名未能正确解析到当前VPS的IP上,请检查!若解析设置正确,请等待生效后再重试安装。如果域名使用了CDN,请先关闭!"); client.Disconnect(); @@ -1576,22 +2773,32 @@ namespace ProxySU //检测是否安装lsof if (string.IsNullOrEmpty(client.RunCommand("command -v lsof").Result) == true) { + sshShellCommand = $"{sshCmdUpdate}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"{sshCmdInstall}lsof"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + //为假则表示系统有相应的组件。 - if (getApt == false) - { - client.RunCommand("apt -qq update"); - client.RunCommand("apt -y -qq install lsof"); - } - else if (getDnf == false) - { - client.RunCommand("dnf -q makecache"); - client.RunCommand("dnf -y -q install lsof"); - } - else if (getYum == false) - { - client.RunCommand("yum -q makecache"); - client.RunCommand("yum -y -q install lsof"); - } + //if (getApt == false) + //{ + // client.RunCommand("apt -qq update"); + // client.RunCommand("apt -y -qq install lsof"); + //} + //else if (getDnf == false) + //{ + // client.RunCommand("dnf -q makecache"); + // client.RunCommand("dnf -y -q install lsof"); + //} + //else if (getYum == false) + //{ + // client.RunCommand("yum -q makecache"); + // client.RunCommand("yum -y -q install lsof"); + //} //else if (getZypper == false) //{ // client.RunCommand("zypper ref"); @@ -1599,16 +2806,35 @@ namespace ProxySU //} } currentStatus = "正在检测端口占用情况......"; - textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); - Thread.Sleep(1000); + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - if (String.IsNullOrEmpty(client.RunCommand(@"lsof -n -P -i :80 | grep LISTEN").Result) == false || String.IsNullOrEmpty(client.RunCommand(@"lsof -n -P -i :443 | grep LISTEN").Result) == false) + Thread.Sleep(1000); + + sshShellCommand = @"lsof -n -P -i :80 | grep LISTEN"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + string testPort80 = currentShellCommandResult; + + sshShellCommand = @"lsof -n -P -i :443 | grep LISTEN"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + string testPort443 = currentShellCommandResult; + + + if (String.IsNullOrEmpty(testPort80) == false || String.IsNullOrEmpty(testPort443) == false) { MessageBoxResult dialogResult = MessageBox.Show("80/443端口之一,或全部被占用,将强制停止占用80/443端口的程序?", "Stop application", MessageBoxButton.YesNo); if (dialogResult == MessageBoxResult.No) { currentStatus = "端口被占用,安装失败......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); client.Disconnect(); return; @@ -1616,53 +2842,182 @@ namespace ProxySU currentStatus = "正在释放80/443端口......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - string cmdTestPort = @"lsof -n -P -i :443 | grep LISTEN"; - string cmdResult = client.RunCommand(cmdTestPort).Result; + //string cmdTestPort = @"lsof -n -P -i :443 | grep LISTEN"; + //string cmdResult = client.RunCommand(cmdTestPort).Result; - if (String.IsNullOrEmpty(cmdResult) == false) + if (String.IsNullOrEmpty(testPort443) == false) { - string[] cmdResultArry443 = cmdResult.Split(' '); - client.RunCommand($"systemctl stop {cmdResultArry443[0]}"); - client.RunCommand($"systemctl disable {cmdResultArry443[0]}"); - client.RunCommand($"kill -9 {cmdResultArry443[3]}"); + string[] cmdResultArry443 = testPort443.Split(' '); + //client.RunCommand($"systemctl stop {cmdResultArry443[0]}"); + //client.RunCommand($"systemctl disable {cmdResultArry443[0]}"); + //client.RunCommand($"kill -9 {cmdResultArry443[3]}"); + sshShellCommand = $"systemctl stop {cmdResultArry443[0]}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"systemctl disable {cmdResultArry443[0]}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"kill -9 {cmdResultArry443[3]}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } - cmdTestPort = @"lsof -n -P -i :80 | grep LISTEN"; - cmdResult = client.RunCommand(cmdTestPort).Result; - if (String.IsNullOrEmpty(cmdResult) == false) + //cmdTestPort = @"lsof -n -P -i :80 | grep LISTEN"; + //cmdResult = client.RunCommand(cmdTestPort).Result; + if (String.IsNullOrEmpty(testPort80) == false) { - string[] cmdResultArry80 = cmdResult.Split(' '); - client.RunCommand($"systemctl stop {cmdResultArry80[0]}"); - client.RunCommand($"systemctl disable {cmdResultArry80[0]}"); - client.RunCommand($"kill -9 {cmdResultArry80[3]}"); + string[] cmdResultArry80 = testPort80.Split(' '); + //client.RunCommand($"systemctl stop {cmdResultArry80[0]}"); + //client.RunCommand($"systemctl disable {cmdResultArry80[0]}"); + //client.RunCommand($"kill -9 {cmdResultArry80[3]}"); + sshShellCommand = $"systemctl stop {cmdResultArry80[0]}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"systemctl disable {cmdResultArry80[0]}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"kill -9 {cmdResultArry80[3]}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } currentStatus = "80/443端口释放完毕!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); } - currentStatus = "符合安装要求,布署中......"; + else + { + currentStatus = "检测结果:未被占用!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + //if (String.IsNullOrEmpty() == false) + // { + // string[] cmdResultArry443 = cmdResult.Split(' '); + // client.RunCommand($"systemctl stop {cmdResultArry443[0]}"); + // client.RunCommand($"systemctl disable {cmdResultArry443[0]}"); + // client.RunCommand($"kill -9 {cmdResultArry443[3]}"); + // } + + // cmdTestPort = @"lsof -n -P -i :80 | grep LISTEN"; + // cmdResult = client.RunCommand(cmdTestPort).Result; + // if (String.IsNullOrEmpty(cmdResult) == false) + // { + // string[] cmdResultArry80 = cmdResult.Split(' '); + // client.RunCommand($"systemctl stop {cmdResultArry80[0]}"); + // client.RunCommand($"systemctl disable {cmdResultArry80[0]}"); + // client.RunCommand($"kill -9 {cmdResultArry80[3]}"); + // } + // currentStatus = "80/443端口释放完毕!"; + // textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + // Thread.Sleep(1000); + //} + + currentStatus = "系统环境检测完毕,符合安装要求,开始布署......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); + //打开防火墙端口 + currentStatus = "开启防火墙相应端口......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + if (String.IsNullOrEmpty(client.RunCommand("command -v firewall-cmd").Result) == false) + { + + //client.RunCommand("firewall-cmd --zone=public --add-port=80/tcp --permanent"); + //client.RunCommand("firewall-cmd --zone=public --add-port=443/tcp --permanent"); + //client.RunCommand("firewall-cmd --reload"); + sshShellCommand = @"firewall-cmd --zone=public --add-port=80/tcp --permanent"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"firewall-cmd --zone=public --add-port=443/tcp --permanent"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"yes | firewall-cmd --reload"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + if (String.IsNullOrEmpty(client.RunCommand("command -v ufw").Result) == false) + { + //client.RunCommand("ufw allow 80"); + //client.RunCommand("ufw allow 443"); + //client.RunCommand("yes | ufw reload"); + + sshShellCommand = @"ufw allow 80"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"ufw allow 443"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"yes | ufw reload"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } //处理极其少见的xz-utils未安装的情况 - if (getApt == false) - { - client.RunCommand("apt -qq update"); - client.RunCommand("apt -y -qq install xz-utils"); - } - else if (getDnf == false) - { - //client.RunCommand("yum -q makecache"); - client.RunCommand("dnf -y -q install xz-utils"); - } - else if (getYum == false) - { - client.RunCommand("yum -q makecache"); - client.RunCommand("yum -y -q install xz-utils"); - } + sshShellCommand = $"{sshCmdUpdate}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"{sshCmdInstall}xz-utils"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + //if (getApt == false) + //{ + // client.RunCommand("apt -qq update"); + // client.RunCommand("apt -y -qq install xz-utils"); + //} + //else if (getDnf == false) + //{ + // //client.RunCommand("yum -q makecache"); + // client.RunCommand("dnf -y -q install xz-utils"); + //} + //else if (getYum == false) + //{ + // client.RunCommand("yum -q makecache"); + // client.RunCommand("yum -y -q install xz-utils"); + //} //else if (getZypper == false) //{ // client.RunCommand("zypper ref"); @@ -1670,12 +3025,34 @@ namespace ProxySU //} - //下载官方安装脚本安装 + //下载安装脚本安装 + currentStatus = "正在安装Trojan......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - client.RunCommand("curl -o /tmp/trojan-quickstart.sh https://raw.githubusercontent.com/trojan-gfw/trojan-quickstart/master/trojan-quickstart.sh"); - client.RunCommand("yes | bash /tmp/trojan-quickstart.sh"); + Thread.Sleep(1000); - string installResult = client.RunCommand("find / -name trojan").Result.ToString(); + //client.RunCommand("curl -o /tmp/trojan-quickstart.sh https://raw.githubusercontent.com/trojan-gfw/trojan-quickstart/master/trojan-quickstart.sh"); + //client.RunCommand("yes | bash /tmp/trojan-quickstart.sh"); + sshShellCommand = @"curl -o /tmp/trojan-quickstart.sh https://raw.githubusercontent.com/trojan-gfw/trojan-quickstart/master/trojan-quickstart.sh"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"yes | bash /tmp/trojan-quickstart.sh"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"find / -name trojan"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string installResult = currentShellCommandResult; + + //string installResult = client.RunCommand("find / -name trojan").Result.ToString(); if (!installResult.Contains("/usr/local/bin/trojan")) { @@ -1683,6 +3060,9 @@ namespace ProxySU currentStatus = "安装Trojan失败(官方脚本运行出错!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + client.Disconnect(); return; } @@ -1690,14 +3070,29 @@ namespace ProxySU { currentStatus = "Trojan安装成功!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - client.RunCommand("systemctl enable trojan"); + //client.RunCommand("systemctl enable trojan"); + sshShellCommand = @"systemctl enable trojan"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } - client.RunCommand("mv /usr/local/etc/trojan/config.json /usr/local/etc/trojan/config.json.1"); + //client.RunCommand("mv /usr/local/etc/trojan/config.json /usr/local/etc/trojan/config.json.1"); + sshShellCommand = @"mv /usr/local/etc/trojan/config.json /usr/local/etc/trojan/config.json.1"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 //上传配置文件 currentStatus = "Trojan程序安装完毕,配置文件上传中......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); //生成服务端配置 @@ -1718,91 +3113,138 @@ namespace ProxySU File.Delete(@"config.json"); - //打开防火墙端口 - string openFireWallPort = ReceiveConfigurationParameters[1]; - if (String.IsNullOrEmpty(client.RunCommand("command -v firewall-cmd").Result) == false) - { - if (String.Equals(openFireWallPort, "443")) - { - client.RunCommand("firewall-cmd --zone=public --add-port=80/tcp --permanent"); - client.RunCommand("firewall-cmd --zone=public --add-port=443/tcp --permanent"); - client.RunCommand("firewall-cmd --reload"); - } - else - { - client.RunCommand($"firewall-cmd --zone=public --add-port={openFireWallPort}/tcp --permanent"); - client.RunCommand($"firewall-cmd --zone=public --add-port={openFireWallPort}/udp --permanent"); - client.RunCommand("firewall-cmd --reload"); - } - } - if (String.IsNullOrEmpty(client.RunCommand("command -v ufw").Result) == false) - { - if (String.Equals(openFireWallPort, "443")) - { - client.RunCommand("ufw allow 80"); - client.RunCommand("ufw allow 443"); - client.RunCommand("yes | ufw reload"); - } - else - { - client.RunCommand($"ufw allow {openFireWallPort}/tcp"); - client.RunCommand($"ufw allow {openFireWallPort}/udp"); - client.RunCommand("yes | ufw reload"); - } - } + ////打开防火墙端口 + //string openFireWallPort = ReceiveConfigurationParameters[1]; + //if (String.IsNullOrEmpty(client.RunCommand("command -v firewall-cmd").Result) == false) + //{ + // if (String.Equals(openFireWallPort, "443")) + // { + // client.RunCommand("firewall-cmd --zone=public --add-port=80/tcp --permanent"); + // client.RunCommand("firewall-cmd --zone=public --add-port=443/tcp --permanent"); + // client.RunCommand("firewall-cmd --reload"); + // } + // else + // { + // client.RunCommand($"firewall-cmd --zone=public --add-port={openFireWallPort}/tcp --permanent"); + // client.RunCommand($"firewall-cmd --zone=public --add-port={openFireWallPort}/udp --permanent"); + // client.RunCommand("firewall-cmd --reload"); + // } + //} + //if (String.IsNullOrEmpty(client.RunCommand("command -v ufw").Result) == false) + //{ + // if (String.Equals(openFireWallPort, "443")) + // { + // client.RunCommand("ufw allow 80"); + // client.RunCommand("ufw allow 443"); + // client.RunCommand("yes | ufw reload"); + // } + // else + // { + // client.RunCommand($"ufw allow {openFireWallPort}/tcp"); + // client.RunCommand($"ufw allow {openFireWallPort}/udp"); + // client.RunCommand("yes | ufw reload"); + // } + //} - currentStatus = "使用Trojan+TLS+Web模式,正在安装acme.sh......"; + currentStatus = "正在安装acme.sh......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - if (getApt == false) - { - //client.RunCommand("apt-get -qq update"); - client.RunCommand("apt-get -y -qq install socat"); - } - else if (getDnf == false) - { - //client.RunCommand("yum -q makecache"); - client.RunCommand("dnf -y -q install socat"); - } - else if (getYum == false) - { - //client.RunCommand("yum -q makecache"); - client.RunCommand("yum -y -q install socat"); - } + //安装所依赖的软件 + sshShellCommand = $"{sshCmdUpdate}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"{sshCmdInstall}socat"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + //if (getApt == false) + //{ + // //client.RunCommand("apt-get -qq update"); + // client.RunCommand("apt-get -y -qq install socat"); + //} + //else if (getDnf == false) + //{ + // //client.RunCommand("yum -q makecache"); + // client.RunCommand("dnf -y -q install socat"); + //} + //else if (getYum == false) + //{ + // //client.RunCommand("yum -q makecache"); + // client.RunCommand("yum -y -q install socat"); + //} //else if (getZypper == false) //{ // // client.RunCommand("zypper ref"); // client.RunCommand("zypper -y install socat"); //} - client.RunCommand("curl https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | INSTALLONLINE=1 sh"); - client.RunCommand("cd ~/.acme.sh/"); - client.RunCommand("alias acme.sh=~/.acme.sh/acme.sh"); + //client.RunCommand("curl https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | INSTALLONLINE=1 sh"); + //client.RunCommand("cd ~/.acme.sh/"); + //client.RunCommand("alias acme.sh=~/.acme.sh/acme.sh"); + sshShellCommand = @"curl https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | INSTALLONLINE=1 sh"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"cd ~/.acme.sh/"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"alias acme.sh=~/.acme.sh/acme.sh"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + currentStatus = "申请域名证书......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); //client.RunCommand("mkdir -p /etc/v2ray/ssl"); - client.RunCommand($"/root/.acme.sh/acme.sh --issue --standalone -d {ReceiveConfigurationParameters[4]}"); + //client.RunCommand($"/root/.acme.sh/acme.sh --issue --standalone -d {ReceiveConfigurationParameters[4]}"); + sshShellCommand = $"/root/.acme.sh/acme.sh --issue --standalone -d {ReceiveConfigurationParameters[4]}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 currentStatus = "安装证书到Trojan......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); - Thread.Sleep(1000); - client.RunCommand($"/root/.acme.sh/acme.sh --installcert -d {ReceiveConfigurationParameters[4]} --certpath /usr/local/etc/trojan/trojan_ssl.crt --keypath /usr/local/etc/trojan/trojan_ssl.key --capath /usr/local/etc/trojan/trojan_ssl.crt --reloadcmd \"systemctl restart trojan\""); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - currentStatus = "正在启动Trojan......"; - textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); Thread.Sleep(1000); - client.RunCommand("systemctl restart trojan"); + //client.RunCommand($"/root/.acme.sh/acme.sh --installcert -d {ReceiveConfigurationParameters[4]} --certpath /usr/local/etc/trojan/trojan_ssl.crt --keypath /usr/local/etc/trojan/trojan_ssl.key --capath /usr/local/etc/trojan/trojan_ssl.crt --reloadcmd \"systemctl restart trojan\""); + sshShellCommand = $"/root/.acme.sh/acme.sh --installcert -d {ReceiveConfigurationParameters[4]} --certpath /usr/local/etc/trojan/trojan_ssl.crt --keypath /usr/local/etc/trojan/trojan_ssl.key --capath /usr/local/etc/trojan/trojan_ssl.crt --reloadcmd \"systemctl restart trojan\""; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - currentStatus = "Trojan启动成功!"; - textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); - Thread.Sleep(1000); + //currentStatus = "正在启动Trojan......"; + //textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + //Thread.Sleep(1000); + + //client.RunCommand("systemctl restart trojan"); + + //currentStatus = "Trojan启动成功!"; + //textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + //Thread.Sleep(1000); currentStatus = "正在安装Caddy"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); //client.RunCommand("curl https://getcaddy.com -o getcaddy"); @@ -1814,55 +3256,176 @@ namespace ProxySU //为假则表示系统有相应的组件。 if (getApt == false) { - client.RunCommand(@"echo ""deb [trusted=yes] https://apt.fury.io/caddy/ /"" | tee -a /etc/apt/sources.list.d/caddy-fury.list"); - client.RunCommand("apt install -y apt-transport-https"); - client.RunCommand("apt -qq update"); - client.RunCommand("apt -y -qq install caddy"); + //client.RunCommand(@"echo ""deb [trusted=yes] https://apt.fury.io/caddy/ /"" | tee -a /etc/apt/sources.list.d/caddy-fury.list"); + //client.RunCommand("apt install -y apt-transport-https"); + //client.RunCommand("apt -qq update"); + //client.RunCommand("apt -y -qq install caddy"); + sshShellCommand = @"echo ""deb [trusted=yes] https://apt.fury.io/caddy/ /"" | tee -a /etc/apt/sources.list.d/caddy-fury.list"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"apt install -y apt-transport-https"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"apt -qq update"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"apt -y -qq install caddy"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } else if (getDnf == false) { - client.RunCommand(@"dnf install 'dnf-command(copr)' -y"); - client.RunCommand(@"dnf copr enable @caddy/caddy -y"); - //client.RunCommand("dnf -q makecache"); - client.RunCommand("dnf -y -q install caddy"); + //client.RunCommand(@"dnf install 'dnf-command(copr)' -y"); + //client.RunCommand(@"dnf copr enable @caddy/caddy -y"); + ////client.RunCommand("dnf -q makecache"); + //client.RunCommand("dnf -y -q install caddy"); + sshShellCommand = @"dnf install 'dnf-command(copr)' -y"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"dnf copr enable @caddy/caddy -y"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + //sshShellCommand = @"dnf -q makecache"; + //TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + //currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + //TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"dnf -y -q install caddy"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } else if (getYum == false) { - client.RunCommand(@"yum install yum-plugin-copr -y"); - client.RunCommand(@"yum copr enable @caddy/caddy -y"); - //client.RunCommand("yum -q makecache"); - client.RunCommand("yum -y -q install caddy"); + //client.RunCommand(@"yum install yum-plugin-copr -y"); + //client.RunCommand(@"yum copr enable @caddy/caddy -y"); + ////client.RunCommand("yum -q makecache"); + //client.RunCommand("yum -y -q install caddy"); + sshShellCommand = @"yum install yum-plugin-copr -y"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"yum copr enable @caddy/caddy -y"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + //sshShellCommand = @"yum -q makecache"; + //TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + //currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + //TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"yum -y -q install caddy"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } + //if (getApt == false) + //{ + // client.RunCommand(@"echo ""deb [trusted=yes] https://apt.fury.io/caddy/ /"" | tee -a /etc/apt/sources.list.d/caddy-fury.list"); + // client.RunCommand("apt install -y apt-transport-https"); + // client.RunCommand("apt -qq update"); + // client.RunCommand("apt -y -qq install caddy"); + //} + //else if (getDnf == false) + //{ + // client.RunCommand(@"dnf install 'dnf-command(copr)' -y"); + // client.RunCommand(@"dnf copr enable @caddy/caddy -y"); + // //client.RunCommand("dnf -q makecache"); + // client.RunCommand("dnf -y -q install caddy"); + //} + //else if (getYum == false) + //{ + // client.RunCommand(@"yum install yum-plugin-copr -y"); + // client.RunCommand(@"yum copr enable @caddy/caddy -y"); + // //client.RunCommand("yum -q makecache"); + // client.RunCommand("yum -y -q install caddy"); + //} //else if (getZypper == false) //{ // client.RunCommand("zypper ref"); // client.RunCommand("zypper -y install curl"); //} - installResult = client.RunCommand("find / -name caddy").Result.ToString(); + + sshShellCommand = @"find / -name caddy"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + installResult = currentShellCommandResult; if (!installResult.Contains("/usr/bin/caddy")) { MessageBox.Show("安装Caddy失败!"); + currentStatus = "安装Caddy失败!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + client.Disconnect(); return; } - else - { - currentStatus = "Caddy安装成功!"; - textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); - Thread.Sleep(1000); - client.RunCommand("systemctl enable caddy"); - } + + currentStatus = "Caddy安装成功!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); + //client.RunCommand("systemctl enable caddy"); + sshShellCommand = @"systemctl enable caddy"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + + //if (!installResult.Contains("/usr/bin/caddy")) + //{ + // MessageBox.Show("安装Caddy失败!"); + // currentStatus = "安装Caddy失败!"; + // textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + // client.Disconnect(); + // return; + //} + //else + //{ + // currentStatus = "Caddy安装成功!"; + // textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + // Thread.Sleep(1000); + // client.RunCommand("systemctl enable caddy"); + //} currentStatus = "上传Caddy配置文件......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); + sshShellCommand = @"mv /etc/caddy/Caddyfile /etc/caddy/Caddyfile.bak"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + string caddyConfig = "TemplateConfg\\trojan_caddy_config.caddyfile"; upLoadPath = "/etc/caddy/Caddyfile"; - client.RunCommand("mv /etc/caddy/Caddyfile /etc/caddy/Caddyfile.bak"); + //client.RunCommand("mv /etc/caddy/Caddyfile /etc/caddy/Caddyfile.bak"); UploadConfig(connectionInfo, caddyConfig, upLoadPath); ////设置Caddyfile文件中的tls 邮箱 @@ -1870,50 +3433,172 @@ namespace ProxySU //string email = $"user@{ReceiveConfigurationParameters[4]}"; //string sshCmd; //设置域名 - string sshCmd = $"sed -i 's/##domain##/{ReceiveConfigurationParameters[4]}:80/' {upLoadPath}"; - client.RunCommand(sshCmd); + //string sshCmd = $"sed -i 's/##domain##/{ReceiveConfigurationParameters[4]}/' {upLoadPath}"; + //client.RunCommand(sshCmd); + sshShellCommand = $"sed -i 's/##domain##/{ReceiveConfigurationParameters[4]}/' {upLoadPath}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + //设置伪装网站 if (String.IsNullOrEmpty(ReceiveConfigurationParameters[7]) == false) { - sshCmd = $"sed -i 's/##sites##/proxy \\/ {ReceiveConfigurationParameters[7]}/' {upLoadPath}"; - //MessageBox.Show(sshCmd); - client.RunCommand(sshCmd); - } - // Thread.Sleep(2000); - - //安装Caddy服务 - //sshCmd = $"caddy -service install -agree -conf /etc/caddy/Caddyfile -email {email}"; - //MessageBox.Show(sshCmd); + //sshCmd = $"sed -i 's/##sites##/proxy \\/ {ReceiveConfigurationParameters[7]}/' {upLoadPath}"; //client.RunCommand(sshCmd); + sshShellCommand = $"sed -i 's/##sites##/proxy \\/ {ReceiveConfigurationParameters[7]}/' {upLoadPath}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + currentStatus = "Caddy配置文件上传成功,OK!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); + // Thread.Sleep(2000); + + //安装Caddy服务 + //sshCmd = $"caddy -service install -agree -conf /etc/caddy/Caddyfile -email {email}"; + //MessageBox.Show(sshCmd); + //client.RunCommand(sshCmd); + + currentStatus = "正在启动Caddy......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); + //启动Caddy服务 + sshShellCommand = @"systemctl restart caddy"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + currentStatus = "Caddy启动成功!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); + + currentStatus = "正在启动Trojan......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); + //启动Trojan-go服务 + //client.RunCommand("systemctl restart trojan-go"); + sshShellCommand = @"systemctl restart trojan"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - //启动Caddy服务 - client.RunCommand("systemctl restart caddy"); - //} + currentStatus = "Trojan启动成功!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); //测试BBR条件,若满足提示是否启用 - var result = client.RunCommand("uname -r"); - string[] linuxKernelVerStr = result.Result.Split('-'); + currentStatus = "BBR测试......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); + + //var result = client.RunCommand("uname -r"); + sshShellCommand = @"uname -r"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string[] linuxKernelVerStr = currentShellCommandResult.Split('-'); bool detectResult = DetectKernelVersionBBR(linuxKernelVerStr[0]); - string resultCmdTestBBR = client.RunCommand(@"sysctl net.ipv4.tcp_congestion_control | grep bbr").Result; + //client.RunCommand(@"sysctl net.ipv4.tcp_congestion_control | grep bbr").Result; + sshShellCommand = @"sysctl net.ipv4.tcp_congestion_control | grep bbr"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + string resultCmdTestBBR = currentShellCommandResult; //如果内核满足大于等于4.9,且还未启用BBR,则启用BBR if (detectResult == true && resultCmdTestBBR.Contains("bbr") == false) { - client.RunCommand(@"bash -c 'echo ""net.core.default_qdisc=fq"" >> /etc/sysctl.conf'"); - client.RunCommand(@"bash -c 'echo ""net.ipv4.tcp_congestion_control=bbr"" >> /etc/sysctl.conf'"); - client.RunCommand(@"sysctl -p"); + currentStatus = "正在启用BBR......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); + + //client.RunCommand(@"bash -c 'echo ""net.core.default_qdisc=fq"" >> /etc/sysctl.conf'"); + //client.RunCommand(@"bash -c 'echo ""net.ipv4.tcp_congestion_control=bbr"" >> /etc/sysctl.conf'"); + //client.RunCommand(@"sysctl -p"); + sshShellCommand = @"bash -c 'echo ""net.core.default_qdisc=fq"" >> /etc/sysctl.conf'"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"bash -c 'echo ""net.ipv4.tcp_congestion_control=bbr"" >> /etc/sysctl.conf'"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"sysctl -p"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } + else if (resultCmdTestBBR.Contains("bbr") == true) + { + currentStatus = "BBR已经启用了!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + else + { + currentStatus = "系统不满足启用BBR的条件,启用失败!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + client.Disconnect();//断开服务器ssh连接 + //var result = client.RunCommand("uname -r"); + //string[] linuxKernelVerStr = result.Result.Split('-'); + + //bool detectResult = DetectKernelVersionBBR(linuxKernelVerStr[0]); + //string resultCmdTestBBR = client.RunCommand(@"sysctl net.ipv4.tcp_congestion_control | grep bbr").Result; + ////如果内核满足大于等于4.9,且还未启用BBR,则启用BBR + //if (detectResult == true && resultCmdTestBBR.Contains("bbr") == false) + //{ + // client.RunCommand(@"bash -c 'echo ""net.core.default_qdisc=fq"" >> /etc/sysctl.conf'"); + // client.RunCommand(@"bash -c 'echo ""net.ipv4.tcp_congestion_control=bbr"" >> /etc/sysctl.conf'"); + // client.RunCommand(@"sysctl -p"); + //} //生成客户端配置 currentStatus = "生成客户端配置......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); if (!Directory.Exists("trojan_config"))//如果不存在就创建file文件夹      { Directory.CreateDirectory("trojan_config");//创建该文件夹   } //string clientConfig = "TemplateConfg\\tcp_client_config.json"; + clientConfig = "TemplateConfg\\trojan_client_config.json"; using (StreamReader reader = File.OpenText(clientConfig)) { JObject clientJson = (JObject)JToken.ReadFrom(new JsonTextReader(reader)); @@ -1928,10 +3613,13 @@ namespace ProxySU } } - client.Disconnect(); + //client.Disconnect(); - currentStatus = "安装成功"; + currentStatus = "Trojan安装成功,祝您使用愉快!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); //显示服务端连接参数 @@ -1974,13 +3662,15 @@ namespace ProxySU } currentStatus = "主机登录失败"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 } #endregion } - //检测升级远程主机Trojan版本 + //检测升级远程主机Trojan版本传递参数 private void ButtonUpdateTrojan_Click(object sender, RoutedEventArgs e) { ConnectionInfo connectionInfo = GenerateConnectionInfo(); @@ -1999,8 +3689,10 @@ namespace ProxySU private void UpdateTojan(ConnectionInfo connectionInfo, TextBlock textBlockName, ProgressBar progressBar) { string currentStatus = "正在登录远程主机......"; - Action updateAction = new Action(UpdateTextBlock); + //Action updateAction = new Action(UpdateTextBlock); textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 try { @@ -2039,23 +3731,55 @@ namespace ProxySU { currentStatus = "主机登录成功"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果在监视窗口 + Thread.Sleep(1000); } //检测是否运行在root权限下 - string testRootAuthority = client.RunCommand(@"id -u").Result; + currentShellCommandResult = "检测是否运行在root权限下..."; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"id -u"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string testRootAuthority = currentShellCommandResult; if (testRootAuthority.Equals("0\n") == false) { MessageBox.Show("请使用具有root权限的账户登录主机!!"); client.Disconnect(); return; } - //检测远程主机V2ray版本 + else + { + currentShellCommandResult = "检测结果:OK!"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + //string testRootAuthority = client.RunCommand(@"id -u").Result; + //if (testRootAuthority.Equals("0\n") == false) + //{ + // MessageBox.Show("请使用具有root权限的账户登录主机!!"); + // client.Disconnect(); + // return; + //} + //检测远程主机Trojan版本 currentStatus = "检测远程主机Trojan版本......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - string cmdTestTrojanInstalled = @"find / -name trojan"; - string resultCmdTestTrojanInstalled = client.RunCommand(cmdTestTrojanInstalled).Result; + //string cmdTestTrojanInstalled = @"find / -name trojan"; + //string resultCmdTestTrojanInstalled = client.RunCommand(cmdTestTrojanInstalled).Result; + sshShellCommand = @"find / -name trojan"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + string resultCmdTestTrojanInstalled = currentShellCommandResult; if (resultCmdTestTrojanInstalled.Contains("/usr/local/bin/trojan") == false) { @@ -2063,18 +3787,34 @@ namespace ProxySU currentStatus = "未安装Trojan,退出"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); client.Disconnect(); return; } - //string sshcmd; - string sshcmd = @"echo ""$(/usr/local/bin/trojan -v 2>&1)"" | head -n 1 | cut -d "" "" -f4"; - string trojanCurrentVersion = client.RunCommand(sshcmd).Result;//不含字母v + //获取当前安装的版本 + //string sshcmd = @"echo ""$(/usr/local/bin/trojan -v 2>&1)"" | head -n 1 | cut -d "" "" -f4"; + //string trojanCurrentVersion = client.RunCommand(sshcmd).Result;//不含字母v + sshShellCommand = @"echo ""$(/usr/local/bin/trojan -v 2>&1)"" | head -n 1 | cut -d "" "" -f4"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - sshcmd = @"curl -fsSL https://api.github.com/repos/trojan-gfw/trojan/releases/latest | grep tag_name | sed -E 's/.*""v(.*)"".*/\1/'"; + string trojanCurrentVersion = currentShellCommandResult;//不含字母v + - string trojanNewVersion = client.RunCommand(sshcmd).Result;//不包含字母v + //sshcmd = @"curl -fsSL https://api.github.com/repos/trojan-gfw/trojan/releases/latest | grep tag_name | sed -E 's/.*""v(.*)"".*/\1/'"; + //获取最新版本 + + sshShellCommand = @"curl -fsSL https://api.github.com/repos/trojan-gfw/trojan/releases/latest | grep tag_name | sed -E 's/.*""v(.*)"".*/\1/'"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string trojanNewVersion = currentShellCommandResult;//不含字母v if (trojanNewVersion.Equals(trojanCurrentVersion) == false) { @@ -2083,27 +3823,73 @@ namespace ProxySU { currentStatus = "正在升级Trojan到最新版本......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); //备份配置文件 - sshcmd = @"mv /usr/local/etc/trojan/config.json /usr/local/etc/trojan/config.json.bak"; - client.RunCommand(sshcmd); - //升级Trojan主程序 - client.RunCommand("curl -o /tmp/trojan-quickstart.sh https://raw.githubusercontent.com/trojan-gfw/trojan-quickstart/master/trojan-quickstart.sh"); - client.RunCommand("yes | bash /tmp/trojan-quickstart.sh"); - sshcmd = @"echo ""$(/usr/local/bin/trojan -v 2>&1)"" | head -n 1 | cut -d "" "" -f4"; + currentStatus = "备份Trojan配置文件......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - trojanCurrentVersion = client.RunCommand(sshcmd).Result;//不含字母v + //string sshcmd = @"mv /usr/local/etc/trojan/config.json /usr/local/etc/trojan/config.json.bak"; + //client.RunCommand(sshcmd); + sshShellCommand = @"mv /usr/local/etc/trojan/config.json /usr/local/etc/trojan/config.json.bak"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + //升级Trojan主程序 + //client.RunCommand("curl -o /tmp/trojan-quickstart.sh https://raw.githubusercontent.com/trojan-gfw/trojan-quickstart/master/trojan-quickstart.sh"); + //client.RunCommand("yes | bash /tmp/trojan-quickstart.sh"); + sshShellCommand = @"curl -o /tmp/trojan-quickstart.sh https://raw.githubusercontent.com/trojan-gfw/trojan-quickstart/master/trojan-quickstart.sh"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"yes | bash /tmp/trojan-quickstart.sh"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + //sshcmd = @"echo ""$(/usr/local/bin/trojan -v 2>&1)"" | head -n 1 | cut -d "" "" -f4"; + sshShellCommand = @"echo ""$(/usr/local/bin/trojan -v 2>&1)"" | head -n 1 | cut -d "" "" -f4"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + trojanCurrentVersion = currentShellCommandResult;//不含字母v + //trojanCurrentVersion = client.RunCommand(sshcmd).Result;//不含字母v if (trojanNewVersion.Equals(trojanCurrentVersion) == true) { //恢复原来的配置文件备份 - sshcmd = @"rm -f /usr/local/etc/trojan/config.json"; - client.RunCommand(sshcmd); - sshcmd = @"mv /usr/local/etc/trojan/config.json.bak /usr/local/etc/trojan/config.json"; - client.RunCommand(sshcmd); + currentStatus = "恢复Trojan配置文件......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + //sshcmd = @"rm -f /usr/local/etc/trojan/config.json"; + //client.RunCommand(sshcmd); + sshShellCommand = @"rm -f /usr/local/etc/trojan/config.json"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + //sshcmd = @"mv /usr/local/etc/trojan/config.json.bak /usr/local/etc/trojan/config.json"; + //client.RunCommand(sshcmd); + sshShellCommand = @"mv /usr/local/etc/trojan/config.json.bak /usr/local/etc/trojan/config.json"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + MessageBox.Show($"升级成功!!\n当前版本为:v{trojanCurrentVersion}\n最新版本为:{trojanNewVersion}"); currentStatus = "升级成功!当前已是最新版本!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); } else @@ -2111,6 +3897,9 @@ namespace ProxySU MessageBox.Show("升级失败,原因未知,请向开发者提问,以寻求支持!"); currentStatus = "升级失败!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); } } @@ -2119,6 +3908,9 @@ namespace ProxySU { currentStatus = "升级取消,退出"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); client.Disconnect(); return; @@ -2129,6 +3921,9 @@ namespace ProxySU MessageBox.Show($"远程主机当前已是最新版本:{trojanNewVersion}\n无需升级!"); currentStatus = "已是最新版本,无需升级,退出"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); } @@ -2168,6 +3963,8 @@ namespace ProxySU } currentStatus = "主机登录失败"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 } #endregion @@ -2223,8 +4020,10 @@ namespace ProxySU private void StartSetUpTrojanGo(ConnectionInfo connectionInfo, TextBlock textBlockName, ProgressBar progressBar, string serverConfig, string clientConfig, string upLoadPath) { string currentStatus = "正在登录远程主机......"; - Action updateAction = new Action(UpdateTextBlock); + //Action updateAction = new Action(UpdateTextBlock); textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 try { @@ -2263,24 +4062,48 @@ namespace ProxySU { currentStatus = "主机登录成功"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果在监视窗口 + Thread.Sleep(1000); } //检测是否运行在root权限下 - string testRootAuthority = client.RunCommand(@"id -u").Result; + currentShellCommandResult = "检测是否运行在root权限下..."; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"id -u"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string testRootAuthority = currentShellCommandResult; if (testRootAuthority.Equals("0\n") == false) { MessageBox.Show("请使用具有root权限的账户登录主机!!"); client.Disconnect(); return; } + else + { + currentShellCommandResult = "检测结果:OK!"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } //检测是否安装有Trojan-Go currentStatus = "检测系统是否已经安装Trojan-Go......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - //string cmdTestTrojanInstalled = @"find / -name trojan"; - string resultCmdTestTrojanInstalled = client.RunCommand(@"find / -name trojan-go").Result; + sshShellCommand = @"find / -name trojan-go"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string resultCmdTestTrojanInstalled = currentShellCommandResult; if (resultCmdTestTrojanInstalled.Contains("/usr/local/bin/trojan-go") == true) { @@ -2289,48 +4112,176 @@ namespace ProxySU { currentStatus = "安装取消,退出"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); client.Disconnect(); return; } + else + { + currentStatus = "已选择强制安装Trojan-go!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); + + } + } + else + { + currentShellCommandResult = "检测结果:未安装Trojan-go!"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } //检测远程主机系统环境是否符合要求 currentStatus = "检测系统是否符合安装要求......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - //检测系统是否支持yum 或 apt-get或zypper,且支持Systemd + //检测系统是否支持dnf\yum 或 apt或zypper,且支持Systemd //如果不存在组件,则命令结果为空,string.IsNullOrEmpty值为真, - bool getApt = String.IsNullOrEmpty(client.RunCommand("command -v apt").Result); - bool getDnf = String.IsNullOrEmpty(client.RunCommand("command -v dnf").Result); - bool getYum = String.IsNullOrEmpty(client.RunCommand("command -v yum").Result); - bool getZypper = String.IsNullOrEmpty(client.RunCommand("command -v zypper").Result); - bool getSystemd = String.IsNullOrEmpty(client.RunCommand("command -v systemctl").Result); - bool getGetenforce = String.IsNullOrEmpty(client.RunCommand("command -v getenforce").Result); + //bool getApt = String.IsNullOrEmpty(client.RunCommand("command -v apt").Result); + //bool getDnf = String.IsNullOrEmpty(client.RunCommand("command -v dnf").Result); + //bool getYum = String.IsNullOrEmpty(client.RunCommand("command -v yum").Result); + //bool getZypper = String.IsNullOrEmpty(client.RunCommand("command -v zypper").Result); + //bool getSystemd = String.IsNullOrEmpty(client.RunCommand("command -v systemctl").Result); + //bool getGetenforce = String.IsNullOrEmpty(client.RunCommand("command -v getenforce").Result); + + sshShellCommand = @"command -v apt"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + bool getApt = String.IsNullOrEmpty(currentShellCommandResult); + + sshShellCommand = @"command -v dnf"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + bool getDnf = String.IsNullOrEmpty(currentShellCommandResult); + + sshShellCommand = @"command -v yum"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + bool getYum = String.IsNullOrEmpty(currentShellCommandResult); + + sshShellCommand = @"command -v zypper"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + bool getZypper = String.IsNullOrEmpty(currentShellCommandResult); + + sshShellCommand = @"command -v systemctl"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + bool getSystemd = String.IsNullOrEmpty(currentShellCommandResult); + + sshShellCommand = @"command -v getenforce"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + bool getGetenforce = String.IsNullOrEmpty(currentShellCommandResult); //没有安装apt,也没有安装dnf\yum,也没有安装zypper,或者没有安装systemd的,不满足安装条件 //也就是apt ,dnf\yum, zypper必须安装其中之一,且必须安装Systemd的系统才能安装。 - if ((getApt && getYum && getZypper) || getSystemd) + if ((getApt && getDnf && getYum && getZypper) || getSystemd) { - MessageBox.Show($"系统缺乏必要的安装组件如:apt-get||yum||zypper||Syetemd,主机系统推荐使用:CentOS 7/8,Debian 8/9/10,Ubuntu 16.04及以上版本"); + MessageBox.Show($"系统缺乏必要的安装组件如:apt||dnf||yum||zypper||Syetemd,主机系统推荐使用:CentOS 7/8,Debian 8/9/10,Ubuntu 16.04及以上版本"); currentStatus = "系统环境不满足要求,安装失败!!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); client.Disconnect(); return; } + else + { + currentStatus = "检测结果:OK!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + //设置安装软件所用的命令格式 + //为假则表示系统有相应的组件。 + + if (getApt == false) + { + //client.RunCommand("apt -qq update"); + //client.RunCommand("apt -y -qq install curl"); + sshCmdUpdate = @"apt -qq update"; + sshCmdInstall = @"apt -y -qq install "; + } + else if (getDnf == false) + { + //client.RunCommand("dnf -q makecache"); + //client.RunCommand("dnf -y -q install curl"); + sshCmdUpdate = @"dnf -q makecache"; + sshCmdInstall = @"dnf -y -q install "; + } + else if (getYum == false) + { + //client.RunCommand("yum -q makecache"); + //client.RunCommand("yum -y -q install curl"); + sshCmdUpdate = @"yum -q makecache"; + sshCmdInstall = @"yum -y -q install "; + } + else if (getZypper == false) + { + //client.RunCommand("zypper ref"); + //client.RunCommand("zypper -y install curl"); + sshCmdUpdate = @"zypper ref"; + sshCmdInstall = @"zypper -y install "; + } + //判断是否启用了SELinux,如果启用了,并且工作在Enforcing模式下,则改为Permissive模式 if (getGetenforce == false) { - string testSELinux = client.RunCommand("getenforce").Result; + // string testSELinux = client.RunCommand("getenforce").Result; + sshShellCommand = @"getenforce"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string testSELinux = currentShellCommandResult; //MessageBox.Show(testSELinux); if (testSELinux.Contains("Enforcing") == true) { + currentStatus = "检测到系统启用SELinux,且工作在严格模式下,需改为宽松模式!修改中..."; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + //MessageBox.Show("Enforcing"); - client.RunCommand("setenforce 0");//不重启改为Permissive模式 - client.RunCommand("sed -i 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config");//重启也工作在Permissive模式下 + // client.RunCommand("setenforce 0");//不重启改为Permissive模式 + // client.RunCommand("sed -i 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config");//重启也工作在Permissive模式下 + sshShellCommand = @"setenforce 0"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + sshShellCommand = @"sed -i 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + currentStatus = "修改完毕!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } } @@ -2339,48 +4290,78 @@ namespace ProxySU currentStatus = "正在检测域名是否解析到当前VPS的IP上......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); //在相应系统内安装curl(如果没有安装curl) if (string.IsNullOrEmpty(client.RunCommand("command -v curl").Result) == true) { - //为假则表示系统有相应的组件。 - if (getApt == false) - { - client.RunCommand("apt-get -qq update"); - client.RunCommand("apt-get -y -qq install curl"); - } - else if (getDnf == false) - { - client.RunCommand("dnf -q makecache"); - client.RunCommand("dnf -y -q install curl"); - } - else if (getYum == false) - { - client.RunCommand("yum -q makecache"); - client.RunCommand("yum -y -q install curl"); - } - else if (getZypper == false) - { - client.RunCommand("zypper ref"); - client.RunCommand("zypper -y install curl"); - } + sshShellCommand = $"{sshCmdUpdate}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"{sshCmdInstall}curl"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + ////为假则表示系统有相应的组件。 + //if (getApt == false) + //{ + // client.RunCommand("apt-get -qq update"); + // client.RunCommand("apt-get -y -qq install curl"); + //} + //else if (getDnf == false) + //{ + // client.RunCommand("dnf -q makecache"); + // client.RunCommand("dnf -y -q install curl"); + //} + //else if (getYum == false) + //{ + // client.RunCommand("yum -q makecache"); + // client.RunCommand("yum -y -q install curl"); + //} + //else if (getZypper == false) + //{ + // client.RunCommand("zypper ref"); + // client.RunCommand("zypper -y install curl"); + //} } - string nativeIp = client.RunCommand("curl -4 ip.sb").Result.ToString(); - string testDomainCmd = "ping " + ReceiveConfigurationParameters[4] + " -c 1 | grep -oE -m1 \"([0-9]{1,3}\\.){3}[0-9]{1,3}\""; - string resultTestDomainCmd = client.RunCommand(testDomainCmd).Result.ToString(); + sshShellCommand = @"curl -4 ip.sb"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string nativeIp = currentShellCommandResult; + + sshShellCommand = "ping " + ReceiveConfigurationParameters[4] + " -c 1 | grep -oE -m1 \"([0-9]{1,3}\\.){3}[0-9]{1,3}\""; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + //string testDomainCmd = "ping " + ReceiveConfigurationParameters[4] + " -c 1 | grep -oE -m1 \"([0-9]{1,3}\\.){3}[0-9]{1,3}\""; + string resultTestDomainCmd = currentShellCommandResult; if (String.Equals(nativeIp, resultTestDomainCmd) == true) { currentStatus = "解析正确!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); } else { currentStatus = "域名未能正确解析到当前VPS的IP上!安装失败!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); MessageBox.Show("域名未能正确解析到当前VPS的IP上,请检查!若解析设置正确,请等待生效后再重试安装。如果域名使用了CDN,请先关闭!"); client.Disconnect(); @@ -2390,40 +4371,68 @@ namespace ProxySU //检测是否安装lsof if (string.IsNullOrEmpty(client.RunCommand("command -v lsof").Result) == true) { + sshShellCommand = $"{sshCmdUpdate}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"{sshCmdInstall}lsof"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + //为假则表示系统有相应的组件。 - if (getApt == false) - { - client.RunCommand("apt -qq update"); - client.RunCommand("apt -y -qq install lsof"); - } - else if (getDnf == false) - { - client.RunCommand("dnf -q makecache"); - client.RunCommand("dnf -y -q install lsof"); - } - else if (getYum == false) - { - client.RunCommand("yum -q makecache"); - client.RunCommand("yum -y -q install lsof"); - } - else if (getZypper == false) - { - client.RunCommand("zypper ref"); - client.RunCommand("zypper -y install lsof"); - } + //if (getApt == false) + //{ + // client.RunCommand("apt -qq update"); + // client.RunCommand("apt -y -qq install lsof"); + //} + //else if (getDnf == false) + //{ + // client.RunCommand("dnf -q makecache"); + // client.RunCommand("dnf -y -q install lsof"); + //} + //else if (getYum == false) + //{ + // client.RunCommand("yum -q makecache"); + // client.RunCommand("yum -y -q install lsof"); + //} + //else if (getZypper == false) + //{ + // client.RunCommand("zypper ref"); + // client.RunCommand("zypper -y install lsof"); + //} } currentStatus = "正在检测端口占用情况......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); //MessageBox.Show(@"lsof -n -P -i :80 | grep LISTEN"); //MessageBox.Show(client.RunCommand(@"lsof -n -P -i :80 | grep LISTEN").Result); - if (String.IsNullOrEmpty(client.RunCommand(@"lsof -n -P -i :80 | grep LISTEN").Result) == false || String.IsNullOrEmpty(client.RunCommand(@"lsof -n -P -i :443 | grep LISTEN").Result) == false) + sshShellCommand = @"lsof -n -P -i :80 | grep LISTEN"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + string testPort80 = currentShellCommandResult; + + sshShellCommand = @"lsof -n -P -i :443 | grep LISTEN"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + string testPort443 = currentShellCommandResult; + + if (String.IsNullOrEmpty(testPort80) == false || String.IsNullOrEmpty(testPort443) == false) { MessageBoxResult dialogResult = MessageBox.Show("80/443端口之一,或全部被占用,将强制停止占用80/443端口的程序?", "Stop application", MessageBoxButton.YesNo); if (dialogResult == MessageBoxResult.No) { currentStatus = "端口被占用,安装失败......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); client.Disconnect(); return; @@ -2431,42 +4440,162 @@ namespace ProxySU currentStatus = "正在释放80/443端口......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - string cmdTestPort = @"lsof -n -P -i :443 | grep LISTEN"; - string cmdResult = client.RunCommand(cmdTestPort).Result; + //string cmdTestPort = @"lsof -n -P -i :443 | grep LISTEN"; + //string cmdResult = client.RunCommand(cmdTestPort).Result; - if (String.IsNullOrEmpty(cmdResult) == false) + if (String.IsNullOrEmpty(testPort443) == false) { - string[] cmdResultArry443 = cmdResult.Split(' '); - client.RunCommand($"systemctl stop {cmdResultArry443[0]}"); - client.RunCommand($"systemctl disable {cmdResultArry443[0]}"); - client.RunCommand($"kill -9 {cmdResultArry443[3]}"); + string[] cmdResultArry443 = testPort443.Split(' '); + //client.RunCommand($"systemctl stop {cmdResultArry443[0]}"); + //client.RunCommand($"systemctl disable {cmdResultArry443[0]}"); + //client.RunCommand($"kill -9 {cmdResultArry443[3]}"); + sshShellCommand = $"systemctl stop {cmdResultArry443[0]}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"systemctl disable {cmdResultArry443[0]}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"kill -9 {cmdResultArry443[3]}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } - cmdTestPort = @"lsof -n -P -i :80 | grep LISTEN"; - cmdResult = client.RunCommand(cmdTestPort).Result; - if (String.IsNullOrEmpty(cmdResult) == false) + //cmdTestPort = @"lsof -n -P -i :80 | grep LISTEN"; + //cmdResult = client.RunCommand(cmdTestPort).Result; + if (String.IsNullOrEmpty(testPort80) == false) { - string[] cmdResultArry80 = cmdResult.Split(' '); - client.RunCommand($"systemctl stop {cmdResultArry80[0]}"); - client.RunCommand($"systemctl disable {cmdResultArry80[0]}"); - client.RunCommand($"kill -9 {cmdResultArry80[3]}"); + string[] cmdResultArry80 = testPort80.Split(' '); + //client.RunCommand($"systemctl stop {cmdResultArry80[0]}"); + //client.RunCommand($"systemctl disable {cmdResultArry80[0]}"); + //client.RunCommand($"kill -9 {cmdResultArry80[3]}"); + sshShellCommand = $"systemctl stop {cmdResultArry80[0]}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"systemctl disable {cmdResultArry80[0]}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"kill -9 {cmdResultArry80[3]}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } currentStatus = "80/443端口释放完毕!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); } - currentStatus = "符合安装要求,布署中......"; + else + { + currentStatus = "检测结果:未被占用!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + + currentStatus = "系统环境检测完毕,符合安装要求,开始布署......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - //下载安装脚本安装 + //打开防火墙端口 + currentStatus = "开启防火墙相应端口......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - client.RunCommand("curl -o /tmp/trojan-go.sh https://raw.githubusercontent.com/proxysu/shellscript/master/trojan-go.sh"); - client.RunCommand("yes | bash /tmp/trojan-go.sh -f"); + if (String.IsNullOrEmpty(client.RunCommand("command -v firewall-cmd").Result) == false) + { - string installResult = client.RunCommand("find / -name trojan-go").Result.ToString(); + //client.RunCommand("firewall-cmd --zone=public --add-port=80/tcp --permanent"); + //client.RunCommand("firewall-cmd --zone=public --add-port=443/tcp --permanent"); + //client.RunCommand("firewall-cmd --reload"); + sshShellCommand = @"firewall-cmd --zone=public --add-port=80/tcp --permanent"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"firewall-cmd --zone=public --add-port=443/tcp --permanent"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"yes | firewall-cmd --reload"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + if (String.IsNullOrEmpty(client.RunCommand("command -v ufw").Result) == false) + { + //client.RunCommand("ufw allow 80"); + //client.RunCommand("ufw allow 443"); + //client.RunCommand("yes | ufw reload"); + + sshShellCommand = @"ufw allow 80"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"ufw allow 443"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"yes | ufw reload"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + + //下载安装脚本安装 + currentStatus = "正在安装Trojan-go......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); + + //client.RunCommand("curl -o /tmp/trojan-go.sh https://raw.githubusercontent.com/proxysu/shellscript/master/trojan-go.sh"); + //client.RunCommand("yes | bash /tmp/trojan-go.sh -f"); + + sshShellCommand = @"curl -o /tmp/trojan-go.sh https://raw.githubusercontent.com/proxysu/shellscript/master/trojan-go.sh"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"yes | bash /tmp/trojan-go.sh -f"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"find / -name trojan-go"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string installResult = currentShellCommandResult; if (!installResult.Contains("/usr/local/bin/trojan-go")) { @@ -2474,6 +4603,9 @@ namespace ProxySU currentStatus = "安装Trojan-Go失败(安装脚本运行出错!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + client.Disconnect(); return; } @@ -2481,14 +4613,30 @@ namespace ProxySU { currentStatus = "Trojan-Go安装成功!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - client.RunCommand("systemctl enable trojan-go"); + //client.RunCommand("systemctl enable trojan-go"); + sshShellCommand = @"systemctl enable trojan-go"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } - client.RunCommand("mv /etc/trojan-go/config.json /etc/trojan-go/config.json.1"); + //client.RunCommand("mv /etc/trojan-go/config.json /etc/trojan-go/config.json.1"); + sshShellCommand = @"mv /etc/trojan-go/config.json /etc/trojan-go/config.json.1"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + //上传配置文件 currentStatus = "Trojan-Go程序安装完毕,配置文件上传中......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); //生成服务端配置 @@ -2499,7 +4647,7 @@ namespace ProxySU serverJson["local_addr"] = "0.0.0.0"; serverJson["local_port"] = 443; serverJson["remote_addr"] = "127.0.0.1"; - serverJson["remote_port"] = 80; + serverJson["remote_port"] = 88; //设置密码 serverJson["password"][0] = ReceiveConfigurationParameters[2]; //设置证书 @@ -2523,97 +4671,188 @@ namespace ProxySU File.Delete(@"config.json"); - //打开防火墙端口 - string openFireWallPort = ReceiveConfigurationParameters[1]; - if (String.IsNullOrEmpty(client.RunCommand("command -v firewall-cmd").Result) == false) - { - client.RunCommand("firewall-cmd --zone=public --add-port=80/tcp --permanent"); - client.RunCommand("firewall-cmd --zone=public --add-port=443/tcp --permanent"); - client.RunCommand("firewall-cmd --reload"); - - } - if (String.IsNullOrEmpty(client.RunCommand("command -v ufw").Result) == false) - { - client.RunCommand("ufw allow 80"); - client.RunCommand("ufw allow 443"); - client.RunCommand("yes | ufw reload"); - - } - currentStatus = "正在安装acme.sh......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - if (getApt == false) - { - //client.RunCommand("apt-get -qq update"); - client.RunCommand("apt-get -y -qq install socat"); - } - else if (getDnf == false) - { - //client.RunCommand("yum -q makecache"); - client.RunCommand("dnf -y -q install socat"); - } - else if (getYum == false) - { - //client.RunCommand("yum -q makecache"); - client.RunCommand("yum -y -q install socat"); - } - else if (getZypper == false) - { - // client.RunCommand("zypper ref"); - client.RunCommand("zypper -y install socat"); - } - client.RunCommand("curl https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | INSTALLONLINE=1 sh"); - client.RunCommand("cd ~/.acme.sh/"); - client.RunCommand("alias acme.sh=~/.acme.sh/acme.sh"); + //安装所依赖的软件 + sshShellCommand = $"{sshCmdUpdate}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = $"{sshCmdInstall}socat"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + //if (getApt == false) + //{ + // //client.RunCommand("apt-get -qq update"); + // client.RunCommand("apt-get -y -qq install socat"); + //} + //else if (getDnf == false) + //{ + // //client.RunCommand("yum -q makecache"); + // client.RunCommand("dnf -y -q install socat"); + //} + //else if (getYum == false) + //{ + // //client.RunCommand("yum -q makecache"); + // client.RunCommand("yum -y -q install socat"); + //} + //else if (getZypper == false) + //{ + // // client.RunCommand("zypper ref"); + // client.RunCommand("zypper -y install socat"); + //} + //client.RunCommand("curl https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | INSTALLONLINE=1 sh"); + //client.RunCommand("cd ~/.acme.sh/"); + //client.RunCommand("alias acme.sh=~/.acme.sh/acme.sh"); + + sshShellCommand = @"curl https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | INSTALLONLINE=1 sh"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"cd ~/.acme.sh/"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"alias acme.sh=~/.acme.sh/acme.sh"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + currentStatus = "申请域名证书......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); //client.RunCommand("mkdir -p /etc/v2ray/ssl"); - client.RunCommand($"/root/.acme.sh/acme.sh --issue --standalone -d {ReceiveConfigurationParameters[4]}"); + //client.RunCommand($"/root/.acme.sh/acme.sh --issue --standalone -d {ReceiveConfigurationParameters[4]}"); + sshShellCommand = $"/root/.acme.sh/acme.sh --issue --standalone -d {ReceiveConfigurationParameters[4]}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 currentStatus = "安装证书到Trojan-Go......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - client.RunCommand($"/root/.acme.sh/acme.sh --installcert -d {ReceiveConfigurationParameters[4]} --certpath /usr/local/etc/trojan-go/trojan-go.crt --keypath /usr/local/etc/trojan-go/trojan-go.key --capath /usr/local/etc/trojan-go/trojan-go.crt --reloadcmd \"systemctl restart trojan-go\""); + //client.RunCommand($"/root/.acme.sh/acme.sh --installcert -d {ReceiveConfigurationParameters[4]} --certpath /usr/local/etc/trojan-go/trojan-go.crt --keypath /usr/local/etc/trojan-go/trojan-go.key --capath /usr/local/etc/trojan-go/trojan-go.crt --reloadcmd \"systemctl restart trojan-go\""); + sshShellCommand = $"/root/.acme.sh/acme.sh --installcert -d {ReceiveConfigurationParameters[4]} --certpath /usr/local/etc/trojan-go/trojan-go.crt --keypath /usr/local/etc/trojan-go/trojan-go.key --capath /usr/local/etc/trojan-go/trojan-go.crt --reloadcmd \"systemctl restart trojan-go\""; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 //安装Caddy currentStatus = "正在安装Caddy"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); //安装Caddy //为假则表示系统有相应的组件。 if (getApt == false) { - client.RunCommand(@"echo ""deb [trusted=yes] https://apt.fury.io/caddy/ /"" | tee -a /etc/apt/sources.list.d/caddy-fury.list"); - client.RunCommand("apt install -y apt-transport-https"); - client.RunCommand("apt -qq update"); - client.RunCommand("apt -y -qq install caddy"); + //client.RunCommand(@"echo ""deb [trusted=yes] https://apt.fury.io/caddy/ /"" | tee -a /etc/apt/sources.list.d/caddy-fury.list"); + //client.RunCommand("apt install -y apt-transport-https"); + //client.RunCommand("apt -qq update"); + //client.RunCommand("apt -y -qq install caddy"); + sshShellCommand = @"echo ""deb [trusted=yes] https://apt.fury.io/caddy/ /"" | tee -a /etc/apt/sources.list.d/caddy-fury.list"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"apt install -y apt-transport-https"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"apt -qq update"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"apt -y -qq install caddy"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } else if (getDnf == false) { - client.RunCommand(@"dnf install 'dnf-command(copr)' -y"); - client.RunCommand(@"dnf copr enable @caddy/caddy -y"); - //client.RunCommand("dnf -q makecache"); - client.RunCommand("dnf -y -q install caddy"); + //client.RunCommand(@"dnf install 'dnf-command(copr)' -y"); + //client.RunCommand(@"dnf copr enable @caddy/caddy -y"); + ////client.RunCommand("dnf -q makecache"); + //client.RunCommand("dnf -y -q install caddy"); + sshShellCommand = @"dnf install 'dnf-command(copr)' -y"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"dnf copr enable @caddy/caddy -y"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + //sshShellCommand = @"dnf -q makecache"; + //TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + //currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + //TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"dnf -y -q install caddy"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } else if (getYum == false) { - client.RunCommand(@"yum install yum-plugin-copr -y"); - client.RunCommand(@"yum copr enable @caddy/caddy -y"); - //client.RunCommand("yum -q makecache"); - client.RunCommand("yum -y -q install caddy"); + //client.RunCommand(@"yum install yum-plugin-copr -y"); + //client.RunCommand(@"yum copr enable @caddy/caddy -y"); + ////client.RunCommand("yum -q makecache"); + //client.RunCommand("yum -y -q install caddy"); + sshShellCommand = @"yum install yum-plugin-copr -y"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"yum copr enable @caddy/caddy -y"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + //sshShellCommand = @"yum -q makecache"; + //TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + //currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + //TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"yum -y -q install caddy"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } - //else if (getZypper == false) - //{ - // client.RunCommand("zypper ref"); - // client.RunCommand("zypper -y install curl"); - //} - installResult = client.RunCommand("find / -name caddy").Result.ToString(); + + sshShellCommand = @"find / -name caddy"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + installResult = currentShellCommandResult; if (!installResult.Contains("/usr/bin/caddy")) { @@ -2621,39 +4860,73 @@ namespace ProxySU currentStatus = "安装Caddy失败!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + client.Disconnect(); return; } currentStatus = "Caddy安装成功!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - client.RunCommand("systemctl enable caddy"); + // client.RunCommand("systemctl enable caddy"); + sshShellCommand = @"systemctl enable caddy"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - //currentStatus = "上传Caddy配置文件......"; - //textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); - //Thread.Sleep(1000); - //string caddyConfig = "TemplateConfg\\trojan_caddy_config.caddyfile"; + currentStatus = "上传Caddy配置文件......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - //upLoadPath = "/etc/caddy/Caddyfile"; - //UploadConfig(connectionInfo, caddyConfig, upLoadPath); + Thread.Sleep(1000); + + //client.RunCommand("mv /etc/caddy/Caddyfile /etc/caddy/Caddyfile.bak");//备份原文件 + sshShellCommand = @"mv /etc/caddy/Caddyfile /etc/caddy/Caddyfile.bak"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + + string caddyConfig = "TemplateConfg\\trojan_caddy_config.caddyfile"; + + upLoadPath = "/etc/caddy/Caddyfile"; + UploadConfig(connectionInfo, caddyConfig, upLoadPath); //设置Caddyfile文件中的tls 邮箱 //string email = $"user@{ReceiveConfigurationParameters[4]}"; //设置域名 - //string sshCmd = $"sed -i 's/##domain##/{ReceiveConfigurationParameters[4]}:80/' {upLoadPath}"; - //MessageBox.Show(sshCmd); + //string sshCmd = $"sed -i 's/##domain##/{ReceiveConfigurationParameters[4]}/' {upLoadPath}"; + sshShellCommand = $"sed -i 's/##domain##/{ReceiveConfigurationParameters[4]}/' {upLoadPath}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + //client.RunCommand(sshCmd); //设置伪装网站 - //if (String.IsNullOrEmpty(ReceiveConfigurationParameters[7]) == false) - //{ - // sshCmd = $"sed -i 's/##sites##/proxy \\/ {ReceiveConfigurationParameters[7]}/' {upLoadPath}"; - // client.RunCommand(sshCmd); - //} - //Thread.Sleep(2000); + if (String.IsNullOrEmpty(ReceiveConfigurationParameters[7]) == false) + { + // sshCmd = $"sed -i 's/##sites##/proxy \\/ {ReceiveConfigurationParameters[7]}/' {upLoadPath}"; + //client.RunCommand(sshCmd); + sshShellCommand = $"sed -i 's/##sites##/proxy \\/ {ReceiveConfigurationParameters[7]}/' {upLoadPath}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } + currentStatus = "Caddy配置文件上传成功,OK!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); //安装Caddy服务 //sshCmd = $"caddy -service install -agree -conf /etc/caddy/Caddyfile -email {email}"; @@ -2661,42 +4934,138 @@ namespace ProxySU //启动Caddy服务 currentStatus = "正在启动Caddy......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); //启动Caddy服务 - client.RunCommand("systemctl restart caddy"); + //client.RunCommand("systemctl restart caddy"); + sshShellCommand = @"systemctl restart caddy"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + currentStatus = "Caddy启动成功!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); currentStatus = "正在启动Trojan-Go......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - //启动V2ray服务 - client.RunCommand("systemctl restart trojan-go"); + //启动Trojan-go服务 + //client.RunCommand("systemctl restart trojan-go"); + sshShellCommand = @"systemctl restart trojan-go"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + currentStatus = "Trojan-go启动成功!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); //测试BBR条件,若满足提示是否启用 - var result = client.RunCommand("uname -r"); - //var result = client.RunCommand("cat /root/test.ver"); - string[] linuxKernelVerStr = result.Result.Split('-'); + currentStatus = "BBR测试......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); + + //var result = client.RunCommand("uname -r"); + sshShellCommand = @"uname -r"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string[] linuxKernelVerStr = currentShellCommandResult.Split('-'); bool detectResult = DetectKernelVersionBBR(linuxKernelVerStr[0]); - string resultCmdTestBBR = client.RunCommand(@"sysctl net.ipv4.tcp_congestion_control | grep bbr").Result; + //client.RunCommand(@"sysctl net.ipv4.tcp_congestion_control | grep bbr").Result; + sshShellCommand = @"sysctl net.ipv4.tcp_congestion_control | grep bbr"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + string resultCmdTestBBR = currentShellCommandResult; //如果内核满足大于等于4.9,且还未启用BBR,则启用BBR if (detectResult == true && resultCmdTestBBR.Contains("bbr") == false) { - client.RunCommand(@"bash -c 'echo ""net.core.default_qdisc=fq"" >> /etc/sysctl.conf'"); - client.RunCommand(@"bash -c 'echo ""net.ipv4.tcp_congestion_control=bbr"" >> /etc/sysctl.conf'"); - client.RunCommand(@"sysctl -p"); + currentStatus = "正在启用BBR......"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + Thread.Sleep(1000); + + //client.RunCommand(@"bash -c 'echo ""net.core.default_qdisc=fq"" >> /etc/sysctl.conf'"); + //client.RunCommand(@"bash -c 'echo ""net.ipv4.tcp_congestion_control=bbr"" >> /etc/sysctl.conf'"); + //client.RunCommand(@"sysctl -p"); + sshShellCommand = @"bash -c 'echo ""net.core.default_qdisc=fq"" >> /etc/sysctl.conf'"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"bash -c 'echo ""net.ipv4.tcp_congestion_control=bbr"" >> /etc/sysctl.conf'"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"sysctl -p"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + } + else if (resultCmdTestBBR.Contains("bbr") == true) + { + currentStatus = "BBR已经启用了!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + else + { + currentStatus = "系统不满足启用BBR的条件,启用失败!"; + textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + + client.Disconnect();//断开服务器ssh连接 + + ////测试BBR条件,若满足提示是否启用 + //var result = client.RunCommand("uname -r"); + ////var result = client.RunCommand("cat /root/test.ver"); + //string[] linuxKernelVerStr = result.Result.Split('-'); + + //bool detectResult = DetectKernelVersionBBR(linuxKernelVerStr[0]); + //string resultCmdTestBBR = client.RunCommand(@"sysctl net.ipv4.tcp_congestion_control | grep bbr").Result; + ////如果内核满足大于等于4.9,且还未启用BBR,则启用BBR + //if (detectResult == true && resultCmdTestBBR.Contains("bbr") == false) + //{ + // client.RunCommand(@"bash -c 'echo ""net.core.default_qdisc=fq"" >> /etc/sysctl.conf'"); + // client.RunCommand(@"bash -c 'echo ""net.ipv4.tcp_congestion_control=bbr"" >> /etc/sysctl.conf'"); + // client.RunCommand(@"sysctl -p"); + //} //生成客户端配置 currentStatus = "生成客户端配置......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); if (!Directory.Exists("trojan-go_config"))//如果不存在就创建file文件夹      { @@ -2726,10 +5095,13 @@ namespace ProxySU } } - client.Disconnect(); + - currentStatus = "安装成功"; + currentStatus = "Trojan-go安装成功,祝您使用愉快!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); //显示服务端连接参数 @@ -2772,13 +5144,15 @@ namespace ProxySU } currentStatus = "主机登录失败"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 } #endregion } - //检测升级Trojan-Go版本 + //检测升级Trojan-Go版本传递参数 private void ButtonUpdateTrojanGo_Click(object sender, RoutedEventArgs e) { ConnectionInfo connectionInfo = GenerateConnectionInfo(); @@ -2797,8 +5171,10 @@ namespace ProxySU private void UpdateTojanGo(ConnectionInfo connectionInfo, TextBlock textBlockName, ProgressBar progressBar) { string currentStatus = "正在登录远程主机......"; - Action updateAction = new Action(UpdateTextBlock); + //Action updateAction = new Action(UpdateTextBlock); textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 try { @@ -2837,23 +5213,56 @@ namespace ProxySU { currentStatus = "主机登录成功"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果在监视窗口 + Thread.Sleep(1000); } //检测是否运行在root权限下 - string testRootAuthority = client.RunCommand(@"id -u").Result; + currentShellCommandResult = "检测是否运行在root权限下..."; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"id -u"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string testRootAuthority = currentShellCommandResult; if (testRootAuthority.Equals("0\n") == false) { MessageBox.Show("请使用具有root权限的账户登录主机!!"); client.Disconnect(); return; } + else + { + currentShellCommandResult = "检测结果:OK!"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + } + ////检测是否运行在root权限下 + //string testRootAuthority = client.RunCommand(@"id -u").Result; + //if (testRootAuthority.Equals("0\n") == false) + //{ + // MessageBox.Show("请使用具有root权限的账户登录主机!!"); + // client.Disconnect(); + // return; + //} //检测当前安装的版本 currentStatus = "检测远程主机Trojan-Go版本......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); - string cmdTestTrojanInstalled = @"find / -name trojan-go"; - string resultCmdTestTrojanInstalled = client.RunCommand(cmdTestTrojanInstalled).Result; + //string cmdTestTrojanInstalled = @"find / -name trojan-go"; + + sshShellCommand = @"find / -name trojan-go"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + string resultCmdTestTrojanInstalled = currentShellCommandResult; if (resultCmdTestTrojanInstalled.Contains("/usr/local/bin/trojan-go") == false) { @@ -2861,17 +5270,30 @@ namespace ProxySU currentStatus = "未安装Trojan-Go,退出"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); client.Disconnect(); return; } //获取当前安装的版本 - string sshcmd = @"echo ""$(/usr/local/bin/trojan-go -version)"" | head -n 1 | cut -d "" "" -f2"; - string trojanCurrentVersion = client.RunCommand(sshcmd).Result;//含字母v + //string sshcmd = @"echo ""$(/usr/local/bin/trojan-go -version)"" | head -n 1 | cut -d "" "" -f2"; + sshShellCommand = @"echo ""$(/usr/local/bin/trojan-go -version)"" | head -n 1 | cut -d "" "" -f2"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string trojanCurrentVersion = currentShellCommandResult;//含字母v //获取最新版本 - sshcmd = @"curl -s https://api.github.com/repos/p4gefau1t/trojan-go/tags | grep 'name' | cut -d\"" -f4 | head -1"; - string trojanNewVersion = client.RunCommand(sshcmd).Result;//含字母v + //sshcmd = @"curl -s https://api.github.com/repos/p4gefau1t/trojan-go/tags | grep 'name' | cut -d\"" -f4 | head -1"; + sshShellCommand = @"curl -s https://api.github.com/repos/p4gefau1t/trojan-go/tags | grep 'name' | cut -d\"" -f4 | head -1"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + string trojanNewVersion = currentShellCommandResult;//含字母v if (trojanNewVersion.Equals(trojanCurrentVersion) == false) { @@ -2880,17 +5302,35 @@ namespace ProxySU { currentStatus = "正在升级Trojan-Go到最新版本......"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); //备份配置文件 //sshcmd = @"mv /usr/local/etc/trojan/config.json /usr/local/etc/trojan/config.json.bak"; //client.RunCommand(sshcmd); //升级Trojan-Go主程序 - client.RunCommand("curl -o /tmp/trojan-go.sh https://raw.githubusercontent.com/proxysu/shellscript/master/trojan-go.sh"); - client.RunCommand("yes | bash /tmp/trojan-go.sh -f"); + //client.RunCommand("curl -o /tmp/trojan-go.sh https://raw.githubusercontent.com/proxysu/shellscript/master/trojan-go.sh"); + //client.RunCommand("yes | bash /tmp/trojan-go.sh -f"); + sshShellCommand = @"curl -o /tmp/trojan-go.sh https://raw.githubusercontent.com/proxysu/shellscript/master/trojan-go.sh"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + sshShellCommand = @"yes | bash /tmp/trojan-go.sh -f"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + //获取升级后的版本 - sshcmd = @"echo ""$(/usr/local/bin/trojan-go -version)"" | head -n 1 | cut -d "" "" -f2"; - trojanCurrentVersion = client.RunCommand(sshcmd).Result;//含字母v + //sshcmd = @"echo ""$(/usr/local/bin/trojan-go -version)"" | head -n 1 | cut -d "" "" -f2"; + sshShellCommand = @"echo ""$(/usr/local/bin/trojan-go -version)"" | head -n 1 | cut -d "" "" -f2"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + trojanCurrentVersion = currentShellCommandResult;//含字母v if (trojanNewVersion.Equals(trojanCurrentVersion) == true) { //恢复原来的配置文件备份 @@ -2901,6 +5341,9 @@ namespace ProxySU MessageBox.Show($"升级成功!!\n当前版本为:v{trojanCurrentVersion}\n最新版本为:{trojanNewVersion}"); currentStatus = "升级成功!当前已是最新版本!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); } else @@ -2908,6 +5351,9 @@ namespace ProxySU MessageBox.Show("升级失败,原因未知,请向开发者提问,以寻求支持!"); currentStatus = "升级失败!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); client.Disconnect(); return; @@ -2918,6 +5364,9 @@ namespace ProxySU { currentStatus = "升级取消,退出"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); client.Disconnect(); return; @@ -2928,6 +5377,9 @@ namespace ProxySU MessageBox.Show($"远程主机当前已是最新版本:{trojanNewVersion}\n无需升级!"); currentStatus = "已是最新版本,无需升级,退出"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + Thread.Sleep(1000); } @@ -2967,6 +5419,8 @@ namespace ProxySU } currentStatus = "主机登录失败"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); + currentShellCommandResult = currentStatus; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 } #endregion @@ -3216,7 +5670,7 @@ namespace ProxySU //也就是apt,dnf\yum, zypper必须安装其中之一,且必须安装Systemd的系统才能安装。 if ((getApt && getDnf && getYum && getZypper) || getSystemd) { - MessageBox.Show($"系统缺乏必要的安装组件如:apt-get||yum||zypper||Syetemd,主机系统推荐使用:CentOS 7/8,Debian 8/9/10,Ubuntu 16.04及以上版本"); + MessageBox.Show($"系统缺乏必要的安装组件如:apt||dnf||yum||zypper||Syetemd,主机系统推荐使用:CentOS 7/8,Debian 8/9/10,Ubuntu 16.04及以上版本"); currentStatus = "系统环境不满足要求,安装失败!!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); currentShellCommandResult = currentStatus; @@ -3234,6 +5688,36 @@ namespace ProxySU TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 } + //设置安装软件所用的命令格式 + //为假则表示系统有相应的组件。 + if (getApt == false) + { + //client.RunCommand("apt -qq update"); + //client.RunCommand("apt -y -qq install curl"); + sshCmdUpdate = @"apt -qq update"; + sshCmdInstall = @"apt -y -qq install "; + } + else if (getDnf == false) + { + //client.RunCommand("dnf -q makecache"); + //client.RunCommand("dnf -y -q install curl"); + sshCmdUpdate = @"dnf -q makecache"; + sshCmdInstall = @"dnf -y -q install "; + } + else if (getYum == false) + { + //client.RunCommand("yum -q makecache"); + //client.RunCommand("yum -y -q install curl"); + sshCmdUpdate = @"yum -q makecache"; + sshCmdInstall = @"yum -y -q install "; + } + else if (getZypper == false) + { + //client.RunCommand("zypper ref"); + //client.RunCommand("zypper -y install curl"); + sshCmdUpdate = @"zypper ref"; + sshCmdInstall = @"zypper -y install "; + } //判断是否启用了SELinux,如果启用了,并且工作在Enforcing模式下,则改为Permissive模式 if (getGetenforce == false) @@ -3276,66 +5760,76 @@ namespace ProxySU currentShellCommandResult = currentStatus; TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - if (getApt == false) - { - //client.RunCommand("apt -qq update"); - //client.RunCommand("apt -y -qq install curl libnss3 xz-utils lsof unzip"); - sshShellCommand = @"apt -qq update"; - TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 - currentShellCommandResult = client.RunCommand(sshShellCommand).Result; - TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + sshShellCommand = $"{sshCmdUpdate}"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - sshShellCommand = @"apt -y -qq install curl libnss3 xz-utils lsof unzip"; - TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 - currentShellCommandResult = client.RunCommand(sshShellCommand).Result; - TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + sshShellCommand = $"{sshCmdInstall}curl libnss3 xz-utils lsof unzip"; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - } - else if (getDnf == false) - { - //client.RunCommand("dnf -q makecache"); - //client.RunCommand("dnf -y -q install curl nss xz lsof unzip"); - sshShellCommand = @"dnf -q makecache"; - TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 - currentShellCommandResult = client.RunCommand(sshShellCommand).Result; - TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + //if (getApt == false) + //{ + // //client.RunCommand("apt -qq update"); + // //client.RunCommand("apt -y -qq install curl libnss3 xz-utils lsof unzip"); + // sshShellCommand = @"apt -qq update"; + // TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + // currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + // TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - sshShellCommand = @"dnf -y -q install curl nss xz lsof unzip"; - TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 - currentShellCommandResult = client.RunCommand(sshShellCommand).Result; - TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + // sshShellCommand = @"apt -y -qq install curl libnss3 xz-utils lsof unzip"; + // TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + // currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + // TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - } - else if (getYum == false) - { - //client.RunCommand("yum -q makecache"); - //client.RunCommand("yum -y -q install curl nss xz lsof unzip"); - sshShellCommand = @"yum -q makecache"; - TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 - currentShellCommandResult = client.RunCommand(sshShellCommand).Result; - TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + //} + //else if (getDnf == false) + //{ + // //client.RunCommand("dnf -q makecache"); + // //client.RunCommand("dnf -y -q install curl nss xz lsof unzip"); + // sshShellCommand = @"dnf -q makecache"; + // TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + // currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + // TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - sshShellCommand = @"yum -y -q install curl nss xz lsof unzip"; - TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 - currentShellCommandResult = client.RunCommand(sshShellCommand).Result; - TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + // sshShellCommand = @"dnf -y -q install curl nss xz lsof unzip"; + // TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + // currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + // TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - } - else if (getZypper == false) - { - //client.RunCommand("zypper ref"); - //client.RunCommand("zypper -y install curl nss xz lsof unzip"); - sshShellCommand = @"zypper ref"; - TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 - currentShellCommandResult = client.RunCommand(sshShellCommand).Result; - TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + //} + //else if (getYum == false) + //{ + // //client.RunCommand("yum -q makecache"); + // //client.RunCommand("yum -y -q install curl nss xz lsof unzip"); + // sshShellCommand = @"yum -q makecache"; + // TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + // currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + // TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - sshShellCommand = @"zypper -y install curl nss xz lsof unzip"; - TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 - currentShellCommandResult = client.RunCommand(sshShellCommand).Result; - TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + // sshShellCommand = @"yum -y -q install curl nss xz lsof unzip"; + // TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + // currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + // TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - } + //} + //else if (getZypper == false) + //{ + // //client.RunCommand("zypper ref"); + // //client.RunCommand("zypper -y install curl nss xz lsof unzip"); + // sshShellCommand = @"zypper ref"; + // TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + // currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + // TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + // sshShellCommand = @"zypper -y install curl nss xz lsof unzip"; + // TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, sshShellCommand);//显示执行的命令 + // currentShellCommandResult = client.RunCommand(sshShellCommand).Result; + // TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 + + //} currentStatus = "安装完毕!OK!"; textBlockName.Dispatcher.BeginInvoke(updateAction, textBlockName, progressBar, currentStatus); currentShellCommandResult = currentStatus; @@ -3497,7 +5991,6 @@ namespace ProxySU currentShellCommandResult = currentStatus; TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult);//显示命令执行的结果 - //string openFireWallPort = "443";//ReceiveConfigurationParameters[1]; if (String.IsNullOrEmpty(client.RunCommand("command -v firewall-cmd").Result) == false) { @@ -5545,14 +8038,7 @@ namespace ProxySU } #endregion - private void Button_Click(object sender, RoutedEventArgs e) - { - string currentStatus = "正在登录远程主机......"; - - currentShellCommandResult = currentStatus; - TextBoxMonitorCommandResults.Dispatcher.BeginInvoke(updateMonitorAction, TextBoxMonitorCommandResults, currentShellCommandResult); - - } + } } diff --git a/ProxySU/Properties/AssemblyInfo.cs b/ProxySU/Properties/AssemblyInfo.cs index a850403..1bc4460 100644 --- a/ProxySU/Properties/AssemblyInfo.cs +++ b/ProxySU/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ using System.Windows; // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 // 方法是按如下所示使用“*”: : // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.8.2.0")] -[assembly: AssemblyFileVersion("1.8.2.0")] +[assembly: AssemblyVersion("1.8.3.0")] +[assembly: AssemblyFileVersion("1.8.3.0")] diff --git a/ProxySU/bin/Beta/Beta.zip b/ProxySU/bin/Beta/Beta.zip index d8f324a603458b1eb2d14b71774bcf8bbd69c80e..404632e58ce2aba3f09b9c1033c3afea17bb501b 100644 GIT binary patch delta 51419 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 I=>q!nFGBgpKmY&$ delta 50332 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%0Dcpa8jZ_*K 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