diff --git a/ProxySuper.Core/Converters/LoginSecretTypeConverter.cs b/ProxySuper.Core/Converters/LoginSecretTypeConverter.cs new file mode 100644 index 0000000..07b11e9 --- /dev/null +++ b/ProxySuper.Core/Converters/LoginSecretTypeConverter.cs @@ -0,0 +1,27 @@ +using MvvmCross.Converters; +using ProxySuper.Core.Models.Hosts; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; + +namespace ProxySuper.Core.Converters +{ + public class LoginSecretTypeConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return value.Equals(parameter); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + if (parameter == null) return LoginSecretType.Password; + return parameter; + } + + } +} diff --git a/ProxySuper.Core/Converters/ProxyTypeConverter.cs b/ProxySuper.Core/Converters/ProxyTypeConverter.cs new file mode 100644 index 0000000..4d36d15 --- /dev/null +++ b/ProxySuper.Core/Converters/ProxyTypeConverter.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; + +namespace ProxySuper.Core.Converters +{ + 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/ProxySuper.Core/Converters/VisibleConverter.cs b/ProxySuper.Core/Converters/VisibleConverter.cs new file mode 100644 index 0000000..70eeaa6 --- /dev/null +++ b/ProxySuper.Core/Converters/VisibleConverter.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Data; + +namespace ProxySuper.Core.Converters +{ + public class VisibleConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return value.Equals(true) ? Visibility.Visible : Visibility.Collapsed; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value == null) + { + return false; + } + + if (value.Equals(Visibility.Visible)) + { + return true; + } + + return false; + } + } +} diff --git a/ProxySuper.Core/Models/Projects/XraySettings.cs b/ProxySuper.Core/Models/Projects/XraySettings.cs index 78ebcf6..e5f0d8b 100644 --- a/ProxySuper.Core/Models/Projects/XraySettings.cs +++ b/ProxySuper.Core/Models/Projects/XraySettings.cs @@ -16,7 +16,7 @@ namespace ProxySuper.Core.Models.Projects { VLESS_KCP_Port, VMESS_KCP_Port, - ShadowsocksPort, + ShadowSocksPort, }; } } diff --git a/ProxySuper.Core/Models/Projects/XraySettings_SS.cs b/ProxySuper.Core/Models/Projects/XraySettings_SS.cs index 2b5f788..aa5f751 100644 --- a/ProxySuper.Core/Models/Projects/XraySettings_SS.cs +++ b/ProxySuper.Core/Models/Projects/XraySettings_SS.cs @@ -21,6 +21,6 @@ namespace ProxySuper.Core.Models.Projects /// /// ss port /// - public int ShadowsocksPort { get; set; } + public int ShadowSocksPort { get; set; } } } diff --git a/ProxySuper.Core/Models/Projects/XraySettings_VLESS.cs b/ProxySuper.Core/Models/Projects/XraySettings_VLESS.cs index b261315..b0d9008 100644 --- a/ProxySuper.Core/Models/Projects/XraySettings_VLESS.cs +++ b/ProxySuper.Core/Models/Projects/XraySettings_VLESS.cs @@ -31,7 +31,7 @@ namespace ProxySuper.Core.Models.Projects /// /// grpc port /// - public string VLESS_gRPC_Port { get; set; } + public int VLESS_gRPC_Port { get; set; } /// /// grpc service name diff --git a/ProxySuper.Core/ProxySuper.Core.csproj b/ProxySuper.Core/ProxySuper.Core.csproj index 890709c..6e97043 100644 --- a/ProxySuper.Core/ProxySuper.Core.csproj +++ b/ProxySuper.Core/ProxySuper.Core.csproj @@ -38,6 +38,7 @@ False ..\json.net\net40\Newtonsoft.Json.dll + ..\packages\SSH.NET.2020.0.1\lib\net40\Renci.SshNet.dll @@ -47,6 +48,7 @@ ..\packages\System.Console.4.3.1\lib\net46\System.Console.dll + @@ -56,6 +58,9 @@ + + + @@ -72,7 +77,9 @@ + + @@ -83,5 +90,6 @@ + \ No newline at end of file diff --git a/ProxySuper.Core/Services/Base64.cs b/ProxySuper.Core/Services/Base64.cs new file mode 100644 index 0000000..d315656 --- /dev/null +++ b/ProxySuper.Core/Services/Base64.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ProxySuper.Core.Services +{ + public class Base64 + { + public static string Encode(string plainText) + { + var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText); + return System.Convert.ToBase64String(plainTextBytes); + } + + public static string Decode(string base64EncodedData) + { + var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData); + return System.Text.Encoding.UTF8.GetString(base64EncodedBytes); + } + } +} diff --git a/ProxySuper.Core/Services/ShareLink.cs b/ProxySuper.Core/Services/ShareLink.cs new file mode 100644 index 0000000..11e683c --- /dev/null +++ b/ProxySuper.Core/Services/ShareLink.cs @@ -0,0 +1,195 @@ +using Newtonsoft.Json; +using ProxySuper.Core.Models.Projects; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Web; + +namespace ProxySuper.Core.Services +{ + public class ShareLink + { + public static string Build(XrayType xrayType, XraySettings settings) + { + + switch (xrayType) + { + case XrayType.VLESS_TCP: + case XrayType.VLESS_TCP_XTLS: + case XrayType.VLESS_WS: + case XrayType.VLESS_KCP: + case XrayType.VLESS_gRPC: + case XrayType.Trojan_TCP: + return BuildVlessShareLink(xrayType, settings); + case XrayType.VMESS_TCP: + case XrayType.VMESS_WS: + case XrayType.VMESS_KCP: + return BuildVmessShareLink(xrayType, settings); + case XrayType.ShadowsocksAEAD: + return BuildShadowSocksShareLink(settings); + default: + return string.Empty; + } + } + + private static string BuildShadowSocksShareLink(XraySettings settings) + { + var _method = settings.ShadowsocksMethod; + var _password = settings.ShadowsocksPassword; + var _server = settings.Domain; + var _port = settings.ShadowSocksPort; + + var base64URL = Base64.Encode($"{_method}:{_password}@{_server}:{_port}"); + return "ss://" + base64URL + "#ShadowSocks"; + } + + private static string BuildVmessShareLink(XrayType xrayType, XraySettings settings) + { + var vmess = new Vmess + { + v = "2", + add = settings.Domain, + port = settings.Port.ToString(), + id = settings.UUID, + aid = "0", + net = "", + type = "none", + host = settings.Domain, + path = "", + tls = "tls", + ps = "", + }; + + switch (xrayType) + { + case XrayType.VMESS_TCP: + vmess.ps = "vmess-tcp-tls"; + vmess.net = "tcp"; + vmess.type = "http"; + vmess.path = settings.VMESS_TCP_Path; + break; + case XrayType.VMESS_WS: + vmess.ps = "vmess-ws-tls"; + vmess.net = "ws"; + vmess.type = "none"; + vmess.path = settings.VMESS_WS_Path; + break; + case XrayType.VMESS_KCP: + vmess.ps = "vmess-mKCP"; + vmess.port = settings.VMESS_KCP_Port.ToString(); + vmess.net = "kcp"; + vmess.type = settings.VMESS_KCP_Type; + vmess.path = settings.VMESS_KCP_Seed; + vmess.tls = ""; + break; + default: + return string.Empty; + } + + var base64Url = Base64.Encode(JsonConvert.SerializeObject(vmess)); + return $"vmess://" + base64Url; + } + + private static string BuildVlessShareLink(XrayType xrayType, XraySettings settings) + { + var _protocol = string.Empty; + var _uuid = settings.UUID; + var _domain = settings.Domain; + var _port = settings.Port; + var _type = string.Empty; + var _encryption = "none"; + var _security = "tls"; + var _path = "/"; + var _host = settings.Domain; + var _descriptiveText = string.Empty; + var _headerType = "none"; + var _seed = string.Empty; + + switch (xrayType) + { + case XrayType.VLESS_TCP: + _protocol = "vless"; + _type = "tcp"; + _descriptiveText = "vless-tcp-tls"; + break; + case XrayType.VLESS_TCP_XTLS: + _protocol = "vless"; + _type = "tcp"; + _security = "xtls"; + _descriptiveText = "vless-tcp-xtls"; + break; + case XrayType.VLESS_WS: + _protocol = "vless"; + _type = "ws"; + _path = settings.VLESS_WS_Path; + _descriptiveText = "vless-ws-tls"; + break; + case XrayType.VLESS_KCP: + _protocol = "vless"; + _type = "kcp"; + _headerType = settings.VLESS_KCP_Type; + _seed = settings.VLESS_KCP_Seed; + _port = settings.VLESS_KCP_Port; + _security = "none"; + _descriptiveText = "vless-mKCP"; + break; + case XrayType.VLESS_gRPC: + _protocol = "vless"; + _type = "grpc"; + _path = settings.VLESS_gRPC_ServiceName; + _descriptiveText = "vless-gRPC"; + break; + case XrayType.Trojan_TCP: + _protocol = "trojan"; + _uuid = settings.TrojanPassword; + _descriptiveText = "trojan-tcp"; + break; + default: + throw new Exception("暂未实现的协议"); + } + + + string parametersURL = string.Empty; + if (xrayType != XrayType.Trojan_TCP) + { + // 4.3 传输层相关段 + parametersURL = $"?type={_type}&encryption={_encryption}&security={_security}&path={HttpUtility.UrlEncode(_path)}&headerType={_headerType}"; + + // kcp + if (xrayType == XrayType.VLESS_KCP) + { + parametersURL += $"&seed={_seed}"; + } + + // 4.4 TLS 相关段 + if (xrayType == XrayType.VLESS_TCP_XTLS) + { + parametersURL += "&flow=xtls-rprx-direct"; + } + } + + + return $"{_protocol}://{HttpUtility.UrlEncode(_uuid)}@{_domain}:{_port}{parametersURL}#{HttpUtility.UrlEncode(_descriptiveText)}"; + } + + } + + + + class Vmess + { + public string v { get; set; } + public string ps { get; set; } + public string add { get; set; } + public string port { get; set; } + public string id { get; set; } + public string aid { get; set; } + public string net { get; set; } + public string type { get; set; } + public string host { get; set; } + public string path { get; set; } + public string tls { get; set; } + } +} diff --git a/ProxySuper.Core/Services/XrayConfigBuilder.cs b/ProxySuper.Core/Services/XrayConfigBuilder.cs index 8f814de..39f98d5 100644 --- a/ProxySuper.Core/Services/XrayConfigBuilder.cs +++ b/ProxySuper.Core/Services/XrayConfigBuilder.cs @@ -200,7 +200,7 @@ namespace ProxySuper.Core.Services if (parameters.Types.Contains(XrayType.ShadowsocksAEAD)) { var ssBound = GetBound("Shadowsocks-AEAD.json"); - ssBound.port = parameters.ShadowsocksPort; + ssBound.port = parameters.ShadowSocksPort; ssBound.settings.clients[0].password = parameters.ShadowsocksPassword; ssBound.settings.clients[0].method = parameters.ShadowsocksMethod; xrayConfig.inbounds.Add(JToken.FromObject(ssBound)); diff --git a/ProxySuper.Core/Services/XrayProject.cs b/ProxySuper.Core/Services/XrayProject.cs index 2d23282..b01068f 100644 --- a/ProxySuper.Core/Services/XrayProject.cs +++ b/ProxySuper.Core/Services/XrayProject.cs @@ -112,7 +112,7 @@ namespace ProxySuper.Core.Services WriteOutput("卸载证书"); UninstallAcme(); WriteOutput("关闭端口"); - ClosePort(Parameters.ShadowsocksPort, Parameters.VMESS_KCP_Port); + ClosePort(Parameters.ShadowSocksPort, Parameters.VMESS_KCP_Port); WriteOutput("************ 卸载完成 ************"); } diff --git a/ProxySuper.Core/ViewModels/XrayEditorViewModel.cs b/ProxySuper.Core/ViewModels/XrayEditorViewModel.cs index e1c3a5b..580472a 100644 --- a/ProxySuper.Core/ViewModels/XrayEditorViewModel.cs +++ b/ProxySuper.Core/ViewModels/XrayEditorViewModel.cs @@ -1,17 +1,27 @@ -using MvvmCross.ViewModels; +using MvvmCross.Commands; +using MvvmCross.ViewModels; +using Newtonsoft.Json; using ProxySuper.Core.Models; using ProxySuper.Core.Models.Hosts; using ProxySuper.Core.Models.Projects; +using ProxySuper.Core.Services; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Windows.Controls; +using System.Windows.Input; namespace ProxySuper.Core.ViewModels { - public class XrayEditorViewModel : MvxViewModel + public partial class XrayEditorViewModel : MvxViewModel { + public XrayEditorViewModel() + { + _randomUuid = new MvxCommand(() => GetUuid()); + } + public Host Host { get; set; } public XraySettings Settings { get; set; } @@ -19,7 +29,383 @@ namespace ProxySuper.Core.ViewModels public override void Prepare(Record parameter) { Host = parameter.Host; - Settings = parameter.Settings as XraySettings; + Settings = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(parameter.Settings)); } } + + public partial class XrayEditorViewModel + { + private readonly ICommand _randomUuid; + + + public ICommand RandomUuid + { + get + { + return _randomUuid; + } + } + + + public int Port + { + get => Settings.Port; + set + { + Settings.Port = value; + RaisePropertyChanged("Port"); + } + } + + public int VLESS_KCP_Port + { + get => Settings.VLESS_KCP_Port; + set + { + Settings.VLESS_KCP_Port = value; + RaisePropertyChanged("VLESS_KCP_Port"); + } + } + + public int VMESS_KCP_Port + { + get => Settings.VMESS_KCP_Port; + set + { + Settings.VMESS_KCP_Port = value; + RaisePropertyChanged("VMESS_KCP_Port"); + } + } + + public int ShadowSocksPort + { + get => Settings.ShadowSocksPort; + set + { + Settings.VMESS_KCP_Port = value; + RaisePropertyChanged("ShadowSocksPort"); + } + } + + + public string UUID + { + get => Settings.UUID; + set + { + Settings.UUID = value; + RaisePropertyChanged("UUID"); + } + } + + public string Domain + { + get => Settings.Domain; + set + { + Settings.Domain = value; + RaisePropertyChanged("Domain"); + } + } + + public string MaskDomain + { + get => Settings.MaskDomain; + set + { + Settings.MaskDomain = value; + RaisePropertyChanged("MaskDomain"); + } + } + + public string TrojanPassword + { + get => Settings.TrojanPassword; + set => Settings.TrojanPassword = value; + } + public bool Checked_Trojan_TCP + { + get + { + return Settings.Types.Contains(XrayType.Trojan_TCP); + } + set + { + if (value == true) + { + if (!Settings.Types.Contains(XrayType.Trojan_TCP)) + Settings.Types.Add(XrayType.Trojan_TCP); + } + else + { + Settings.Types.Remove(XrayType.Trojan_TCP); + } + RaisePropertyChanged("Checked_Trojan_TCP"); + } + } + public string Trojan_TCP_ShareLink + { + get => ShareLink.Build(XrayType.Trojan_TCP, Settings); + } + + private List _ssMethods = new List { "aes-256-gcm", "aes-128-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305" }; + public List ShadowSocksMethods => _ssMethods; + public bool CheckedShadowSocks + { + + get => Settings.Types.Contains(XrayType.ShadowsocksAEAD); + set + { + CheckBoxChanged(value, XrayType.ShadowsocksAEAD); + RaisePropertyChanged("CheckedShadowSocks"); + } + } + public string ShadowSocksPassword + { + get => Settings.ShadowsocksPassword; + set => Settings.ShadowsocksPassword = value; + } + public string ShadowSocksMethod + { + get => Settings.ShadowsocksMethod; + set + { + var namespaceStr = typeof(ComboBoxItem).FullName + ":"; + var trimValue = value.Replace(namespaceStr, ""); + trimValue = trimValue.Trim(); + Settings.ShadowsocksMethod = trimValue; + RaisePropertyChanged("ShadowSocksMethod"); + } + } + public string ShadowSocksShareLink + { + get => ShareLink.Build(XrayType.ShadowsocksAEAD, Settings); + } + + + private void CheckBoxChanged(bool value, XrayType type) + { + if (value == true) + { + if (!Settings.Types.Contains(type)) + { + Settings.Types.Add(type); + } + } + else + { + Settings.Types.RemoveAll(x => x == type); + } + } + + + + private void GetUuid() + { + UUID = Guid.NewGuid().ToString(); + RaisePropertyChanged("UUID"); + } + + } + + /// + /// VMESS + /// + public partial class XrayEditorViewModel + { + // vmess tcp + public bool Checked_VMESS_TCP + { + get => Settings.Types.Contains(XrayType.VMESS_TCP); + set + { + CheckBoxChanged(value, XrayType.VMESS_TCP); + RaisePropertyChanged("Checked_VMESS_TCP"); + } + } + public string VMESS_TCP_Path + { + get => Settings.VMESS_TCP_Path; + set => Settings.VMESS_TCP_Path = value; + } + public string VMESS_TCP_ShareLink + { + get => ShareLink.Build(XrayType.VMESS_TCP, Settings); + } + + // vmess ws + public bool Checked_VMESS_WS + { + get => Settings.Types.Contains(XrayType.VMESS_WS); + set + { + CheckBoxChanged(value, XrayType.VMESS_WS); + RaisePropertyChanged("Checked_VMESS_WS"); + } + } + public string VMESS_WS_Path + { + get => Settings.VMESS_WS_Path; + set => Settings.VMESS_WS_Path = value; + } + public string VMESS_WS_ShareLink + { + get => ShareLink.Build(XrayType.VMESS_WS, Settings); + } + + // vmess kcp + public string VMESS_KCP_Seed + { + get => Settings.VMESS_KCP_Seed; + set => Settings.VMESS_KCP_Seed = value; + } + public string VMESS_KCP_Type + { + get => Settings.VMESS_KCP_Type; + set + { + var namespaceStr = typeof(ComboBoxItem).FullName + ":"; + var trimValue = value.Replace(namespaceStr, ""); + trimValue = trimValue.Trim(); + Settings.VMESS_KCP_Type = trimValue; + RaisePropertyChanged("VMESS_KCP_Type"); + } + } + public bool Checked_VMESS_KCP + { + get => Settings.Types.Contains(XrayType.VMESS_KCP); + set + { + CheckBoxChanged(value, XrayType.VMESS_KCP); + RaisePropertyChanged("Checked_VMESS_KCP"); + } + } + public string VMESS_KCP_ShareLink + { + get => ShareLink.Build(XrayType.VMESS_KCP, Settings); + } + + + private List _kcpTypes = new List { "none", "srtp", "utp", "wechat-video", "dtls", "wireguard", }; + public List KcpTypes => _kcpTypes; + } + + /// + /// VLESS + /// + public partial class XrayEditorViewModel + { + + // vless xtls + public bool Checked_VLESS_TCP_XTLS + { + get => Settings.Types.Contains(XrayType.VLESS_TCP_XTLS); + set + { + CheckBoxChanged(value, XrayType.VLESS_TCP_XTLS); + RaisePropertyChanged("Checked_VLESS_TCP_XTLS"); + } + } + public string VLESS_TCP_XTLS_ShareLink + { + get => ShareLink.Build(XrayType.VLESS_TCP_XTLS, Settings); + } + + // vless tcp + public bool Checked_VLESS_TCP + { + get => Settings.Types.Contains(XrayType.VLESS_TCP); + set + { + CheckBoxChanged(value, XrayType.VLESS_TCP); + RaisePropertyChanged("Checked_VLESS_TCP"); + } + } + public string VLESS_TCP_ShareLink + { + get => ShareLink.Build(XrayType.VLESS_TCP, Settings); + } + + + // vless ws + public string VLESS_WS_Path + { + get => Settings.VLESS_WS_Path; + set => Settings.VLESS_WS_Path = value; + } + public bool Checked_VLESS_WS + { + get + { + return Settings.Types.Contains(XrayType.VLESS_WS); + } + set + { + CheckBoxChanged(value, XrayType.VLESS_WS); + RaisePropertyChanged("Checked_VLESS_WS"); + } + } + public string VLESS_WS_ShareLink + { + get => ShareLink.Build(XrayType.VLESS_WS, Settings); + } + + // vless kcp + public string VLESS_KCP_Seed + { + get => Settings.VLESS_KCP_Seed; + set => Settings.VLESS_KCP_Seed = value; + } + public string VLESS_KCP_Type + { + get => Settings.VLESS_KCP_Type; + set + { + var namespaceStr = typeof(ComboBoxItem).FullName + ":"; + var trimValue = value.Replace(namespaceStr, ""); + trimValue = trimValue.Trim(); + Settings.VLESS_KCP_Type = trimValue; + RaisePropertyChanged("VLESS_KCP_Type"); + } + } + public bool Checked_VLESS_KCP + { + get => Settings.Types.Contains(XrayType.VLESS_KCP); + set + { + CheckBoxChanged(value, XrayType.VLESS_KCP); + RaisePropertyChanged("Checked_VLESS_KCP"); + } + } + public string VLESS_KCP_ShareLink + { + get => ShareLink.Build(XrayType.VLESS_KCP, Settings); + } + + // vless grpc + public string VLESS_gRPC_ServiceName + { + get => Settings.VLESS_gRPC_ServiceName; + set => Settings.VLESS_gRPC_ServiceName = value; + } + public int VLESS_gRPC_Port + { + get => Settings.VLESS_gRPC_Port; + set => Settings.VLESS_gRPC_Port = value; + } + public bool Checked_VLESS_gRPC + { + get => Settings.Types.Contains(XrayType.VLESS_gRPC); + set + { + CheckBoxChanged(value, XrayType.VLESS_gRPC); + RaisePropertyChanged("Checked_VLESS_gRPC"); + } + } + public string VLESS_gRPC_ShareLink + { + get => ShareLink.Build(XrayType.VLESS_gRPC, Settings); + } + } + } diff --git a/ProxySuper.WPF/App.xaml b/ProxySuper.WPF/App.xaml index 384ef4b..05d46b7 100644 --- a/ProxySuper.WPF/App.xaml +++ b/ProxySuper.WPF/App.xaml @@ -11,19 +11,22 @@ - - - + - + + + + diff --git a/ProxySuper.WPF/Controls/HostControl.xaml b/ProxySuper.WPF/Controls/HostControl.xaml index 00ea36b..ce397ce 100644 --- a/ProxySuper.WPF/Controls/HostControl.xaml +++ b/ProxySuper.WPF/Controls/HostControl.xaml @@ -4,9 +4,24 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:ProxySuper.WPF.Controls" + xmlns:convert="clr-namespace:ProxySuper.Core.Converters;assembly=ProxySuper.Core" + xmlns:host="clr-namespace:ProxySuper.Core.Models.Hosts;assembly=ProxySuper.Core" + mc:Ignorable="d"> + + + + + + + - + + + + + +