diff --git a/v2rayN/ServiceLib/Global.cs b/v2rayN/ServiceLib/Global.cs index cb651ac6..103c993c 100644 --- a/v2rayN/ServiceLib/Global.cs +++ b/v2rayN/ServiceLib/Global.cs @@ -557,7 +557,6 @@ public class Global "http", "tls", "quic", - "fakedns", ]; public static readonly List TunMtus = @@ -737,6 +736,12 @@ public class Global "reply", ]; + public static readonly List FakeIPRanges = + [ + "198.18.0.0/15", + "11.0.0.0/8", + ]; + public static readonly List RootCertProviders = [ "system", diff --git a/v2rayN/ServiceLib/Handler/ConfigHandler.cs b/v2rayN/ServiceLib/Handler/ConfigHandler.cs index 572d3e7d..eeece698 100644 --- a/v2rayN/ServiceLib/Handler/ConfigHandler.cs +++ b/v2rayN/ServiceLib/Handler/ConfigHandler.cs @@ -115,6 +115,7 @@ public static class ConfigHandler config.ConstItem ??= new ConstItem(); config.SimpleDNSItem ??= InitBuiltinSimpleDNS(); + config.SimpleDNSItem.FakeIPRange ??= Global.FakeIPRanges.FirstOrDefault(); config.SimpleDNSItem.GlobalFakeIp ??= true; config.SimpleDNSItem.BootstrapDNS ??= Global.DomainPureIPDNSAddress.FirstOrDefault(); config.SimpleDNSItem.ServeStale ??= false; diff --git a/v2rayN/ServiceLib/Models/Configs/ConfigItems.cs b/v2rayN/ServiceLib/Models/Configs/ConfigItems.cs index 4d44f5c3..c1e1619e 100644 --- a/v2rayN/ServiceLib/Models/Configs/ConfigItems.cs +++ b/v2rayN/ServiceLib/Models/Configs/ConfigItems.cs @@ -274,6 +274,7 @@ public class SimpleDNSItem public bool? AddCommonHosts { get; set; } public bool? FakeIP { get; set; } public bool? GlobalFakeIp { get; set; } + public string? FakeIPRange { get; set; } public bool? BlockBindingQuery { get; set; } public string? DirectDNS { get; set; } public string? RemoteDNS { get; set; } diff --git a/v2rayN/ServiceLib/Models/CoreConfigs/V2rayConfig.cs b/v2rayN/ServiceLib/Models/CoreConfigs/V2rayConfig.cs index dd2d6855..ae415ac9 100644 --- a/v2rayN/ServiceLib/Models/CoreConfigs/V2rayConfig.cs +++ b/v2rayN/ServiceLib/Models/CoreConfigs/V2rayConfig.cs @@ -4,6 +4,7 @@ public class V2rayConfig { public Log4Ray log { get; set; } public object dns { get; set; } + public FakeDns4Ray? fakedns { get; set; } public List inbounds { get; set; } public List outbounds { get; set; } public Routing4Ray routing { get; set; } @@ -43,6 +44,12 @@ public class Log4Ray public string? loglevel { get; set; } } +public class FakeDns4Ray +{ + public string? ipPool { get; set; } + public long? poolSize { get; set; } +} + public class Inbounds4Ray { public string tag { get; set; } diff --git a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs index 28f4d92e..3cf47d8a 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs +++ b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs @@ -3106,7 +3106,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Applies globally by default, with built-in FakeIP filtering (sing-box only). 的本地化字符串。 + /// 查找类似 Applies globally by default, and built-in FakeIP filtering is only built into sing-box. 的本地化字符串。 /// public static string TbFakeIPTips { get { diff --git a/v2rayN/ServiceLib/Resx/ResUI.fa.resx b/v2rayN/ServiceLib/Resx/ResUI.fa.resx index 6c55b7de..7bdc75b4 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.fa.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.fa.resx @@ -1495,7 +1495,7 @@ Select Profile - Applies globally by default, with built-in FakeIP filtering (sing-box only). + Applies globally by default, and built-in FakeIP filtering is only built into sing-box. Please Add At Least One Configuration diff --git a/v2rayN/ServiceLib/Resx/ResUI.fr.resx b/v2rayN/ServiceLib/Resx/ResUI.fr.resx index cfee0bd9..9688fbd4 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.fr.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.fr.resx @@ -1492,7 +1492,7 @@ Choisir une config. - Actif globalement par défaut, avec filtre FakeIP intégré ; ne fonctionne que dans sing-box + Applies globally by default, and built-in FakeIP filtering is only built into sing-box. Veuillez ajouter au moins une configuration diff --git a/v2rayN/ServiceLib/Resx/ResUI.hu.resx b/v2rayN/ServiceLib/Resx/ResUI.hu.resx index 756e8e32..3adc061f 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.hu.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.hu.resx @@ -1495,7 +1495,7 @@ Select Profile - Applies globally by default, with built-in FakeIP filtering (sing-box only). + Applies globally by default, and built-in FakeIP filtering is only built into sing-box. Please Add At Least One Configuration diff --git a/v2rayN/ServiceLib/Resx/ResUI.id.resx b/v2rayN/ServiceLib/Resx/ResUI.id.resx index 73c26704..7fc105cf 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.id.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.id.resx @@ -1495,7 +1495,7 @@ Pilih profil - Berlaku secara global secara default, dengan filter FakeIP bawaan (hanya sing-box). + Applies globally by default, and built-in FakeIP filtering is only built into sing-box. Silakan tambahkan setidaknya satu konfigurasi. diff --git a/v2rayN/ServiceLib/Resx/ResUI.resx b/v2rayN/ServiceLib/Resx/ResUI.resx index 544f9a9f..24b92359 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.resx @@ -1501,7 +1501,7 @@ Select Profile - Applies globally by default, with built-in FakeIP filtering (sing-box only). + Applies globally by default, and built-in FakeIP filtering is only built into sing-box. Please Add At Least One Configuration diff --git a/v2rayN/ServiceLib/Resx/ResUI.ru.resx b/v2rayN/ServiceLib/Resx/ResUI.ru.resx index dec7cc50..b8876133 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.ru.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.ru.resx @@ -1501,7 +1501,7 @@ Выбрать профиль - По умолчанию применяется глобально, со встроенной фильтрацией FakeIP (только sing-box). + Applies globally by default, and built-in FakeIP filtering is only built into sing-box. Добавьте хотя бы одну конфигурацию diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx index 0ef0e4ce..a767d784 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx @@ -1498,7 +1498,7 @@ 选择配置 - 默认全局生效,内置 FakeIP 过滤,仅在 sing-box 中生效 + 默认全局生效,仅在 sing-box 中内置 FakeIP 过滤。 请至少添加一个配置 diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx index 08b1ac63..8a81f7ee 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx @@ -1498,7 +1498,7 @@ 選擇節點 - 默認全域生效,內置 FakeIP 過濾,僅在 sing-box 中生效 + 默認全局生效,僅在 sing-box 中內置 FakeIP 過濾。 請至少添加一個節點 @@ -1827,4 +1827,4 @@ 僅適用於 v2rayN GUI 的下載與網路請求,不影響核心的憑證驗證 - + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxDnsService.cs b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxDnsService.cs index 4e813c63..547061d6 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxDnsService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxDnsService.cs @@ -137,12 +137,12 @@ public partial class CoreConfigSingboxService // fake ip if (simpleDnsItem.FakeIP == true) { + var fakeipRange = simpleDnsItem.FakeIPRange.IsNullOrEmpty() ? Global.FakeIPRanges.First() : simpleDnsItem.FakeIPRange; var fakeip = new Server4Sbox { tag = Global.SingboxFakeDNSTag, type = "fakeip", - inet4_range = "198.18.0.0/15", - inet6_range = "fc00::/18", + inet4_range = fakeipRange, }; _coreConfig.dns.servers.Add(fakeip); } @@ -266,7 +266,7 @@ public partial class CoreConfigSingboxService }); } - if (simpleDnsItem.FakeIP == true && simpleDnsItem.GlobalFakeIp == true) + if (simpleDnsItem.FakeIP == true && simpleDnsItem.GlobalFakeIp != false) { var fakeipFilterRule = JsonUtils.Deserialize(EmbedUtils.GetEmbedText(Global.SingboxFakeIPFilterFileName)); fakeipFilterRule.invert = true; diff --git a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayDnsService.cs b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayDnsService.cs index 1cae354b..cb61aa69 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayDnsService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayDnsService.cs @@ -28,7 +28,7 @@ public partial class CoreConfigV2rayService _coreConfig.routing.rules.Add(new RulesItem4Ray { type = "field", - inboundTag = new List { Global.DnsTag }, + inboundTag = [Global.DnsTag], outboundTag = Global.ProxyTag, }); return; @@ -120,6 +120,33 @@ public partial class CoreConfigV2rayService } } + private void GenFakeDns() + { + var fakeipRange = _config.SimpleDNSItem.FakeIPRange.IsNullOrEmpty() ? Global.FakeIPRanges.First() : _config.SimpleDNSItem.FakeIPRange; + var poolSize = 65535L; + try + { + var fakeipNetwork = IPNetwork2.Parse(fakeipRange); + var totalIPs = fakeipNetwork.Total; + // see https://github.com/XTLS/Xray-core/blob/6e3322d219140a025285ded1114fe17a5edb74d8/app/dns/fakedns/fake.go#L88 + // if math.Log2(float64(lruSize)) >= float64(rooms) { return errors.New("LRU size is bigger than subnet size").AtError() } + totalIPs -= 1; + if (totalIPs > 0) + { + poolSize = (totalIPs >= long.MaxValue) ? long.MaxValue : (long)totalIPs; + } + } + catch + { + // Ignore + } + _coreConfig.fakedns = new() + { + ipPool = fakeipRange, + poolSize = poolSize, + }; + } + private void FillDnsServers(Dns4Ray dnsItem) { var simpleDNSItem = context.SimpleDnsItem; @@ -246,6 +273,23 @@ public partial class CoreConfigV2rayService var directDnsTagIndex = 1; + if (simpleDNSItem.FakeIP == true) + { + var fakeIPMatchDomain = new HashSet(proxyDomainList); + fakeIPMatchDomain.UnionWith(proxyGeositeList); + if (simpleDNSItem.GlobalFakeIp != false) + { + fakeIPMatchDomain.UnionWith(directDomainList); + fakeIPMatchDomain.UnionWith(directGeositeList); + fakeIPMatchDomain.UnionWith(expectedDomainList); + } + if (fakeIPMatchDomain.Count > 0) + { + GenFakeDns(); + AddDnsServers(["fakedns"], fakeIPMatchDomain.ToList()); + } + } + AddDnsServers(remoteDNSAddress, proxyDomainList); AddDnsServers(directDNSAddress, directDomainList, true); AddDnsServers(remoteDNSAddress, proxyGeositeList); diff --git a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayInboundService.cs b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayInboundService.cs index d9b677d9..4041f0fd 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayInboundService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayInboundService.cs @@ -152,6 +152,16 @@ public partial class CoreConfigV2rayService inbound.sniffing.destOverride = inItem.DestOverride; inbound.sniffing.routeOnly = inItem.RouteOnly; + if (_config.SimpleDNSItem.FakeIP == true) + { + // Ensure destOverride contains "fakedns" if FakeIP is enabled + inbound.sniffing.destOverride ??= []; + if (!inbound.sniffing.destOverride.Contains("fakedns")) + { + inbound.sniffing.destOverride.Add("fakedns"); + } + } + return inbound; } } diff --git a/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs b/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs index 6f7f9f98..562e50cf 100644 --- a/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs @@ -7,6 +7,7 @@ public class DNSSettingViewModel : MyReactiveObject, ICloseable [Reactive] public bool UseSystemHosts { get; set; } [Reactive] public bool AddCommonHosts { get; set; } [Reactive] public bool FakeIP { get; set; } + [Reactive] public string FakeIPRange { get; set; } [Reactive] public bool BlockBindingQuery { get; set; } [Reactive] public string DirectDNS { get; set; } [Reactive] public string RemoteDNS { get; set; } @@ -72,6 +73,7 @@ public class DNSSettingViewModel : MyReactiveObject, ICloseable UseSystemHosts = item.UseSystemHosts ?? false; AddCommonHosts = item.AddCommonHosts ?? false; FakeIP = item.FakeIP ?? false; + FakeIPRange = item.FakeIPRange ?? string.Empty; BlockBindingQuery = item.BlockBindingQuery ?? false; DirectDNS = item.DirectDNS ?? string.Empty; RemoteDNS = item.RemoteDNS ?? string.Empty; @@ -105,6 +107,7 @@ public class DNSSettingViewModel : MyReactiveObject, ICloseable _config.SimpleDNSItem.UseSystemHosts = UseSystemHosts; _config.SimpleDNSItem.AddCommonHosts = AddCommonHosts; _config.SimpleDNSItem.FakeIP = FakeIP; + _config.SimpleDNSItem.FakeIPRange = FakeIPRange; _config.SimpleDNSItem.BlockBindingQuery = BlockBindingQuery; _config.SimpleDNSItem.DirectDNS = DirectDNS; _config.SimpleDNSItem.RemoteDNS = RemoteDNS; diff --git a/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml b/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml index 11fba165..ebd8f6ac 100644 --- a/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml +++ b/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml @@ -286,13 +286,24 @@ Margin="{StaticResource Margin4}" VerticalAlignment="Center" Text="{x:Static resx:ResUI.TbFakeIP}" /> - + ColumnDefinitions="Auto,*"> + + + cmbDirectDNS.ItemsSource = Global.DomainDirectDNSAddress; cmbRemoteDNS.ItemsSource = Global.DomainRemoteDNSAddress; cmbBootstrapDNS.ItemsSource = Global.DomainPureIPDNSAddress; + cmbFakeIPRange.ItemsSource = Global.FakeIPRanges; cmbDirectExpectedIPs.ItemsSource = Global.ExpectedIPs; cmbdomainStrategy4FreedomCompatible.ItemsSource = Global.DomainStrategy; @@ -32,6 +33,7 @@ public partial class DNSSettingWindow : WindowBase this.Bind(ViewModel, vm => vm.UseSystemHosts, v => v.togUseSystemHosts.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.AddCommonHosts, v => v.togAddCommonHosts.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.FakeIP, v => v.togFakeIP.IsChecked).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.FakeIPRange, v => v.cmbFakeIPRange.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.BlockBindingQuery, v => v.togBlockBindingQuery.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.DirectDNS, v => v.cmbDirectDNS.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.RemoteDNS, v => v.cmbRemoteDNS.Text).DisposeWith(disposables); diff --git a/v2rayN/v2rayN/Views/DNSSettingWindow.xaml b/v2rayN/v2rayN/Views/DNSSettingWindow.xaml index 716a00f6..57775c1f 100644 --- a/v2rayN/v2rayN/Views/DNSSettingWindow.xaml +++ b/v2rayN/v2rayN/Views/DNSSettingWindow.xaml @@ -331,12 +331,25 @@ VerticalAlignment="Center" Style="{StaticResource ToolbarTextBlock}" Text="{x:Static resx:ResUI.TbFakeIP}" /> - + + + + + + + + + vm.UseSystemHosts, v => v.togUseSystemHosts.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.AddCommonHosts, v => v.togAddCommonHosts.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.FakeIP, v => v.togFakeIP.IsChecked).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.FakeIPRange, v => v.cmbFakeIPRange.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.BlockBindingQuery, v => v.togBlockBindingQuery.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.DirectDNS, v => v.cmbDirectDNS.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.RemoteDNS, v => v.cmbRemoteDNS.Text).DisposeWith(disposables);