diff --git a/.gitignore b/.gitignore index 2397d07..6ec5eb5 100644 --- a/.gitignore +++ b/.gitignore @@ -198,3 +198,4 @@ FakesAssemblies/ # vs code .vscode/* +/ProxySU_Core/Data/Record.json diff --git a/ProxySU.Core/App.xaml b/ProxySU.Core/App.xaml deleted file mode 100644 index 6f169ad..0000000 --- a/ProxySU.Core/App.xaml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - diff --git a/ProxySU.Core/MainWindow.xaml b/ProxySU.Core/MainWindow.xaml deleted file mode 100644 index 01c479c..0000000 --- a/ProxySU.Core/MainWindow.xaml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - 肖文杰 - - - - - - - - - diff --git a/ProxySU.Core/MainWindow.xaml.cs b/ProxySU.Core/MainWindow.xaml.cs deleted file mode 100644 index 920ed49..0000000 --- a/ProxySU.Core/MainWindow.xaml.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; - -namespace ProxySU.Core -{ - /// - /// Interaction logic for MainWindow.xaml - /// - public partial class MainWindow : Window - { - public MainWindow() - { - InitializeComponent(); - } - } -} diff --git a/ProxySU.Core/ProxySU.Core.csproj b/ProxySU.Core/ProxySU.Core.csproj deleted file mode 100644 index 1480162..0000000 --- a/ProxySU.Core/ProxySU.Core.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - WinExe - netcoreapp3.1 - true - - - - - - - diff --git a/ProxySU.sln b/ProxySU.sln index 89f5ff9..6b8b4af 100644 --- a/ProxySU.sln +++ b/ProxySU.sln @@ -1,10 +1,12 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.1022 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31005.135 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProxySU", "ProxySU\ProxySU.csproj", "{DD5505BC-E7F1-4D03-ABC7-B636E893FC09}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProxySU_Core", "ProxySU_Core\ProxySU_Core.csproj", "{B066015C-D347-4493-92F1-6556D3863996}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ Global {DD5505BC-E7F1-4D03-ABC7-B636E893FC09}.Debug|Any CPU.Build.0 = Debug|Any CPU {DD5505BC-E7F1-4D03-ABC7-B636E893FC09}.Release|Any CPU.ActiveCfg = Release|Any CPU {DD5505BC-E7F1-4D03-ABC7-B636E893FC09}.Release|Any CPU.Build.0 = Release|Any CPU + {B066015C-D347-4493-92F1-6556D3863996}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B066015C-D347-4493-92F1-6556D3863996}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B066015C-D347-4493-92F1-6556D3863996}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B066015C-D347-4493-92F1-6556D3863996}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ProxySU_Core/App.config b/ProxySU_Core/App.config new file mode 100644 index 0000000..731f6de --- /dev/null +++ b/ProxySU_Core/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/ProxySU_Core/App.xaml b/ProxySU_Core/App.xaml new file mode 100644 index 0000000..d59fcda --- /dev/null +++ b/ProxySU_Core/App.xaml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ProxySU.Core/App.xaml.cs b/ProxySU_Core/App.xaml.cs similarity index 92% rename from ProxySU.Core/App.xaml.cs rename to ProxySU_Core/App.xaml.cs index ba24f85..2ccb782 100644 --- a/ProxySU.Core/App.xaml.cs +++ b/ProxySU_Core/App.xaml.cs @@ -6,7 +6,7 @@ using System.Linq; using System.Threading.Tasks; using System.Windows; -namespace ProxySU.Core +namespace ProxySU_Core { /// /// Interaction logic for App.xaml diff --git a/ProxySU.Core/AssemblyInfo.cs b/ProxySU_Core/AssemblyInfo.cs similarity index 100% rename from ProxySU.Core/AssemblyInfo.cs rename to ProxySU_Core/AssemblyInfo.cs diff --git a/ProxySU_Core/Converters/LoginSecretTypeConverter.cs b/ProxySU_Core/Converters/LoginSecretTypeConverter.cs new file mode 100644 index 0000000..be26ed8 --- /dev/null +++ b/ProxySU_Core/Converters/LoginSecretTypeConverter.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; +using System.Windows.Data; + +namespace ProxySU_Core.Converters +{ + public class LoginSecretTypeConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return value != null && value.Equals(parameter); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value == null) + { + return Binding.DoNothing; + } + + if (!value.Equals(true)) + { + return Binding.DoNothing; + } + + return parameter; + + } + } +} diff --git a/ProxySU_Core/Converters/ProxyTypeConverter.cs b/ProxySU_Core/Converters/ProxyTypeConverter.cs new file mode 100644 index 0000000..771cb62 --- /dev/null +++ b/ProxySU_Core/Converters/ProxyTypeConverter.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; +using System.Windows.Data; + +namespace ProxySU_Core.Converters +{ + public class ProxyTypeConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return value != null && value.Equals(parameter); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value == null) + { + return Binding.DoNothing; + } + + if (!value.Equals(true)) + { + return Binding.DoNothing; + } + + return parameter; + } + } +} diff --git a/ProxySU_Core/Properties/AssemblyInfo.cs b/ProxySU_Core/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..82eaa44 --- /dev/null +++ b/ProxySU_Core/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("ProxySU_Core")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ProxySU_Core")] +[assembly: AssemblyCopyright("Copyright © 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +//若要开始生成可本地化的应用程序,请设置 +//.csproj 文件中的 CultureYouAreCodingWith +//例如,如果您在源文件中使用的是美国英语, +//使用的是美国英语,请将 设置为 en-US。 然后取消 +//对以下 NeutralResourceLanguage 特性的注释。 更新 +//以下行中的“en-US”以匹配项目文件中的 UICulture 设置。 + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //主题特定资源词典所处位置 + //(未在页面中找到资源时使用, + //或应用程序资源字典中找到时使用) + ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置 + //(未在页面中找到资源时使用, + //、应用程序或任何主题专用资源字典中找到时使用) +)] + + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ProxySU_Core/Properties/Resources.Designer.cs b/ProxySU_Core/Properties/Resources.Designer.cs new file mode 100644 index 0000000..5d55848 --- /dev/null +++ b/ProxySU_Core/Properties/Resources.Designer.cs @@ -0,0 +1,70 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本: 4.0.30319.42000 +// +// 对此文件的更改可能导致不正确的行为,如果 +// 重新生成代码,则所做更改将丢失。 +// +//------------------------------------------------------------------------------ + + +namespace ProxySU_Core.Properties +{ + /// + /// 强类型资源类,用于查找本地化字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// 返回此类使用的缓存 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ProxySU_Core.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性,对 + /// 使用此强类型资源类的所有资源查找执行重写。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/ProxySU_Core/Properties/Resources.resx b/ProxySU_Core/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/ProxySU_Core/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ProxySU_Core/Properties/Settings.Designer.cs b/ProxySU_Core/Properties/Settings.Designer.cs new file mode 100644 index 0000000..e09e8d5 --- /dev/null +++ b/ProxySU_Core/Properties/Settings.Designer.cs @@ -0,0 +1,29 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + + +namespace ProxySU_Core.Properties +{ + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/ProxySU_Core/Properties/Settings.settings b/ProxySU_Core/Properties/Settings.settings new file mode 100644 index 0000000..033d7a5 --- /dev/null +++ b/ProxySU_Core/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/ProxySU_Core/ProxySU_Core.csproj b/ProxySU_Core/ProxySU_Core.csproj new file mode 100644 index 0000000..d88a0b8 --- /dev/null +++ b/ProxySU_Core/ProxySU_Core.csproj @@ -0,0 +1,304 @@ + + + + + Debug + AnyCPU + {B066015C-D347-4493-92F1-6556D3863996} + WinExe + ProxySU_Core + ProxySU_Core + v4.6.1 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + true + true + + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\ControlzEx.4.3.0\lib\net45\ControlzEx.dll + + + ..\packages\MahApps.Metro.2.0.0\lib\net46\MahApps.Metro.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.BootstrapIcons.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.BoxIcons.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Codicons.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Core.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Entypo.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.EvaIcons.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.FeatherIcons.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.FileIcons.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Fontaudio.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.FontAwesome.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.ForkAwesome.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Ionicons.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.JamIcons.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Material.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.MaterialDesign.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.MaterialLight.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Microns.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Modern.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Octicons.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.PicolIcons.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.PixelartIcons.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.RadixIcons.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.RemixIcon.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.RPGAwesome.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.SimpleIcons.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Typicons.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Unicons.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.VaadinIcons.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.WeatherIcons.dll + + + ..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Zondicons.dll + + + ..\packages\MaterialDesignColors.2.0.0\lib\net452\MaterialDesignColors.dll + + + ..\packages\MaterialDesignThemes.MahApps.0.1.6\lib\net452\MaterialDesignThemes.MahApps.dll + + + ..\packages\MaterialDesignThemes.4.0.0\lib\net452\MaterialDesignThemes.Wpf.dll + + + ..\packages\Microsoft.Xaml.Behaviors.Wpf.1.1.19\lib\net45\Microsoft.Xaml.Behaviors.dll + + + ..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll + + + ..\packages\SSH.NET.2020.0.1\lib\net40\Renci.SshNet.dll + + + + + + + + + + + + + + + 4.0 + + + + + + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + + + + + + + + + + + + + + + HostEditorWindow.xaml + + + MainWindow.xaml + + + TerminalWindow.xaml + + + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + PreserveNewest + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + + + + + 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 + + + + + \ No newline at end of file diff --git a/ProxySU_Core/Resources/Languages/en.xaml b/ProxySU_Core/Resources/Languages/en.xaml new file mode 100644 index 0000000..47fb3c3 --- /dev/null +++ b/ProxySU_Core/Resources/Languages/en.xaml @@ -0,0 +1,48 @@ + + Deployment + Language + Chinese + English + Hosts + Add Host + Actions + Connect + Edit + Delete + Install + Save + Info + Warning + Error + + + Server Manager + Connection + User + Password + Tag + Host + Port + Method + Password Login + KeyLogin + Key + Upload + Proxy + Method + None + Http + Socks5 + Host + Port + User + Password + Please enter host + Please enter port + Please enter proxy host + Please enter proxy port + + + \ No newline at end of file diff --git a/ProxySU_Core/Resources/Languages/zh_cn.xaml b/ProxySU_Core/Resources/Languages/zh_cn.xaml new file mode 100644 index 0000000..505c9aa --- /dev/null +++ b/ProxySU_Core/Resources/Languages/zh_cn.xaml @@ -0,0 +1,48 @@ + + 应用布署 + 语言 + 中文 + 英文 + 主机列表 + 添加主机 + 操作 + 连接 + 安装 + 编辑 + 删除 + 保存 + 消息 + 提示 + 错误 + + + 服务器管理 + 连接 + 用户名 + 密码 + 别名 + 主机 + 端口 + 登陆方式 + 密码登陆 + 密钥登陆 + 密钥 + 上传 + 代理 + 类型 + + Http + Socks5 + 代理地址 + 代理端口 + 用户名 + 密码 + 请输入主机 + 请输入端口号 + 请输入代理地址 + 请输入代理端口号 + + + \ No newline at end of file diff --git a/ProxySU_Core/Resources/Styles/MaterialDesignThemes.Overrides.xaml b/ProxySU_Core/Resources/Styles/MaterialDesignThemes.Overrides.xaml new file mode 100644 index 0000000..5909ff8 --- /dev/null +++ b/ProxySU_Core/Resources/Styles/MaterialDesignThemes.Overrides.xaml @@ -0,0 +1,48 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/base.json b/ProxySU_Core/Templates/xray/base.json new file mode 100644 index 0000000..84a9d1f --- /dev/null +++ b/ProxySU_Core/Templates/xray/base.json @@ -0,0 +1,12 @@ +{ + "log": {}, + "api": {}, + "dns": {}, + "routing": {}, + "policy": {}, + "inbounds": [], + "outbounds": [], + "transport": {}, + "stats": {}, + "reverse": {} +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/caddy/Http2Web.caddyfile b/ProxySU_Core/Templates/xray/caddy/Http2Web.caddyfile new file mode 100644 index 0000000..7e62dbc --- /dev/null +++ b/ProxySU_Core/Templates/xray/caddy/Http2Web.caddyfile @@ -0,0 +1,18 @@ +##domain## { + root * /usr/share/caddy + file_server + tls { + protocols tls1.2 tls1.3 + ciphers TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + curves x25519 + } + + reverse_proxy ##path## http://localhost:10000 { + transport http { + versions h2c 2 + } + } + ##reverse_Proxy1## + ##reverse_Proxy2## + ##reverse_Proxy3## +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/caddy/WebSocketTLSWeb.caddyfile b/ProxySU_Core/Templates/xray/caddy/WebSocketTLSWeb.caddyfile new file mode 100644 index 0000000..bddb8f6 --- /dev/null +++ b/ProxySU_Core/Templates/xray/caddy/WebSocketTLSWeb.caddyfile @@ -0,0 +1,18 @@ +##domain## { + root * /usr/share/caddy + file_server + tls { + protocols tls1.2 tls1.3 + ciphers TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + curves x25519 + } + @xray_websocket { + path ##path## + header Connection *Upgrade* + header Upgrade websocket + } + reverse_proxy @xray_websocket localhost:10000 + ##reverse_Proxy1## + ##reverse_Proxy2## + ##reverse_Proxy3## +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/caddy/vlessTcpTlsWeb.caddyfile b/ProxySU_Core/Templates/xray/caddy/vlessTcpTlsWeb.caddyfile new file mode 100644 index 0000000..0e9f3d2 --- /dev/null +++ b/ProxySU_Core/Templates/xray/caddy/vlessTcpTlsWeb.caddyfile @@ -0,0 +1,10 @@ +:8800 { + root * /usr/share/caddy + file_server + ##reverse_Proxy1## + ##reverse_Proxy2## + ##reverse_Proxy3## +} +##domain##:80 { + redir https://##domain##{uri} +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/client/00_log/00_log.json b/ProxySU_Core/Templates/xray/client/00_log/00_log.json new file mode 100644 index 0000000..6a4cf00 --- /dev/null +++ b/ProxySU_Core/Templates/xray/client/00_log/00_log.json @@ -0,0 +1,5 @@ +{ + "log": { + "loglevel": "warning" + } +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/client/01_api/01_api.json b/ProxySU_Core/Templates/xray/client/01_api/01_api.json new file mode 100644 index 0000000..aa1982b --- /dev/null +++ b/ProxySU_Core/Templates/xray/client/01_api/01_api.json @@ -0,0 +1,3 @@ +{ + "api": null +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/client/02_dns/02_dns.json b/ProxySU_Core/Templates/xray/client/02_dns/02_dns.json new file mode 100644 index 0000000..63472d2 --- /dev/null +++ b/ProxySU_Core/Templates/xray/client/02_dns/02_dns.json @@ -0,0 +1,3 @@ +{ + "dns": {} +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/client/03_routing/03_routing.json b/ProxySU_Core/Templates/xray/client/03_routing/03_routing.json new file mode 100644 index 0000000..a187d31 --- /dev/null +++ b/ProxySU_Core/Templates/xray/client/03_routing/03_routing.json @@ -0,0 +1,3 @@ +{ + "routing": {} +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/client/04_policy/04_policy.json b/ProxySU_Core/Templates/xray/client/04_policy/04_policy.json new file mode 100644 index 0000000..4beed61 --- /dev/null +++ b/ProxySU_Core/Templates/xray/client/04_policy/04_policy.json @@ -0,0 +1,3 @@ +{ + "policy": {} +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/client/05_inbounds/05_inbounds.json b/ProxySU_Core/Templates/xray/client/05_inbounds/05_inbounds.json new file mode 100644 index 0000000..c402972 --- /dev/null +++ b/ProxySU_Core/Templates/xray/client/05_inbounds/05_inbounds.json @@ -0,0 +1,23 @@ +{ + "inbounds": [ + { + "protocol": "http", + "port": 1081 + }, + { + "port": 1080, + "protocol": "socks", + "sniffing": { + "enabled": true, + "destOverride": [ + "http", + "tls" + ] + }, + "settings": { + "udp": true, + "auth": "noauth" + } + } + ] +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/client/06_outbounds/06_outbounds.json b/ProxySU_Core/Templates/xray/client/06_outbounds/06_outbounds.json new file mode 100644 index 0000000..20e2beb --- /dev/null +++ b/ProxySU_Core/Templates/xray/client/06_outbounds/06_outbounds.json @@ -0,0 +1,3 @@ +{ + "outbounds": [] +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/client/06_outbounds/VLESS_HTTP2_TLS.json b/ProxySU_Core/Templates/xray/client/06_outbounds/VLESS_HTTP2_TLS.json new file mode 100644 index 0000000..8718383 --- /dev/null +++ b/ProxySU_Core/Templates/xray/client/06_outbounds/VLESS_HTTP2_TLS.json @@ -0,0 +1,31 @@ +{ + "outbounds": [ + { + "protocol": "vless", + "settings": { + "vnext": [ + { + "address": "", + "port": 443, + "users": [ + { + "id": "", + "encryption": "none" + } + ] + } + ] + }, + "streamSettings": { + "network": "h2", + "security": "tls", + "httpSettings": { + "host": [ + "" + ], + "path": null + } + } + } + ] +} diff --git a/ProxySU_Core/Templates/xray/client/06_outbounds/VLESS_TCP_TLS_WS.json b/ProxySU_Core/Templates/xray/client/06_outbounds/VLESS_TCP_TLS_WS.json new file mode 100644 index 0000000..7a3c871 --- /dev/null +++ b/ProxySU_Core/Templates/xray/client/06_outbounds/VLESS_TCP_TLS_WS.json @@ -0,0 +1,32 @@ +{ + "outbounds": [ + { + "protocol": "vless", + "settings": { + "vnext": [ + { + "address": "", + "port": 443, + "users": [ + { + "id": "", + "encryption": "none", + "level": 0 + } + ] + } + ] + }, + "streamSettings": { + "network": "ws", + "security": "tls", + "tlsSettings": { + "serverName": "" + }, + "wsSettings": { + "path": "" + } + } + } + ] +} diff --git a/ProxySU_Core/Templates/xray/client/07_transport/07_transport.json b/ProxySU_Core/Templates/xray/client/07_transport/07_transport.json new file mode 100644 index 0000000..6269103 --- /dev/null +++ b/ProxySU_Core/Templates/xray/client/07_transport/07_transport.json @@ -0,0 +1,3 @@ +{ + "transport": {} +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/client/08_stats/08_stats.json b/ProxySU_Core/Templates/xray/client/08_stats/08_stats.json new file mode 100644 index 0000000..02c9ed0 --- /dev/null +++ b/ProxySU_Core/Templates/xray/client/08_stats/08_stats.json @@ -0,0 +1,3 @@ +{ + "stats": null +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/client/09_reverse/09_reverse.json b/ProxySU_Core/Templates/xray/client/09_reverse/09_reverse.json new file mode 100644 index 0000000..6fa38a4 --- /dev/null +++ b/ProxySU_Core/Templates/xray/client/09_reverse/09_reverse.json @@ -0,0 +1,3 @@ +{ + "reverse": {} +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/server/00_log/00_log.json b/ProxySU_Core/Templates/xray/server/00_log/00_log.json new file mode 100644 index 0000000..6a4cf00 --- /dev/null +++ b/ProxySU_Core/Templates/xray/server/00_log/00_log.json @@ -0,0 +1,5 @@ +{ + "log": { + "loglevel": "warning" + } +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/server/01_api/01_api.json b/ProxySU_Core/Templates/xray/server/01_api/01_api.json new file mode 100644 index 0000000..aa1982b --- /dev/null +++ b/ProxySU_Core/Templates/xray/server/01_api/01_api.json @@ -0,0 +1,3 @@ +{ + "api": null +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/server/02_dns/02_dns.json b/ProxySU_Core/Templates/xray/server/02_dns/02_dns.json new file mode 100644 index 0000000..63472d2 --- /dev/null +++ b/ProxySU_Core/Templates/xray/server/02_dns/02_dns.json @@ -0,0 +1,3 @@ +{ + "dns": {} +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/server/03_routing/03_routing.json b/ProxySU_Core/Templates/xray/server/03_routing/03_routing.json new file mode 100644 index 0000000..0aa4964 --- /dev/null +++ b/ProxySU_Core/Templates/xray/server/03_routing/03_routing.json @@ -0,0 +1,14 @@ +{ + "routing": { + "domainStrategy": "AsIs", + "rules": [ + { + "type": "field", + "ip": [ + "geoip:private" + ], + "outboundTag": "block" + } + ] + } +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/server/04_policy/04_policy.json b/ProxySU_Core/Templates/xray/server/04_policy/04_policy.json new file mode 100644 index 0000000..4beed61 --- /dev/null +++ b/ProxySU_Core/Templates/xray/server/04_policy/04_policy.json @@ -0,0 +1,3 @@ +{ + "policy": {} +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/server/05_inbounds/05_inbounds.json b/ProxySU_Core/Templates/xray/server/05_inbounds/05_inbounds.json new file mode 100644 index 0000000..9a8d634 --- /dev/null +++ b/ProxySU_Core/Templates/xray/server/05_inbounds/05_inbounds.json @@ -0,0 +1,3 @@ +{ + "inbounds": [] +} diff --git a/ProxySU_Core/Templates/xray/server/05_inbounds/VLESS_HTTP2_TLS.json b/ProxySU_Core/Templates/xray/server/05_inbounds/VLESS_HTTP2_TLS.json new file mode 100644 index 0000000..a9e1b2f --- /dev/null +++ b/ProxySU_Core/Templates/xray/server/05_inbounds/VLESS_HTTP2_TLS.json @@ -0,0 +1,27 @@ +{ + "inbounds": [ + { + "port": 10000, + "listen": "127.0.0.1", + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "" + } + ], + "decryption": "none" + }, + "streamSettings": { + "security": "none", + "network": "h2", + "httpSettings": { + "path": "", + "host": [ + "" + ] + } + } + } + ] +} diff --git a/ProxySU_Core/Templates/xray/server/05_inbounds/VLESS_TCP_TLS_WS.json b/ProxySU_Core/Templates/xray/server/05_inbounds/VLESS_TCP_TLS_WS.json new file mode 100644 index 0000000..fa16dbf --- /dev/null +++ b/ProxySU_Core/Templates/xray/server/05_inbounds/VLESS_TCP_TLS_WS.json @@ -0,0 +1,24 @@ +{ + "inbounds": [ + { + "port": 443, + "listen": "127.0.0.1", + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "" + } + ], + "decryption": "none" + }, + "streamSettings": { + "network": "ws", + "security": "none", + "wsSettings": { + "path": "" + } + } + } + ] +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/server/06_outbounds/06_outbounds.json b/ProxySU_Core/Templates/xray/server/06_outbounds/06_outbounds.json new file mode 100644 index 0000000..467a4e1 --- /dev/null +++ b/ProxySU_Core/Templates/xray/server/06_outbounds/06_outbounds.json @@ -0,0 +1,12 @@ +{ + "outbounds": [ + { + "protocol": "freedom", + "tag": "direct" + }, + { + "protocol": "blackhole", + "tag": "block" + } + ] +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/server/07_transport/07_transport.json b/ProxySU_Core/Templates/xray/server/07_transport/07_transport.json new file mode 100644 index 0000000..6269103 --- /dev/null +++ b/ProxySU_Core/Templates/xray/server/07_transport/07_transport.json @@ -0,0 +1,3 @@ +{ + "transport": {} +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/server/08_stats/08_stats.json b/ProxySU_Core/Templates/xray/server/08_stats/08_stats.json new file mode 100644 index 0000000..02c9ed0 --- /dev/null +++ b/ProxySU_Core/Templates/xray/server/08_stats/08_stats.json @@ -0,0 +1,3 @@ +{ + "stats": null +} \ No newline at end of file diff --git a/ProxySU_Core/Templates/xray/server/09_reverse/09_reverse.json b/ProxySU_Core/Templates/xray/server/09_reverse/09_reverse.json new file mode 100644 index 0000000..6fa38a4 --- /dev/null +++ b/ProxySU_Core/Templates/xray/server/09_reverse/09_reverse.json @@ -0,0 +1,3 @@ +{ + "reverse": {} +} \ No newline at end of file diff --git a/ProxySU_Core/Tools/DateTimeUtils.cs b/ProxySU_Core/Tools/DateTimeUtils.cs new file mode 100644 index 0000000..32cb7b5 --- /dev/null +++ b/ProxySU_Core/Tools/DateTimeUtils.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Net; +using System.Runtime.InteropServices; +using System.Text; + +namespace ProxySU_Core.Tools +{ + public static class DateTimeUtils + { + /// + /// 从国家授时中心获取标准GMT时间,读取https://www.tsa.cn + /// GMT时间与UTC时间没有差别,可以UTC=GMT + /// + /// 返回网络时间 + public static DateTime GetUTCTime() + { + DateTime time; + try + { + HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://www.tsa.cn"); + request.Method = "HEAD"; + request.AllowAutoRedirect = false; + HttpWebResponse reponse = (HttpWebResponse)request.GetResponse(); + string cc = reponse.GetResponseHeader("date"); + reponse.Close(); + + bool s = GMTStrParse(cc, out time); + return time; + } + catch + { + return new DateTime(1970, 1, 1, 0, 0, 0, 0); + } + } + + public static bool GMTStrParse(string gmtStr, out DateTime gmtTime) //抓取的date是GMT格式的字符串,这里转成datetime + { + CultureInfo enUS = new CultureInfo("en-US"); + bool s = DateTime.TryParseExact(gmtStr, "r", enUS, DateTimeStyles.None, out gmtTime); + return s; + } + + //设置系统时间的API函数 + [DllImport("kernel32.dll")] + private static extern bool SetLocalTime(ref SYSTEMTIME time); + + [StructLayout(LayoutKind.Sequential)] + private struct SYSTEMTIME + { + public short year; + public short month; + public short dayOfWeek; + public short day; + public short hour; + public short minute; + public short second; + public short milliseconds; + } + + /// + /// 设置系统时间 + /// + /// 需要设置的时间 + /// 返回系统时间设置状态,true为成功,false为失败 + public static bool SetDate(DateTime dt) + { + SYSTEMTIME st; + + st.year = (short)dt.Year; + st.month = (short)dt.Month; + st.dayOfWeek = (short)dt.DayOfWeek; + st.day = (short)dt.Day; + st.hour = (short)dt.Hour; + st.minute = (short)dt.Minute; + st.second = (short)dt.Second; + st.milliseconds = (short)dt.Millisecond; + bool rt = SetLocalTime(ref st); + return rt; + } + } +} diff --git a/ProxySU_Core/ViewModels/BaseCommand.cs b/ProxySU_Core/ViewModels/BaseCommand.cs new file mode 100644 index 0000000..21860cd --- /dev/null +++ b/ProxySU_Core/ViewModels/BaseCommand.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Input; + +namespace ProxySU_Core.ViewModels +{ + public class BaseCommand : ICommand + { + private readonly Action _execution; + private readonly Func _canExecute; + + public BaseCommand(Action execution, Func canExecute = null) + { + _execution = execution; + _canExecute = canExecute; + } + + + + public event EventHandler CanExecuteChanged; + + public bool CanExecute(object parameter) + { + if (_canExecute == null) + { + return true; + } + + return _canExecute(parameter); + } + + public void Execute(object parameter) + { + if (_execution != null && CanExecute(parameter)) + { + _execution.Invoke(parameter); + } + } + } +} diff --git a/ProxySU_Core/ViewModels/BaseModel.cs b/ProxySU_Core/ViewModels/BaseModel.cs new file mode 100644 index 0000000..88d3837 --- /dev/null +++ b/ProxySU_Core/ViewModels/BaseModel.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Text; + +namespace ProxySU_Core.ViewModels +{ + public abstract class BaseModel : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + + public void Notify(string propertyName) + { + if (PropertyChanged != null) + { + PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } + } +} diff --git a/ProxySU_Core/ViewModels/Developers/Developer.cs b/ProxySU_Core/ViewModels/Developers/Developer.cs new file mode 100644 index 0000000..9488632 --- /dev/null +++ b/ProxySU_Core/ViewModels/Developers/Developer.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ProxySU_Core.ViewModels.Developers +{ + public class Developer + { + public string Name { get; set; } + + public string TemplateName { get; set; } + + public string Description { get; set; } + } +} diff --git a/ProxySU_Core/ViewModels/Developers/IParameters.cs b/ProxySU_Core/ViewModels/Developers/IParameters.cs new file mode 100644 index 0000000..c54bcbf --- /dev/null +++ b/ProxySU_Core/ViewModels/Developers/IParameters.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ProxySU_Core.ViewModels.Developers +{ + public interface IParameters + { + int Port { get; set; } + + string Domain { get; set; } + } +} diff --git a/ProxySU_Core/ViewModels/Developers/Project.cs b/ProxySU_Core/ViewModels/Developers/Project.cs new file mode 100644 index 0000000..bef77c6 --- /dev/null +++ b/ProxySU_Core/ViewModels/Developers/Project.cs @@ -0,0 +1,531 @@ +using ProxySU_Core.Tools; +using Renci.SshNet; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; + +namespace ProxySU_Core.ViewModels.Developers +{ + public enum CmdType + { + None, + Apt, + Dnf, + Yum + } + + public abstract class Project : BaseModel where TParameters : IParameters + { + private SshClient _sshClient; + + protected Action WriteOutput; + + protected CmdType CmdType { get; set; } + + protected bool IsSELinux { get; set; } + + protected bool OnlyIpv6 { get; set; } + + protected string IPv4 { get; set; } + + protected string IPv6 { get; set; } + + protected TParameters Parameters { get; set; } + + public Project(SshClient sshClient, TParameters parameters, Action writeOutput) + { + _sshClient = sshClient; + WriteOutput = writeOutput; + Parameters = parameters; + } + + protected string RunCmd(string cmdStr) + { + var cmd = _sshClient.CreateCommand(cmdStr); + WriteOutput(cmdStr); + + var result = cmd.Execute(); + WriteOutput(result); + return result; + } + + /// + /// 执行安装命令 + /// + public abstract void Execute(); + + /// + /// 配置系统基础环境 + /// + protected void EnsureSystemEnv() + { + string cmd; + + // 确认安装命令 + if (CmdType == CmdType.None) + { + cmd = RunCmd("command -v apt-get"); + if (!string.IsNullOrEmpty(cmd)) + { + CmdType = CmdType.Apt; + } + } + + if (CmdType == CmdType.None) + { + cmd = RunCmd("command -v dnf"); + if (!string.IsNullOrEmpty(cmd)) + { + CmdType = CmdType.Dnf; + } + } + + if (CmdType == CmdType.None) + { + cmd = RunCmd("command -v yum"); + if (!string.IsNullOrEmpty(cmd)) + { + CmdType = CmdType.Yum; + } + } + + // systemctl + cmd = RunCmd("command -v systemctl"); + var hasSystemCtl = !string.IsNullOrEmpty(cmd); + + // SELinux + cmd = RunCmd("command -v getenforce"); + IsSELinux = !string.IsNullOrEmpty(cmd); + + if (CmdType == CmdType.None || !hasSystemCtl) + { + throw new Exception("系统缺乏必要的安装组件如:apt-get||dnf||yum||Syetemd,主机系统推荐使用:CentOS 7/8,Debian 8/9/10,Ubuntu 16.04及以上版本"); + } + + + // 判断是否启用了SELinux,如果启用了,并且工作在Enforcing模式下,则改为Permissive模式 + if (IsSELinux) + { + cmd = RunCmd("getenforce"); + + // 检测到系统启用SELinux,且工作在严格模式下,需改为宽松模式 + if (cmd.Contains("Enforcing")) + { + RunCmd("setenforce 0"); + RunCmd(@"sed -i 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config"); + } + } + } + + /// + /// 确保Root账户登陆 + /// + protected void EnsureRootAuth() + { + // 禁止一些可能产生的干扰信息 + RunCmd(@"sed -i 's/echo/#echo/g' ~/.bashrc"); + RunCmd(@"sed -i 's/echo/#echo/g' ~/.profile"); + + + // 检测是否运行在Root权限下 + var cmd = RunCmd("id -u"); + if (!cmd.Equals("0\n")) + { + throw new Exception("请使用Root账户登陆主机"); + } + } + + /// + /// 配置IPV6环境 + /// + protected void ConfigureIPv6() + { + if (IsOnlyIpv6()) + { + SetNat64(); + } + } + + /// + /// 配置必要的软件 + /// + protected void ConfigureSoftware() + { + // 安装curl,wget,unzip + string cmd = RunCmd("command -v curl"); + if (string.IsNullOrEmpty(cmd)) + { + RunCmd(GetInstallCmd("curl")); + } + + cmd = RunCmd("command -v wget"); + if (string.IsNullOrEmpty(cmd)) + { + RunCmd(GetInstallCmd("wget")); + } + + cmd = RunCmd("command -v unzip"); + if (string.IsNullOrEmpty(cmd)) + { + RunCmd(GetInstallCmd("unzip")); + } + + // 安装dig + cmd = RunCmd("command -v dig"); + if (string.IsNullOrEmpty(cmd)) + { + if (CmdType == CmdType.Apt) + { + RunCmd(GetUpdateCmd()); + RunCmd(GetInstallCmd("dnsutils")); + } + else if (CmdType == CmdType.Dnf) + { + RunCmd(GetUpdateCmd()); + RunCmd(GetInstallCmd("bind-utils")); + } + else if (CmdType == CmdType.Yum) + { + RunCmd(GetUpdateCmd()); + RunCmd(GetInstallCmd("bind-utils")); + } + } + + + // 处理极其少见的xz-utils未安装的情况 + if (CmdType == CmdType.Apt) + { + RunCmd(GetInstallCmd("xz-utils")); + } + else + { + RunCmd(GetInstallCmd("xz-devel")); + } + + // 检测是否安装lsof + cmd = RunCmd("command -v lsof"); + if (string.IsNullOrEmpty(cmd)) + { + RunCmd(GetInstallCmd("lsof")); + } + } + + /// + /// 配置防火墙 + /// + protected void ConfigureFirewall() + { + string cmd; + + cmd = RunCmd("command -v firewall-cmd"); + if (!string.IsNullOrEmpty(cmd)) + { + //有很奇怪的vps主机,在firewalld未运行时,端口是关闭的,无法访问。所以要先启动firewalld + //用于保证acme.sh申请证书成功 + cmd = RunCmd("firewall-cmd --state"); + if (cmd.Trim() != "running") + { + RunCmd("systemctl restart firewalld"); + } + + if (Parameters.Port == 443) + { + RunCmd("firewall-cmd --zone=public --add-port=80/tcp --permanent"); + RunCmd("firewall-cmd --zone=public --add-port=443/tcp --permanent"); + RunCmd("firewall-cmd --zone=public --add-port=80/udp --permanent"); + RunCmd("firewall-cmd --zone=public --add-port=443/udp --permanent"); + RunCmd("yes | firewall-cmd --reload"); + } + else + { + RunCmd($"firewall-cmd --zone=public --add-port={Parameters.Port}/tcp --permanent"); + RunCmd($"firewall-cmd --zone=public --add-port={Parameters.Port}/udp --permanent"); + RunCmd("yes | firewall-cmd --reload"); + } + return; + } + + cmd = RunCmd("command -v ufw"); + if (!string.IsNullOrEmpty(cmd)) + { + if (Parameters.Port == 443) + { + RunCmd("ufw allow 80/tcp"); + RunCmd("ufw allow 443/tcp"); + RunCmd("ufw allow 80/udp"); + RunCmd("ufw allow 443/udp"); + RunCmd("yes | ufw reload"); + } + else + { + RunCmd($"ufw allow {Parameters.Port}/tcp"); + RunCmd($"ufw allow {Parameters.Port}/udp"); + RunCmd("yes | ufw reload"); + } + } + } + + /// + /// 配置同步时间差 + /// + protected void SyncTimeDiff() + { + RunCmd("rm -f /etc/localtime"); + RunCmd("ln -s /usr/share/zoneinfo/UTC /etc/localtime"); + + var result = RunCmd("date +%s"); + var vpsSeconds = Convert.ToInt64(result); + var localSeconds = (int)(DateTime.Now.ToUniversalTime() - DateTime.Parse("1970-01-01")).TotalSeconds; + + if (Math.Abs(vpsSeconds - localSeconds) >= 90) + { + // 同步本地时间 + var netUtcTime = DateTimeUtils.GetUTCTime(); + DateTimeUtils.SetDate(netUtcTime.ToLocalTime()); + + // 同步VPS时间 + var utcTS = DateTimeUtils.GetUTCTime() - new DateTime(1970, 1, 1, 0, 0, 0, 0); + long timeStampVPS = Convert.ToInt64(utcTS.TotalSeconds); + RunCmd($"date --set=\"$(date \"+%Y-%m-%d %H:%M:%S\" -d @{timeStampVPS.ToString()})\""); + } + } + + /// + /// 验证域名是否绑定了主机 + /// + protected void ValidateDomain() + { + if (OnlyIpv6) + { + string cmdFilter = @"| grep -oE '(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))' | head -n 1"; + var cmd = $"dig @resolver1.opendns.com AAAA {Parameters.Domain} +short -6 {cmdFilter}"; + var result = RunCmd(cmd).TrimEnd('\r', '\n'); + + if (result != IPv6) + { + } + } + + else + { + string cmdFilter = @"| grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | head -n 1"; + var cmd = $"dig @resolver1.opendns.com A {Parameters.Domain} +short -4 {cmdFilter}"; + var result = RunCmd(cmd).TrimEnd('\r', '\n'); + + if (result != IPv4) + { + throw new Exception("域名未能解析到服务器IP,请检查域名配置"); + } + } + } + + /// + /// 判断是否安装某个软件 + /// + /// + /// + protected bool FileExists(string path) + { + var cmdStr = $"if [[ -f {path} ]];then echo '1';else echo '0'; fi"; + var cmd = RunCmd(cmdStr); + return cmd.Trim() == "1"; + } + + + + #region 检测系统环境 + + private bool IsOnlyIpv6() + { + string cmd; + + cmd = RunCmd(@"curl -s https://api.ip.sb/ip --ipv4 --max-time 8"); + IPv4 = cmd.TrimEnd('\r', '\n'); + + if (!string.IsNullOrEmpty(IPv4)) + { + OnlyIpv6 = false; + return false; + } + + cmd = RunCmd(@"curl -s https://api.ip.sb/ip --ipv6 --max-time 8"); + IPv6 = cmd.TrimEnd('\r', '\n'); + + if (string.IsNullOrEmpty(IPv6)) + { + throw new Exception("未检测可用的的IP地址"); + } + + OnlyIpv6 = true; + return OnlyIpv6; + } + + private bool SetPortFree(int port, bool force = true) + { + string result = RunCmd($"lsof -n -P -i :{port} | grep LISTEN"); + + if (!string.IsNullOrEmpty(result)) + { + if (force) + { + var btnResult = MessageBox.Show("80/443端口之一,或全部被占用,将强制停止占用80/443端口的程序?", "提示", MessageBoxButton.YesNo); + if (btnResult == MessageBoxResult.No) + { + throw new Exception($"{port}端口被占用,安装停止!"); + } + + string[] process = result.Split(' '); + RunCmd($"systemctl stop {process[0]}"); + RunCmd($"systemctl disable {process[0]}"); + RunCmd($"pkill {process[0]}"); + return SetPortFree(port, force: false); + } + else + { + return false; + } + } + + return true; + } + + private void ConfigurePort(bool force = true) + { + if (Parameters.Port == 80 || Parameters.Port == 443) + { + SetPortFree(80); + SetPortFree(443); + } + else + { + SetPortFree(Parameters.Port); + } + } + + private void SetNat64() + { + var dns64List = FilterFastestIP(); + if (dns64List.Count == 0) + { + throw new Exception("未找到有效的Nat64网关"); + } + + var exists = FileExists("/etc/resolv.conf.proxysu"); + if (!exists) + { + var cmdStr = @"mv /etc/resolv.conf /etc/resolv.conf.proxysu"; + RunCmd(cmdStr); + } + + foreach (var gateip in dns64List) + { + RunCmd($"echo \"nameserver {gateip}\" > /etc/resolv.conf"); + } + } + + private void RemoveNat64() + { + RunCmd("rm /etc/resolv.conf"); + RunCmd("mv /etc/resolv.conf.proxysu /etc/resolv.conf"); + } + + private List FilterFastestIP() + { + string[] gateNat64 = { + "2a01:4f9:c010:3f02::1", + "2001:67c:2b0::4", + "2001:67c:2b0::6", + "2a09:11c0:f1:bbf0::70", + "2a01:4f8:c2c:123f::1", + "2001:67c:27e4:15::6411", + "2001:67c:27e4::64", + "2001:67c:27e4:15::64", + "2001:67c:27e4::60", + "2a00:1098:2b::1", + "2a03:7900:2:0:31:3:104:161", + "2a00:1098:2c::1", + "2a09:11c0:100::53", + }; + + Dictionary dns64List = new Dictionary(); + foreach (var gateip in gateNat64) + { + var cmdStr = $"ping6 -c4 {gateip} | grep avg | awk '{{print $4}}'|cut -d/ -f2"; + var cmd = RunCmd(cmdStr); + if (!string.IsNullOrEmpty(cmd)) + { + if (float.TryParse(cmd, out float delay)) + { + dns64List.Add(gateip, delay); + } + } + } + + return dns64List.Keys.ToList(); + } + + #endregion + + + protected void UploadFile(Stream stream, string path) + { + using (var sftp = new SftpClient(_sshClient.ConnectionInfo)) + { + sftp.Connect(); + sftp.UploadFile(stream, path, true); + sftp.Disconnect(); + } + } + + /// + /// 根据系统环境匹配更新命令 + /// + /// + protected string GetUpdateCmd() + { + if (CmdType == CmdType.Apt) + { + return "apt-get update "; + } + else if (CmdType == CmdType.Dnf) + { + return "dnf clean all;dnf makecache"; + } + else if (CmdType == CmdType.Yum) + { + return "yum clean all;yum makecache"; + } + + throw new Exception("未识别的系统"); + } + + /// + /// 根据系统匹配安装命令 + /// + /// + /// + protected string GetInstallCmd(string soft) + { + if (CmdType == CmdType.Apt) + { + return "apt-get install " + soft; + } + else if (CmdType == CmdType.Dnf) + { + return "dnf -y install " + soft; + } + else if (CmdType == CmdType.Yum) + { + return "yum -y install " + soft; + } + + throw new Exception("未识别的系统"); + } + + } +} diff --git a/ProxySU_Core/ViewModels/Developers/XrayParameters.cs b/ProxySU_Core/ViewModels/Developers/XrayParameters.cs new file mode 100644 index 0000000..cb612bb --- /dev/null +++ b/ProxySU_Core/ViewModels/Developers/XrayParameters.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ProxySU_Core.ViewModels.Developers +{ + public class XrayParameters : IParameters + { + /// + /// 访问端口 + /// + public int Port { get; set; } + + /// + /// UUID + /// + public string UUID { get; set; } + + /// + /// vless ws路径 + /// + public string VlessWsPath { get; set; } + + /// + /// vless tcp路径 + /// + public string VlessTcpPath { get; set; } + + /// + /// vless http路径 + /// + public string VlessHttpPath { get; set; } + + /// + /// vmess ws路径 + /// + public string VmessWsPath { get; set; } + + /// + /// vmess tcp路径 + /// + public string VmessTcpPath { get; set; } + + /// + /// vmess http路径 + /// + public string VmessHttpPath { get; set; } + + /// + /// 域名 + /// + public string Domain { get; set; } + + /// + /// 伪装域名 + /// + public string MaskDomain { get; set; } + + /// + /// 安装类型 + /// + public XrayType Type { get; set; } + } + + public enum XrayType + { + Shadowsocks_AEAD, + Shadowsocks_TCP, + Sockets5_TLS, + Trojan_TCP_TLS, + + // vless + VLESS_H2C_Caddy2, + VLESS_TCP_TLS_WS, + VLESS_TCP_XTLS_WHATEVER, + VLESS_mKCPSeed, + + // vmess + VMess_HTTP2, + VMess_TCP_TLS, + VMess_WebSocket_TLS, + VMess_mKCPSeed, + } +} diff --git a/ProxySU_Core/ViewModels/Developers/XrayProject.cs b/ProxySU_Core/ViewModels/Developers/XrayProject.cs new file mode 100644 index 0000000..7ef84d3 --- /dev/null +++ b/ProxySU_Core/ViewModels/Developers/XrayProject.cs @@ -0,0 +1,238 @@ +using Renci.SshNet; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Windows; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace ProxySU_Core.ViewModels.Developers +{ + public class XrayProject : Project + { + + private const string ServerLogPath = "/Templates/xray/server/00_log/00_log.json"; + private const string ServerApiPath = "/Templates/xray/server/01_api/01_api.json"; + private const string ServerDnsPath = "/Templates/xray/server/02_dns/02_dns.json"; + private const string ServerRoutingPath = "/Templates/xray/server/03_routing/03_routing.json"; + private const string ServerPolicyPath = "/Templates/xray/server/04_policy/04_policy.json"; + private const string ServerInboundsPath = "/Templates/xray/server/05_inbounds/05_inbounds.json"; + private const string ServerOutboundsPath = "/Templates/xray/server/06_outbounds/06_outbounds.json"; + private const string ServerTransportPath = "/Templates/xray/server/07_transport/07_transport.json"; + private const string ServerStatsPath = "/Templates/xray/server/08_stats/08_stats.json"; + private const string ServerReversePath = "/Templates/xray/server/09_reverse/09_reverse.json"; + + public XrayProject(SshClient sshClient, XrayParameters parameters, Action writeOutput) : base(sshClient, parameters, writeOutput) + { + } + + public override void Execute() + { + try + { + EnsureRootAuth(); + + if (FileExists("/usr/local/bin/xray")) + { + var btnResult = MessageBox.Show("已经安装Xray,是否需要重装?", "提示", MessageBoxButton.YesNo); + if (btnResult == MessageBoxResult.No) + { + MessageBox.Show("安装终止", "提示"); + return; + } + } + + EnsureSystemEnv(); + + ConfigureSoftware(); + + ConfigureIPv6(); + + ConfigureFirewall(); + + SyncTimeDiff(); + + ValidateDomain(); + + InstallXray(); + } + catch (Exception ex) + { + MessageBox.Show("安装终止," + ex.Message); + } + } + + private void InstallXray() + { + RunCmd("bash -c \"$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)\" @ install"); + + if (FileExists("/usr/local/bin/xray")) + { + WriteOutput("Xray安装成功"); + } + + RunCmd($"sed -i 's/User=nobody/User=root/g' /etc/systemd/system/xray.service"); + RunCmd($"sed -i 's/CapabilityBoundingSet=/#CapabilityBoundingSet=/g' /etc/systemd/system/xray.service"); + RunCmd($"sed -i 's/AmbientCapabilities=/#AmbientCapabilities=/g' /etc/systemd/system/xray.service"); + RunCmd($"systemctl daemon-reload"); + + if (FileExists("/usr/local/etc/xray/config.json")) + { + RunCmd(@"mv /usr/local/etc/xray/config.json /usr/local/etc/xray/config.json.1"); + } + + UploadXrayConfig(); + } + + private int GetRandomPort() + { + var random = new Random(); + return random.Next(10001, 60000); + } + + private void UploadXrayConfig() + { + dynamic logObj = JsonConvert.DeserializeObject(File.ReadAllText(ServerLogPath)); + dynamic apiObj = JsonConvert.DeserializeObject(File.ReadAllText(ServerApiPath)); + dynamic dnsObj = JsonConvert.DeserializeObject(File.ReadAllText(ServerDnsPath)); + dynamic routingObj = JsonConvert.DeserializeObject(File.ReadAllText(ServerRoutingPath)); + dynamic policyObj = JsonConvert.DeserializeObject(File.ReadAllText(ServerPolicyPath)); + dynamic inboundsObj = JsonConvert.DeserializeObject(File.ReadAllText(ServerInboundsPath)); + dynamic outboundsObj = JsonConvert.DeserializeObject(File.ReadAllText(ServerOutboundsPath)); + dynamic transportObj = JsonConvert.DeserializeObject(File.ReadAllText(ServerTransportPath)); + dynamic statsObj = JsonConvert.DeserializeObject(File.ReadAllText(ServerStatsPath)); + dynamic reverseObj = JsonConvert.DeserializeObject(File.ReadAllText(ServerReversePath)); + + switch (Parameters.Type) + { + case XrayType.Shadowsocks_AEAD: + break; + case XrayType.Shadowsocks_TCP: + break; + case XrayType.Sockets5_TLS: + break; + case XrayType.Trojan_TCP_TLS: + break; + case XrayType.VLESS_H2C_Caddy2: + inboundsObj = JsonConvert.DeserializeObject(File.ReadAllText("/Templates/xray/server/05_inbounds/VLESS_HTTP2_TLS.json")); + inboundsObj[0]["port"] = GetRandomPort(); + inboundsObj[0]["settings"]["clients"][0]["id"] = Parameters.UUID; + inboundsObj[0]["streamSettings"]["httpSettings"]["path"] = Parameters.VlessHttpPath; + inboundsObj[0]["streamSettings"]["httpSettings"]["host"][0] = Parameters.Domain; + break; + case XrayType.VLESS_TCP_TLS_WS: + inboundsObj = JsonConvert.DeserializeObject(File.ReadAllText("/Templates/xray/server/05_inbounds/VLESS_TCP_TLS_WS.json")); + inboundsObj[0]["port"] = GetRandomPort(); + inboundsObj[0]["settings"]["clients"][0]["id"] = Parameters.UUID; + inboundsObj[0]["streamSettings"]["httpSettings"]["path"] = Parameters.VlessWsPath; + break; + case XrayType.VLESS_TCP_XTLS_WHATEVER: + break; + case XrayType.VLESS_mKCPSeed: + break; + case XrayType.VMess_HTTP2: + break; + case XrayType.VMess_TCP_TLS: + break; + case XrayType.VMess_WebSocket_TLS: + break; + case XrayType.VMess_mKCPSeed: + break; + default: + break; + } + + var serverConfig = new + { + log = logObj["log"], + api = apiObj["api"], + dns = dnsObj["dns"], + routing = routingObj["routing"], + policy = policyObj["policy"], + inbounds = inboundsObj["inbounds"], + outbounds = outboundsObj["outbounds"], + transport = transportObj["transport"], + stats = statsObj["stats"], + reverse = reverseObj["reverse"] + }; + + var json = JsonConvert.SerializeObject(serverConfig); + var jsonStream = new MemoryStream(Encoding.UTF8.GetBytes(json)); + UploadFile(jsonStream, "/usr/local/etc/xray/config.json"); + jsonStream.Dispose(); + } + + private void InstallCert() + { + // 安装依赖 + RunCmd(GetInstallCmd("socat")); + + // 解决搬瓦工CentOS缺少问题 + RunCmd(GetInstallCmd("automake autoconf libtool")); + + // 安装Acme + var result = RunCmd($"curl https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | sh -s -- --install-online -m {GetRandomEmail()}"); + if (result.Contains("Install success")) + { + WriteOutput("安装 acme.sh 成功"); + } + else + { + throw new Exception("安装 acme.sh 失败,请联系开发者!"); + } + + RunCmd("cd ~/.acme.sh/"); + RunCmd("alias acme.sh=~/.acme.sh/acme.sh"); + + // 申请证书 + if (OnlyIpv6) + { + var cmd = $"/root/.acme.sh/acme.sh --force --debug --issue --standalone -d {Parameters.Domain} --listen-v6"; + result = RunCmd(cmd); + } + else + { + var cmd = $"/root/.acme.sh/acme.sh --force --debug --issue --standalone -d {Parameters.Domain}"; + result = RunCmd(cmd); + } + + if (result.Contains("Cert success")) + { + WriteOutput("申请证书成功"); + } + else + { + throw new Exception("申请证书失败,请联系开发者!"); + } + + // 安装证书到xray + RunCmd("mkdir -p /usr/local/etc/xray/ssl"); + RunCmd($"/root/.acme.sh/acme.sh --installcert -d {Parameters.Domain} --certpath /usr/local/etc/xray/ssl/xray_ssl.crt --keypath /usr/local/etc/xray/ssl/xray_ssl.key --capath /usr/local/etc/xray/ssl/xray_ssl.crt --reloadcmd \"systemctl restart xray\""); + result = RunCmd(@"if [ ! -f ""/usr/local/etc/xray/ssl/xray_ssl.key"" ]; then echo ""0""; else echo ""1""; fi | head -n 1"); + if (result.Contains("1")) + { + WriteOutput("安装证书成功"); + } + else + { + throw new Exception("安装证书失败,请联系开发者!"); + } + + + RunCmd(@"chmod 644 /usr/local/etc/xray/ssl/xray_ssl.key"); + } + + private void InstallCaddy() + { + + } + + private string GetRandomEmail() + { + Random r = new Random(); + var num = r.Next(200000000, 900000000); + return $"{num}@qq.com"; + } + } +} diff --git a/ProxySU_Core/ViewModels/Host.cs b/ProxySU_Core/ViewModels/Host.cs new file mode 100644 index 0000000..d2af885 --- /dev/null +++ b/ProxySU_Core/ViewModels/Host.cs @@ -0,0 +1,129 @@ +using Microsoft.Win32; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Windows; +using System.Windows.Input; + +namespace ProxySU_Core.ViewModels +{ + public class Host : BaseModel + { + private LoginSecretType _secretType; + private string tag = string.Empty; + private string _address; + private LocalProxy proxy; + private readonly ICommand _selectKeyCommand; + + public Host() + { + _selectKeyCommand = new BaseCommand(obj => OpenFileDialog(obj)); + Proxy = new LocalProxy(); + } + + + public string Tag + { + get => tag; set + { + tag = value; + Notify("Tag"); + } + } + + public string Address + { + get => _address; + set + { + _address = value; + Notify("Address"); + } + } + + public string UserName { get; set; } + + public string Password { get; set; } + + public int Port { get; set; } = 22; + + public string PrivateKeyPath { get; set; } + + public LocalProxy Proxy + { + get => proxy; set + { + proxy = value; + Notify("Proxy"); + } + } + + public LoginSecretType SecretType + { + get + { + return _secretType; + } + set + { + _secretType = value; + Notify("SecretType"); + Notify("KeyUploaderVisiblity"); + Notify("PasswordVisiblity"); + } + } + + [JsonIgnore] + public Visibility PasswordVisiblity + { + get + { + if (SecretType == LoginSecretType.Password) + { + return Visibility.Visible; + } + return Visibility.Collapsed; + } + } + + [JsonIgnore] + public Visibility KeyUploaderVisiblity + { + get + { + if (SecretType == LoginSecretType.PrivateKey) + { + return Visibility.Visible; + } + return Visibility.Collapsed; + } + } + + + [JsonIgnore] + public ICommand SelectKeyCommand + { + get + { + return _selectKeyCommand; + } + } + + + private void OpenFileDialog(object obj) + { + var fileDialog = new OpenFileDialog(); + fileDialog.FileOk += OnFileOk; + fileDialog.ShowDialog(); + } + + private void OnFileOk(object sender, CancelEventArgs e) + { + var file = sender as OpenFileDialog; + PrivateKeyPath = file.FileName; + } + } + + +} diff --git a/ProxySU_Core/ViewModels/LocalProxy.cs b/ProxySU_Core/ViewModels/LocalProxy.cs new file mode 100644 index 0000000..c6984ca --- /dev/null +++ b/ProxySU_Core/ViewModels/LocalProxy.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ProxySU_Core.ViewModels +{ + public class LocalProxy : BaseModel + { + private LocalProxyType type = LocalProxyType.None; + + public string Address { get; set; } = "127.0.0.1"; + + public int Port { get; set; } = 1080; + + public LocalProxyType Type + { + get => type; set + { + type = value; + Notify("Type"); + } + + } + + public string UserName { get; set; } + + public string Password { get; set; } + + } + + +} diff --git a/ProxySU_Core/ViewModels/LocalProxyType.cs b/ProxySU_Core/ViewModels/LocalProxyType.cs new file mode 100644 index 0000000..df6f158 --- /dev/null +++ b/ProxySU_Core/ViewModels/LocalProxyType.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ProxySU_Core.ViewModels +{ + public enum LocalProxyType + { + None = 0, + // + // 摘要: + // A SOCKS4 proxy server. + Socks4 = 1, + // + // 摘要: + // A SOCKS5 proxy server. + Socks5 = 2, + // + // 摘要: + // A HTTP proxy server. + Http = 3 + } +} diff --git a/ProxySU_Core/ViewModels/LoginSecretType.cs b/ProxySU_Core/ViewModels/LoginSecretType.cs new file mode 100644 index 0000000..e897261 --- /dev/null +++ b/ProxySU_Core/ViewModels/LoginSecretType.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ProxySU_Core.ViewModels +{ + public enum LoginSecretType + { + Password = 0, + PrivateKey = 1 + } +} diff --git a/ProxySU_Core/ViewModels/Record.cs b/ProxySU_Core/ViewModels/Record.cs new file mode 100644 index 0000000..9f6af0d --- /dev/null +++ b/ProxySU_Core/ViewModels/Record.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ProxySU_Core.ViewModels +{ + public class Record + { + public Host Host { get; set; } + + } +} diff --git a/ProxySU_Core/ViewModels/Terminal.cs b/ProxySU_Core/ViewModels/Terminal.cs new file mode 100644 index 0000000..63a2cad --- /dev/null +++ b/ProxySU_Core/ViewModels/Terminal.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Text; + +namespace ProxySU_Core.ViewModels +{ + public class Terminal : BaseModel + { + private string outputText; + + public Terminal(Host host) + { + Host = host; + } + + public Host Host { get; set; } + + public string CommandText { get; set; } + + public string OutputText + { + get => outputText; + } + + public void ClearOutput() + { + outputText = ""; + Notify("OutputText"); + } + + public void AddOutput(string text) + { + outputText += text; + + if (!text.EndsWith("\n")) + { + outputText += "\n"; + } + Notify("OutputText"); + } + } +} diff --git a/ProxySU_Core/Views/HostEditorWindow.xaml b/ProxySU_Core/Views/HostEditorWindow.xaml new file mode 100644 index 0000000..d343726 --- /dev/null +++ b/ProxySU_Core/Views/HostEditorWindow.xaml @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +