mirror of
https://github.com/MaxiFan/TunnelX.git
synced 2026-05-19 08:04:41 +03:00
8283b9d6d1
Co-authored-by: Cursor <cursoragent@cursor.com>
299 lines
8.4 KiB
C#
299 lines
8.4 KiB
C#
using System.Text.Json.Serialization;
|
|
using System.ComponentModel;
|
|
using System.IO;
|
|
using System.Runtime.CompilerServices;
|
|
|
|
namespace AppTunnel.Models;
|
|
|
|
public enum TunnelType
|
|
{
|
|
L2tpIpsec,
|
|
V2Ray,
|
|
OpenVpn,
|
|
SocksProxy
|
|
}
|
|
|
|
public enum ProxyProtocol
|
|
{
|
|
Socks5,
|
|
Http
|
|
}
|
|
|
|
/// <summary>
|
|
/// A named connection profile containing server settings and selected applications.
|
|
/// Multiple profiles can be saved and quickly switched between.
|
|
/// </summary>
|
|
public class ConnectionProfile : INotifyPropertyChanged
|
|
{
|
|
private string _id = Guid.NewGuid().ToString("N")[..8];
|
|
private string _name = "پروفایل جدید";
|
|
private DateTime _createdAt = DateTime.Now;
|
|
private DateTime _lastUsedAt = DateTime.Now;
|
|
private string _serverAddress = string.Empty;
|
|
private string _username = string.Empty;
|
|
private string _password = string.Empty;
|
|
private string _preSharedKey = string.Empty;
|
|
private List<ProfileApp> _tunnelApps = new();
|
|
private List<string> _excludedDestinations = new();
|
|
private TunnelType _tunnelType = TunnelType.L2tpIpsec;
|
|
private string _v2RayConfig = "";
|
|
private string _openVpnConfig = "";
|
|
private string _openVpnConfigPath = "";
|
|
private string _openVpnUsername = "";
|
|
private string _openVpnPassword = "";
|
|
private ProxyProtocol _proxyProtocol = ProxyProtocol.Socks5;
|
|
private string _proxyServerAddress = "";
|
|
private int _proxyPort = 1080;
|
|
private string _proxyUsername = "";
|
|
private string _proxyPassword = "";
|
|
private int _mixedProxyPort = 1080;
|
|
private bool _autoTuneMtu = true;
|
|
private bool _enableDnsOptimization = true;
|
|
private bool _enableGameMode = false;
|
|
|
|
public string Id
|
|
{
|
|
get => _id;
|
|
set => SetField(ref _id, value);
|
|
}
|
|
|
|
public string Name
|
|
{
|
|
get => _name;
|
|
set => SetField(ref _name, value);
|
|
}
|
|
|
|
public DateTime CreatedAt
|
|
{
|
|
get => _createdAt;
|
|
set => SetField(ref _createdAt, value);
|
|
}
|
|
|
|
public DateTime LastUsedAt
|
|
{
|
|
get => _lastUsedAt;
|
|
set => SetField(ref _lastUsedAt, value);
|
|
}
|
|
|
|
// Server configuration
|
|
public string ServerAddress
|
|
{
|
|
get => _serverAddress;
|
|
set => SetField(ref _serverAddress, value);
|
|
}
|
|
|
|
public string Username
|
|
{
|
|
get => _username;
|
|
set => SetField(ref _username, value);
|
|
}
|
|
|
|
public string Password
|
|
{
|
|
get => _password;
|
|
set => SetField(ref _password, value);
|
|
}
|
|
|
|
public string PreSharedKey
|
|
{
|
|
get => _preSharedKey;
|
|
set => SetField(ref _preSharedKey, value);
|
|
}
|
|
|
|
// Selected apps for this profile
|
|
public List<ProfileApp> TunnelApps
|
|
{
|
|
get => _tunnelApps;
|
|
set => SetField(ref _tunnelApps, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Domains or IPs that should bypass the tunnel even for target apps.
|
|
/// </summary>
|
|
public List<string> ExcludedDestinations
|
|
{
|
|
get => _excludedDestinations;
|
|
set => SetField(ref _excludedDestinations, value);
|
|
}
|
|
|
|
public TunnelType TunnelType
|
|
{
|
|
get => _tunnelType;
|
|
set => SetField(ref _tunnelType, value);
|
|
}
|
|
|
|
public string V2RayConfig
|
|
{
|
|
get => _v2RayConfig;
|
|
set => SetField(ref _v2RayConfig, value);
|
|
}
|
|
|
|
public string OpenVpnConfig
|
|
{
|
|
get => _openVpnConfig;
|
|
set => SetField(ref _openVpnConfig, value);
|
|
}
|
|
|
|
public string OpenVpnConfigPath
|
|
{
|
|
get => _openVpnConfigPath;
|
|
set => SetField(ref _openVpnConfigPath, value);
|
|
}
|
|
|
|
public string OpenVpnUsername
|
|
{
|
|
get => _openVpnUsername;
|
|
set => SetField(ref _openVpnUsername, value);
|
|
}
|
|
|
|
public string OpenVpnPassword
|
|
{
|
|
get => _openVpnPassword;
|
|
set => SetField(ref _openVpnPassword, value);
|
|
}
|
|
|
|
public ProxyProtocol ProxyProtocol
|
|
{
|
|
get => _proxyProtocol;
|
|
set => SetField(ref _proxyProtocol, value);
|
|
}
|
|
|
|
public string ProxyServerAddress
|
|
{
|
|
get => _proxyServerAddress;
|
|
set => SetField(ref _proxyServerAddress, value);
|
|
}
|
|
|
|
public int ProxyPort
|
|
{
|
|
get => _proxyPort;
|
|
set => SetField(ref _proxyPort, value);
|
|
}
|
|
|
|
public string ProxyUsername
|
|
{
|
|
get => _proxyUsername;
|
|
set => SetField(ref _proxyUsername, value);
|
|
}
|
|
|
|
public string ProxyPassword
|
|
{
|
|
get => _proxyPassword;
|
|
set => SetField(ref _proxyPassword, value);
|
|
}
|
|
|
|
[JsonPropertyName("socks5Port")]
|
|
public int MixedProxyPort
|
|
{
|
|
get => _mixedProxyPort;
|
|
set => SetField(ref _mixedProxyPort, value);
|
|
}
|
|
|
|
public bool AutoTuneMtu
|
|
{
|
|
get => _autoTuneMtu;
|
|
set => SetField(ref _autoTuneMtu, value);
|
|
}
|
|
|
|
public bool EnableDnsOptimization
|
|
{
|
|
get => _enableDnsOptimization;
|
|
set => SetField(ref _enableDnsOptimization, value);
|
|
}
|
|
|
|
public bool EnableGameMode
|
|
{
|
|
get => _enableGameMode;
|
|
set => SetField(ref _enableGameMode, value);
|
|
}
|
|
|
|
[JsonIgnore]
|
|
public string ConnectionName => $"TunnelX-{Id}";
|
|
|
|
[JsonIgnore]
|
|
public string TunnelTypeDisplay => TunnelType switch
|
|
{
|
|
TunnelType.L2tpIpsec => "L2TP/IPsec",
|
|
TunnelType.V2Ray => "V2Ray / Xray",
|
|
TunnelType.OpenVpn => "OpenVPN",
|
|
TunnelType.SocksProxy => ProxyProtocol == ProxyProtocol.Http ? "HTTP Proxy" : "SOCKS5 Proxy",
|
|
_ => "نامشخص"
|
|
};
|
|
|
|
[JsonIgnore]
|
|
public string EndpointDisplay => TunnelType switch
|
|
{
|
|
TunnelType.L2tpIpsec => string.IsNullOrWhiteSpace(ServerAddress) ? "آدرس سرور وارد نشده" : ServerAddress,
|
|
TunnelType.V2Ray => string.IsNullOrWhiteSpace(V2RayConfig) ? "کانفیگ وارد نشده" : "کانفیگ آماده",
|
|
TunnelType.OpenVpn => string.IsNullOrWhiteSpace(OpenVpnConfigPath) ? "فایل .ovpn انتخاب نشده" : Path.GetFileName(OpenVpnConfigPath),
|
|
TunnelType.SocksProxy => string.IsNullOrWhiteSpace(ProxyServerAddress) ? "آدرس پراکسی وارد نشده" : $"{ProxyServerAddress}:{ProxyPort}",
|
|
_ => ""
|
|
};
|
|
|
|
[JsonIgnore]
|
|
public bool IsReady => TunnelType switch
|
|
{
|
|
TunnelType.L2tpIpsec => !string.IsNullOrWhiteSpace(ServerAddress),
|
|
TunnelType.V2Ray => !string.IsNullOrWhiteSpace(V2RayConfig),
|
|
TunnelType.OpenVpn => !string.IsNullOrWhiteSpace(OpenVpnConfig),
|
|
TunnelType.SocksProxy => !string.IsNullOrWhiteSpace(ProxyServerAddress) && ProxyPort is > 0 and <= 65535,
|
|
_ => false
|
|
};
|
|
|
|
[JsonIgnore]
|
|
public string ReadinessText => IsReady ? "آماده اتصال" : "نیاز به تکمیل";
|
|
|
|
[JsonIgnore]
|
|
public string ReadinessColor => IsReady ? "#6CCB5F" : "#E0A020";
|
|
|
|
public ServerConfig ToServerConfig() => new()
|
|
{
|
|
ServerAddress = ServerAddress,
|
|
Username = Username,
|
|
Password = Password,
|
|
PreSharedKey = PreSharedKey,
|
|
ConnectionName = ConnectionName,
|
|
TunnelType = TunnelType,
|
|
V2RayConfig = V2RayConfig,
|
|
OpenVpnConfig = OpenVpnConfig,
|
|
OpenVpnUsername = OpenVpnUsername,
|
|
OpenVpnPassword = OpenVpnPassword,
|
|
ProxyProtocol = ProxyProtocol,
|
|
ProxyServerAddress = ProxyServerAddress,
|
|
ProxyPort = ProxyPort,
|
|
ProxyUsername = ProxyUsername,
|
|
ProxyPassword = ProxyPassword,
|
|
AutoTuneMtu = AutoTuneMtu,
|
|
EnableDnsOptimization = EnableDnsOptimization,
|
|
EnableGameMode = EnableGameMode
|
|
};
|
|
|
|
public override string ToString() => Name;
|
|
|
|
public event PropertyChangedEventHandler? PropertyChanged;
|
|
|
|
private void OnPropertyChanged([CallerMemberName] string? propertyName = null)
|
|
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
|
|
private bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
|
|
{
|
|
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
|
|
field = value;
|
|
OnPropertyChanged(propertyName);
|
|
OnPropertyChanged(nameof(TunnelTypeDisplay));
|
|
OnPropertyChanged(nameof(EndpointDisplay));
|
|
OnPropertyChanged(nameof(IsReady));
|
|
OnPropertyChanged(nameof(ReadinessText));
|
|
OnPropertyChanged(nameof(ReadinessColor));
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public class ProfileApp
|
|
{
|
|
public string DisplayName { get; set; } = string.Empty;
|
|
public string ExecutablePath { get; set; } = string.Empty;
|
|
public string ExecutableName { get; set; } = string.Empty;
|
|
public bool IsEnabled { get; set; } = true;
|
|
}
|