1
0
mirror of https://github.com/proxysu/ProxySU.git synced 2024-11-22 13:16:09 +03:00

add proxysu core

This commit is contained in:
next-autumn 2021-02-25 09:59:06 +08:00
parent 7034a1dc22
commit bdac51e8ea
70 changed files with 3122 additions and 82 deletions

1
.gitignore vendored
View File

@ -198,3 +198,4 @@ FakesAssemblies/
# vs code # vs code
.vscode/* .vscode/*
/ProxySU_Core/Data/Record.json

View File

@ -1,10 +0,0 @@
<Application x:Class="ProxySU.Core.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ProxySU.Core"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

View File

@ -1,28 +0,0 @@
<Window x:Class="ProxySU.Core.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ProxySU.Core"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Menu Style="{DynamicResource MaterialDesignMenu}">
<MenuItem Header="文件" Style="{DynamicResource MaterialDesignMenuItem}">
<MenuItem Header="SubMenu">肖文杰</MenuItem>
</MenuItem>
<MenuItem Header="文件" Style="{DynamicResource MaterialDesignMenuItem}"></MenuItem>
<MenuItem Header="文件" Style="{DynamicResource MaterialDesignMenuItem}"></MenuItem>
</Menu>
<!--<TabControl Style="{DynamicResource MaterialDesignNavigatilRailTabControl}" >
<TabItem Header="Item2" Style="{DynamicResource MaterialDesignNavigationRailTabItem}">
<Button Style="{DynamicResource MaterialDesignRaisedButton}" Content="Hello!"></Button>
</TabItem>
<TabItem Header="Item2"></TabItem>
</TabControl>-->
</Grid>
</Window>

View File

@ -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
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}

View File

@ -1,13 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MaterialDesignThemes" Version="3.2.0" />
</ItemGroup>
</Project>

View File

@ -1,10 +1,12 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15 # Visual Studio Version 16
VisualStudioVersion = 15.0.28307.1022 VisualStudioVersion = 16.0.31005.135
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProxySU", "ProxySU\ProxySU.csproj", "{DD5505BC-E7F1-4D03-ABC7-B636E893FC09}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProxySU", "ProxySU\ProxySU.csproj", "{DD5505BC-E7F1-4D03-ABC7-B636E893FC09}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProxySU_Core", "ProxySU_Core\ProxySU_Core.csproj", "{B066015C-D347-4493-92F1-6556D3863996}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU 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}.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.ActiveCfg = Release|Any CPU
{DD5505BC-E7F1-4D03-ABC7-B636E893FC09}.Release|Any CPU.Build.0 = 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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

6
ProxySU_Core/App.config Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
</configuration>

33
ProxySU_Core/App.xaml Normal file
View File

@ -0,0 +1,33 @@
<Application x:Class="ProxySU_Core.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ProxySU_Core"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
StartupUri="Views/MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!--Languages-->
<ResourceDictionary Source="/Resources/Languages/zh_cn.xaml" />
<!-- MahApps -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Teal.xaml" />
<!-- Material Design -->
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.Teal.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Teal.xaml" />
<!-- Material Design: MahApps Compatibility -->
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.MahApps;component/Themes/MaterialDesignTheme.MahApps.Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.MahApps;component/Themes/MaterialDesignTheme.MahApps.Flyout.xaml" />
<!--Override Themes-->
<ResourceDictionary Source="/Resources/Styles/MaterialDesignThemes.Overrides.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

View File

@ -6,7 +6,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
namespace ProxySU.Core namespace ProxySU_Core
{ {
/// <summary> /// <summary>
/// Interaction logic for App.xaml /// Interaction logic for App.xaml

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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 文件中的 <UICulture>CultureYouAreCodingWith</UICulture>
//例如,如果您在源文件中使用的是美国英语,
//使用的是美国英语,请将 <UICulture> 设置为 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")]

View File

@ -0,0 +1,70 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本: 4.0.30319.42000
//
// 对此文件的更改可能导致不正确的行为,如果
// 重新生成代码,则所做更改将丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace ProxySU_Core.Properties
{
/// <summary>
/// 强类型资源类,用于查找本地化字符串等。
/// </summary>
// 此类是由 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()
{
}
/// <summary>
/// 返回此类使用的缓存 ResourceManager 实例。
/// </summary>
[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;
}
}
/// <summary>
/// 重写当前线程的 CurrentUICulture 属性,对
/// 使用此强类型资源类的所有资源查找执行重写。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,29 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
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;
}
}
}
}

View File

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@ -0,0 +1,304 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B066015C-D347-4493-92F1-6556D3863996}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>ProxySU_Core</RootNamespace>
<AssemblyName>ProxySU_Core</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="ControlzEx, Version=4.0.0.0, Culture=neutral, PublicKeyToken=69f1c32f803d307e, processorArchitecture=MSIL">
<HintPath>..\packages\ControlzEx.4.3.0\lib\net45\ControlzEx.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro, Version=2.0.0.0, Culture=neutral, PublicKeyToken=51482d6f650b2b3f, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.2.0.0\lib\net46\MahApps.Metro.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.BootstrapIcons, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.BootstrapIcons.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.BoxIcons, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.BoxIcons.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.Codicons, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Codicons.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Core.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.Entypo, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Entypo.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.EvaIcons, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.EvaIcons.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.FeatherIcons, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.FeatherIcons.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.FileIcons, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.FileIcons.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.Fontaudio, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Fontaudio.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.FontAwesome, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.FontAwesome.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.ForkAwesome, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.ForkAwesome.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.Ionicons, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Ionicons.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.JamIcons, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.JamIcons.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.Material, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Material.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.MaterialDesign, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.MaterialDesign.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.MaterialLight, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.MaterialLight.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.Microns, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Microns.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.Modern, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Modern.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.Octicons, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Octicons.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.PicolIcons, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.PicolIcons.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.PixelartIcons, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.PixelartIcons.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.RadixIcons, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.RadixIcons.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.RemixIcon, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.RemixIcon.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.RPGAwesome, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.RPGAwesome.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.SimpleIcons, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.SimpleIcons.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.Typicons, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Typicons.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.Unicons, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Unicons.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.VaadinIcons, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.VaadinIcons.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.WeatherIcons, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.WeatherIcons.dll</HintPath>
</Reference>
<Reference Include="MahApps.Metro.IconPacks.Zondicons, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0c0d510f9915137a, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.IconPacks.4.8.0\lib\net46\MahApps.Metro.IconPacks.Zondicons.dll</HintPath>
</Reference>
<Reference Include="MaterialDesignColors, Version=2.0.0.2422, Culture=neutral, PublicKeyToken=df2a72020bd7962a, processorArchitecture=MSIL">
<HintPath>..\packages\MaterialDesignColors.2.0.0\lib\net452\MaterialDesignColors.dll</HintPath>
</Reference>
<Reference Include="MaterialDesignThemes.MahApps, Version=0.1.6.2422, Culture=neutral, PublicKeyToken=df2a72020bd7962a, processorArchitecture=MSIL">
<HintPath>..\packages\MaterialDesignThemes.MahApps.0.1.6\lib\net452\MaterialDesignThemes.MahApps.dll</HintPath>
</Reference>
<Reference Include="MaterialDesignThemes.Wpf, Version=4.0.0.2422, Culture=neutral, PublicKeyToken=df2a72020bd7962a, processorArchitecture=MSIL">
<HintPath>..\packages\MaterialDesignThemes.4.0.0\lib\net452\MaterialDesignThemes.Wpf.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Xaml.Behaviors, Version=1.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Xaml.Behaviors.Wpf.1.1.19\lib\net45\Microsoft.Xaml.Behaviors.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Renci.SshNet, Version=2020.0.1.0, Culture=neutral, PublicKeyToken=1cee9f8bde3db106, processorArchitecture=MSIL">
<HintPath>..\packages\SSH.NET.2020.0.1\lib\net40\Renci.SshNet.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Configuration" />
<Reference Include="System.Data" />
<Reference Include="System.Web" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Tools\DateTimeUtils.cs" />
<Compile Include="ViewModels\BaseCommand.cs" />
<Compile Include="ViewModels\BaseModel.cs" />
<Compile Include="ViewModels\Developers\Developer.cs" />
<Compile Include="ViewModels\Developers\IParameters.cs" />
<Compile Include="ViewModels\Developers\Project.cs" />
<Compile Include="ViewModels\Developers\XrayParameters.cs" />
<Compile Include="ViewModels\Developers\XrayProject.cs" />
<Compile Include="ViewModels\Host.cs" />
<Compile Include="ViewModels\LocalProxy.cs" />
<Compile Include="ViewModels\LocalProxyType.cs" />
<Compile Include="ViewModels\LoginSecretType.cs" />
<Compile Include="ViewModels\Record.cs" />
<Compile Include="ViewModels\Terminal.cs" />
<Compile Include="Views\HostEditorWindow.xaml.cs">
<DependentUpon>HostEditorWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Views\MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Views\TerminalWindow.xaml.cs">
<DependentUpon>TerminalWindow.xaml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="Converters\LoginSecretTypeConverter.cs" />
<Compile Include="Converters\ProxyTypeConverter.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="Data\Record.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<None Include="Templates\xray\base.json" />
<None Include="Templates\xray\caddy\Http2Web.caddyfile" />
<None Include="Templates\xray\caddy\vlessTcpTlsWeb.caddyfile" />
<None Include="Templates\xray\caddy\WebSocketTLSWeb.caddyfile" />
<None Include="Templates\xray\client\00_log\00_log.json" />
<None Include="Templates\xray\client\01_api\01_api.json" />
<None Include="Templates\xray\client\02_dns\02_dns.json" />
<None Include="Templates\xray\client\03_routing\03_routing.json" />
<None Include="Templates\xray\client\04_policy\04_policy.json" />
<None Include="Templates\xray\client\05_inbounds\05_inbounds.json" />
<None Include="Templates\xray\client\06_outbounds\06_outbounds.json" />
<None Include="Templates\xray\client\06_outbounds\VLESS_HTTP2_TLS.json" />
<None Include="Templates\xray\client\06_outbounds\VLESS_TCP_TLS_WS.json" />
<None Include="Templates\xray\client\07_transport\07_transport.json" />
<None Include="Templates\xray\client\08_stats\08_stats.json" />
<None Include="Templates\xray\client\09_reverse\09_reverse.json" />
<None Include="Templates\xray\server\00_log\00_log.json" />
<None Include="Templates\xray\server\01_api\01_api.json" />
<None Include="Templates\xray\server\02_dns\02_dns.json" />
<None Include="Templates\xray\server\03_routing\03_routing.json" />
<None Include="Templates\xray\server\04_policy\04_policy.json" />
<None Include="Templates\xray\server\05_inbounds\05_inbounds.json" />
<None Include="Templates\xray\server\05_inbounds\VLESS_HTTP2_TLS.json" />
<None Include="Templates\xray\server\05_inbounds\VLESS_TCP_TLS_WS.json" />
<None Include="Templates\xray\server\06_outbounds\06_outbounds.json" />
<None Include="Templates\xray\server\07_transport\07_transport.json" />
<None Include="Templates\xray\server\08_stats\08_stats.json" />
<None Include="Templates\xray\server\09_reverse\09_reverse.json" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<Page Include="Resources\Languages\en.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Resources\Languages\zh_cn.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Resources\Styles\MaterialDesignThemes.Overrides.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\HostEditorWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\TerminalWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\MaterialDesignThemes.4.0.0\build\MaterialDesignThemes.targets" Condition="Exists('..\packages\MaterialDesignThemes.4.0.0\build\MaterialDesignThemes.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\MaterialDesignThemes.4.0.0\build\MaterialDesignThemes.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MaterialDesignThemes.4.0.0\build\MaterialDesignThemes.targets'))" />
</Target>
<ProjectExtensions />
</Project>

View File

@ -0,0 +1,48 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<sys:String x:Key="TabItemHeaderAppDeployment">Deployment</sys:String>
<sys:String x:Key="LanguageText">Language</sys:String>
<sys:String x:Key="LanguageChinese">Chinese</sys:String>
<sys:String x:Key="LanguageEnglish">English</sys:String>
<sys:String x:Key="Hosts">Hosts</sys:String>
<sys:String x:Key="AddHost">Add Host</sys:String>
<sys:String x:Key="Actions">Actions</sys:String>
<sys:String x:Key="Connect">Connect</sys:String>
<sys:String x:Key="Edit">Edit</sys:String>
<sys:String x:Key="Delete">Delete</sys:String>
<sys:String x:Key="Install">Install</sys:String>
<sys:String x:Key="Save">Save</sys:String>
<sys:String x:Key="Info">Info</sys:String>
<sys:String x:Key="Warning">Warning</sys:String>
<sys:String x:Key="Error">Error</sys:String>
<!--Host Window-->
<sys:String x:Key="HostWindowTitle">Server Manager</sys:String>
<sys:String x:Key="ConnectionGroupName">Connection</sys:String>
<sys:String x:Key="HostUserName">User</sys:String>
<sys:String x:Key="HostPassword">Password</sys:String>
<sys:String x:Key="HostTag">Tag</sys:String>
<sys:String x:Key="HostAddress">Host</sys:String>
<sys:String x:Key="HostPort">Port</sys:String>
<sys:String x:Key="HostLoginType">Method</sys:String>
<sys:String x:Key="PasswordLogin">Password Login</sys:String>
<sys:String x:Key="CertLogin">KeyLogin</sys:String>
<sys:String x:Key="KeyLoginField">Key</sys:String>
<sys:String x:Key="KeyUpload">Upload</sys:String>
<sys:String x:Key="ProxyGroupName">Proxy</sys:String>
<sys:String x:Key="ProxyType">Method</sys:String>
<sys:String x:Key="ProxyTypeNone">None</sys:String>
<sys:String x:Key="ProxyTypeHttp">Http</sys:String>
<sys:String x:Key="ProxyTypeSocks5">Socks5</sys:String>
<sys:String x:Key="ProxyHostName">Host</sys:String>
<sys:String x:Key="ProxyHostPort">Port</sys:String>
<sys:String x:Key="ProxyUserName">User</sys:String>
<sys:String x:Key="ProxyPassword">Password</sys:String>
<sys:String x:Key="HostAddressNotNull">Please enter host</sys:String>
<sys:String x:Key="HostPortNotNull">Please enter port</sys:String>
<sys:String x:Key="PorxyAddressNotNull">Please enter proxy host</sys:String>
<sys:String x:Key="ProxyProtNotNull">Please enter proxy port</sys:String>
<!--Terminal Window-->
</ResourceDictionary>

View File

@ -0,0 +1,48 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<sys:String x:Key="TabItemHeaderAppDeployment">应用布署</sys:String>
<sys:String x:Key="LanguageText">语言</sys:String>
<sys:String x:Key="LanguageChinese">中文</sys:String>
<sys:String x:Key="LanguageEnglish">英文</sys:String>
<sys:String x:Key="Hosts">主机列表</sys:String>
<sys:String x:Key="AddHost">添加主机</sys:String>
<sys:String x:Key="Actions">操作</sys:String>
<sys:String x:Key="Connect">连接</sys:String>
<sys:String x:Key="Install">安装</sys:String>
<sys:String x:Key="Edit">编辑</sys:String>
<sys:String x:Key="Delete">删除</sys:String>
<sys:String x:Key="Save">保存</sys:String>
<sys:String x:Key="Info">消息</sys:String>
<sys:String x:Key="Warning">提示</sys:String>
<sys:String x:Key="Error">错误</sys:String>
<!--Host Window-->
<sys:String x:Key="HostWindowTitle">服务器管理</sys:String>
<sys:String x:Key="ConnectionGroupName">连接</sys:String>
<sys:String x:Key="HostUserName">用户名</sys:String>
<sys:String x:Key="HostPassword">密码</sys:String>
<sys:String x:Key="HostTag">别名</sys:String>
<sys:String x:Key="HostAddress">主机</sys:String>
<sys:String x:Key="HostPort">端口</sys:String>
<sys:String x:Key="HostLoginType">登陆方式</sys:String>
<sys:String x:Key="PasswordLogin">密码登陆</sys:String>
<sys:String x:Key="KeyLogin">密钥登陆</sys:String>
<sys:String x:Key="KeyLoginField">密钥</sys:String>
<sys:String x:Key="KeyUpload">上传</sys:String>
<sys:String x:Key="ProxyGroupName">代理</sys:String>
<sys:String x:Key="ProxyType">类型</sys:String>
<sys:String x:Key="ProxyTypeNone">无</sys:String>
<sys:String x:Key="ProxyTypeHttp">Http</sys:String>
<sys:String x:Key="ProxyTypeSocks5">Socks5</sys:String>
<sys:String x:Key="ProxyHostName">代理地址</sys:String>
<sys:String x:Key="ProxyHostPort">代理端口</sys:String>
<sys:String x:Key="ProxyUserName">用户名</sys:String>
<sys:String x:Key="ProxyPassword">密码</sys:String>
<sys:String x:Key="HostAddressNotNull">请输入主机</sys:String>
<sys:String x:Key="HostPortNotNull">请输入端口号</sys:String>
<sys:String x:Key="PorxyAddressNotNull">请输入代理地址</sys:String>
<sys:String x:Key="ProxyProtNotNull">请输入代理端口号</sys:String>
<!--Terminal Window-->
</ResourceDictionary>

View File

@ -0,0 +1,48 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:materialDesign="clr-namespace:MaterialDesignThemes.Wpf;assembly=MaterialDesignThemes.Wpf">
<Style
TargetType="{x:Type TabItem}"
BasedOn="{StaticResource MaterialDesignNavigationRailTabItem}"
x:Key="MaterialDesignNavigationRailTabItem">
<Setter Property="Height" Value="52" />
<Setter Property="Padding" Value="12,0" />
</Style>
<Style
TargetType="GroupBox"
x:Key="MaterialDesignHeaderedContentControl">
</Style>
<Style
TargetType="DataGridCell"
BasedOn="{StaticResource MahApps.Styles.DataGridCell}"
x:Key="DataGridCell">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="Padding" Value="10,7"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{DynamicResource MahApps.Brushes.Accent}" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="{DynamicResource MahApps.Brushes.Accent}" />
<Setter Property="FontWeight" Value="Bold"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="DataGridColumnHeader"
BasedOn="{StaticResource MaterialDesignDataGridColumnHeader}"
x:Key="DataGridColumnHeader">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="BorderThickness" Value="0,0,0,1"/>
</Style>
<Style
TargetType="DataGrid"
BasedOn="{StaticResource MahApps.Styles.DataGrid}"
x:Key="DataGrid">
</Style>
</ResourceDictionary>

View File

@ -0,0 +1,12 @@
{
"log": {},
"api": {},
"dns": {},
"routing": {},
"policy": {},
"inbounds": [],
"outbounds": [],
"transport": {},
"stats": {},
"reverse": {}
}

View File

@ -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##
}

View File

@ -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##
}

View File

@ -0,0 +1,10 @@
:8800 {
root * /usr/share/caddy
file_server
##reverse_Proxy1##
##reverse_Proxy2##
##reverse_Proxy3##
}
##domain##:80 {
redir https://##domain##{uri}
}

View File

@ -0,0 +1,5 @@
{
"log": {
"loglevel": "warning"
}
}

View File

@ -0,0 +1,3 @@
{
"api": null
}

View File

@ -0,0 +1,3 @@
{
"dns": {}
}

View File

@ -0,0 +1,3 @@
{
"routing": {}
}

View File

@ -0,0 +1,3 @@
{
"policy": {}
}

View File

@ -0,0 +1,23 @@
{
"inbounds": [
{
"protocol": "http",
"port": 1081
},
{
"port": 1080,
"protocol": "socks",
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls"
]
},
"settings": {
"udp": true,
"auth": "noauth"
}
}
]
}

View File

@ -0,0 +1,3 @@
{
"outbounds": []
}

View File

@ -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
}
}
}
]
}

View File

@ -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": ""
}
}
}
]
}

View File

@ -0,0 +1,3 @@
{
"transport": {}
}

View File

@ -0,0 +1,3 @@
{
"stats": null
}

View File

@ -0,0 +1,3 @@
{
"reverse": {}
}

View File

@ -0,0 +1,5 @@
{
"log": {
"loglevel": "warning"
}
}

View File

@ -0,0 +1,3 @@
{
"api": null
}

View File

@ -0,0 +1,3 @@
{
"dns": {}
}

View File

@ -0,0 +1,14 @@
{
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"ip": [
"geoip:private"
],
"outboundTag": "block"
}
]
}
}

View File

@ -0,0 +1,3 @@
{
"policy": {}
}

View File

@ -0,0 +1,3 @@
{
"inbounds": []
}

View File

@ -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": [
""
]
}
}
}
]
}

View File

@ -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": ""
}
}
}
]
}

View File

@ -0,0 +1,12 @@
{
"outbounds": [
{
"protocol": "freedom",
"tag": "direct"
},
{
"protocol": "blackhole",
"tag": "block"
}
]
}

View File

@ -0,0 +1,3 @@
{
"transport": {}
}

View File

@ -0,0 +1,3 @@
{
"stats": null
}

View File

@ -0,0 +1,3 @@
{
"reverse": {}
}

View File

@ -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
{
/// <summary>
/// 从国家授时中心获取标准GMT时间读取https://www.tsa.cn
/// GMT时间与UTC时间没有差别可以UTC=GMT
/// </summary>
/// <returns>返回网络时间</returns>
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;
}
/// <summary>
/// 设置系统时间
/// </summary>
/// <param name="dt">需要设置的时间</param>
/// <returns>返回系统时间设置状态true为成功false为失败</returns>
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;
}
}
}

View File

@ -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<object> _execution;
private readonly Func<object, bool> _canExecute;
public BaseCommand(Action<object> execution, Func<object, bool> 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);
}
}
}
}

View File

@ -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));
}
}
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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<TParameters> : BaseModel where TParameters : IParameters
{
private SshClient _sshClient;
protected Action<string> 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<string> 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;
}
/// <summary>
/// 执行安装命令
/// </summary>
public abstract void Execute();
/// <summary>
/// 配置系统基础环境
/// </summary>
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");
}
}
}
/// <summary>
/// 确保Root账户登陆
/// </summary>
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账户登陆主机");
}
}
/// <summary>
/// 配置IPV6环境
/// </summary>
protected void ConfigureIPv6()
{
if (IsOnlyIpv6())
{
SetNat64();
}
}
/// <summary>
/// 配置必要的软件
/// </summary>
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"));
}
}
/// <summary>
/// 配置防火墙
/// </summary>
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");
}
}
}
/// <summary>
/// 配置同步时间差
/// </summary>
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()})\"");
}
}
/// <summary>
/// 验证域名是否绑定了主机
/// </summary>
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请检查域名配置");
}
}
}
/// <summary>
/// 判断是否安装某个软件
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
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<string> 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<string, float> dns64List = new Dictionary<string, float>();
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();
}
}
/// <summary>
/// 根据系统环境匹配更新命令
/// </summary>
/// <returns></returns>
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("未识别的系统");
}
/// <summary>
/// 根据系统匹配安装命令
/// </summary>
/// <param name="soft"></param>
/// <returns></returns>
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("未识别的系统");
}
}
}

View File

@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ProxySU_Core.ViewModels.Developers
{
public class XrayParameters : IParameters
{
/// <summary>
/// 访问端口
/// </summary>
public int Port { get; set; }
/// <summary>
/// UUID
/// </summary>
public string UUID { get; set; }
/// <summary>
/// vless ws路径
/// </summary>
public string VlessWsPath { get; set; }
/// <summary>
/// vless tcp路径
/// </summary>
public string VlessTcpPath { get; set; }
/// <summary>
/// vless http路径
/// </summary>
public string VlessHttpPath { get; set; }
/// <summary>
/// vmess ws路径
/// </summary>
public string VmessWsPath { get; set; }
/// <summary>
/// vmess tcp路径
/// </summary>
public string VmessTcpPath { get; set; }
/// <summary>
/// vmess http路径
/// </summary>
public string VmessHttpPath { get; set; }
/// <summary>
/// 域名
/// </summary>
public string Domain { get; set; }
/// <summary>
/// 伪装域名
/// </summary>
public string MaskDomain { get; set; }
/// <summary>
/// 安装类型
/// </summary>
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,
}
}

View File

@ -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<XrayParameters>
{
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<string> 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";
}
}
}

View File

@ -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;
}
}
}

View File

@ -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; }
}
}

View File

@ -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
}
}

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ProxySU_Core.ViewModels
{
public enum LoginSecretType
{
Password = 0,
PrivateKey = 1
}
}

View File

@ -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; }
}
}

View File

@ -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");
}
}
}

View File

@ -0,0 +1,206 @@
<metro:MetroWindow x:Class="ProxySU_Core.HostEditorWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:converters="clr-namespace:ProxySU_Core.Converters"
xmlns:models="clr-namespace:ProxySU_Core.ViewModels"
xmlns:metro="http://metro.mahapps.com/winfx/xaml/controls"
FontSize="14"
mc:Ignorable="d"
Title="{DynamicResource HostWindowTitle}" Height="650" Width="400">
<Window.Resources>
<converters:LoginSecretTypeConverter x:Key="LoginSecretTypeConverter" />
<converters:ProxyTypeConverter x:Key="ProxyTypeConverter" />
</Window.Resources>
<StackPanel VerticalAlignment="Top" Margin="10">
<GroupBox
Style="{StaticResource MaterialDesignHeaderedContentControl}"
Header="{StaticResource ConnectionGroupName}">
<StackPanel Margin="10">
<StackPanel Orientation="Horizontal" Margin="0,0,0,0">
<TextBlock
Width="100"
Text="{DynamicResource HostTag}"
VerticalAlignment="Center"/>
<TextBox
Text="{Binding Path=Tag}"
Width="200" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,15,0,0">
<TextBlock
Width="100"
Text="{DynamicResource HostAddress}"
VerticalAlignment="Center"/>
<TextBox
Text="{Binding Path=Address}"
Width="200" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,15,0,0">
<TextBlock
Width="100"
Text="{DynamicResource HostPort}"
VerticalAlignment="Center" />
<TextBox
Text="{Binding Path=Port}"
Width="200"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,15,0,0">
<TextBlock
Width="100"
Text="{DynamicResource HostUserName}"
VerticalAlignment="Center" />
<TextBox
Text="{Binding Path=UserName}"
Width="200"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,15,0,0">
<TextBlock
Width="100"
Text="{DynamicResource HostLoginType}"
VerticalAlignment="Center" />
<RadioButton
GroupName="LoginType"
IsChecked="{
Binding Path=SecretType,
Converter={StaticResource LoginSecretTypeConverter},
ConverterParameter={x:Static models:LoginSecretType.Password}
}"
Content="{DynamicResource PasswordLogin}" />
<RadioButton
Margin="10,0,0,0"
GroupName="LoginType"
IsChecked="{
Binding Path=SecretType,
Converter={StaticResource LoginSecretTypeConverter},
ConverterParameter={x:Static models:LoginSecretType.PrivateKey}
}"
Content="{DynamicResource KeyLogin}" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,15,0,0" Visibility="{Binding PasswordVisiblity}">
<TextBlock
Width="100"
Text="{DynamicResource HostPassword}"
VerticalAlignment="Center" />
<TextBox
IsEnabled="{
Binding Path=SecretType,
Converter={StaticResource LoginSecretTypeConverter},
ConverterParameter={x:Static models:LoginSecretType.Password}
}"
Text="{Binding Path=Password}"
Width="200"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,15,0,0" Visibility="{Binding Path=KeyUploaderVisiblity}">
<TextBlock
Width="100"
Text="{DynamicResource KeyLoginField}"
VerticalAlignment="Center" />
<Button
IsEnabled="{
Binding Path=SecretType,
Converter={StaticResource LoginSecretTypeConverter},
ConverterParameter={x:Static models:LoginSecretType.PrivateKey}
}"
Command="{Binding Path=SelectKeyCommand}"
Content="{DynamicResource KeyUpload}" />
</StackPanel>
</StackPanel>
</GroupBox>
<GroupBox
Margin="0,20,0,0"
Header="{DynamicResource ProxyGroupName}"
Style="{StaticResource MaterialDesignHeaderedContentControl}">
<StackPanel Margin="10">
<StackPanel Orientation="Horizontal" Margin="0,0,0,0">
<TextBlock
Width="100"
Text="{DynamicResource ProxyType}" />
<RadioButton
GroupName="ProxyType"
Content="{StaticResource ProxyTypeNone}"
IsChecked="{
Binding Path=Proxy.Type,
Converter={StaticResource ProxyTypeConverter},
ConverterParameter={x:Static models:LocalProxyType.None}
}"/>
<RadioButton
Margin="10,0,0,0"
GroupName="ProxyType"
Content="{DynamicResource ProxyTypeHttp}"
IsChecked="{
Binding Path=Proxy.Type,
Converter={StaticResource ProxyTypeConverter},
ConverterParameter={x:Static models:LocalProxyType.Http}
}"/>
<RadioButton
Margin="10,0,0,0"
GroupName="ProxyType"
Content="{DynamicResource ProxyTypeSocks5}"
IsChecked="{
Binding Path=Proxy.Type,
Converter={StaticResource ProxyTypeConverter},
ConverterParameter={x:Static models:LocalProxyType.Socks5}
}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,15,0,0">
<TextBlock
Width="100"
Text="{DynamicResource ProxyHostName}"
VerticalAlignment="Center" />
<TextBox
Width="200"
Text="{Binding Path=Proxy.Address}" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,15,0,0">
<TextBlock
Width="100"
Text="{DynamicResource ProxyHostPort}"
VerticalAlignment="Center"/>
<TextBox
Width="200"
Text="{Binding Path=Proxy.Port}" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,15,0,0">
<TextBlock
Width="100"
Text="{DynamicResource ProxyUserName}"
VerticalAlignment="Center"/>
<TextBox
Width="200"
Text="{Binding Path=Proxy.UserName}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,15,0,0">
<TextBlock
Width="100"
Text="{DynamicResource ProxyPassword}"
VerticalAlignment="Center"/>
<TextBox
Width="200"
Text="{Binding Path=Proxy.Password}"/>
</StackPanel>
</StackPanel>
</GroupBox>
<Button
Margin="0,20,0,0"
Click="Save"
Content="{DynamicResource Save}" />
</StackPanel>
</metro:MetroWindow>

View File

@ -0,0 +1,87 @@
using MahApps.Metro.Controls;
using MahApps.Metro.Controls.Dialogs;
using ProxySU_Core.ViewModels;
using System;
using System.Collections.Generic;
using System.Text;
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.Shapes;
namespace ProxySU_Core
{
/// <summary>
/// HostEditorWindow.xaml 的交互逻辑
/// </summary>
public partial class HostEditorWindow
{
private readonly Host vm;
public event EventHandler<Host> OnSaveEvent;
public HostEditorWindow(Host host = null)
{
ResizeMode = ResizeMode.NoResize;
WindowStartupLocation = WindowStartupLocation.CenterScreen;
InitializeComponent();
vm = host ?? new Host();
DataContext = vm;
}
public void Save(object sender, RoutedEventArgs e)
{
var isValid = ValidateForm();
if (isValid == false) return;
OnSaveEvent?.Invoke(sender, vm);
Close();
}
private bool ValidateForm()
{
var res = Application.Current.Resources.MergedDictionaries[0];
var warning = Application.Current.FindResource("Warning").ToString();
if (string.IsNullOrWhiteSpace(vm.Address))
{
DialogManager.ShowMessageAsync(this,
warning,
res["HostAddressNotNull"].ToString());
return false;
}
if (vm.Port <= 0)
{
DialogManager.ShowMessageAsync(this,
res["Warning"].ToString(),
res["HostPortNotNull"].ToString());
return false;
}
if (vm.Proxy.Type > LocalProxyType.None)
{
if (string.IsNullOrEmpty(vm.Proxy.Address))
{
DialogManager.ShowMessageAsync(this,
res["Warning"].ToString(),
res["HostAddressNotNull"].ToString());
return false;
}
if (vm.Proxy.Port <= 0)
{
DialogManager.ShowMessageAsync(this,
res["Warning"].ToString(),
res["ProxyPortNotNull"].ToString());
return false;
}
}
return true;
}
}
}

View File

@ -0,0 +1,123 @@
<metro:MetroWindow x:Class="ProxySU_Core.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ProxySU_Core"
mc:Ignorable="d"
GlowBrush="{DynamicResource AccentColorBrush}"
BorderThickness="1"
xmlns:metro="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
TextElement.FontSize="14"
Title="ProxySU Core" Height="800" Width="1200">
<mah:MetroWindow.LeftWindowCommands>
<mah:WindowCommands>
<Button Click="LaunchGitHubSite" ToolTip="Open up the GitHub site">
<iconPacks:PackIconModern
Width="22"
Height="22"
Kind="SocialGithubOctocat" />
</Button>
</mah:WindowCommands>
</mah:MetroWindow.LeftWindowCommands>
<mah:MetroWindow.RightWindowCommands>
<mah:WindowCommands>
<StackPanel Orientation="Horizontal" Margin="0,0,20,0">
<TextBlock Text="{DynamicResource LanguageText}" VerticalAlignment="Center" Margin="0,0,20,0" />
<ComboBox
SelectionChanged="ChangeLanguage"
x:Name="cmbLanguage"
SelectedIndex="0">
<ComboBoxItem x:Name="zh_cn" Content="{DynamicResource LanguageChinese}"></ComboBoxItem>
<ComboBoxItem x:Name="en" Content="{DynamicResource LanguageEnglish}"></ComboBoxItem>
</ComboBox>
</StackPanel>
</mah:WindowCommands>
</mah:MetroWindow.RightWindowCommands>
<Window.Resources>
<DataTemplate x:Key="HostTagTemplate">
<TextBlock Text="{Binding Tag}" />
</DataTemplate>
</Window.Resources>
<Grid>
<TabControl
Background="#fff"
Style="{StaticResource MaterialDesignNavigatilRailTabControl}"
Padding="10">
<TabItem
Width="160"
Style="{StaticResource MaterialDesignNavigationRailTabItem}"
Header="{DynamicResource TabItemHeaderAppDeployment}">
<StackPanel Orientation="Vertical">
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
<Button
Content="{DynamicResource AddHost}"
Click="AddHost"
Width="100"/>
</StackPanel>
<DataGrid ItemsSource="{Binding Path=ProjectList}"
Margin="0,20,0,0"
IsReadOnly="True"
x:Name="DataGrid"
CellStyle="{StaticResource DataGridCell}"
Style="{StaticResource MaterialDesignDataGrid}"
ColumnHeaderStyle="{StaticResource DataGridColumnHeader}"
SelectionUnit="FullRow"
BorderBrush="#eee"
BorderThickness="1"
CopyingRowClipboardContent="DataGrid_CopyingRowClipboardContent"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="{DynamicResource HostTag}"
Binding="{Binding Path=Host.Tag}"
Width="150"/>
<DataGridTextColumn Header="{DynamicResource HostAddress}"
Binding="{Binding Path=Host.Address}"
Width="200"/>
<DataGridTextColumn Header="{DynamicResource HostPort}"
Binding="{Binding Path=Host.Port}"
Width="100"/>
<DataGridTextColumn Header="{DynamicResource ProxyGroupName}"
Binding="{Binding Path=Host.Proxy.Type}"
Width="100"/>
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>
<TextBlock Text="{DynamicResource Actions}" />
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Button Content="{DynamicResource Connect}" FontSize="12" Height="24" Click="Connect" />
<Button Content="{DynamicResource Edit}" FontSize="12" Height="24" Margin="10,0,0,0" Click="EditHost" />
<Button Content="{DynamicResource Delete}" FontSize="12" Height="24" Margin="10,0,0,0" Click="DeleteHost" />
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</StackPanel>
</TabItem>
<TabItem
Width="160"
Style="{StaticResource MaterialDesignNavigationRailTabItem}"
Header="V2ray">
<StackPanel>
<TextBox />
</StackPanel>
</TabItem>
</TabControl>
</Grid>
</metro:MetroWindow>

View File

@ -0,0 +1,144 @@
using MahApps.Metro.Controls.Dialogs;
using Newtonsoft.Json;
using ProxySU_Core.ViewModels;
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;
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
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow
{
private const string RecordPath = @"Data\Record.json";
public ObservableCollection<Record> ProjectList { get; set; }
public MainWindow()
{
WindowStartupLocation = WindowStartupLocation.CenterScreen;
InitializeComponent();
ProjectList = new ObservableCollection<Record>();
if (File.Exists(RecordPath))
{
var recordsJson = File.ReadAllText(RecordPath, Encoding.UTF8);
var records = JsonConvert.DeserializeObject<List<Record>>(recordsJson);
records.ForEach(item => ProjectList.Add(item));
}
DataContext = this;
}
private void LaunchGitHubSite(object sender, RoutedEventArgs e)
{
System.Diagnostics.Process.Start("explorer.exe", "https://github.com/proxysu/ProxySU");
}
private void LaunchCoffeeSite(object sender, RoutedEventArgs e)
{
System.Diagnostics.Process.Start("explorer.exe", "https://github.com/proxysu/ProxySU");
}
private void ChangeLanguage(object sender, SelectionChangedEventArgs e)
{
var selection = cmbLanguage.SelectedValue as ComboBoxItem;
if (selection.Name == "zh_cn")
{
ChangeLanguage("zh_cn");
}
else if (selection.Name == "en")
{
ChangeLanguage("en");
}
}
private void ChangeLanguage(string culture)
{
ResourceDictionary resource = new ResourceDictionary();
if (string.Equals(culture, "zh_cn", StringComparison.OrdinalIgnoreCase))
{
resource.Source = new Uri(@"Resources\Languages\zh_cn.xaml", UriKind.Relative);
}
else if (string.Equals(culture, "en", StringComparison.OrdinalIgnoreCase))
{
resource.Source = new Uri(@"Resources\Languages\en.xaml", UriKind.Relative);
}
Application.Current.Resources.MergedDictionaries[0] = resource;
}
private void DataGrid_CopyingRowClipboardContent(object sender, DataGridRowClipboardEventArgs e)
{
var currentCell = e.ClipboardRowContent[DataGrid.CurrentCell.Column.DisplayIndex];
e.ClipboardRowContent.Clear();
e.ClipboardRowContent.Add(currentCell);
}
private void AddHost(object sender, RoutedEventArgs e)
{
var hostWindow = new HostEditorWindow();
hostWindow.OnSaveEvent += (s, host) =>
{
ProjectList.Add(new Record() { Host = host });
};
hostWindow.ShowDialog();
}
private void EditHost(object sender, RoutedEventArgs e)
{
if (DataGrid.SelectedItem is Record project)
{
var hostWindow = new HostEditorWindow(project.Host);
hostWindow.ShowDialog();
}
}
private void DeleteHost(object sender, RoutedEventArgs e)
{
if (DataGrid.SelectedItem is Record project)
{
var result = MessageBox.Show($"您确认删除主机{project.Host.Tag}吗?", "提示", MessageBoxButton.OKCancel);
if (result == MessageBoxResult.OK)
{
ProjectList.Remove(project);
}
}
}
private void Connect(object sender, RoutedEventArgs e)
{
var project = DataGrid.SelectedItem as Record;
if (project == null)
{
DialogManager.ShowMessageAsync(this, "提示", "请选择一个服务器");
}
TerminalWindow terminalWindow = new TerminalWindow(project);
terminalWindow.Show();
}
}
}

View File

@ -0,0 +1,31 @@
<metro:MetroWindow x:Class="ProxySU_Core.TerminalWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ProxySU_Core"
xmlns:metro="http://metro.mahapps.com/winfx/xaml/controls"
mc:Ignorable="d"
Title="TerminalWindow" Height="500" Width="800">
<StackPanel>
<RichTextBox IsReadOnly="True"
Block.LineHeight="18"
Background="#000"
Foreground="LawnGreen"
FontSize="14"
FontFamily="Consolas"
Height="400">
<FlowDocument>
<Paragraph>
<Run Text="{Binding Path=OutputText, Mode=OneWay}" />
</Paragraph>
</FlowDocument>
</RichTextBox>
<StackPanel Margin="0,10,0,0">
<Button Content="{DynamicResource Install}"
Click="Install"/>
</StackPanel>
</StackPanel>
</metro:MetroWindow>

View File

@ -0,0 +1,129 @@
using MahApps.Metro.Controls.Dialogs;
using ProxySU_Core.ViewModels;
using ProxySU_Core.ViewModels.Developers;
using Renci.SshNet;
using System;
using System.Collections.Generic;
using System.IO;
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.Shapes;
namespace ProxySU_Core
{
/// <summary>
/// TerminalWindow.xaml 的交互逻辑
/// </summary>
public partial class TerminalWindow
{
private readonly Terminal _vm;
private SshClient _sshClient;
public TerminalWindow(Record project)
{
InitializeComponent();
_vm = new Terminal(project.Host);
DataContext = _vm;
_vm.AddOutput("Connect ...");
Task.Factory.StartNew(() =>
{
try
{
OpenConnect(_vm.Host);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
});
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
if (_sshClient != null)
_sshClient.Disconnect();
if (_sshClient != null)
_sshClient.Dispose();
}
private ConnectionInfo CreateConnectionInfo(Host host)
{
AuthenticationMethod auth = null;
if (host.SecretType == LoginSecretType.Password)
{
auth = new PasswordAuthenticationMethod(host.UserName, host.Password);
}
else if (host.SecretType == LoginSecretType.PrivateKey)
{
auth = new PrivateKeyAuthenticationMethod(host.UserName, new PrivateKeyFile(host.PrivateKeyPath));
}
if (host.Proxy.Type == LocalProxyType.None)
{
return new ConnectionInfo(host.Address, host.Port, host.UserName, auth);
}
else
{
return new ConnectionInfo(
host: host.Address,
port: host.Port,
username: host.UserName,
proxyType: (ProxyTypes)(int)host.Proxy.Type,
proxyHost: host.Proxy.Address,
proxyPort: host.Proxy.Port,
proxyUsername: host.Proxy.UserName,
proxyPassword: host.Proxy.Password,
authenticationMethods: auth);
}
}
private void OpenConnect(Host host)
{
var conneInfo = CreateConnectionInfo(host);
_sshClient = new SshClient(conneInfo);
_sshClient.Connect();
_vm.AddOutput("Connected");
}
private void WriteShell(string outShell)
{
_vm.AddOutput(outShell);
}
private void Install(object sender, RoutedEventArgs e)
{
var project = new XrayProject(
_sshClient,
new XrayParameters { Port = 443 },
WriteShell
);
Task.Run(() =>
{
try
{
project.Execute();
}
catch (Exception ex)
{
_vm.AddOutput(ex.Message);
}
});
}
}
}

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ControlzEx" version="4.3.0" targetFramework="net461" />
<package id="MahApps.Metro" version="2.0.0" targetFramework="net461" />
<package id="MahApps.Metro.IconPacks" version="4.8.0" targetFramework="net461" />
<package id="MaterialDesignColors" version="2.0.0" targetFramework="net461" />
<package id="MaterialDesignThemes" version="4.0.0" targetFramework="net461" />
<package id="MaterialDesignThemes.MahApps" version="0.1.6" targetFramework="net461" />
<package id="Microsoft.Xaml.Behaviors.Wpf" version="1.1.19" targetFramework="net461" />
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net461" />
<package id="SSH.NET" version="2020.0.1" targetFramework="net461" />
</packages>