diff --git a/v2rayN/ServiceLib.Tests/CoreConfigV2rayServiceTests.cs b/v2rayN/ServiceLib.Tests/CoreConfigV2rayServiceTests.cs index 52f5d58a..7d9ecdcb 100644 --- a/v2rayN/ServiceLib.Tests/CoreConfigV2rayServiceTests.cs +++ b/v2rayN/ServiceLib.Tests/CoreConfigV2rayServiceTests.cs @@ -75,9 +75,7 @@ public class CoreConfigV2rayServiceTests var service = new CoreConfigV2rayService(CreateContext( node, config, - isTunEnabled: true, - tunProtectSsPort: 10811, - proxyRelaySsPort: 10812)); + isTunEnabled: true)); var result = service.GenerateClientConfigContent(); @@ -91,9 +89,7 @@ public class CoreConfigV2rayServiceTests ProfileItem node, Config? config = null, Dictionary? allProxiesMap = null, - bool isTunEnabled = false, - int tunProtectSsPort = 0, - int proxyRelaySsPort = 0) + bool isTunEnabled = false) { return new CoreConfigContext { @@ -103,8 +99,6 @@ public class CoreConfigV2rayServiceTests AllProxiesMap = allProxiesMap ?? new(), SimpleDnsItem = new SimpleDNSItem(), IsTunEnabled = isTunEnabled, - TunProtectSocksPort = tunProtectSsPort, - ProxyRelaySocksPort = proxyRelaySsPort, }; } diff --git a/v2rayN/ServiceLib/Common/WindowsUtils.cs b/v2rayN/ServiceLib/Common/WindowsUtils.cs index 2215a3e3..d801c343 100644 --- a/v2rayN/ServiceLib/Common/WindowsUtils.cs +++ b/v2rayN/ServiceLib/Common/WindowsUtils.cs @@ -53,19 +53,23 @@ internal static class WindowsUtils public static async Task RemoveTunDevice() { - try + var tunNameList = new List { "singbox_tun", "xray_tun" }; + foreach (var tunName in tunNameList) { - var sum = MD5.HashData(Encoding.UTF8.GetBytes("wintunsingbox_tun")); - var guid = new Guid(sum); - var pnpUtilPath = @"C:\Windows\System32\pnputil.exe"; - var arg = $$""" /remove-device "SWD\Wintun\{{{guid}}}" """; + try + { + var sum = MD5.HashData(Encoding.UTF8.GetBytes($"wintun{tunName}")); + var guid = new Guid(sum); + var pnpUtilPath = @"C:\Windows\System32\pnputil.exe"; + var arg = $$""" /remove-device "SWD\Wintun\{{{guid}}}" """; - // Try to remove the device - _ = await Utils.GetCliWrapOutput(pnpUtilPath, arg); - } - catch (Exception ex) - { - Logging.SaveLog(_tag, ex); + // Try to remove the device + _ = await Utils.GetCliWrapOutput(pnpUtilPath, arg); + } + catch (Exception ex) + { + Logging.SaveLog(_tag, ex); + } } } } diff --git a/v2rayN/ServiceLib/Global.cs b/v2rayN/ServiceLib/Global.cs index d6792115..5df4e1fc 100644 --- a/v2rayN/ServiceLib/Global.cs +++ b/v2rayN/ServiceLib/Global.cs @@ -24,6 +24,8 @@ public class Global public const string V2raySampleHttpResponseFileName = NamespaceSample + "SampleHttpResponse"; public const string V2raySampleInbound = NamespaceSample + "SampleInbound"; public const string V2raySampleOutbound = NamespaceSample + "SampleOutbound"; + public const string V2raySampleTunInbound = NamespaceSample + "SampleTunInbound"; + public const string V2raySampleTunRules = NamespaceSample + "SampleTunRules"; public const string SingboxSampleOutbound = NamespaceSample + "SingboxSampleOutbound"; public const string CustomRoutingFileName = NamespaceSample + "custom_routing_"; public const string TunSingboxDNSFileName = NamespaceSample + "tun_singbox_dns"; @@ -48,6 +50,7 @@ public class Global public const string ProxyTag = "proxy"; public const string DirectTag = "direct"; public const string BlockTag = "block"; + public const string DnsOutboundTag = "dns"; public const string DnsTag = "dns-module"; public const string DirectDnsTag = "direct-dns"; public const string BalancerTagSuffix = "-round"; diff --git a/v2rayN/ServiceLib/Handler/Builder/CoreConfigContextBuilder.cs b/v2rayN/ServiceLib/Handler/Builder/CoreConfigContextBuilder.cs index 5017250e..d0db8bea 100644 --- a/v2rayN/ServiceLib/Handler/Builder/CoreConfigContextBuilder.cs +++ b/v2rayN/ServiceLib/Handler/Builder/CoreConfigContextBuilder.cs @@ -23,19 +23,6 @@ public record CoreConfigContextBuilderAllResult( public NodeValidatorResult CombinedValidatorResult => new( [.. MainResult.ValidatorResult.Errors, .. PreSocksResult?.ValidatorResult.Errors ?? []], [.. MainResult.ValidatorResult.Warnings, .. PreSocksResult?.ValidatorResult.Warnings ?? []]); - - /// - /// The main context with TunProtectSocksPort/ProxyRelaySocksPort and ProtectDomainList merged in - /// from the pre-socks result (if any). Pass this to the core runner. - /// - public CoreConfigContext ResolvedMainContext => PreSocksResult is not null - ? MainResult.Context with - { - TunProtectSocksPort = PreSocksResult.Context.TunProtectSocksPort, - ProxyRelaySocksPort = PreSocksResult.Context.ProxyRelaySocksPort, - ProtectDomainList = [.. MainResult.Context.ProtectDomainList ?? [], .. PreSocksResult.Context.ProtectDomainList ?? []], - } - : MainResult.Context; } public class CoreConfigContextBuilder @@ -58,8 +45,6 @@ public class CoreConfigContextBuilder IsTunEnabled = config.TunModeItem.EnableTun, SimpleDnsItem = config.SimpleDNSItem, ProtectDomainList = [], - TunProtectSocksPort = 0, - ProxyRelaySocksPort = 0, RawDnsItem = await AppManager.Instance.GetDNSItem(coreType), RoutingItem = await ConfigHandler.GetDefaultRouting(config), }; @@ -122,7 +107,20 @@ public class CoreConfigContextBuilder } var preResult = await BuildPreSocksIfNeeded(mainResult.Context); - return new CoreConfigContextBuilderAllResult(mainResult, preResult); + if (preResult is null) + { + return new CoreConfigContextBuilderAllResult(mainResult, null); + } + + var resolvedMainResult = mainResult with + { + Context = mainResult.Context with + { + IsTunEnabled = false, // main core doesn't handle tun directly when pre-socks is used + ProtectDomainList = [.. mainResult.Context.ProtectDomainList, .. preResult.Context.ProtectDomainList], + } + }; + return new CoreConfigContextBuilderAllResult(resolvedMainResult, preResult); } /// @@ -148,32 +146,7 @@ public class CoreConfigContextBuilder }; } - if (!nodeContext.IsTunEnabled - || coreType != ECoreType.Xray - || node.ConfigType == EConfigType.Custom) - { - return null; - } - - var tunProtectSocksPort = Utils.GetFreePort(); - var proxyRelaySocksPort = Utils.GetFreePort(); - var preItem = new ProfileItem() - { - CoreType = ECoreType.sing_box, - ConfigType = EConfigType.SOCKS, - Address = Global.Loopback, - Port = proxyRelaySocksPort, - }; - var preResult2 = await Build(nodeContext.AppConfig, preItem); - return preResult2 with - { - Context = preResult2.Context with - { - ProtectDomainList = [.. nodeContext.ProtectDomainList ?? [], .. preResult2.Context.ProtectDomainList ?? []], - TunProtectSocksPort = tunProtectSocksPort, - ProxyRelaySocksPort = proxyRelaySocksPort, - } - }; + return null; } /// diff --git a/v2rayN/ServiceLib/Handler/ConfigHandler.cs b/v2rayN/ServiceLib/Handler/ConfigHandler.cs index 78229e6c..9fbc5613 100644 --- a/v2rayN/ServiceLib/Handler/ConfigHandler.cs +++ b/v2rayN/ServiceLib/Handler/ConfigHandler.cs @@ -1417,10 +1417,12 @@ public static class ConfigHandler public static ProfileItem? GetPreSocksItem(Config config, ProfileItem node, ECoreType coreType) { ProfileItem? itemSocks = null; + var enableLegacyProtect = config.TunModeItem.EnableLegacyProtect + || Utils.IsNonWindows(); if (node.ConfigType != EConfigType.Custom && coreType != ECoreType.sing_box && config.TunModeItem.EnableTun - && config.TunModeItem.EnableLegacyProtect) + && enableLegacyProtect) { itemSocks = new ProfileItem() { diff --git a/v2rayN/ServiceLib/Models/CoreConfigContext.cs b/v2rayN/ServiceLib/Models/CoreConfigContext.cs index 4aa891e9..8123f19f 100644 --- a/v2rayN/ServiceLib/Models/CoreConfigContext.cs +++ b/v2rayN/ServiceLib/Models/CoreConfigContext.cs @@ -16,10 +16,5 @@ public record CoreConfigContext // TUN Compatibility public bool IsTunEnabled { get; init; } = false; - public HashSet ProtectDomainList { get; init; } = new(); - // -> tun inbound --(if routing proxy)--> relay outbound - // -> proxy core (relay inbound --> proxy outbound --(dialerProxy)--> protect outbound) - // -> protect inbound -> direct proxy outbound data -> internet - public int TunProtectSocksPort { get; init; } = 0; - public int ProxyRelaySocksPort { get; init; } = 0; + public HashSet ProtectDomainList { get; init; } = []; } diff --git a/v2rayN/ServiceLib/Models/V2rayConfig.cs b/v2rayN/ServiceLib/Models/V2rayConfig.cs index 1bde2dc2..b7e70116 100644 --- a/v2rayN/ServiceLib/Models/V2rayConfig.cs +++ b/v2rayN/ServiceLib/Models/V2rayConfig.cs @@ -47,9 +47,9 @@ public class Inbounds4Ray { public string tag { get; set; } - public int port { get; set; } + public int? port { get; set; } - public string listen { get; set; } + public string? listen { get; set; } public string protocol { get; set; } @@ -75,6 +75,18 @@ public class Inboundsettings4Ray public bool? allowTransparent { get; set; } public List? accounts { get; set; } + + public string? name { get; set; } + + public List? MTU { get; set; } + + public List? gateway { get; set; } + + public List? autoSystemRoutingTable { get; set; } + + public string? autoOutboundsInterface { get; set; } + + // public List? dns { get; set; } } public class UsersItem4Ray @@ -511,6 +523,8 @@ public class AccountsItem4Ray public class Sockopt4Ray { public string? dialerProxy { get; set; } + [JsonPropertyName("interface")] + public string? Interface { get; set; } } public class FragmentItem4Ray diff --git a/v2rayN/ServiceLib/Sample/SampleTunInbound b/v2rayN/ServiceLib/Sample/SampleTunInbound new file mode 100644 index 00000000..03467b3e --- /dev/null +++ b/v2rayN/ServiceLib/Sample/SampleTunInbound @@ -0,0 +1,26 @@ +{ + "tag": "tun", + "protocol": "tun", + "settings": { + "name": "xray_tun", + "MTU": [ + 9000 + ], + "gateway": [ + "172.18.0.1/30", + "fdfe:dcba:9876::1/126" + ], + "autoSystemRoutingTable": [ + "0.0.0.0/0", + "::/0" + ], + "autoOutboundsInterface": "auto" + }, + "sniffing": { + "enabled": true, + "destOverride": [ + "http", + "tls" + ] + } +} \ No newline at end of file diff --git a/v2rayN/ServiceLib/Sample/SampleTunRules b/v2rayN/ServiceLib/Sample/SampleTunRules new file mode 100644 index 00000000..ca6eb051 --- /dev/null +++ b/v2rayN/ServiceLib/Sample/SampleTunRules @@ -0,0 +1,14 @@ +[ + { + "network": "udp", + "port": "135,137-139,5353", + "outboundTag": "block" + }, + { + "ip": [ + "224.0.0.0/3", + "ff00::/8" + ], + "outboundTag": "block" + } +] \ No newline at end of file diff --git a/v2rayN/ServiceLib/ServiceLib.csproj b/v2rayN/ServiceLib/ServiceLib.csproj index 8cfbf8ca..169c1080 100644 --- a/v2rayN/ServiceLib/ServiceLib.csproj +++ b/v2rayN/ServiceLib/ServiceLib.csproj @@ -38,6 +38,8 @@ + + diff --git a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/CoreConfigSingboxService.cs b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/CoreConfigSingboxService.cs index f0a4f0ef..fe00861d 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/CoreConfigSingboxService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/CoreConfigSingboxService.cs @@ -63,59 +63,6 @@ public partial class CoreConfigSingboxService(CoreConfigContext context) ret.Success = true; ret.Data = ApplyFullConfigTemplate(); - if (!context.AppConfig.TunModeItem.EnableLegacyProtect - && context.TunProtectSocksPort is > 0 and <= 65535) - { - // Replace relay proxy outbound, avoid mux or other feature cause issue, and add a socks inbound for tun protect - var relayProxyIndex = _coreConfig.outbounds.FindIndex(o => o.tag == Global.ProxyTag); - _coreConfig.outbounds[relayProxyIndex] = new Outbound4Sbox() - { - type = Global.ProtocolTypes[EConfigType.SOCKS], - tag = Global.ProxyTag, - server = Global.Loopback, - server_port = context.ProxyRelaySocksPort, - }; - var ssInbound = new - { - type = "socks", - tag = "tun-protect-socks", - listen = Global.Loopback, - listen_port = context.TunProtectSocksPort, - }; - var directRule = new Rule4Sbox() - { - inbound = new List { ssInbound.tag }, - outbound = Global.DirectTag, - }; - var singboxConfigNode = JsonUtils.ParseJson(ret.Data.ToString())!.AsObject(); - var inboundsNode = singboxConfigNode["inbounds"]!.AsArray(); - inboundsNode.Add(JsonUtils.SerializeToNode(ssInbound, new JsonSerializerOptions - { - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull - })); - var routeNode = singboxConfigNode["route"]?.AsObject(); - var rulesNode = routeNode?["rules"]?.AsArray(); - var protectRuleNode = JsonUtils.SerializeToNode(directRule, - new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }); - if (rulesNode != null) - { - rulesNode.Insert(0, protectRuleNode); - } - else - { - var newRulesNode = new JsonArray() { protectRuleNode }; - if (routeNode is null) - { - var newRouteNode = new JsonObject() { ["rules"] = newRulesNode }; - singboxConfigNode["route"] = newRouteNode; - } - else - { - routeNode["rules"] = newRulesNode; - } - } - ret.Data = JsonUtils.Serialize(singboxConfigNode); - } return ret; } catch (Exception ex) diff --git a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxRoutingService.cs b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxRoutingService.cs index e220aa21..92ee56a2 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxRoutingService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxRoutingService.cs @@ -24,7 +24,7 @@ public partial class CoreConfigSingboxService strategy = directDnsStrategy }; - if (_config.TunModeItem.EnableTun) + if (context.IsTunEnabled) { _coreConfig.route.auto_detect_interface = true; diff --git a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/CoreConfigV2rayService.cs b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/CoreConfigV2rayService.cs index fb8d92a7..d1cf14d7 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/CoreConfigV2rayService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/CoreConfigV2rayService.cs @@ -15,13 +15,6 @@ public partial class CoreConfigV2rayService(CoreConfigContext context) var ret = new RetResult(); try { - if (!context.AppConfig.TunModeItem.EnableLegacyProtect - && context.IsTunEnabled - && context.TunProtectSocksPort is > 0 and <= 65535 - && context.ProxyRelaySocksPort is > 0 and <= 65535) - { - return GenerateClientProxyRelayConfig(); - } if (_node == null || !_node.IsValid()) { @@ -272,139 +265,5 @@ public partial class CoreConfigV2rayService(CoreConfigContext context) } } - public RetResult GenerateClientProxyRelayConfig() - { - var ret = new RetResult(); - try - { - if (_node == null - || !_node.IsValid()) - { - ret.Msg = ResUI.CheckServerSettings; - return ret; - } - - if (_node.GetNetwork() is nameof(ETransport.quic)) - { - ret.Msg = ResUI.Incorrectconfiguration + $" - {_node.GetNetwork()}"; - return ret; - } - - var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient); - if (result.IsNullOrEmpty()) - { - ret.Msg = ResUI.FailedGetDefaultConfiguration; - return ret; - } - - _coreConfig = JsonUtils.Deserialize(result); - if (_coreConfig == null) - { - ret.Msg = ResUI.FailedGenDefaultConfiguration; - return ret; - } - - GenLog(); - _coreConfig.outbounds.Clear(); - GenOutbounds(); - GenStatistic(); - - var protectNode = new ProfileItem() - { - CoreType = ECoreType.Xray, - ConfigType = EConfigType.SOCKS, - Address = Global.Loopback, - Port = context.TunProtectSocksPort, - }; - protectNode.SetProtocolExtra(protectNode.GetProtocolExtra() with - { - SsMethod = Global.None, - }); - - const string protectTag = "tun-protect-socks"; - foreach (var outbound in _coreConfig.outbounds - .Where(o => o.streamSettings?.sockopt?.dialerProxy?.IsNullOrEmpty() ?? true)) - { - outbound.streamSettings ??= new(); - outbound.streamSettings.sockopt ??= new(); - outbound.streamSettings.sockopt.dialerProxy = protectTag; - } - // ech protected - foreach (var outbound in _coreConfig.outbounds - .Where(outbound => outbound.streamSettings?.tlsSettings?.echConfigList?.IsNullOrEmpty() == false)) - { - outbound.streamSettings!.tlsSettings!.echSockopt ??= new(); - outbound.streamSettings.tlsSettings.echSockopt.dialerProxy = protectTag; - } - // xhttp download protected - foreach (var outbound in _coreConfig.outbounds - .Where(o => o.streamSettings?.xhttpSettings?.extra is not null)) - { - var xhttpExtra = JsonUtils.ParseJson(JsonUtils.Serialize(outbound.streamSettings.xhttpSettings!.extra)); - if (xhttpExtra is not JsonObject xhttpExtraObject - || xhttpExtraObject["downloadSettings"] is not JsonObject downloadSettings) - { - continue; - } - // dialerProxy - var sockopt = downloadSettings["sockopt"] as JsonObject ?? new JsonObject(); - sockopt["dialerProxy"] = protectTag; - downloadSettings["sockopt"] = sockopt; - // ech protected - if (downloadSettings["tlsSettings"] is JsonObject tlsSettings - && tlsSettings["echConfigList"] is not null) - { - tlsSettings["echSockopt"] = new JsonObject - { - ["dialerProxy"] = protectTag - }; - } - outbound.streamSettings.xhttpSettings.extra = xhttpExtraObject; - } - _coreConfig.outbounds.Add(new CoreConfigV2rayService(context with - { - Node = protectNode, - }).BuildProxyOutbound(protectTag)); - - _coreConfig.routing.rules ??= []; - var hasBalancer = _coreConfig.routing.balancers is { Count: > 0 }; - _coreConfig.routing.rules.Add(new() - { - inboundTag = ["proxy-relay-socks"], - outboundTag = hasBalancer ? null : Global.ProxyTag, - balancerTag = hasBalancer ? Global.ProxyTag + Global.BalancerTagSuffix : null, - type = "field" - }); - - //_coreConfig.inbounds.Clear(); - - ApplyOutboundSendThrough(); - var configNode = JsonUtils.ParseJson(JsonUtils.Serialize(_coreConfig))!; - configNode["inbounds"]!.AsArray().Add(new - { - listen = Global.Loopback, - port = context.ProxyRelaySocksPort, - protocol = "socks", - settings = new - { - auth = "noauth", - udp = true, - }, - tag = "proxy-relay-socks", - }); - - ret.Msg = string.Format(ResUI.SuccessfulConfiguration, ""); - ret.Success = true; - ret.Data = JsonUtils.Serialize(configNode); - return ret; - } - catch (Exception ex) - { - Logging.SaveLog(_tag, ex); - ret.Msg = ResUI.FailedGenDefaultConfiguration; - return ret; - } - } - #endregion public gen function } diff --git a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayInboundService.cs b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayInboundService.cs index 7ae12c7c..5c52fb13 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayInboundService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayInboundService.cs @@ -7,36 +7,61 @@ public partial class CoreConfigV2rayService try { var listen = "0.0.0.0"; + var listenPort = AppManager.Instance.GetLocalPort(EInboundProtocol.socks); _coreConfig.inbounds = []; - var inbound = BuildInbound(_config.Inbound.First(), EInboundProtocol.socks, true); - _coreConfig.inbounds.Add(inbound); - if (_config.Inbound.First().SecondLocalPortEnabled) + if (!context.IsTunEnabled + || (context.IsTunEnabled && _node.Address != Global.Loopback && _node.Port != listenPort)) { - var inbound2 = BuildInbound(_config.Inbound.First(), EInboundProtocol.socks2, true); - _coreConfig.inbounds.Add(inbound2); - } + _coreConfig.inbounds.Add(inbound); - if (_config.Inbound.First().AllowLANConn) - { - if (_config.Inbound.First().NewPort4LAN) + if (_config.Inbound.First().SecondLocalPortEnabled) { - var inbound3 = BuildInbound(_config.Inbound.First(), EInboundProtocol.socks3, true); - inbound3.listen = listen; - _coreConfig.inbounds.Add(inbound3); + var inbound2 = BuildInbound(_config.Inbound.First(), EInboundProtocol.socks2, true); + _coreConfig.inbounds.Add(inbound2); + } - //auth - if (_config.Inbound.First().User.IsNotEmpty() && _config.Inbound.First().Pass.IsNotEmpty()) + if (_config.Inbound.First().AllowLANConn) + { + if (_config.Inbound.First().NewPort4LAN) { - inbound3.settings.auth = "password"; - inbound3.settings.accounts = new List { new() { user = _config.Inbound.First().User, pass = _config.Inbound.First().Pass } }; + var inbound3 = BuildInbound(_config.Inbound.First(), EInboundProtocol.socks3, true); + inbound3.listen = listen; + _coreConfig.inbounds.Add(inbound3); + + //auth + if (_config.Inbound.First().User.IsNotEmpty() && _config.Inbound.First().Pass.IsNotEmpty()) + { + inbound3.settings.auth = "password"; + inbound3.settings.accounts = new List + { + new() { user = _config.Inbound.First().User, pass = _config.Inbound.First().Pass } + }; + } + } + else + { + inbound.listen = listen; } } - else + } + + if (context.IsTunEnabled) + { + if (_config.TunModeItem.Mtu <= 0) { - inbound.listen = listen; + _config.TunModeItem.Mtu = Global.TunMtus.First(); } + var tunInbound = JsonUtils.Deserialize(EmbedUtils.GetEmbedText(Global.V2raySampleTunInbound)) ?? new Inbounds4Ray { }; + tunInbound.settings.name = Utils.IsMacOS() ? $"utun{new Random().Next(99)}" : "xray_tun"; + tunInbound.settings.MTU = [_config.TunModeItem.Mtu]; + if (_config.TunModeItem.EnableIPv6Address == false) + { + tunInbound.settings.gateway = ["172.18.0.1/30"]; + } + tunInbound.sniffing = inbound.sniffing; + _coreConfig.inbounds.Add(tunInbound); } } catch (Exception ex) diff --git a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs index b04f777f..f5e8cd1e 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs @@ -12,6 +12,10 @@ public partial class CoreConfigV2rayService GenObservatory(multipleLoad); GenBalancer(multipleLoad); } + if (context.IsTunEnabled) + { + _coreConfig.outbounds.Add(BuildDnsOutbound()); + } } private List BuildAllProxyOutbounds(string baseTagName = Global.ProxyTag) @@ -825,4 +829,10 @@ public partial class CoreConfigV2rayService } } } + + private static Outbounds4Ray BuildDnsOutbound() + { + var outbound = new Outbounds4Ray { tag = Global.DnsOutboundTag, protocol = "dns", }; + return outbound; + } } diff --git a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayRoutingService.cs b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayRoutingService.cs index dd752a68..4f7431fc 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayRoutingService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayRoutingService.cs @@ -6,6 +6,31 @@ public partial class CoreConfigV2rayService { try { + if (context.IsTunEnabled) + { + var tunRules = JsonUtils.Deserialize>(EmbedUtils.GetEmbedText(Global.V2raySampleTunRules)); + if (tunRules != null) + { + _coreConfig.routing.rules.AddRange(tunRules); + } + var (lstDnsExe, lstDirectExe) = BuildRoutingDirectExe(); + _coreConfig.routing.rules.Add(new() + { + port = "53", + process = lstDnsExe, + outboundTag = Global.DnsOutboundTag, + }); + _coreConfig.routing.rules.Add(new() + { + process = lstDirectExe, + outboundTag = Global.DirectTag, + }); + _coreConfig.routing.rules.Add(new() + { + port = "53", + outboundTag = Global.DnsOutboundTag, + }); + } if (_coreConfig.routing?.rules != null) { _coreConfig.routing.domainStrategy = _config.RoutingBasicItem.DomainStrategy; @@ -205,4 +230,37 @@ public partial class CoreConfigV2rayService } return finalRule; } + + private static (List lstDnsExe, List lstDirectExe) BuildRoutingDirectExe() + { + var dnsExeSet = new HashSet(StringComparer.OrdinalIgnoreCase); + var directExeSet = new HashSet(StringComparer.OrdinalIgnoreCase); + + var coreInfoResult = CoreInfoManager.Instance.GetCoreInfo(); + + foreach (var coreConfig in coreInfoResult) + { + if (coreConfig.CoreType == ECoreType.v2rayN) + { + continue; + } + + foreach (var baseExeName in coreConfig.CoreExes) + { + if (coreConfig.CoreType != ECoreType.Xray) + { + dnsExeSet.Add(Utils.GetExeName(baseExeName)); + } + directExeSet.Add(Utils.GetExeName(baseExeName)); + } + } + + directExeSet.Add("xray/"); + directExeSet.Add("self/"); + + var lstDnsExe = new List(dnsExeSet); + var lstDirectExe = new List(directExeSet); + + return (lstDnsExe, lstDirectExe); + } } diff --git a/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs b/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs index 36027b79..53ad06c8 100644 --- a/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs @@ -559,7 +559,7 @@ public class MainWindowViewModel : MyReactiveObject await Task.Run(async () => { - await LoadCore(allResult.ResolvedMainContext, allResult.PreSocksResult?.Context); + await LoadCore(allResult.MainResult.Context, allResult.PreSocksResult?.Context); await SysProxyHandler.UpdateSysProxy(_config, false); await Task.Delay(1000); });