From 0d452328a20638d3554163816dc3d226d32cad79 Mon Sep 17 00:00:00 2001 From: DHR60 <192860629+DHR60@users.noreply.github.com> Date: Fri, 28 Aug 2026 06:38:43 +0000 Subject: [PATCH] Add wireguard remote dns support (#10036) --- .../ServiceLib.Tests/Fmt/WireguardFmtTests.cs | 2 ++ v2rayN/ServiceLib/Handler/ConfigHandler.cs | 1 + v2rayN/ServiceLib/Handler/Fmt/WireguardFmt.cs | 7 +++++++ .../Models/CoreConfigs/V2rayConfig.cs | 2 ++ .../Models/Entities/ProtocolExtraItem.cs | 1 + v2rayN/ServiceLib/Resx/ResUI.Designer.cs | 9 +++++++++ v2rayN/ServiceLib/Resx/ResUI.resx | 3 +++ v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx | 3 +++ .../CoreConfig/V2ray/V2rayOutboundService.cs | 3 ++- .../ViewModels/AddServerViewModel.cs | 5 +++++ .../Views/AddServerWindow.axaml | 19 ++++++++++++++++-- .../Views/AddServerWindow.axaml.cs | 1 + v2rayN/v2rayN/Views/AddServerWindow.xaml | 20 ++++++++++++++++++- v2rayN/v2rayN/Views/AddServerWindow.xaml.cs | 1 + 14 files changed, 73 insertions(+), 4 deletions(-) diff --git a/v2rayN/ServiceLib.Tests/Fmt/WireguardFmtTests.cs b/v2rayN/ServiceLib.Tests/Fmt/WireguardFmtTests.cs index 8f156b47..3096b9db 100644 --- a/v2rayN/ServiceLib.Tests/Fmt/WireguardFmtTests.cs +++ b/v2rayN/ServiceLib.Tests/Fmt/WireguardFmtTests.cs @@ -11,6 +11,7 @@ public class WireguardFmtTests PrivateKey = interface-private-key Address = 10.0.0.2/32, fd00::2/128 ; inline comment MTU = 1420 + DNS = 2001::db8::53, 1.2.3.4, 2001:db8::54 [Peer] PublicKey = peer-public-key @@ -35,6 +36,7 @@ public class WireguardFmtTests await first.GetProtocolExtra().WgReserved.Should().BeEqualTo("1, 2, 3"); await first.GetProtocolExtra().WgInterfaceAddress.Should().BeEqualTo("10.0.0.2/32, fd00::2/128"); await first.GetProtocolExtra().WgMtu.Should().BeEqualTo(1420); + await first.GetProtocolExtra().WgDns.Should().BeEqualTo("2001::db8::53, 1.2.3.4, 2001:db8::54"); var second = resolved[1]; await second.Address.Should().BeEqualTo("example.com"); diff --git a/v2rayN/ServiceLib/Handler/ConfigHandler.cs b/v2rayN/ServiceLib/Handler/ConfigHandler.cs index 39dc1e2a..ddce2c16 100644 --- a/v2rayN/ServiceLib/Handler/ConfigHandler.cs +++ b/v2rayN/ServiceLib/Handler/ConfigHandler.cs @@ -922,6 +922,7 @@ public static class ConfigHandler WgInterfaceAddress = profileItem.GetProtocolExtra().WgInterfaceAddress?.TrimEx(), WgReserved = wgReserved, WgMtu = profileItem.GetProtocolExtra().WgMtu is null or <= 0 ? Global.TunMtus.First() : profileItem.GetProtocolExtra().WgMtu, + WgDns = profileItem.GetProtocolExtra().WgDns?.TrimEx(), }); if (profileItem.Password.IsNullOrEmpty()) diff --git a/v2rayN/ServiceLib/Handler/Fmt/WireguardFmt.cs b/v2rayN/ServiceLib/Handler/Fmt/WireguardFmt.cs index b0de1068..431869c8 100644 --- a/v2rayN/ServiceLib/Handler/Fmt/WireguardFmt.cs +++ b/v2rayN/ServiceLib/Handler/Fmt/WireguardFmt.cs @@ -31,6 +31,7 @@ public class WireguardFmt : BaseFmt WgReserved = GetQueryDecoded(query, "reserved"), WgInterfaceAddress = GetQueryDecoded(query, "address"), WgMtu = int.TryParse(GetQueryDecoded(query, "mtu"), out var mtuVal) ? mtuVal : null, + WgDns = GetQueryDecoded(query, "dns"), }); return item; @@ -71,6 +72,10 @@ public class WireguardFmt : BaseFmt { dicQuery.Add("mtu", protoExtra.WgMtu.ToString()); } + if (!protoExtra.WgDns.IsNullOrEmpty()) + { + dicQuery.Add("dns", Utils.UrlEncode(protoExtra.WgDns)); + } return ToUri(EConfigType.WireGuard, item.Address, item.Port, item.Password, dicQuery, remark); } @@ -133,6 +138,7 @@ public class WireguardFmt : BaseFmt var wgMtu = interfaceDic.TryGetValue("MTU", out var mtuStr) && int.TryParse(mtuStr, out var mtuVal) ? mtuVal : 0; var wgInterfaceAddress = interfaceDic.TryGetValue("Address", out var interfaceAddress) ? interfaceAddress : string.Empty; + var wgDns = interfaceDic.TryGetValue("DNS", out var dns) ? dns : string.Empty; var index = 0; var resultList = new List(); @@ -156,6 +162,7 @@ public class WireguardFmt : BaseFmt WgInterfaceAddress = wgInterfaceAddress, WgReserved = (peerDic.TryGetValue("Reserved", out var reserved) ? reserved : string.Empty).NullIfEmpty(), WgMtu = wgMtu > 0 ? wgMtu : null, + WgDns = wgDns, }; var item = new ProfileItem diff --git a/v2rayN/ServiceLib/Models/CoreConfigs/V2rayConfig.cs b/v2rayN/ServiceLib/Models/CoreConfigs/V2rayConfig.cs index cfa6f9d1..b8b3844d 100644 --- a/v2rayN/ServiceLib/Models/CoreConfigs/V2rayConfig.cs +++ b/v2rayN/ServiceLib/Models/CoreConfigs/V2rayConfig.cs @@ -172,6 +172,8 @@ public class Outboundsettings4Ray public int? workers { get; set; } public int? version { get; set; } + + public List? remoteDNS { get; set; } } public class WireguardPeer4Ray diff --git a/v2rayN/ServiceLib/Models/Entities/ProtocolExtraItem.cs b/v2rayN/ServiceLib/Models/Entities/ProtocolExtraItem.cs index 54e4479c..eb3297b3 100644 --- a/v2rayN/ServiceLib/Models/Entities/ProtocolExtraItem.cs +++ b/v2rayN/ServiceLib/Models/Entities/ProtocolExtraItem.cs @@ -27,6 +27,7 @@ public record ProtocolExtraItem public string? WgInterfaceAddress { get; init; } public string? WgReserved { get; init; } public int? WgMtu { get; init; } + public string? WgDns { get; init; } // hysteria2 public string? SalamanderPass { get; init; } diff --git a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs index 3b654b11..f7ceb75a 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs +++ b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs @@ -3015,6 +3015,15 @@ namespace ServiceLib.Resx { } } + /// + /// 查找类似 DNS 的本地化字符串。 + /// + public static string TbDNS { + get { + return ResourceManager.GetString("TbDNS", resourceCulture); + } + } + /// /// 查找类似 DNS Hosts: ("domain1 ip1 ip2" per line) 的本地化字符串。 /// diff --git a/v2rayN/ServiceLib/Resx/ResUI.resx b/v2rayN/ServiceLib/Resx/ResUI.resx index 0412b2ce..a92c9bc4 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.resx @@ -1869,4 +1869,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if Block IPv6 queries when enabled + + DNS + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx index 5a372476..da3f5770 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx @@ -1870,4 +1870,7 @@ 开启后将阻止 IPv6 查询 + + DNS + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs index 8209f28b..e02137e9 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs @@ -297,7 +297,8 @@ public partial class CoreConfigV2rayService secretKey = _node.Password, reserved = Utils.String2List(protocolExtra.WgReserved)?.Select(s => s.Trim()).Select(int.Parse).ToList(), mtu = protocolExtra.WgMtu > 0 ? protocolExtra.WgMtu : Global.TunMtus.First(), - peers = [peer] + remoteDNS = Utils.String2List(protocolExtra.WgDns)?.Select(s => s.Trim()).ToList(), + peers = [peer], }; outbound.settings = setting; outbound.settings.vnext = null; diff --git a/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs b/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs index 3f01261d..b8ef98c1 100644 --- a/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs @@ -70,6 +70,9 @@ public partial class AddServerViewModel : MyReactiveObject, ICloseable [Reactive] public partial int WgMtu { get; set; } + [Reactive] + public partial string WgDns { get; set; } + [Reactive] public partial bool Uot { get; set; } @@ -310,6 +313,7 @@ public partial class AddServerViewModel : MyReactiveObject, ICloseable WgInterfaceAddress = protocolExtra.WgInterfaceAddress ?? string.Empty; WgReserved = protocolExtra.WgReserved ?? string.Empty; WgMtu = protocolExtra.WgMtu ?? 1280; + WgDns = protocolExtra.WgDns ?? string.Empty; Uot = protocolExtra.Uot ?? false; CongestionControl = protocolExtra.CongestionControl ?? string.Empty; InsecureConcurrency = protocolExtra.InsecureConcurrency > 0 ? protocolExtra.InsecureConcurrency : null; @@ -431,6 +435,7 @@ public partial class AddServerViewModel : MyReactiveObject, ICloseable WgInterfaceAddress = WgInterfaceAddress.NullIfEmpty(), WgReserved = WgReserved.NullIfEmpty(), WgMtu = WgMtu >= 576 ? WgMtu : null, + WgDns = WgDns.NullIfEmpty(), Uot = Uot ? true : null, CongestionControl = CongestionControl.NullIfEmpty(), InsecureConcurrency = InsecureConcurrency > 0 ? InsecureConcurrency : null, diff --git a/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml b/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml index 04a305b3..fc25b577 100644 --- a/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml +++ b/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml @@ -580,7 +580,7 @@ Grid.Row="2" ColumnDefinitions="300,Auto" IsVisible="False" - RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto"> + RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto"> + PlaceholderText="Ipv4, Ipv6" /> + + + this.Bind(ViewModel, vm => vm.WgReserved, v => v.txtPath9.Text).DisposeWith(currentTypeDisposables); this.Bind(ViewModel, vm => vm.WgInterfaceAddress, v => v.txtRequestHost9.Text).DisposeWith(currentTypeDisposables); this.Bind(ViewModel, vm => vm.WgMtu, v => v.txtShortId9.Text).DisposeWith(currentTypeDisposables); + this.Bind(ViewModel, vm => vm.WgDns, v => v.txtDns.Text).DisposeWith(currentTypeDisposables); break; case EConfigType.Anytls: diff --git a/v2rayN/v2rayN/Views/AddServerWindow.xaml b/v2rayN/v2rayN/Views/AddServerWindow.xaml index a8c03128..02071984 100644 --- a/v2rayN/v2rayN/Views/AddServerWindow.xaml +++ b/v2rayN/v2rayN/Views/AddServerWindow.xaml @@ -748,6 +748,7 @@ + @@ -830,7 +831,7 @@ Grid.Column="1" Width="400" Margin="{StaticResource Margin4}" - materialDesign:HintAssist.Hint="Ipv4,Ipv6" + materialDesign:HintAssist.Hint="Ipv4, Ipv6" Style="{StaticResource DefTextBox}" /> + + + vm.WgReserved, v => v.txtPath9.Text).DisposeWith(currentTypeDisposables); this.Bind(ViewModel, vm => vm.WgInterfaceAddress, v => v.txtRequestHost9.Text).DisposeWith(currentTypeDisposables); this.Bind(ViewModel, vm => vm.WgMtu, v => v.txtShortId9.Text).DisposeWith(currentTypeDisposables); + this.Bind(ViewModel, vm => vm.WgDns, v => v.txtDns.Text).DisposeWith(currentTypeDisposables); break; case EConfigType.Anytls: