├── v2rayN ├── v2rayN │ ├── Resources │ │ ├── v2rayN.ico │ │ ├── NotifyIcon1.ico │ │ ├── NotifyIcon2.ico │ │ ├── NotifyIcon3.ico │ │ └── NotifyIcon4.ico │ ├── FodyWeavers.xml │ ├── Base │ │ └── MyDGTextColumn.cs │ ├── Views │ │ ├── QrcodeView.xaml.cs │ │ ├── ThemeSettingView.xaml.cs │ │ ├── QrcodeView.xaml │ │ ├── CheckUpdateView.xaml.cs │ │ ├── BackupAndRestoreView.xaml.cs │ │ ├── ClashConnectionsView.xaml.cs │ │ ├── AddServer2Window.xaml.cs │ │ ├── MsgView.xaml.cs │ │ ├── SubEditWindow.xaml.cs │ │ └── DNSSettingWindow.xaml.cs │ ├── GlobalUsings.cs │ ├── AssemblyInfo.cs │ ├── Converters │ │ ├── InverseBooleanConverter.cs │ │ ├── MaterialDesignFonts.cs │ │ └── DelayColorConverter.cs │ ├── app.manifest │ ├── v2rayN.csproj │ ├── Common │ │ ├── UI.cs │ │ └── QRCodeHelper.cs │ └── App.xaml.cs ├── v2rayN.Desktop │ ├── Assets │ │ ├── v2rayN.ico │ │ ├── NotifyIcon1.ico │ │ ├── NotifyIcon2.ico │ │ ├── NotifyIcon3.ico │ │ ├── NotifyIcon4.ico │ │ ├── Fonts │ │ │ └── NotoSansSC-Regular.ttf │ │ └── GlobalStyles.axaml │ ├── FodyWeavers.xml │ ├── GlobalUsings.cs │ ├── Common │ │ ├── AppBuilderExtension.cs │ │ ├── AvaUtils.cs │ │ └── UI.cs │ ├── Converters │ │ └── DelayColorConverter.cs │ ├── Views │ │ ├── QrcodeView.axaml.cs │ │ ├── QrcodeView.axaml │ │ ├── ThemeSettingView.axaml.cs │ │ ├── CheckUpdateView.axaml.cs │ │ ├── MsgView.axaml.cs │ │ ├── BackupAndRestoreView.axaml.cs │ │ ├── ClashConnectionsView.axaml.cs │ │ ├── AddServer2Window.axaml.cs │ │ ├── SubEditWindow.axaml.cs │ │ ├── ThemeSettingView.axaml │ │ ├── DNSSettingWindow.axaml.cs │ │ └── SubSettingWindow.axaml │ ├── Program.cs │ ├── v2rayN.Desktop.csproj │ └── App.axaml.cs ├── ServiceLib │ ├── Sample │ │ ├── SingboxSampleOutbound │ │ ├── clash_tun_yaml │ │ ├── SampleHttpResponse │ │ ├── SampleHttpRequest │ │ ├── linux_autostart_config │ │ ├── tun_singbox_inbound │ │ ├── tun_singbox_rules │ │ ├── SampleInbound │ │ ├── dns_v2ray_normal │ │ ├── SingboxSampleClientConfig │ │ ├── custom_routing_global │ │ ├── SampleOutbound │ │ ├── dns_singbox_normal │ │ ├── tun_singbox_dns │ │ ├── clash_mixin_yaml │ │ ├── SampleClientConfig │ │ └── custom_routing_white │ ├── Enums │ │ ├── EPresetType.cs │ │ ├── EGirdOrientation.cs │ │ ├── ERuleMode.cs │ │ ├── ESpeedActionType.cs │ │ ├── EMove.cs │ │ ├── ESysProxyType.cs │ │ ├── EInboundProtocol.cs │ │ ├── EMsgCommand.cs │ │ ├── EGlobalHotkey.cs │ │ ├── ETransport.cs │ │ ├── EConfigType.cs │ │ ├── ECoreType.cs │ │ ├── EServerColName.cs │ │ └── EViewAction.cs │ ├── FodyWeavers.xml │ ├── Models │ │ ├── CmdItem.cs │ │ ├── RoutingItemModel.cs │ │ ├── RoutingTemplate.cs │ │ ├── ComboItem.cs │ │ ├── SpeedTestResult.cs │ │ ├── RulesItemModel.cs │ │ ├── CheckUpdateModel.cs │ │ ├── ProfileExItem.cs │ │ ├── ServerTestItem.cs │ │ ├── ClashProxyModel.cs │ │ ├── IPAPIInfo.cs │ │ ├── V2rayMetricsVars.cs │ │ ├── ServerStatItem.cs │ │ ├── V2rayTcpRequest.cs │ │ ├── ServerSpeedItem.cs │ │ ├── SsSIP008.cs │ │ ├── ClashProviders.cs │ │ ├── DNSItem.cs │ │ ├── ClashConnectionModel.cs │ │ ├── ProfileItemModel.cs │ │ ├── RetResult.cs │ │ ├── RulesItem.cs │ │ ├── ClashProxies.cs │ │ ├── RoutingItem.cs │ │ ├── CoreInfo.cs │ │ ├── SubItem.cs │ │ ├── ClashConnections.cs │ │ ├── VmessQRCode.cs │ │ ├── Config.cs │ │ ├── GitHubRelease.cs │ │ └── ProfileItem.cs │ ├── Base │ │ └── MyReactiveObject.cs │ ├── GlobalUsings.cs │ ├── Handler │ │ ├── Fmt │ │ │ ├── ClashFmt.cs │ │ │ ├── NaiveproxyFmt.cs │ │ │ ├── TrojanFmt.cs │ │ │ ├── VLESSFmt.cs │ │ │ ├── TuicFmt.cs │ │ │ ├── SingboxFmt.cs │ │ │ ├── V2rayFmt.cs │ │ │ ├── WireguardFmt.cs │ │ │ ├── Hysteria2Fmt.cs │ │ │ └── FmtHandler.cs │ │ ├── NoticeHandler.cs │ │ ├── TaskHandler.cs │ │ ├── SysProxy │ │ │ └── ProxySettingOSX.cs │ │ └── PacHandler.cs │ ├── Common │ │ ├── WindowsUtils.cs │ │ ├── StringEx.cs │ │ ├── SqliteHelper.cs │ │ ├── Logging.cs │ │ ├── YamlUtils.cs │ │ ├── DesUtils.cs │ │ ├── QRCodeHelper.cs │ │ └── JsonUtils.cs │ ├── ViewModels │ │ ├── SubEditViewModel.cs │ │ ├── RoutingRuleDetailsViewModel.cs │ │ └── AddServerViewModel.cs │ └── ServiceLib.csproj ├── AmazTool │ ├── Program.cs │ └── AmazTool.csproj ├── build-osx.sh ├── build.ps1 ├── v2rayN.sln └── .gitattributes ├── .github ├── dependabot.yml ├── workflows │ ├── build-osx.yml │ ├── winget-publish.yml │ └── build.yml └── ISSUE_TEMPLATE │ ├── 02_feature_request.yml │ └── 01_bug_report.yml ├── .gitignore └── README.md /v2rayN/v2rayN/Resources/v2rayN.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/v2rayN/master/v2rayN/v2rayN/Resources/v2rayN.ico -------------------------------------------------------------------------------- /v2rayN/v2rayN.Desktop/Assets/v2rayN.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/v2rayN/master/v2rayN/v2rayN.Desktop/Assets/v2rayN.ico -------------------------------------------------------------------------------- /v2rayN/v2rayN/Resources/NotifyIcon1.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/v2rayN/master/v2rayN/v2rayN/Resources/NotifyIcon1.ico -------------------------------------------------------------------------------- /v2rayN/v2rayN/Resources/NotifyIcon2.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/v2rayN/master/v2rayN/v2rayN/Resources/NotifyIcon2.ico -------------------------------------------------------------------------------- /v2rayN/v2rayN/Resources/NotifyIcon3.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/v2rayN/master/v2rayN/v2rayN/Resources/NotifyIcon3.ico -------------------------------------------------------------------------------- /v2rayN/v2rayN/Resources/NotifyIcon4.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/v2rayN/master/v2rayN/v2rayN/Resources/NotifyIcon4.ico -------------------------------------------------------------------------------- /v2rayN/v2rayN.Desktop/Assets/NotifyIcon1.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/v2rayN/master/v2rayN/v2rayN.Desktop/Assets/NotifyIcon1.ico -------------------------------------------------------------------------------- /v2rayN/v2rayN.Desktop/Assets/NotifyIcon2.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/v2rayN/master/v2rayN/v2rayN.Desktop/Assets/NotifyIcon2.ico -------------------------------------------------------------------------------- /v2rayN/v2rayN.Desktop/Assets/NotifyIcon3.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/v2rayN/master/v2rayN/v2rayN.Desktop/Assets/NotifyIcon3.ico -------------------------------------------------------------------------------- /v2rayN/v2rayN.Desktop/Assets/NotifyIcon4.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/v2rayN/master/v2rayN/v2rayN.Desktop/Assets/NotifyIcon4.ico -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Sample/SingboxSampleOutbound: -------------------------------------------------------------------------------- 1 | { 2 | "type": "vless", 3 | "tag": "proxy", 4 | "server": "", 5 | "server_port": 443 6 | } -------------------------------------------------------------------------------- /v2rayN/v2rayN.Desktop/Assets/Fonts/NotoSansSC-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/v2rayN/master/v2rayN/v2rayN.Desktop/Assets/Fonts/NotoSansSC-Regular.ttf -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Enums/EPresetType.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Enums 2 | { 3 | public enum EPresetType 4 | { 5 | Default = 0, 6 | Russia = 1, 7 | } 8 | } -------------------------------------------------------------------------------- /v2rayN/v2rayN/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /v2rayN/ServiceLib/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Sample/clash_tun_yaml: -------------------------------------------------------------------------------- 1 | tun: 2 | enable: true 3 | stack: gvisor 4 | dns-hijack: 5 | - 0.0.0.0:53 6 | auto-route: true 7 | auto-detect-interface: true 8 | -------------------------------------------------------------------------------- /v2rayN/v2rayN.Desktop/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Enums/EGirdOrientation.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Enums 2 | { 3 | public enum EGirdOrientation 4 | { 5 | Horizontal, 6 | Vertical, 7 | Tab, 8 | } 9 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/CmdItem.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Models 2 | { 3 | public class CmdItem 4 | { 5 | public string? Cmd { get; set; } 6 | public List? Arguments { get; set; } 7 | } 8 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/RoutingItemModel.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Models 2 | { 3 | [Serializable] 4 | public class RoutingItemModel : RoutingItem 5 | { 6 | public bool IsActive { get; set; } 7 | } 8 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Enums/ERuleMode.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Enums 2 | { 3 | public enum ERuleMode 4 | { 5 | Rule = 0, 6 | Global = 1, 7 | Direct = 2, 8 | Unchanged = 3 9 | } 10 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Enums/ESpeedActionType.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Enums 2 | { 3 | public enum ESpeedActionType 4 | { 5 | Tcping, 6 | Realping, 7 | Speedtest, 8 | Mixedtest 9 | } 10 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Sample/SampleHttpResponse: -------------------------------------------------------------------------------- 1 | {"version":"1.1","status":"200","reason":"OK","headers":{"Content-Type":["application/octet-stream","video/mpeg"],"Transfer-Encoding":["chunked"],"Connection":["keep-alive"],"Pragma":"no-cache"}} -------------------------------------------------------------------------------- /v2rayN/v2rayN/Base/MyDGTextColumn.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | 3 | namespace v2rayN.Base 4 | { 5 | internal class MyDGTextColumn : DataGridTextColumn 6 | { 7 | public string ExName { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Enums/EMove.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Enums 2 | { 3 | public enum EMove 4 | { 5 | Top = 1, 6 | Up = 2, 7 | Down = 3, 8 | Bottom = 4, 9 | Position = 5 10 | } 11 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Enums/ESysProxyType.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Enums 2 | { 3 | public enum ESysProxyType 4 | { 5 | ForcedClear = 0, 6 | ForcedChange = 1, 7 | Unchanged = 2, 8 | Pac = 3 9 | } 10 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Sample/SampleHttpRequest: -------------------------------------------------------------------------------- 1 | {"version":"1.1","method":"GET","path":[$requestPath$],"headers":{"Host":[$requestHost$],"User-Agent":[$requestUserAgent$],"Accept-Encoding":["gzip, deflate"],"Connection":["keep-alive"],"Pragma":"no-cache"}} -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/RoutingTemplate.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Models 2 | { 3 | [Serializable] 4 | public class RoutingTemplate 5 | { 6 | public string Version { get; set; } 7 | public RoutingItem[] RoutingItems { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Sample/linux_autostart_config: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Exec=$ExecPath$ 4 | Hidden=false 5 | NoDisplay=false 6 | X-GNOME-Autostart-enabled=true 7 | Name[en_US]=v2rayN 8 | Name=v2rayN 9 | Comment[en_US]=v2rayN 10 | Comment=v2rayN -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Set update schedule for GitHub Actions 2 | 3 | version: 2 4 | updates: 5 | 6 | - package-ecosystem: "github-actions" 7 | directory: "/" 8 | schedule: 9 | # Check for updates to GitHub Actions every daily 10 | interval: "daily" 11 | -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Enums/EInboundProtocol.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Enums 2 | { 3 | public enum EInboundProtocol 4 | { 5 | socks = 0, 6 | socks2, 7 | pac, 8 | api, 9 | api2, 10 | mixed, 11 | speedtest = 21 12 | } 13 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Enums/EMsgCommand.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Enums 2 | { 3 | public enum EMsgCommand 4 | { 5 | ClearMsg, 6 | SendMsgView, 7 | SendSnackMsg, 8 | RefreshProfiles, 9 | StopSpeedtest, 10 | AppExit 11 | } 12 | } -------------------------------------------------------------------------------- /v2rayN/v2rayN/Views/QrcodeView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | 3 | namespace v2rayN.Views 4 | { 5 | public partial class QrcodeView : UserControl 6 | { 7 | public QrcodeView() 8 | { 9 | InitializeComponent(); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Enums/EGlobalHotkey.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Enums 2 | { 3 | public enum EGlobalHotkey 4 | { 5 | ShowForm = 0, 6 | SystemProxyClear = 1, 7 | SystemProxySet = 2, 8 | SystemProxyUnchanged = 3, 9 | SystemProxyPac = 4, 10 | } 11 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Enums/ETransport.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Enums 2 | { 3 | public enum ETransport 4 | { 5 | tcp, 6 | kcp, 7 | ws, 8 | httpupgrade, 9 | xhttp, 10 | h2, 11 | http, 12 | quic, 13 | grpc 14 | } 15 | } -------------------------------------------------------------------------------- /v2rayN/v2rayN/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using ServiceLib; 2 | global using ServiceLib.Base; 3 | global using ServiceLib.Common; 4 | global using ServiceLib.Enums; 5 | global using ServiceLib.Handler; 6 | global using ServiceLib.Models; 7 | global using ServiceLib.Resx; 8 | global using ServiceLib.ViewModels; -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Base/MyReactiveObject.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI; 2 | 3 | namespace ServiceLib.Base 4 | { 5 | public class MyReactiveObject : ReactiveObject 6 | { 7 | protected static Config? _config; 8 | protected Func>? _updateView; 9 | } 10 | } -------------------------------------------------------------------------------- /v2rayN/v2rayN.Desktop/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using ServiceLib; 2 | global using ServiceLib.Base; 3 | global using ServiceLib.Common; 4 | global using ServiceLib.Enums; 5 | global using ServiceLib.Handler; 6 | global using ServiceLib.Models; 7 | global using ServiceLib.Resx; 8 | global using ServiceLib.ViewModels; -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/ComboItem.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Models 2 | { 3 | public class ComboItem 4 | { 5 | public string? ID 6 | { 7 | get; set; 8 | } 9 | 10 | public string? Text 11 | { 12 | get; set; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/SpeedTestResult.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Models 2 | { 3 | [Serializable] 4 | public class SpeedTestResult 5 | { 6 | public string? IndexId { get; set; } 7 | 8 | public string? Delay { get; set; } 9 | 10 | public string? Speed { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Sample/tun_singbox_inbound: -------------------------------------------------------------------------------- 1 | { 2 | "type": "tun", 3 | "tag": "tun-in", 4 | "interface_name": "singbox_tun", 5 | "address": [ 6 | "172.18.0.1/30", 7 | "fdfe:dcba:9876::1/126" 8 | ], 9 | "mtu": 9000, 10 | "auto_route": true, 11 | "strict_route": false, 12 | "stack": "system", 13 | "sniff": true 14 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Sample/tun_singbox_rules: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "network": "udp", 4 | "port": [ 5 | 135, 6 | 137, 7 | 138, 8 | 139, 9 | 5353 10 | ], 11 | "outbound": "block" 12 | }, 13 | { 14 | "ip_cidr": [ 15 | "224.0.0.0/3", 16 | "ff00::/8" 17 | ], 18 | "outbound": "block" 19 | } 20 | ] -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Sample/SampleInbound: -------------------------------------------------------------------------------- 1 | { 2 | "tag": "tag1", 3 | "port": 10808, 4 | "protocol": "socks", 5 | "listen": "127.0.0.1", 6 | "settings": { 7 | "auth": "noauth", 8 | "udp": true, 9 | "allowTransparent": false 10 | }, 11 | "sniffing": { 12 | "enabled": true, 13 | "destOverride": [ 14 | "http", 15 | "tls" 16 | ] 17 | } 18 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/RulesItemModel.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Models 2 | { 3 | [Serializable] 4 | public class RulesItemModel : RulesItem 5 | { 6 | public string InboundTags { get; set; } 7 | public string Ips { get; set; } 8 | public string Domains { get; set; } 9 | public string Protocols { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Enums/EConfigType.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Enums 2 | { 3 | public enum EConfigType 4 | { 5 | VMess = 1, 6 | Custom = 2, 7 | Shadowsocks = 3, 8 | SOCKS = 4, 9 | VLESS = 5, 10 | Trojan = 6, 11 | Hysteria2 = 7, 12 | TUIC = 8, 13 | WireGuard = 9, 14 | HTTP = 10 15 | } 16 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/CheckUpdateModel.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Models 2 | { 3 | public class CheckUpdateModel 4 | { 5 | public bool? IsSelected { get; set; } 6 | public string? CoreType { get; set; } 7 | public string? Remarks { get; set; } 8 | public string? FileName { get; set; } 9 | public bool? IsFinished { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/ProfileExItem.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace ServiceLib.Models 4 | { 5 | [Serializable] 6 | public class ProfileExItem 7 | { 8 | [PrimaryKey] 9 | public string IndexId { get; set; } 10 | 11 | public int Delay { get; set; } 12 | public decimal Speed { get; set; } 13 | public int Sort { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Enums/ECoreType.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Enums 2 | { 3 | public enum ECoreType 4 | { 5 | v2fly = 1, 6 | Xray = 2, 7 | v2fly_v5 = 4, 8 | mihomo = 13, 9 | hysteria = 21, 10 | naiveproxy = 22, 11 | tuic = 23, 12 | sing_box = 24, 13 | juicity = 25, 14 | hysteria2 = 26, 15 | v2rayN = 99 16 | } 17 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Sample/dns_v2ray_normal: -------------------------------------------------------------------------------- 1 | { 2 | "hosts": { 3 | "dns.google": "8.8.8.8", 4 | "proxy.example.com": "127.0.0.1" 5 | }, 6 | "servers": [ 7 | { 8 | "address": "223.5.5.5", 9 | "domains": [ 10 | "geosite:cn" 11 | ], 12 | "expectIPs": [ 13 | "geoip:cn" 14 | ] 15 | }, 16 | "1.1.1.1", 17 | "8.8.8.8", 18 | "https://dns.google/dns-query" 19 | ] 20 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/ServerTestItem.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Models 2 | { 3 | [Serializable] 4 | public class ServerTestItem 5 | { 6 | public string? IndexId { get; set; } 7 | public string? Address { get; set; } 8 | public int Port { get; set; } 9 | public EConfigType ConfigType { get; set; } 10 | public bool AllowTest { get; set; } 11 | public int Delay { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Enums/EServerColName.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Enums 2 | { 3 | public enum EServerColName 4 | { 5 | Def = 0, 6 | ConfigType, 7 | Remarks, 8 | Address, 9 | Port, 10 | Network, 11 | StreamSecurity, 12 | SubRemarks, 13 | DelayVal, 14 | SpeedVal, 15 | 16 | TodayDown, 17 | TodayUp, 18 | TotalDown, 19 | TotalUp 20 | } 21 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using ServiceLib.Base; 2 | global using ServiceLib.Common; 3 | global using ServiceLib.Enums; 4 | global using ServiceLib.Handler; 5 | global using ServiceLib.Handler.Fmt; 6 | global using ServiceLib.Services; 7 | global using ServiceLib.Services.Statistics; 8 | global using ServiceLib.Services.CoreConfig; 9 | global using ServiceLib.Models; 10 | global using ServiceLib.Resx; 11 | global using ServiceLib.Handler.SysProxy; -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/ClashProxyModel.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Models 2 | { 3 | [Serializable] 4 | public class ClashProxyModel 5 | { 6 | public string? Name { get; set; } 7 | 8 | public string? Type { get; set; } 9 | 10 | public string? Now { get; set; } 11 | 12 | public int Delay { get; set; } 13 | 14 | public string? DelayName { get; set; } 15 | 16 | public bool IsActive { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/IPAPIInfo.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Models 2 | { 3 | internal class IPAPIInfo 4 | { 5 | public string? ip { get; set; } 6 | public string? city { get; set; } 7 | public string? region { get; set; } 8 | public string? region_code { get; set; } 9 | public string? country { get; set; } 10 | public string? country_name { get; set; } 11 | public string? country_code { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/V2rayMetricsVars.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | 3 | namespace ServiceLib.Models 4 | { 5 | internal class V2rayMetricsVars 6 | { 7 | public V2rayMetricsVarsStats? stats { get; set; } 8 | } 9 | } 10 | 11 | public class V2rayMetricsVarsStats 12 | { 13 | public Hashtable? outbound { get; set; } 14 | } 15 | 16 | public class V2rayMetricsVarsLink 17 | { 18 | public long downlink { get; set; } 19 | public long uplink { get; set; } 20 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/ServerStatItem.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace ServiceLib.Models 4 | { 5 | [Serializable] 6 | public class ServerStatItem 7 | { 8 | [PrimaryKey] 9 | public string IndexId { get; set; } 10 | 11 | public long TotalUp { get; set; } 12 | 13 | public long TotalDown { get; set; } 14 | 15 | public long TodayUp { get; set; } 16 | 17 | public long TodayDown { get; set; } 18 | 19 | public long DateNow { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/V2rayTcpRequest.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Models 2 | { 3 | /// 4 | /// Tcp伪装http的Request,只要Host 5 | /// 6 | public class V2rayTcpRequest 7 | { 8 | /// 9 | /// 10 | /// 11 | public RequestHeaders headers { get; set; } 12 | } 13 | 14 | public class RequestHeaders 15 | { 16 | /// 17 | /// 18 | /// 19 | public List Host { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/ServerSpeedItem.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Models 2 | { 3 | [Serializable] 4 | public class ServerSpeedItem : ServerStatItem 5 | { 6 | public long ProxyUp { get; set; } 7 | 8 | public long ProxyDown { get; set; } 9 | 10 | public long DirectUp { get; set; } 11 | 12 | public long DirectDown { get; set; } 13 | } 14 | 15 | [Serializable] 16 | public class TrafficItem 17 | { 18 | public ulong Up { get; set; } 19 | 20 | public ulong Down { get; set; } 21 | } 22 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/SsSIP008.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Models 2 | { 3 | public class SsSIP008 4 | { 5 | public List? servers { get; set; } 6 | } 7 | 8 | [Serializable] 9 | public class SsServer 10 | { 11 | public string? remarks { get; set; } 12 | public string? server { get; set; } 13 | public string? server_port { get; set; } 14 | public string? method { get; set; } 15 | public string? password { get; set; } 16 | public string? plugin { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/ClashProviders.cs: -------------------------------------------------------------------------------- 1 | using static ServiceLib.Models.ClashProxies; 2 | 3 | namespace ServiceLib.Models 4 | { 5 | public class ClashProviders 6 | { 7 | public Dictionary? providers { get; set; } 8 | 9 | public class ProvidersItem 10 | { 11 | public string? name { get; set; } 12 | public List? proxies { get; set; } 13 | public string? type { get; set; } 14 | public string? vehicleType { get; set; } 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Sample/SingboxSampleClientConfig: -------------------------------------------------------------------------------- 1 | { 2 | "log": { 3 | "level": "debug", 4 | "timestamp": true 5 | }, 6 | "inbounds": [], 7 | "outbounds": [ 8 | { 9 | "type": "vless", 10 | "tag": "proxy", 11 | "server": "", 12 | "server_port": 443 13 | }, 14 | { 15 | "type": "direct", 16 | "tag": "direct" 17 | }, 18 | { 19 | "type": "block", 20 | "tag": "block" 21 | }, 22 | { 23 | "tag": "dns_out", 24 | "type": "dns" 25 | } 26 | ], 27 | "route": { 28 | "rules": [ 29 | { 30 | "protocol": [ "dns" ], 31 | "outbound": "dns_out" 32 | } 33 | ] 34 | } 35 | } -------------------------------------------------------------------------------- /v2rayN/AmazTool/Program.cs: -------------------------------------------------------------------------------- 1 | namespace AmazTool 2 | { 3 | internal static class Program 4 | { 5 | /// 6 | /// 应用程序的主入口点。 7 | /// 8 | [STAThread] 9 | private static void Main(string[] args) 10 | { 11 | if (args.Length == 0) 12 | { 13 | Console.WriteLine(Resx.Resource.Guidelines); 14 | Thread.Sleep(5000); 15 | return; 16 | } 17 | 18 | var fileName = Uri.UnescapeDataString(string.Join(" ", args)); 19 | UpgradeApp.Upgrade(fileName); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # 此 .gitignore 文件已由 Microsoft(R) Visual Studio 自动创建。 3 | ################################################################################ 4 | 5 | /v2rayN/.vs/ 6 | /v2rayN/v2rayN/bin/Debug/app.publish 7 | /v2rayN/v2rayN/bin/Debug 8 | /v2rayN/v2rayN/bin/Release 9 | /v2rayN/v2rayN/obj/ 10 | /v2rayN/.vs/v2rayN/DesignTimeBuild 11 | /v2rayN/packages 12 | .vs/ProjectSettings.json 13 | .vs/slnx.sqlite 14 | .vs/VSWorkspaceState.json 15 | /v2rayN/v2rayUpgrade/bin/Debug 16 | /v2rayN/v2rayUpgrade/bin/Release 17 | /v2rayN/v2rayUpgrade/obj/ 18 | *.user 19 | /.vs/v2rayN 20 | -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Sample/custom_routing_global: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "remarks": "阻断udp443", 4 | "outboundTag": "block", 5 | "port": "443", 6 | "network": "udp" 7 | }, 8 | { 9 | "remarks": "阻断广告", 10 | "outboundTag": "block", 11 | "domain": [ 12 | "geosite:category-ads-all" 13 | ] 14 | }, 15 | { 16 | "remarks": "绕过局域网IP", 17 | "outboundTag": "direct", 18 | "ip": [ 19 | "geoip:private" 20 | ] 21 | }, 22 | { 23 | "remarks": "绕过局域网域名", 24 | "outboundTag": "direct", 25 | "domain": [ 26 | "geosite:private" 27 | ] 28 | }, 29 | { 30 | "remarks": "最终代理", 31 | "port": "0-65535", 32 | "outboundTag": "proxy" 33 | } 34 | ] -------------------------------------------------------------------------------- /v2rayN/v2rayN.Desktop/Common/AppBuilderExtension.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Media; 3 | 4 | namespace v2rayN.Desktop.Common 5 | { 6 | public static class AppBuilderExtension 7 | { 8 | public static AppBuilder WithFontByDefault(this AppBuilder appBuilder) 9 | { 10 | var uri = Path.Combine(Global.AvaAssets, "Fonts#Noto Sans SC"); 11 | return appBuilder.With(new FontManagerOptions() 12 | { 13 | DefaultFamilyName = uri, 14 | FontFallbacks = new[] { new FontFallback { FontFamily = new FontFamily(uri) } } 15 | }); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /v2rayN/v2rayN/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | [assembly: ThemeInfo( 4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 5 | //(used if a resource is not found in the page, 6 | // or application resource dictionaries) 7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 8 | //(used if a resource is not found in the page, 9 | // app, or any theme specific resource dictionaries) 10 | )] -------------------------------------------------------------------------------- /v2rayN/build-osx.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo 'Building' 4 | 5 | OutputPath='./bin/v2rayN' 6 | 7 | dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r osx-x64 --self-contained true -p:PublishReadyToRun=false -p:PublishSingleFile=true -o "${OutputPath}/osx-x64" 8 | dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r osx-arm64 --self-contained true -p:PublishReadyToRun=false -p:PublishSingleFile=true -o "${OutputPath}/osx-arm64" 9 | 10 | rm -rf "$OutputPath/osx-x64/*.pdb" 11 | rm -rf "$OutputPath/osx-arm64/*.pdb" 12 | 13 | echo 'Build done' 14 | 15 | ls $OutputPath 16 | 7z a v2rayN-osx.zip $OutputPath 17 | exit 0 18 | -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/DNSItem.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace ServiceLib.Models 4 | { 5 | [Serializable] 6 | public class DNSItem 7 | { 8 | [PrimaryKey] 9 | public string Id { get; set; } 10 | 11 | public string Remarks { get; set; } 12 | public bool Enabled { get; set; } = true; 13 | public ECoreType CoreType { get; set; } 14 | public bool UseSystemHosts { get; set; } 15 | public string? NormalDNS { get; set; } 16 | public string? TunDNS { get; set; } 17 | public string? DomainStrategy4Freedom { get; set; } 18 | public string? DomainDNSAddress { get; set; } 19 | } 20 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Sample/SampleOutbound: -------------------------------------------------------------------------------- 1 | { 2 | "tag": "proxy", 3 | "protocol": "vmess", 4 | "settings": { 5 | "vnext": [ 6 | { 7 | "address": "v2ray.cool", 8 | "port": 10086, 9 | "users": [ 10 | { 11 | "id": "a3482e88-686a-4a58-8126-99c9df64b7bf", 12 | "security": "auto" 13 | } 14 | ] 15 | } 16 | ], 17 | "servers": [ 18 | { 19 | "address": "v2ray.cool", 20 | "method": "chacha20", 21 | "ota": false, 22 | "password": "123456", 23 | "port": 10086, 24 | "level": 1 25 | } 26 | ] 27 | }, 28 | "streamSettings": { 29 | "network": "tcp" 30 | }, 31 | "mux": { 32 | "enabled": false 33 | } 34 | } -------------------------------------------------------------------------------- /.github/workflows/build-osx.yml: -------------------------------------------------------------------------------- 1 | name: release macos 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | 9 | jobs: 10 | build: 11 | strategy: 12 | matrix: 13 | configuration: [Release] 14 | 15 | runs-on: macos-latest 16 | 17 | steps: 18 | - name: Checkout 19 | uses: actions/checkout@v4 20 | 21 | - name: Build 22 | run: cd v2rayN && 23 | ./build-osx.sh 24 | 25 | - name: Upload build artifacts 26 | uses: actions/upload-artifact@v4 27 | with: 28 | name: v2rayN-osx 29 | path: | 30 | ./v2rayN/v2rayN-osx.zip 31 | 32 | -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/ClashConnectionModel.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Models 2 | { 3 | public class ClashConnectionModel 4 | { 5 | public string? Id { get; set; } 6 | public string? Network { get; set; } 7 | public string? Type { get; set; } 8 | public string? Host { get; set; } 9 | public ulong Upload { get; set; } 10 | public ulong Download { get; set; } 11 | public string? UploadTraffic { get; set; } 12 | public string? DownloadTraffic { get; set; } 13 | public double Time { get; set; } 14 | public string? Elapsed { get; set; } 15 | public string? Chain { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/ProfileItemModel.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Models 2 | { 3 | [Serializable] 4 | public class ProfileItemModel : ProfileItem 5 | { 6 | public bool IsActive { get; set; } 7 | public string SubRemarks { get; set; } 8 | public int Delay { get; set; } 9 | public decimal Speed { get; set; } 10 | public int Sort { get; set; } 11 | public string DelayVal { get; set; } 12 | public string SpeedVal { get; set; } 13 | public string TodayUp { get; set; } 14 | public string TodayDown { get; set; } 15 | public string TotalUp { get; set; } 16 | public string TotalDown { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/RetResult.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Models 2 | { 3 | public class RetResult 4 | { 5 | public bool Success { get; set; } 6 | public string? Msg { get; set; } 7 | public object? Data { get; set; } 8 | 9 | public RetResult(bool success = false) 10 | { 11 | Success = success; 12 | } 13 | 14 | public RetResult(bool success, string? msg) 15 | { 16 | Success = success; 17 | Msg = msg; 18 | } 19 | 20 | public RetResult(bool success, string? msg, object? data) 21 | { 22 | Success = success; 23 | Msg = msg; 24 | Data = data; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Sample/dns_singbox_normal: -------------------------------------------------------------------------------- 1 | { 2 | "servers": [ 3 | { 4 | "tag": "remote", 5 | "address": "8.8.8.8", 6 | "strategy": "prefer_ipv4", 7 | "detour": "proxy" 8 | }, 9 | { 10 | "tag": "local", 11 | "address": "223.5.5.5", 12 | "strategy": "prefer_ipv4", 13 | "detour": "direct" 14 | }, 15 | { 16 | "tag": "block", 17 | "address": "rcode://success" 18 | } 19 | ], 20 | "rules": [ 21 | { 22 | "rule_set": [ 23 | "geosite-cn" 24 | ], 25 | "server": "local" 26 | }, 27 | { 28 | "rule_set": [ 29 | "geosite-category-ads-all" 30 | ], 31 | "server": "block" 32 | } 33 | ], 34 | "final": "remote" 35 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/RulesItem.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Models 2 | { 3 | [Serializable] 4 | public class RulesItem 5 | { 6 | public string Id { get; set; } 7 | public string? Type { get; set; } 8 | public string? Port { get; set; } 9 | public string? Network { get; set; } 10 | public List? InboundTag { get; set; } 11 | public string? OutboundTag { get; set; } 12 | public List? Ip { get; set; } 13 | public List? Domain { get; set; } 14 | public List? Protocol { get; set; } 15 | public List? Process { get; set; } 16 | public bool Enabled { get; set; } = true; 17 | public string? Remarks { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Handler/Fmt/ClashFmt.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Handler.Fmt 2 | { 3 | public class ClashFmt : BaseFmt 4 | { 5 | public static ProfileItem? ResolveFull(string strData, string? subRemarks) 6 | { 7 | if (Contains(strData, "port", "socks-port", "proxies")) 8 | { 9 | var fileName = WriteAllText(strData, "yaml"); 10 | 11 | var profileItem = new ProfileItem 12 | { 13 | CoreType = ECoreType.mihomo, 14 | Address = fileName, 15 | Remarks = subRemarks ?? "clash_custom" 16 | }; 17 | return profileItem; 18 | } 19 | 20 | return null; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Handler/Fmt/NaiveproxyFmt.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Handler.Fmt 2 | { 3 | public class NaiveproxyFmt : BaseFmt 4 | { 5 | public static ProfileItem? ResolveFull(string strData, string? subRemarks) 6 | { 7 | if (Contains(strData, "listen", "proxy", "", "")) 8 | { 9 | var fileName = WriteAllText(strData); 10 | 11 | var profileItem = new ProfileItem 12 | { 13 | CoreType = ECoreType.naiveproxy, 14 | Address = fileName, 15 | Remarks = subRemarks ?? "naiveproxy_custom" 16 | }; 17 | return profileItem; 18 | } 19 | 20 | return null; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Sample/tun_singbox_dns: -------------------------------------------------------------------------------- 1 | { 2 | "servers": [ 3 | { 4 | "tag": "remote", 5 | "address": "8.8.8.8", 6 | "strategy": "prefer_ipv4", 7 | "detour": "proxy" 8 | }, 9 | { 10 | "tag": "local", 11 | "address": "223.5.5.5", 12 | "strategy": "prefer_ipv4", 13 | "detour": "direct" 14 | }, 15 | { 16 | "tag": "block", 17 | "address": "rcode://success" 18 | } 19 | ], 20 | "rules": [ 21 | { 22 | "rule_set": [ 23 | "geosite-cn", 24 | "geosite-geolocation-cn" 25 | ], 26 | "server": "local" 27 | }, 28 | { 29 | "rule_set": [ 30 | "geosite-category-ads-all" 31 | ], 32 | "server": "block" 33 | } 34 | ], 35 | "final": "remote" 36 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/ClashProxies.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Models 2 | { 3 | public class ClashProxies 4 | { 5 | public Dictionary? proxies { get; set; } 6 | 7 | public class ProxiesItem 8 | { 9 | public List? all { get; set; } 10 | public List? history { get; set; } 11 | public string? name { get; set; } 12 | public string? type { get; set; } 13 | public bool udp { get; set; } 14 | public string? now { get; set; } 15 | public int delay { get; set; } 16 | } 17 | 18 | public class HistoryItem 19 | { 20 | public string? time { get; set; } 21 | public int delay { get; set; } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/RoutingItem.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace ServiceLib.Models 4 | { 5 | [Serializable] 6 | public class RoutingItem 7 | { 8 | [PrimaryKey] 9 | public string Id { get; set; } 10 | 11 | public string Remarks { get; set; } 12 | public string Url { get; set; } 13 | public string RuleSet { get; set; } 14 | public int RuleNum { get; set; } 15 | public bool Enabled { get; set; } = true; 16 | public bool Locked { get; set; } 17 | public string CustomIcon { get; set; } 18 | public string CustomRulesetPath4Singbox { get; set; } 19 | public string DomainStrategy { get; set; } 20 | public string DomainStrategy4Singbox { get; set; } 21 | public int Sort { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /v2rayN/v2rayN/Converters/InverseBooleanConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Windows.Data; 3 | 4 | namespace v2rayN.Converters 5 | { 6 | [ValueConversion(typeof(bool), typeof(bool))] 7 | public class InverseBooleanConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | if (targetType != typeof(bool)) 12 | { 13 | throw new InvalidOperationException("The target must be a boolean"); 14 | } 15 | 16 | return !(bool)value; 17 | } 18 | 19 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 20 | { 21 | throw new NotImplementedException(); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/02_feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature 请求 2 | description: "为这个项目提出一个建议" 3 | title: "[Feature request]: " 4 | labels: ['enhancement'] 5 | body: 6 | - type: input 7 | id: problem 8 | attributes: 9 | label: 相关问题 10 | description: "清楚而简洁地描述问题是什么。" 11 | placeholder: "当我想要……时,软件不能……" 12 | validations: 13 | required: true 14 | - type: input 15 | id: way-to-solve 16 | attributes: 17 | label: 描述你希望的解决方案 18 | description: "你希望发生什么" 19 | validations: 20 | required: true 21 | - type: input 22 | id: instead 23 | attributes: 24 | label: 描述你所考虑的替代方案 25 | validations: 26 | required: false 27 | - type: checkboxes 28 | id: "issues" 29 | attributes: 30 | label: "我确认已查询历史issues" 31 | description: "否则请查询后提出" 32 | options: 33 | - label: 是 34 | required: true 35 | -------------------------------------------------------------------------------- /v2rayN/v2rayN/Converters/MaterialDesignFonts.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Media; 2 | 3 | namespace v2rayN.Converters 4 | { 5 | public class MaterialDesignFonts 6 | { 7 | public static FontFamily MyFont { get; } 8 | 9 | static MaterialDesignFonts() 10 | { 11 | try 12 | { 13 | var fontFamily = AppHandler.Instance.Config.UiItem.CurrentFontFamily; 14 | if (Utils.IsNotEmpty(fontFamily)) 15 | { 16 | var fontPath = Utils.GetFontsPath(); 17 | MyFont = new FontFamily(new Uri(@$"file:///{fontPath}\"), $"./#{fontFamily}"); 18 | } 19 | } 20 | catch 21 | { 22 | } 23 | MyFont ??= new FontFamily("Microsoft YaHei"); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /v2rayN/AmazTool/AmazTool.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | Copyright © 2017-2024 (GPLv3) 9 | 1.3.0 10 | 11 | 12 | 13 | 14 | True 15 | True 16 | Resource.resx 17 | 18 | 19 | 20 | 21 | 22 | ResXFileCodeGenerator 23 | Resource.Designer.cs 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /v2rayN/v2rayN.Desktop/Assets/GlobalStyles.axaml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 14 | 17 | 20 | 23 | -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/CoreInfo.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Models 2 | { 3 | [Serializable] 4 | public class CoreInfo 5 | { 6 | public ECoreType CoreType { get; set; } 7 | public List? CoreExes { get; set; } 8 | public string? Arguments { get; set; } 9 | public string? Url { get; set; } 10 | public string? ReleaseApiUrl { get; set; } 11 | public string? DownloadUrlWin64 { get; set; } 12 | public string? DownloadUrlWinArm64 { get; set; } 13 | public string? DownloadUrlLinux64 { get; set; } 14 | public string? DownloadUrlLinuxArm64 { get; set; } 15 | public string? DownloadUrlOSX64 { get; set; } 16 | public string? DownloadUrlOSXArm64 { get; set; } 17 | public string? Match { get; set; } 18 | public string? VersionArg { get; set; } 19 | public bool RedirectInfo { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /v2rayN/v2rayN/Converters/DelayColorConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Data; 2 | using System.Windows.Media; 3 | 4 | namespace v2rayN.Converters 5 | { 6 | public class DelayColorConverter : IValueConverter 7 | { 8 | public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 9 | { 10 | int.TryParse(value.ToString(), out var delay); 11 | 12 | if (delay <= 0) 13 | return new SolidColorBrush(Colors.Red); 14 | if (delay <= 500) 15 | return new SolidColorBrush(Colors.Green); 16 | else 17 | return new SolidColorBrush(Colors.IndianRed); 18 | } 19 | 20 | public object? ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 21 | { 22 | return null; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /v2rayN/v2rayN.Desktop/Converters/DelayColorConverter.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Data.Converters; 2 | using Avalonia.Media; 3 | using System.Globalization; 4 | 5 | namespace v2rayN.Desktop.Converters 6 | { 7 | public class DelayColorConverter : IValueConverter 8 | { 9 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 10 | { 11 | int.TryParse(value?.ToString(), out var delay); 12 | 13 | if (delay <= 0) 14 | return new SolidColorBrush(Colors.Red); 15 | if (delay <= 500) 16 | return new SolidColorBrush(Colors.Green); 17 | else 18 | return new SolidColorBrush(Colors.IndianRed); 19 | } 20 | 21 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 22 | { 23 | return null; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /v2rayN/v2rayN.Desktop/Views/QrcodeView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using Avalonia.Media.Imaging; 3 | 4 | namespace v2rayN.Desktop.Views 5 | { 6 | public partial class QrcodeView : UserControl 7 | { 8 | public QrcodeView(string? url) 9 | { 10 | InitializeComponent(); 11 | 12 | txtContent.Text = url; 13 | imgQrcode.Source = GetQRCode(url); 14 | 15 | // btnCancel.Click += (s, e) => this.Close(); 16 | } 17 | 18 | private Bitmap? GetQRCode(string? url) 19 | { 20 | var bytes = QRCodeHelper.GenQRCode(url); 21 | return ByteToBitmap(bytes); 22 | } 23 | 24 | private Bitmap? ByteToBitmap(byte[]? bytes) 25 | { 26 | if (bytes is null) return null; 27 | 28 | using var ms = new MemoryStream(bytes); 29 | return new Bitmap(ms); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /v2rayN/v2rayN/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true 6 | PerMonitorV2 7 | 8 | 9 | 10 | 11 | 12 | 13 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/SubItem.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace ServiceLib.Models 4 | { 5 | [Serializable] 6 | public class SubItem 7 | { 8 | [PrimaryKey] 9 | public string Id { get; set; } 10 | 11 | public string Remarks { get; set; } 12 | 13 | public string Url { get; set; } 14 | 15 | public string MoreUrl { get; set; } 16 | 17 | public bool Enabled { get; set; } = true; 18 | 19 | public string UserAgent { get; set; } = string.Empty; 20 | 21 | public int Sort { get; set; } 22 | 23 | public string? Filter { get; set; } 24 | 25 | public int AutoUpdateInterval { get; set; } 26 | 27 | public long UpdateTime { get; set; } 28 | 29 | public string? ConvertTarget { get; set; } 30 | 31 | public string? PrevProfile { get; set; } 32 | 33 | public string? NextProfile { get; set; } 34 | 35 | public int? PreSocksPort { get; set; } 36 | 37 | public string? Memo { get; set; } 38 | } 39 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Sample/clash_mixin_yaml: -------------------------------------------------------------------------------- 1 | # 2 | # 配置文件内容不会被修改,混合行为只会发生在内存中 3 | # 4 | # 注意下面缩进,请用支持yaml显示的编辑器打开 5 | # 6 | # 使用clash配置文件关键字则覆盖原配置 7 | # 8 | # removed-rules 循环匹配rules数组每行,符合则移除当前行 (此规则请放最前面) 9 | # 10 | # append-rules 数组合并至原配置rules数组后 11 | # prepend-rules 数组合并至原配置rules数组前 12 | # append-proxies 数组合并至原配置proxies数组后 13 | # prepend-proxies 数组合并至原配置proxies数组前 14 | # append-proxy-groups 数组合并至原配置proxy-groups数组后 15 | # prepend-proxy-groups 数组合并至原配置proxy-groups数组前 16 | # append-rule-providers 数组合并至原配置rule-providers数组后 17 | # prepend-rule-providers 数组合并至原配置rule-providers数组前 18 | # 19 | 20 | dns: 21 | enable: true 22 | enhanced-mode: fake-ip 23 | nameserver: 24 | - 114.114.114.114 25 | - 223.5.5.5 26 | - 8.8.8.8 27 | fallback: [] 28 | fake-ip-filter: 29 | - +.stun.*.* 30 | - +.stun.*.*.* 31 | - +.stun.*.*.*.* 32 | - +.stun.*.*.*.*.* 33 | - "*.n.n.srv.nintendo.net" 34 | - +.stun.playstation.net 35 | - xbox.*.*.microsoft.com 36 | - "*.*.xboxlive.com" 37 | - "*.msftncsi.com" 38 | - "*.msftconnecttest.com" 39 | - WORKGROUP -------------------------------------------------------------------------------- /v2rayN/v2rayN.Desktop/Views/QrcodeView.axaml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Sample/SampleClientConfig: -------------------------------------------------------------------------------- 1 | { 2 | "log": { 3 | "access": "Vaccess.log", 4 | "error": "Verror.log", 5 | "loglevel": "warning" 6 | }, 7 | "inbounds": [], 8 | "outbounds": [{ 9 | "tag": "proxy", 10 | "protocol": "vmess", 11 | "settings": { 12 | "vnext": [{ 13 | "address": "v2ray.cool", 14 | "port": 10086, 15 | "users": [{ 16 | "id": "a3482e88-686a-4a58-8126-99c9df64b7bf", 17 | "security": "auto" 18 | }] 19 | }], 20 | "servers": [{ 21 | "address": "v2ray.cool", 22 | "method": "chacha20", 23 | "ota": false, 24 | "password": "123456", 25 | "port": 10086, 26 | "level": 1 27 | }] 28 | }, 29 | "streamSettings": { 30 | "network": "tcp" 31 | }, 32 | "mux": { 33 | "enabled": false 34 | } 35 | }, 36 | { 37 | "protocol": "freedom", 38 | "settings": {}, 39 | "tag": "direct" 40 | }, 41 | { 42 | "protocol": "blackhole", 43 | "tag": "block", 44 | "settings": { 45 | "response": { 46 | "type": "http" 47 | } 48 | } 49 | } 50 | ], 51 | "routing": { 52 | "domainStrategy": "IPIfNonMatch", 53 | "rules": [ 54 | { 55 | "inboundTag": ["api"], 56 | "outboundTag": "api", 57 | "type": "field" 58 | } 59 | ] 60 | } 61 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Handler/NoticeHandler.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI; 2 | 3 | namespace ServiceLib.Handler 4 | { 5 | public class NoticeHandler 6 | { 7 | private static readonly Lazy _instance = new(() => new()); 8 | public static NoticeHandler Instance => _instance.Value; 9 | 10 | public void Enqueue(string? content) 11 | { 12 | if (content.IsNullOrEmpty()) 13 | { 14 | return; 15 | } 16 | MessageBus.Current.SendMessage(content, EMsgCommand.SendSnackMsg.ToString()); 17 | } 18 | 19 | public void SendMessage(string? content) 20 | { 21 | if (content.IsNullOrEmpty()) 22 | { 23 | return; 24 | } 25 | MessageBus.Current.SendMessage(content, EMsgCommand.SendMsgView.ToString()); 26 | } 27 | 28 | public void SendMessageEx(string? content) 29 | { 30 | if (content.IsNullOrEmpty()) 31 | { 32 | return; 33 | } 34 | content = $"{DateTime.Now:yyyy/MM/dd HH:mm:ss} {content}"; 35 | SendMessage(content); 36 | } 37 | 38 | public void SendMessageAndEnqueue(string? msg) 39 | { 40 | Enqueue(msg); 41 | SendMessage(msg); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Enums/EViewAction.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Enums 2 | { 3 | public enum EViewAction 4 | { 5 | CloseWindow, 6 | ShowYesNo, 7 | SaveFileDialog, 8 | AddBatchRoutingRulesYesNo, 9 | AdjustMainLvColWidth, 10 | SetClipboardData, 11 | AddServerViaClipboard, 12 | ImportRulesFromClipboard, 13 | ProfilesFocus, 14 | ShareSub, 15 | ShareServer, 16 | ShowHideWindow, 17 | ScanScreenTask, 18 | ScanImageTask, 19 | Shutdown, 20 | BrowseServer, 21 | ImportRulesFromFile, 22 | InitSettingFont, 23 | SubEditWindow, 24 | RoutingRuleSettingWindow, 25 | RoutingRuleDetailsWindow, 26 | AddServerWindow, 27 | AddServer2Window, 28 | DNSSettingWindow, 29 | RoutingSettingWindow, 30 | OptionSettingWindow, 31 | GlobalHotkeySettingWindow, 32 | SubSettingWindow, 33 | DispatcherSpeedTest, 34 | DispatcherRefreshConnections, 35 | DispatcherRefreshProxyGroups, 36 | DispatcherProxiesDelayTest, 37 | DispatcherStatistics, 38 | DispatcherServerAvailability, 39 | DispatcherReload, 40 | DispatcherRefreshServersBiz, 41 | DispatcherRefreshIcon, 42 | DispatcherCheckUpdate, 43 | DispatcherCheckUpdateFinished, 44 | DispatcherShowMsg, 45 | } 46 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/ClashConnections.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Models 2 | { 3 | public class ClashConnections 4 | { 5 | public ulong downloadTotal { get; set; } 6 | public ulong uploadTotal { get; set; } 7 | public List? connections { get; set; } 8 | } 9 | 10 | public class ConnectionItem 11 | { 12 | public string? id { get; set; } 13 | public MetadataItem? metadata { get; set; } 14 | public ulong upload { get; set; } 15 | public ulong download { get; set; } 16 | public DateTime start { get; set; } 17 | public List? chains { get; set; } 18 | public string? rule { get; set; } 19 | public string? rulePayload { get; set; } 20 | } 21 | 22 | public class MetadataItem 23 | { 24 | public string? network { get; set; } 25 | public string? type { get; set; } 26 | public string? sourceIP { get; set; } 27 | public string? destinationIP { get; set; } 28 | public string? sourcePort { get; set; } 29 | public string? destinationPort { get; set; } 30 | public string? host { get; set; } 31 | public string? nsMode { get; set; } 32 | public object uid { get; set; } 33 | public string? process { get; set; } 34 | public string? processPath { get; set; } 35 | public string? remoteDestination { get; set; } 36 | } 37 | } -------------------------------------------------------------------------------- /.github/workflows/winget-publish.yml: -------------------------------------------------------------------------------- 1 | name: WinGet submission on release 2 | # based off of https://github.com/nushell/nushell/blob/main/.github/workflows/winget-submission.yml 3 | # inspired by https://github.com/microsoft/PowerToys/blob/main/.github/workflows/package-submissions.yml 4 | # Modified by @MerrickZ https://github.com/anpho 5 | 6 | on: 7 | workflow_dispatch: 8 | release: 9 | types: [released] 10 | 11 | jobs: 12 | winget: 13 | name: Publish winget package 14 | runs-on: windows-latest 15 | steps: 16 | - name: Submit v2ray package to Windows Package Manager Community Repository 17 | run: | 18 | 19 | $wingetPackage = "2dust.v2rayN" 20 | $gitToken = "${{ secrets.PT_WINGET }}" 21 | 22 | $github = Invoke-RestMethod -uri "https://api.github.com/repos/2dust/v2rayN/releases" 23 | 24 | $targetRelease = $github | Where-Object -Property prerelease -match 'False' | Select -First 1 25 | $installerUrl = $targetRelease | Select -ExpandProperty assets -First 1 | Where-Object -Property name -match 'v2rayN-windows-64-With-Core\.zip*' | Select -ExpandProperty browser_download_url 26 | 27 | $ver = $targetRelease.tag_name 28 | 29 | # getting latest wingetcreate file 30 | iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe 31 | .\wingetcreate.exe update $wingetPackage -s -v $ver -u "$installerUrl|x64" -t $gitToken 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # v2rayN 2 | A GUI client for Windows and Linux, support [Xray core](https://github.com/XTLS/Xray-core) and [sing-box-core](https://github.com/SagerNet/sing-box/releases) and [others](https://github.com/2dust/v2rayN/wiki/List-of-supported-cores) 3 | 4 | 5 | [![GitHub commit activity](https://img.shields.io/github/commit-activity/m/2dust/v2rayN)](https://github.com/2dust/v2rayN/commits/master) 6 | [![CodeFactor](https://www.codefactor.io/repository/github/2dust/v2rayn/badge)](https://www.codefactor.io/repository/github/2dust/v2rayn) 7 | [![GitHub Releases](https://img.shields.io/github/downloads/2dust/v2rayN/latest/total?logo=github)](https://github.com/2dust/v2rayN/releases) 8 | [![Chat on Telegram](https://img.shields.io/badge/Chat%20on-Telegram-brightgreen.svg)](https://t.me/v2rayn) 9 | 10 | 11 | ## How to use 12 | Check [Release files introduction](https://github.com/2dust/v2rayN/wiki/Release-files-introduction) and select the version you need to download 13 | ### Windows 14 | - Run `v2rayN.exe` 15 | ### Linux 16 | - `chmod +x v2rayN` Run `./v2rayN` under user permissions 17 | ``` 18 | Debian 9+ 19 | Ubuntu 16.04+ 20 | Fedora 30+ 21 | ``` 22 | 23 | ## Requirements 24 | - [Microsoft .NET 8.0 Desktop Runtime ](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) 25 | - [Supported cores](https://github.com/2dust/v2rayN/wiki/List-of-supported-cores) 26 | 27 | 28 | ## Telegram Channel 29 | [github_2dust](https://t.me/github_2dust) 30 | -------------------------------------------------------------------------------- /v2rayN/v2rayN.Desktop/Views/ThemeSettingView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.ReactiveUI; 3 | using ReactiveUI; 4 | using System.Reactive.Disposables; 5 | using v2rayN.Desktop.ViewModels; 6 | 7 | namespace v2rayN.Desktop.Views 8 | { 9 | /// 10 | /// ThemeSettingView.xaml 11 | /// 12 | public partial class ThemeSettingView : ReactiveUserControl 13 | { 14 | public ThemeSettingView() 15 | { 16 | InitializeComponent(); 17 | ViewModel = new ThemeSettingViewModel(); 18 | 19 | for (int i = Global.MinFontSize; i <= Global.MinFontSize + 10; i++) 20 | { 21 | cmbCurrentFontSize.Items.Add(i); 22 | } 23 | 24 | Global.Languages.ForEach(it => 25 | { 26 | cmbCurrentLanguage.Items.Add(it); 27 | }); 28 | 29 | this.WhenActivated(disposables => 30 | { 31 | this.Bind(ViewModel, vm => vm.ColorModeDark, v => v.togDarkMode.IsChecked).DisposeWith(disposables); 32 | this.Bind(ViewModel, vm => vm.FollowSystemTheme, v => v.togFollowSystemTheme.IsChecked).DisposeWith(disposables); 33 | this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.SelectedValue).DisposeWith(disposables); 34 | this.Bind(ViewModel, vm => vm.CurrentLanguage, v => v.cmbCurrentLanguage.SelectedValue).DisposeWith(disposables); 35 | }); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/01_bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug 报告 2 | description: 在提出问题前请先自行排除服务器端问题和升级到最新客户端,同时也请通过搜索确认是否有人提出过相同问题。 3 | title: "[Bug]: " 4 | labels: ["bug"] 5 | body: 6 | - type: input 7 | id: "expectation" 8 | attributes: 9 | label: "预期情况" 10 | description: "描述你认为应该发生什么" 11 | validations: 12 | required: true 13 | - type: textarea 14 | id: "describe-the-bug" 15 | attributes: 16 | label: "实际情况" 17 | description: "描述实际发生了什么" 18 | validations: 19 | required: true 20 | - type: textarea 21 | id: "reproduction-method" 22 | attributes: 23 | label: "复现方法" 24 | description: "在BUG出现前执行了哪些操作" 25 | placeholder: 标序号 26 | validations: 27 | required: true 28 | - type: textarea 29 | id: "log" 30 | attributes: 31 | label: "日志信息" 32 | description: "位置在软件当前目录下的guiLogs" 33 | placeholder: 在日志开始和结束位置粘贴冒号后的内容:``` 34 | validations: 35 | required: true 36 | - type: textarea 37 | id: "more" 38 | attributes: 39 | label: "额外信息" 40 | description: "可选" 41 | validations: 42 | required: false 43 | - type: checkboxes 44 | id: "latest-version" 45 | attributes: 46 | label: "我确认已更新至最新版本" 47 | description: "否则请更新后尝试" 48 | options: 49 | - label: 是 50 | required: true 51 | - type: checkboxes 52 | id: "issues" 53 | attributes: 54 | label: "我确认已查询历史issues" 55 | description: "否则请查询后提出" 56 | options: 57 | - label: 是 58 | required: true 59 | -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Handler/Fmt/TrojanFmt.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Handler.Fmt 2 | { 3 | public class TrojanFmt : BaseFmt 4 | { 5 | public static ProfileItem? Resolve(string str, out string msg) 6 | { 7 | msg = ResUI.ConfigurationFormatIncorrect; 8 | 9 | ProfileItem item = new() 10 | { 11 | ConfigType = EConfigType.Trojan 12 | }; 13 | 14 | var url = Utils.TryUri(str); 15 | if (url == null) return null; 16 | 17 | item.Address = url.IdnHost; 18 | item.Port = url.Port; 19 | item.Remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped); 20 | item.Id = Utils.UrlDecode(url.UserInfo); 21 | 22 | var query = Utils.ParseQueryString(url.Query); 23 | ResolveStdTransport(query, ref item); 24 | 25 | return item; 26 | } 27 | 28 | public static string? ToUri(ProfileItem? item) 29 | { 30 | if (item == null) return null; 31 | string url = string.Empty; 32 | 33 | string remark = string.Empty; 34 | if (Utils.IsNotEmpty(item.Remarks)) 35 | { 36 | remark = "#" + Utils.UrlEncode(item.Remarks); 37 | } 38 | var dicQuery = new Dictionary(); 39 | GetStdTransport(item, null, ref dicQuery); 40 | 41 | return ToUri(EConfigType.Trojan, item.Address, item.Port, item.Id, dicQuery, remark); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/VmessQRCode.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace ServiceLib.Models 4 | { 5 | /// 6 | /// https://github.com/2dust/v2rayN/wiki/ 7 | /// 8 | [Serializable] 9 | public class VmessQRCode 10 | { 11 | [JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)] 12 | public int v { get; set; } = 2; 13 | 14 | public string ps { get; set; } = string.Empty; 15 | 16 | public string add { get; set; } = string.Empty; 17 | 18 | [JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)] 19 | public int port { get; set; } = 0; 20 | 21 | public string id { get; set; } = string.Empty; 22 | 23 | [JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)] 24 | public int aid { get; set; } = 0; 25 | 26 | public string scy { get; set; } = string.Empty; 27 | 28 | public string net { get; set; } = string.Empty; 29 | 30 | public string type { get; set; } = string.Empty; 31 | 32 | public string host { get; set; } = string.Empty; 33 | 34 | public string path { get; set; } = string.Empty; 35 | 36 | public string tls { get; set; } = string.Empty; 37 | 38 | public string sni { get; set; } = string.Empty; 39 | 40 | public string alpn { get; set; } = string.Empty; 41 | 42 | public string fp { get; set; } = string.Empty; 43 | } 44 | } -------------------------------------------------------------------------------- /v2rayN/build.ps1: -------------------------------------------------------------------------------- 1 | param ( 2 | [Parameter()] 3 | [ValidateNotNullOrEmpty()] 4 | [string] 5 | $OutputPath = './bin/v2rayN' 6 | ) 7 | 8 | Write-Host 'Building' 9 | 10 | dotnet publish ` 11 | ./v2rayN/v2rayN.csproj ` 12 | -c Release ` 13 | -r win-x64 ` 14 | --self-contained false ` 15 | -p:PublishReadyToRun=false ` 16 | -p:PublishSingleFile=true ` 17 | -o "$OutputPath/win-x64" 18 | 19 | dotnet publish ` 20 | ./v2rayN/v2rayN.csproj ` 21 | -c Release ` 22 | -r win-arm64 ` 23 | --self-contained false ` 24 | -p:PublishReadyToRun=false ` 25 | -p:PublishSingleFile=true ` 26 | -o "$OutputPath/win-arm64" 27 | 28 | dotnet publish ` 29 | ./v2rayN.Desktop/v2rayN.Desktop.csproj ` 30 | -c Release ` 31 | -r linux-x64 ` 32 | --self-contained true ` 33 | -p:PublishReadyToRun=false ` 34 | -p:PublishSingleFile=true ` 35 | -o "$OutputPath/linux-x64" 36 | 37 | dotnet publish ` 38 | ./v2rayN.Desktop/v2rayN.Desktop.csproj ` 39 | -c Release ` 40 | -r linux-arm64 ` 41 | --self-contained true ` 42 | -p:PublishReadyToRun=false ` 43 | -p:PublishSingleFile=true ` 44 | -o "$OutputPath/linux-arm64" 45 | 46 | 47 | if ( -Not $? ) { 48 | exit $lastExitCode 49 | } 50 | 51 | if ( Test-Path -Path ./bin/v2rayN ) { 52 | rm -Force "$OutputPath/win-x64/*.pdb" 53 | rm -Force "$OutputPath/win-arm64/*.pdb" 54 | rm -Force "$OutputPath/linux-x64/*.pdb" 55 | rm -Force "$OutputPath/linux-arm64/*.pdb" 56 | } 57 | 58 | Write-Host 'Build done' 59 | 60 | ls $OutputPath 61 | 7z a v2rayN.zip $OutputPath 62 | exit 0 -------------------------------------------------------------------------------- /v2rayN/v2rayN.Desktop/Common/AvaUtils.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using Avalonia.Input; 4 | using Avalonia.Media.Imaging; 5 | using Avalonia.Platform; 6 | 7 | namespace v2rayN.Desktop.Common 8 | { 9 | internal class AvaUtils 10 | { 11 | public static async Task GetClipboardData(Window owner) 12 | { 13 | try 14 | { 15 | var clipboard = TopLevel.GetTopLevel(owner)?.Clipboard; 16 | if (clipboard == null) return null; 17 | return await clipboard.GetTextAsync(); 18 | } 19 | catch 20 | { 21 | return null; 22 | } 23 | } 24 | 25 | public static async Task SetClipboardData(Visual? visual, string strData) 26 | { 27 | try 28 | { 29 | var clipboard = TopLevel.GetTopLevel(visual)?.Clipboard; 30 | if (clipboard == null) return; 31 | var dataObject = new DataObject(); 32 | dataObject.Set(DataFormats.Text, strData); 33 | await clipboard.SetDataObjectAsync(dataObject); 34 | } 35 | catch 36 | { 37 | } 38 | } 39 | 40 | public static WindowIcon GetAppIcon(ESysProxyType sysProxyType) 41 | { 42 | var index = (int)sysProxyType + 1; 43 | var uri = new Uri(Path.Combine(Global.AvaAssets, $"NotifyIcon{index}.ico")); 44 | using var bitmap = new Bitmap(AssetLoader.Open(uri)); 45 | return new(bitmap); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /v2rayN/v2rayN/Views/ThemeSettingView.xaml.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI; 2 | using System.Reactive.Disposables; 3 | using v2rayN.ViewModels; 4 | 5 | namespace v2rayN.Views 6 | { 7 | /// 8 | /// ThemeSettingView.xaml 9 | /// 10 | public partial class ThemeSettingView 11 | { 12 | public ThemeSettingView() 13 | { 14 | InitializeComponent(); 15 | ViewModel = new ThemeSettingViewModel(); 16 | 17 | for (int i = Global.MinFontSize; i <= Global.MinFontSize + 10; i++) 18 | { 19 | cmbCurrentFontSize.Items.Add(i.ToString()); 20 | } 21 | 22 | Global.Languages.ForEach(it => 23 | { 24 | cmbCurrentLanguage.Items.Add(it); 25 | }); 26 | 27 | this.WhenActivated(disposables => 28 | { 29 | this.Bind(ViewModel, vm => vm.ColorModeDark, v => v.togDarkMode.IsChecked).DisposeWith(disposables); 30 | this.Bind(ViewModel, vm => vm.FollowSystemTheme, v => v.togFollowSystemTheme.IsChecked).DisposeWith(disposables); 31 | this.OneWayBind(ViewModel, vm => vm.Swatches, v => v.cmbSwatches.ItemsSource).DisposeWith(disposables); 32 | this.Bind(ViewModel, vm => vm.SelectedSwatch, v => v.cmbSwatches.SelectedItem).DisposeWith(disposables); 33 | this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.Text).DisposeWith(disposables); 34 | this.Bind(ViewModel, vm => vm.CurrentLanguage, v => v.cmbCurrentLanguage.Text).DisposeWith(disposables); 35 | }); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Common/WindowsUtils.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32; 2 | 3 | namespace ServiceLib.Common 4 | { 5 | internal static class WindowsUtils 6 | { 7 | public static string? RegReadValue(string path, string name, string def) 8 | { 9 | RegistryKey? regKey = null; 10 | try 11 | { 12 | regKey = Registry.CurrentUser.OpenSubKey(path, false); 13 | var value = regKey?.GetValue(name) as string; 14 | return Utils.IsNullOrEmpty(value) ? def : value; 15 | } 16 | catch (Exception ex) 17 | { 18 | Logging.SaveLog(ex.Message, ex); 19 | } 20 | finally 21 | { 22 | regKey?.Close(); 23 | } 24 | return def; 25 | } 26 | 27 | public static void RegWriteValue(string path, string name, object value) 28 | { 29 | RegistryKey? regKey = null; 30 | try 31 | { 32 | regKey = Registry.CurrentUser.CreateSubKey(path); 33 | if (Utils.IsNullOrEmpty(value.ToString())) 34 | { 35 | regKey?.DeleteValue(name, false); 36 | } 37 | else 38 | { 39 | regKey?.SetValue(name, value); 40 | } 41 | } 42 | catch (Exception ex) 43 | { 44 | Logging.SaveLog(ex.Message, ex); 45 | } 46 | finally 47 | { 48 | regKey?.Close(); 49 | } 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /v2rayN/v2rayN/v2rayN.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | WinExe 6 | net8.0-windows10.0.17763 7 | enable 8 | true 9 | app.manifest 10 | enable 11 | Resources\v2rayN.ico 12 | Copyright © 2017-2024 (GPLv3) 13 | 7.0 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | Never 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /v2rayN/v2rayN/Common/UI.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32; 2 | using System.Windows; 3 | 4 | namespace v2rayN 5 | { 6 | internal class UI 7 | { 8 | private static readonly string caption = Global.AppName; 9 | 10 | public static void Show(string msg) 11 | { 12 | MessageBox.Show(msg, caption, MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK); 13 | } 14 | 15 | public static MessageBoxResult ShowYesNo(string msg) 16 | { 17 | return MessageBox.Show(msg, caption, MessageBoxButton.YesNo, MessageBoxImage.Question); 18 | } 19 | 20 | public static bool? OpenFileDialog(out string fileName, string filter) 21 | { 22 | fileName = string.Empty; 23 | 24 | var fileDialog = new OpenFileDialog 25 | { 26 | Multiselect = false, 27 | Filter = filter 28 | }; 29 | 30 | if (fileDialog.ShowDialog() != true) 31 | { 32 | return false; 33 | } 34 | fileName = fileDialog.FileName; 35 | 36 | return true; 37 | } 38 | 39 | public static bool? SaveFileDialog(out string fileName, string filter) 40 | { 41 | fileName = string.Empty; 42 | 43 | SaveFileDialog fileDialog = new() 44 | { 45 | Filter = filter, 46 | FilterIndex = 2, 47 | RestoreDirectory = true 48 | }; 49 | if (fileDialog.ShowDialog() != true) 50 | { 51 | return false; 52 | } 53 | 54 | fileName = fileDialog.FileName; 55 | 56 | return true; 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | 9 | jobs: 10 | build: 11 | strategy: 12 | matrix: 13 | configuration: [Release] 14 | 15 | runs-on: windows-latest 16 | 17 | steps: 18 | - name: Checkout 19 | uses: actions/checkout@v4 20 | 21 | # - name: 删除工作流运行 22 | # uses: Mattraks/delete-workflow-runs@v2 23 | # with: 24 | # token: ${{ github.token }} 25 | # repository: ${{ github.repository }} 26 | # retain_days: 0 27 | # keep_minimum_runs: 1 28 | 29 | - name: Build 30 | run: cd v2rayN && 31 | ./build.ps1 32 | 33 | # - name: Package 34 | # shell: pwsh 35 | # run: | 36 | # 7z a -mx9 ..\v2rayN.7z $env:Wap_Project_Directory 37 | 38 | - name: Upload build artifacts 39 | uses: actions/upload-artifact@v4 40 | with: 41 | name: v2rayN 42 | path: | 43 | ./v2rayN/v2rayN.zip 44 | 45 | # - name: Release 46 | # uses: softprops/action-gh-release@v1 47 | # env: 48 | # GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }} 49 | # with: 50 | # prerelease: ${{ contains(github.ref, '-') }} 51 | # draft: false 52 | # files: | 53 | # .\v2rayN\v2rayN.zip 54 | # body: | 55 | # [![](https://img.shields.io/badge/Telegram-Channel-blue)](https://t.me/netch_channel) [![](https://img.shields.io/badge/Telegram-Group-green)](https://t.me/netch_group) 56 | # ## Changelogs 57 | # * This is an automated deployment of GitHub Actions, the change log should be updated manually soon 58 | 59 | # ## 更新日志 60 | # * 这是 GitHub Actions 自动化部署,更新日志应该很快会手动更新 61 | -------------------------------------------------------------------------------- /v2rayN/v2rayN.Desktop/Common/UI.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using Avalonia.Platform.Storage; 3 | using MsBox.Avalonia; 4 | using MsBox.Avalonia.Enums; 5 | 6 | namespace v2rayN.Desktop.Common 7 | { 8 | internal class UI 9 | { 10 | private static readonly string caption = Global.AppName; 11 | 12 | public static async Task ShowYesNo(Window owner, string msg) 13 | { 14 | var box = MessageBoxManager.GetMessageBoxStandard(caption, msg, ButtonEnum.YesNo); 15 | return await box.ShowWindowDialogAsync(owner); 16 | } 17 | 18 | public static async Task OpenFileDialog(Window owner, FilePickerFileType? filter) 19 | { 20 | var topLevel = TopLevel.GetTopLevel(owner); 21 | if (topLevel == null) 22 | { 23 | return null; 24 | } 25 | // Start async operation to open the dialog. 26 | var files = await topLevel.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions 27 | { 28 | AllowMultiple = false, 29 | FileTypeFilter = filter is null ? [FilePickerFileTypes.All, FilePickerFileTypes.ImagePng] : [filter] 30 | }); 31 | 32 | return files.FirstOrDefault()?.TryGetLocalPath(); 33 | } 34 | 35 | public static async Task SaveFileDialog(Window owner, string filter) 36 | { 37 | var topLevel = TopLevel.GetTopLevel(owner); 38 | if (topLevel == null) 39 | { 40 | return null; 41 | } 42 | // Start async operation to open the dialog. 43 | var files = await topLevel.StorageProvider.SaveFilePickerAsync(new FilePickerSaveOptions 44 | { 45 | }); 46 | 47 | return files?.TryGetLocalPath(); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /v2rayN/v2rayN.Desktop/Program.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.ReactiveUI; 3 | using v2rayN.Desktop.Common; 4 | 5 | namespace v2rayN.Desktop; 6 | 7 | internal class Program 8 | { 9 | public static EventWaitHandle ProgramStarted; 10 | 11 | // Initialization code. Don't use any Avalonia, third-party APIs or any 12 | // SynchronizationContext-reliant code before AppMain is called: things aren't initialized 13 | // yet and stuff might break. 14 | [STAThread] 15 | public static void Main(string[] args) 16 | { 17 | OnStartup(args); 18 | 19 | BuildAvaloniaApp() 20 | .StartWithClassicDesktopLifetime(args); 21 | } 22 | 23 | private static void OnStartup(string[]? Args) 24 | { 25 | if (Utils.IsWindows()) 26 | { 27 | var exePathKey = Utils.GetMd5(Utils.GetExePath()); 28 | var rebootas = (Args ?? Array.Empty()).Any(t => t == Global.RebootAs); 29 | ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, exePathKey, out bool bCreatedNew); 30 | if (!rebootas && !bCreatedNew) 31 | { 32 | ProgramStarted.Set(); 33 | Environment.Exit(0); 34 | return; 35 | } 36 | } 37 | else 38 | { 39 | _ = new Mutex(true, "v2rayN", out var bOnlyOneInstance); 40 | if (!bOnlyOneInstance) 41 | { 42 | Environment.Exit(0); 43 | return; 44 | } 45 | } 46 | } 47 | 48 | // Avalonia configuration, don't remove; also used by visual designer. 49 | public static AppBuilder BuildAvaloniaApp() 50 | => AppBuilder.Configure() 51 | .UsePlatformDetect() 52 | //.WithInterFont() 53 | .WithFontByDefault() 54 | .LogToTrace() 55 | .UseReactiveUI(); 56 | } -------------------------------------------------------------------------------- /v2rayN/v2rayN/Views/QrcodeView.xaml: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 26 | 27 | 37 | 38 | 70 | -------------------------------------------------------------------------------- /v2rayN/ServiceLib/ViewModels/RoutingRuleDetailsViewModel.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI; 2 | using ReactiveUI.Fody.Helpers; 3 | using System.Reactive; 4 | 5 | namespace ServiceLib.ViewModels 6 | { 7 | public class RoutingRuleDetailsViewModel : MyReactiveObject 8 | { 9 | public IList ProtocolItems { get; set; } 10 | public IList InboundTagItems { get; set; } 11 | 12 | [Reactive] 13 | public RulesItem SelectedSource { get; set; } 14 | 15 | [Reactive] 16 | public string Domain { get; set; } 17 | 18 | [Reactive] 19 | public string IP { get; set; } 20 | 21 | [Reactive] 22 | public string Process { get; set; } 23 | 24 | [Reactive] 25 | public bool AutoSort { get; set; } 26 | 27 | public ReactiveCommand SaveCmd { get; } 28 | 29 | public RoutingRuleDetailsViewModel(RulesItem rulesItem, Func>? updateView) 30 | { 31 | _config = AppHandler.Instance.Config; 32 | _updateView = updateView; 33 | 34 | SaveCmd = ReactiveCommand.CreateFromTask(async () => 35 | { 36 | await SaveRulesAsync(); 37 | }); 38 | 39 | if (rulesItem.Id.IsNullOrEmpty()) 40 | { 41 | rulesItem.Id = Utils.GetGuid(false); 42 | rulesItem.OutboundTag = Global.ProxyTag; 43 | rulesItem.Enabled = true; 44 | SelectedSource = rulesItem; 45 | } 46 | else 47 | { 48 | SelectedSource = rulesItem; 49 | } 50 | 51 | Domain = Utils.List2String(SelectedSource.Domain, true); 52 | IP = Utils.List2String(SelectedSource.Ip, true); 53 | Process = Utils.List2String(SelectedSource.Process, true); 54 | } 55 | 56 | private async Task SaveRulesAsync() 57 | { 58 | Domain = Utils.Convert2Comma(Domain); 59 | IP = Utils.Convert2Comma(IP); 60 | Process = Utils.Convert2Comma(Process); 61 | 62 | if (AutoSort) 63 | { 64 | SelectedSource.Domain = Utils.String2ListSorted(Domain); 65 | SelectedSource.Ip = Utils.String2ListSorted(IP); 66 | SelectedSource.Process = Utils.String2ListSorted(Process); 67 | } 68 | else 69 | { 70 | SelectedSource.Domain = Utils.String2List(Domain); 71 | SelectedSource.Ip = Utils.String2List(IP); 72 | SelectedSource.Process = Utils.String2List(Process); 73 | } 74 | SelectedSource.Protocol = ProtocolItems?.ToList(); 75 | SelectedSource.InboundTag = InboundTagItems?.ToList(); 76 | 77 | bool hasRule = SelectedSource.Domain?.Count > 0 78 | || SelectedSource.Ip?.Count > 0 79 | || SelectedSource.Protocol?.Count > 0 80 | || SelectedSource.Process?.Count > 0 81 | || Utils.IsNotEmpty(SelectedSource.Port); 82 | 83 | if (!hasRule) 84 | { 85 | NoticeHandler.Instance.Enqueue(string.Format(ResUI.RoutingRuleDetailRequiredTips, "Port/Protocol/Domain/IP/Process")); 86 | return; 87 | } 88 | //NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess); 89 | await _updateView?.Invoke(EViewAction.CloseWindow, null); 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Models/ProfileItem.cs: -------------------------------------------------------------------------------- 1 | using SQLite; 2 | 3 | namespace ServiceLib.Models 4 | { 5 | [Serializable] 6 | public class ProfileItem 7 | { 8 | public ProfileItem() 9 | { 10 | IndexId = string.Empty; 11 | ConfigType = EConfigType.VMess; 12 | ConfigVersion = 2; 13 | Address = string.Empty; 14 | Port = 0; 15 | Id = string.Empty; 16 | AlterId = 0; 17 | Security = string.Empty; 18 | Network = string.Empty; 19 | Remarks = string.Empty; 20 | HeaderType = string.Empty; 21 | RequestHost = string.Empty; 22 | Path = string.Empty; 23 | StreamSecurity = string.Empty; 24 | AllowInsecure = string.Empty; 25 | Subid = string.Empty; 26 | Flow = string.Empty; 27 | } 28 | 29 | #region function 30 | 31 | public string GetSummary() 32 | { 33 | var summary = $"[{(ConfigType).ToString()}] "; 34 | var arrAddr = Address.Split('.'); 35 | var addr = arrAddr.Length switch 36 | { 37 | > 2 => $"{arrAddr.First()}***{arrAddr.Last()}", 38 | > 1 => $"***{arrAddr.Last()}", 39 | _ => Address 40 | }; 41 | summary += ConfigType switch 42 | { 43 | EConfigType.Custom => $"[{CoreType.ToString()}]{Remarks}", 44 | _ => $"{Remarks}({addr}:{Port})" 45 | }; 46 | return summary; 47 | } 48 | 49 | public List? GetAlpn() 50 | { 51 | return Utils.IsNullOrEmpty(Alpn) ? null : Utils.String2List(Alpn); 52 | } 53 | 54 | public string GetNetwork() 55 | { 56 | if (Utils.IsNullOrEmpty(Network) || !Global.Networks.Contains(Network)) 57 | { 58 | return Global.DefaultNetwork; 59 | } 60 | return Network.TrimEx(); 61 | } 62 | 63 | #endregion function 64 | 65 | [PrimaryKey] 66 | public string IndexId { get; set; } 67 | 68 | public EConfigType ConfigType { get; set; } 69 | public int ConfigVersion { get; set; } 70 | public string Address { get; set; } 71 | public int Port { get; set; } 72 | public string Id { get; set; } 73 | public int AlterId { get; set; } 74 | public string Security { get; set; } 75 | public string Network { get; set; } 76 | public string Remarks { get; set; } 77 | public string HeaderType { get; set; } 78 | public string RequestHost { get; set; } 79 | public string Path { get; set; } 80 | public string StreamSecurity { get; set; } 81 | public string AllowInsecure { get; set; } 82 | public string Subid { get; set; } 83 | public bool IsSub { get; set; } = true; 84 | public string Flow { get; set; } 85 | public string Sni { get; set; } 86 | public string Alpn { get; set; } = string.Empty; 87 | public ECoreType? CoreType { get; set; } 88 | public int? PreSocksPort { get; set; } 89 | public string Fingerprint { get; set; } 90 | public bool DisplayLog { get; set; } = true; 91 | public string PublicKey { get; set; } 92 | public string ShortId { get; set; } 93 | public string SpiderX { get; set; } 94 | public string Extra { get; set; } 95 | } 96 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Handler/Fmt/Hysteria2Fmt.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Handler.Fmt 2 | { 3 | public class Hysteria2Fmt : BaseFmt 4 | { 5 | public static ProfileItem? Resolve(string str, out string msg) 6 | { 7 | msg = ResUI.ConfigurationFormatIncorrect; 8 | ProfileItem item = new() 9 | { 10 | ConfigType = EConfigType.Hysteria2 11 | }; 12 | 13 | var url = Utils.TryUri(str); 14 | if (url == null) return null; 15 | 16 | item.Address = url.IdnHost; 17 | item.Port = url.Port; 18 | item.Remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped); 19 | item.Id = Utils.UrlDecode(url.UserInfo); 20 | 21 | var query = Utils.ParseQueryString(url.Query); 22 | ResolveStdTransport(query, ref item); 23 | item.Path = Utils.UrlDecode(query["obfs-password"] ?? ""); 24 | item.AllowInsecure = (query["insecure"] ?? "") == "1" ? "true" : "false"; 25 | 26 | return item; 27 | } 28 | 29 | public static string? ToUri(ProfileItem? item) 30 | { 31 | if (item == null) return null; 32 | string url = string.Empty; 33 | 34 | string remark = string.Empty; 35 | if (Utils.IsNotEmpty(item.Remarks)) 36 | { 37 | remark = "#" + Utils.UrlEncode(item.Remarks); 38 | } 39 | var dicQuery = new Dictionary(); 40 | if (Utils.IsNotEmpty(item.Sni)) 41 | { 42 | dicQuery.Add("sni", item.Sni); 43 | } 44 | if (Utils.IsNotEmpty(item.Alpn)) 45 | { 46 | dicQuery.Add("alpn", Utils.UrlEncode(item.Alpn)); 47 | } 48 | if (Utils.IsNotEmpty(item.Path)) 49 | { 50 | dicQuery.Add("obfs", "salamander"); 51 | dicQuery.Add("obfs-password", Utils.UrlEncode(item.Path)); 52 | } 53 | dicQuery.Add("insecure", item.AllowInsecure.ToLower() == "true" ? "1" : "0"); 54 | 55 | return ToUri(EConfigType.Hysteria2, item.Address, item.Port, item.Id, dicQuery, remark); 56 | } 57 | 58 | public static ProfileItem? ResolveFull(string strData, string? subRemarks) 59 | { 60 | if (Contains(strData, "server", "up", "down", "listen", "", "")) 61 | { 62 | var fileName = WriteAllText(strData); 63 | 64 | var profileItem = new ProfileItem 65 | { 66 | CoreType = ECoreType.hysteria, 67 | Address = fileName, 68 | Remarks = subRemarks ?? "hysteria_custom" 69 | }; 70 | return profileItem; 71 | } 72 | 73 | return null; 74 | } 75 | 76 | public static ProfileItem? ResolveFull2(string strData, string? subRemarks) 77 | { 78 | if (Contains(strData, "server", "auth", "up", "down", "listen")) 79 | { 80 | var fileName = WriteAllText(strData); 81 | 82 | var profileItem = new ProfileItem 83 | { 84 | CoreType = ECoreType.hysteria2, 85 | Address = fileName, 86 | Remarks = subRemarks ?? "hysteria2_custom" 87 | }; 88 | return profileItem; 89 | } 90 | 91 | return null; 92 | } 93 | } 94 | } -------------------------------------------------------------------------------- /v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Interactivity; 2 | using Avalonia.ReactiveUI; 3 | using ReactiveUI; 4 | using System.Reactive.Disposables; 5 | 6 | namespace v2rayN.Desktop.Views 7 | { 8 | public partial class DNSSettingWindow : ReactiveWindow 9 | { 10 | private static Config _config; 11 | 12 | public DNSSettingWindow() 13 | { 14 | InitializeComponent(); 15 | 16 | _config = AppHandler.Instance.Config; 17 | btnCancel.Click += (s, e) => this.Close(); 18 | ViewModel = new DNSSettingViewModel(UpdateViewHandler); 19 | 20 | Global.DomainStrategy4Freedoms.ForEach(it => 21 | { 22 | cmbdomainStrategy4Freedom.Items.Add(it); 23 | }); 24 | Global.SingboxDomainStrategy4Out.ForEach(it => 25 | { 26 | cmbdomainStrategy4Out.Items.Add(it); 27 | }); 28 | Global.DomainDNSAddress.ForEach(it => 29 | { 30 | cmbdomainDNSAddress.Items.Add(it); 31 | }); 32 | Global.SingboxDomainDNSAddress.ForEach(it => 33 | { 34 | cmbdomainDNSAddress2.Items.Add(it); 35 | }); 36 | 37 | this.WhenActivated(disposables => 38 | { 39 | this.Bind(ViewModel, vm => vm.useSystemHosts, v => v.togUseSystemHosts.IsChecked).DisposeWith(disposables); 40 | this.Bind(ViewModel, vm => vm.domainStrategy4Freedom, v => v.cmbdomainStrategy4Freedom.SelectedValue).DisposeWith(disposables); 41 | this.Bind(ViewModel, vm => vm.domainDNSAddress, v => v.cmbdomainDNSAddress.SelectedValue).DisposeWith(disposables); 42 | this.Bind(ViewModel, vm => vm.normalDNS, v => v.txtnormalDNS.Text).DisposeWith(disposables); 43 | 44 | this.Bind(ViewModel, vm => vm.domainStrategy4Freedom2, v => v.cmbdomainStrategy4Out.SelectedValue).DisposeWith(disposables); 45 | this.Bind(ViewModel, vm => vm.domainDNSAddress2, v => v.cmbdomainDNSAddress2.SelectedValue).DisposeWith(disposables); 46 | this.Bind(ViewModel, vm => vm.normalDNS2, v => v.txtnormalDNS2.Text).DisposeWith(disposables); 47 | this.Bind(ViewModel, vm => vm.tunDNS2, v => v.txttunDNS2.Text).DisposeWith(disposables); 48 | 49 | this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables); 50 | this.BindCommand(ViewModel, vm => vm.ImportDefConfig4V2rayCmd, v => v.btnImportDefConfig4V2ray).DisposeWith(disposables); 51 | this.BindCommand(ViewModel, vm => vm.ImportDefConfig4SingboxCmd, v => v.btnImportDefConfig4Singbox).DisposeWith(disposables); 52 | }); 53 | } 54 | 55 | private async Task UpdateViewHandler(EViewAction action, object? obj) 56 | { 57 | switch (action) 58 | { 59 | case EViewAction.CloseWindow: 60 | this.Close(true); 61 | break; 62 | } 63 | return await Task.FromResult(true); 64 | } 65 | 66 | private void linkDnsObjectDoc_Click(object? sender, RoutedEventArgs e) 67 | { 68 | Utils.ProcessStart("https://xtls.github.io/config/dns.html#dnsobject"); 69 | } 70 | 71 | private void linkDnsSingboxObjectDoc_Click(object? sender, RoutedEventArgs e) 72 | { 73 | Utils.ProcessStart("https://sing-box.sagernet.org/zh/configuration/dns/"); 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Common/JsonUtils.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using System.Text.Json.Nodes; 3 | using System.Text.Json.Serialization; 4 | 5 | namespace ServiceLib.Common 6 | { 7 | public class JsonUtils 8 | { 9 | /// 10 | /// DeepCopy 11 | /// 12 | /// 13 | /// 14 | /// 15 | public static T DeepCopy(T obj) 16 | { 17 | return Deserialize(Serialize(obj, false))!; 18 | } 19 | 20 | /// 21 | /// Deserialize to object 22 | /// 23 | /// 24 | /// 25 | /// 26 | public static T? Deserialize(string? strJson) 27 | { 28 | try 29 | { 30 | if (string.IsNullOrWhiteSpace(strJson)) 31 | { 32 | return default; 33 | } 34 | var options = new JsonSerializerOptions 35 | { 36 | PropertyNameCaseInsensitive = true 37 | }; 38 | return JsonSerializer.Deserialize(strJson, options); 39 | } 40 | catch 41 | { 42 | return default; 43 | } 44 | } 45 | 46 | /// 47 | /// parse 48 | /// 49 | /// 50 | /// 51 | public static JsonNode? ParseJson(string strJson) 52 | { 53 | try 54 | { 55 | if (string.IsNullOrWhiteSpace(strJson)) 56 | { 57 | return null; 58 | } 59 | return JsonNode.Parse(strJson); 60 | } 61 | catch 62 | { 63 | //SaveLog(ex.Message, ex); 64 | return null; 65 | } 66 | } 67 | 68 | /// 69 | /// Serialize Object to Json string 70 | /// 71 | /// 72 | /// 73 | /// 74 | /// 75 | public static string Serialize(object? obj, bool indented = true, bool nullValue = false) 76 | { 77 | var result = string.Empty; 78 | try 79 | { 80 | if (obj == null) 81 | { 82 | return result; 83 | } 84 | var options = new JsonSerializerOptions 85 | { 86 | WriteIndented = indented, 87 | DefaultIgnoreCondition = nullValue ? JsonIgnoreCondition.Never : JsonIgnoreCondition.WhenWritingNull 88 | }; 89 | result = JsonSerializer.Serialize(obj, options); 90 | } 91 | catch (Exception ex) 92 | { 93 | Logging.SaveLog(ex.Message, ex); 94 | } 95 | return result; 96 | } 97 | 98 | /// 99 | /// SerializeToNode 100 | /// 101 | /// 102 | /// 103 | public static JsonNode? SerializeToNode(object? obj) => JsonSerializer.SerializeToNode(obj); 104 | } 105 | } -------------------------------------------------------------------------------- /v2rayN/v2rayN/Views/DNSSettingWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI; 2 | using System.Reactive.Disposables; 3 | using System.Windows; 4 | 5 | namespace v2rayN.Views 6 | { 7 | public partial class DNSSettingWindow 8 | { 9 | private static Config _config; 10 | 11 | public DNSSettingWindow() 12 | { 13 | InitializeComponent(); 14 | 15 | this.Owner = Application.Current.MainWindow; 16 | _config = AppHandler.Instance.Config; 17 | 18 | ViewModel = new DNSSettingViewModel(UpdateViewHandler); 19 | 20 | Global.DomainStrategy4Freedoms.ForEach(it => 21 | { 22 | cmbdomainStrategy4Freedom.Items.Add(it); 23 | }); 24 | Global.SingboxDomainStrategy4Out.ForEach(it => 25 | { 26 | cmbdomainStrategy4Out.Items.Add(it); 27 | }); 28 | Global.DomainDNSAddress.ForEach(it => 29 | { 30 | cmbdomainDNSAddress.Items.Add(it); 31 | }); 32 | Global.SingboxDomainDNSAddress.ForEach(it => 33 | { 34 | cmbdomainDNSAddress2.Items.Add(it); 35 | }); 36 | 37 | this.WhenActivated(disposables => 38 | { 39 | this.Bind(ViewModel, vm => vm.useSystemHosts, v => v.togUseSystemHosts.IsChecked).DisposeWith(disposables); 40 | this.Bind(ViewModel, vm => vm.domainStrategy4Freedom, v => v.cmbdomainStrategy4Freedom.Text).DisposeWith(disposables); 41 | this.Bind(ViewModel, vm => vm.domainDNSAddress, v => v.cmbdomainDNSAddress.Text).DisposeWith(disposables); 42 | this.Bind(ViewModel, vm => vm.normalDNS, v => v.txtnormalDNS.Text).DisposeWith(disposables); 43 | 44 | this.Bind(ViewModel, vm => vm.domainStrategy4Freedom2, v => v.cmbdomainStrategy4Out.Text).DisposeWith(disposables); 45 | this.Bind(ViewModel, vm => vm.domainDNSAddress2, v => v.cmbdomainDNSAddress2.Text).DisposeWith(disposables); 46 | this.Bind(ViewModel, vm => vm.normalDNS2, v => v.txtnormalDNS2.Text).DisposeWith(disposables); 47 | this.Bind(ViewModel, vm => vm.tunDNS2, v => v.txttunDNS2.Text).DisposeWith(disposables); 48 | 49 | this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables); 50 | this.BindCommand(ViewModel, vm => vm.ImportDefConfig4V2rayCmd, v => v.btnImportDefConfig4V2ray).DisposeWith(disposables); 51 | this.BindCommand(ViewModel, vm => vm.ImportDefConfig4SingboxCmd, v => v.btnImportDefConfig4Singbox).DisposeWith(disposables); 52 | }); 53 | WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? WindowsUtils.IsDarkTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark); 54 | } 55 | 56 | private async Task UpdateViewHandler(EViewAction action, object? obj) 57 | { 58 | switch (action) 59 | { 60 | case EViewAction.CloseWindow: 61 | this.DialogResult = true; 62 | break; 63 | } 64 | return await Task.FromResult(true); 65 | } 66 | 67 | private void linkDnsObjectDoc_Click(object sender, RoutedEventArgs e) 68 | { 69 | Utils.ProcessStart("https://xtls.github.io/config/dns.html#dnsobject"); 70 | } 71 | 72 | private void linkDnsSingboxObjectDoc_Click(object sender, RoutedEventArgs e) 73 | { 74 | Utils.ProcessStart("https://sing-box.sagernet.org/zh/configuration/dns/"); 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Handler/Fmt/FmtHandler.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceLib.Handler.Fmt 2 | { 3 | public class FmtHandler 4 | { 5 | public static string? GetShareUri(ProfileItem item) 6 | { 7 | try 8 | { 9 | var url = item.ConfigType switch 10 | { 11 | EConfigType.VMess => VmessFmt.ToUri(item), 12 | EConfigType.Shadowsocks => ShadowsocksFmt.ToUri(item), 13 | EConfigType.SOCKS => SocksFmt.ToUri(item), 14 | EConfigType.Trojan => TrojanFmt.ToUri(item), 15 | EConfigType.VLESS => VLESSFmt.ToUri(item), 16 | EConfigType.Hysteria2 => Hysteria2Fmt.ToUri(item), 17 | EConfigType.TUIC => TuicFmt.ToUri(item), 18 | EConfigType.WireGuard => WireguardFmt.ToUri(item), 19 | _ => null, 20 | }; 21 | 22 | return url; 23 | } 24 | catch (Exception ex) 25 | { 26 | Logging.SaveLog(ex.Message, ex); 27 | return ""; 28 | } 29 | } 30 | 31 | public static ProfileItem? ResolveConfig(string config, out string msg) 32 | { 33 | msg = ResUI.ConfigurationFormatIncorrect; 34 | 35 | try 36 | { 37 | string str = config.TrimEx(); 38 | if (Utils.IsNullOrEmpty(str)) 39 | { 40 | msg = ResUI.FailedReadConfiguration; 41 | return null; 42 | } 43 | 44 | if (str.StartsWith(Global.ProtocolShares[EConfigType.VMess])) 45 | { 46 | return VmessFmt.Resolve(str, out msg); 47 | } 48 | else if (str.StartsWith(Global.ProtocolShares[EConfigType.Shadowsocks])) 49 | { 50 | return ShadowsocksFmt.Resolve(str, out msg); 51 | } 52 | else if (str.StartsWith(Global.ProtocolShares[EConfigType.SOCKS])) 53 | { 54 | return SocksFmt.Resolve(str, out msg); 55 | } 56 | else if (str.StartsWith(Global.ProtocolShares[EConfigType.Trojan])) 57 | { 58 | return TrojanFmt.Resolve(str, out msg); 59 | } 60 | else if (str.StartsWith(Global.ProtocolShares[EConfigType.VLESS])) 61 | { 62 | return VLESSFmt.Resolve(str, out msg); 63 | } 64 | else if (str.StartsWith(Global.ProtocolShares[EConfigType.Hysteria2]) || str.StartsWith(Global.Hysteria2ProtocolShare)) 65 | { 66 | return Hysteria2Fmt.Resolve(str, out msg); 67 | } 68 | else if (str.StartsWith(Global.ProtocolShares[EConfigType.TUIC])) 69 | { 70 | return TuicFmt.Resolve(str, out msg); 71 | } 72 | else if (str.StartsWith(Global.ProtocolShares[EConfigType.WireGuard])) 73 | { 74 | return WireguardFmt.Resolve(str, out msg); 75 | } 76 | else 77 | { 78 | msg = ResUI.NonvmessOrssProtocol; 79 | return null; 80 | } 81 | } 82 | catch (Exception ex) 83 | { 84 | Logging.SaveLog(ex.Message, ex); 85 | msg = ResUI.Incorrectconfiguration; 86 | return null; 87 | } 88 | } 89 | } 90 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/Handler/PacHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Sockets; 2 | using System.Text; 3 | 4 | namespace ServiceLib.Handler 5 | { 6 | public class PacHandler 7 | { 8 | private static string _configPath; 9 | private static int _httpPort; 10 | private static int _pacPort; 11 | private static TcpListener? _tcpListener; 12 | private static byte[] _writeContent; 13 | private static bool _isRunning; 14 | private static bool _needRestart = true; 15 | 16 | public static async Task Start(string configPath, int httpPort, int pacPort) 17 | { 18 | _needRestart = (configPath != _configPath || httpPort != _httpPort || pacPort != _pacPort || !_isRunning); 19 | 20 | _configPath = configPath; 21 | _httpPort = httpPort; 22 | _pacPort = pacPort; 23 | 24 | await InitText(); 25 | 26 | if (_needRestart) 27 | { 28 | Stop(); 29 | RunListener(); 30 | } 31 | } 32 | 33 | private static async Task InitText() 34 | { 35 | var path = Path.Combine(_configPath, "pac.txt"); 36 | if (!File.Exists(path)) 37 | { 38 | var pac = Utils.GetEmbedText(Global.PacFileName); 39 | await File.AppendAllTextAsync(path, pac); 40 | } 41 | 42 | var pacText = 43 | (await File.ReadAllTextAsync(path)).Replace("__PROXY__", $"PROXY 127.0.0.1:{_httpPort};DIRECT;"); 44 | 45 | var sb = new StringBuilder(); 46 | sb.AppendLine("HTTP/1.0 200 OK"); 47 | sb.AppendLine("Content-type:application/x-ns-proxy-autoconfig"); 48 | sb.AppendLine("Connection:close"); 49 | sb.AppendLine("Content-Length:" + Encoding.UTF8.GetByteCount(pacText)); 50 | sb.AppendLine(); 51 | sb.Append(pacText); 52 | _writeContent = Encoding.UTF8.GetBytes(sb.ToString()); 53 | } 54 | 55 | private static void RunListener() 56 | { 57 | _tcpListener = TcpListener.Create(_pacPort); 58 | _isRunning = true; 59 | _tcpListener.Start(); 60 | Task.Factory.StartNew(async () => 61 | { 62 | while (_isRunning) 63 | { 64 | try 65 | { 66 | if (!_tcpListener.Pending()) 67 | { 68 | await Task.Delay(10); 69 | continue; 70 | } 71 | 72 | var client = await _tcpListener.AcceptTcpClientAsync(); 73 | await Task.Run(() => { WriteContent(client); }); 74 | } 75 | catch 76 | { 77 | // ignored 78 | } 79 | } 80 | }, TaskCreationOptions.LongRunning); 81 | } 82 | 83 | private static void WriteContent(TcpClient client) 84 | { 85 | var stream = client.GetStream(); 86 | stream.Write(_writeContent, 0, _writeContent.Length); 87 | stream.Flush(); 88 | } 89 | 90 | public static void Stop() 91 | { 92 | if (_tcpListener == null) return; 93 | try 94 | { 95 | _isRunning = false; 96 | _tcpListener.Stop(); 97 | _tcpListener = null; 98 | } 99 | catch 100 | { 101 | // ignored 102 | } 103 | } 104 | } 105 | } -------------------------------------------------------------------------------- /v2rayN/ServiceLib/ServiceLib.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 7.4.1 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | ResUI.resx 51 | True 52 | True 53 | 54 | 55 | 56 | 57 | 58 | Designer 59 | PublicResXFileCodeGenerator 60 | 61 | 62 | PublicResXFileCodeGenerator 63 | 64 | 65 | Designer 66 | ResUI.Designer.cs 67 | PublicResXFileCodeGenerator 68 | 69 | 70 | Designer 71 | PublicResXFileCodeGenerator 72 | 73 | 74 | Designer 75 | PublicResXFileCodeGenerator 76 | 77 | 78 | Designer 79 | PublicResXFileCodeGenerator 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI; 2 | using ReactiveUI.Fody.Helpers; 3 | using System.Reactive; 4 | 5 | namespace ServiceLib.ViewModels 6 | { 7 | public class AddServerViewModel : MyReactiveObject 8 | { 9 | [Reactive] 10 | public ProfileItem SelectedSource { get; set; } 11 | 12 | [Reactive] 13 | public string? CoreType { get; set; } 14 | 15 | public ReactiveCommand SaveCmd { get; } 16 | 17 | public AddServerViewModel(ProfileItem profileItem, Func>? updateView) 18 | { 19 | _config = AppHandler.Instance.Config; 20 | _updateView = updateView; 21 | 22 | SaveCmd = ReactiveCommand.CreateFromTask(async () => 23 | { 24 | await SaveServerAsync(); 25 | }); 26 | 27 | if (profileItem.IndexId.IsNullOrEmpty()) 28 | { 29 | profileItem.Network = Global.DefaultNetwork; 30 | profileItem.HeaderType = Global.None; 31 | profileItem.RequestHost = ""; 32 | profileItem.StreamSecurity = ""; 33 | SelectedSource = profileItem; 34 | } 35 | else 36 | { 37 | SelectedSource = JsonUtils.DeepCopy(profileItem); 38 | } 39 | CoreType = SelectedSource?.CoreType?.ToString(); 40 | } 41 | 42 | private async Task SaveServerAsync() 43 | { 44 | if (Utils.IsNullOrEmpty(SelectedSource.Remarks)) 45 | { 46 | NoticeHandler.Instance.Enqueue(ResUI.PleaseFillRemarks); 47 | return; 48 | } 49 | 50 | if (Utils.IsNullOrEmpty(SelectedSource.Address)) 51 | { 52 | NoticeHandler.Instance.Enqueue(ResUI.FillServerAddress); 53 | return; 54 | } 55 | var port = SelectedSource.Port.ToString(); 56 | if (Utils.IsNullOrEmpty(port) || !Utils.IsNumeric(port) 57 | || SelectedSource.Port <= 0 || SelectedSource.Port >= Global.MaxPort) 58 | { 59 | NoticeHandler.Instance.Enqueue(ResUI.FillCorrectServerPort); 60 | return; 61 | } 62 | if (SelectedSource.ConfigType == EConfigType.Shadowsocks) 63 | { 64 | if (Utils.IsNullOrEmpty(SelectedSource.Id)) 65 | { 66 | NoticeHandler.Instance.Enqueue(ResUI.FillPassword); 67 | return; 68 | } 69 | if (Utils.IsNullOrEmpty(SelectedSource.Security)) 70 | { 71 | NoticeHandler.Instance.Enqueue(ResUI.PleaseSelectEncryption); 72 | return; 73 | } 74 | } 75 | if (SelectedSource.ConfigType != EConfigType.SOCKS 76 | && SelectedSource.ConfigType != EConfigType.HTTP) 77 | { 78 | if (Utils.IsNullOrEmpty(SelectedSource.Id)) 79 | { 80 | NoticeHandler.Instance.Enqueue(ResUI.FillUUID); 81 | return; 82 | } 83 | } 84 | SelectedSource.CoreType = CoreType.IsNullOrEmpty() ? null : (ECoreType)Enum.Parse(typeof(ECoreType), CoreType); 85 | 86 | if (await ConfigHandler.AddServer(_config, SelectedSource) == 0) 87 | { 88 | NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess); 89 | _updateView?.Invoke(EViewAction.CloseWindow, null); 90 | } 91 | else 92 | { 93 | NoticeHandler.Instance.Enqueue(ResUI.OperationFailed); 94 | } 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /v2rayN/v2rayN.Desktop/Views/SubSettingWindow.axaml: -------------------------------------------------------------------------------- 1 | 17 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 45 | 46 | 47 | 48 | 49 | 53 | 57 | 61 | 65 | 69 | 73 | 74 | 75 | 76 | 77 | --------------------------------------------------------------------------------