我想设置一个 VPN 服务器,以便仅在访问服务器内的资源时使用 VPN 连接。通常,我会使用服务器的内部IP来执行此操作,但我想使用域名来访问该服务器。
有几种方法可以实现这一目标:
使用自定义 DNS 服务器
将另一个IP绑定到该服务器
设置为与“客户端”中
Endpoint
的相同AllowedIPs
(我知道wg不使用服务器-客户端架构,但这样对我来说更容易理解)。例如:# client [Interface] PrivateKey = ... Address = 10.0.0.2/24 [Peer] PublicKey = ... AllowedIPs = 1.2.3.4/32 Endpoint = 1.2.3.4:51820
长话短说,选项 3 最适合我的用例,但它会导致路由表中出现循环。经过一些研究(wireguard 页面中的“改进的基于规则的路由”部分和此解决方案),我了解到FwMark
在“服务器”配置中使用可以解决该问题。
所以我想出了这个:
# server
[Interface]
PrivateKey = ...
ListenPort = 51820
Address = 10.0.0.1/24
FwMark = 51820
PostUp = ip route add default dev wg0 table 2468
PostUp = ip rule add not fwmark 51820 table 2468
PostDown = ip route del default dev wg0 table 2468
PostDown = ip rule del not fwmark 51820 table 2468
[Peer]
...
不用说,这不起作用(VPN 和直接通信都会超时,所以我猜我搞乱了路由规则)我的问题是:
- 为什么这不起作用?
FwMark = 51820
“服务器”配置中的设置是否标记 VPN 路由数据包?或者我需要类似的东西吗PostUp = wg set wg0 fwmark 51820
?- 如果我替换
2468
为default
,main
, 甚至 ,会发生什么local
?我想我不明白为什么官方文档必须为此设置一个新表。
谢谢
编辑:修复端口的拼写错误
介绍
有两个命令:
wg
低级 WireGuard(“WG”)命令,仅影响type wireguard
接口的设置(包括为传出信封流量设置标记),此外wg-quick
还将配置地址、路由,有时还配置路由规则、附加路由表,甚至nftables规则将所有这些联系在一起。这个答案将解释如何使其发挥作用
FwMark = 51820
标记传出信封(不是有效负载)。wg
设置此参数后,将运行适当的命令。Table =
告诉wg-quick
在哪里添加路线。如果未提供,则默认为
Table = auto
. 它的行为就像Table = main
除非还有AllowedIPs = 0.0.0.0/0
(或对于 IPv6)它完全改变了附加路由表、路由规则、标记和nftables(如果未安装nftables则为iptablesAllowedIPs = ::/0
)规则的行为。这种改变的行为使得完整隧道 VPN(而不是分割 VPN)配置能够正常工作。我稍后举个例子。如果
Table = off
那么就wg-quick
根本不会碰路线。这一切都必须由管理员处理(可能还有PreUp/PostUp
规则)。其他有用的情况是选择一个任意表,稍后将通过自定义路由规则重用该表。
Table = 2468
该答案将在客户端上使用。wg-quick
会将路由添加到此路由表而不是main
路由表中。另一种选择可能是使用Table = off
并添加任何相关的路由条目PostUp
。路由
local
表应该保持不变。它由内核填充,并处理与系统上为发往该系统的传入流量(包括广播)分配的地址相关的本地路由。路由
default
表几乎从未使用过,并且在标准设置中为空。它可能在某些路由守护程序中使用。只有当路由表中没有默认路由时,其中的条目才有意义main
,否则该路由表将永远没有机会在默认路由规则到位的情况下到达(main
一旦找到默认路由就会停止该路由)抬头)。下面的设置假设客户端正在运行 Linux,安装了nftables并且其主接口(将被命名为
eth0
)或实际上其所有接口都启用了严格反向路径转发(“SRPF”)(sysctlnet.conf.ipv4.all.rp_filter=1
)。下面的nftables规则(包括客户端段落的极端情况)仅用于充分标记信封传入流量,以便被视为使用正确的路由并成功通过 SRPF 检查。如果没有启用此类设置或至少将主界面 (eth0
) 设置为Loose RPF ( ),则可以忽略net.conf.ipv4.eth0.rp_filter=2
整个nftables部分。那么就不再重要了传入数据包使用了错误的路径:它们被接收并将由路由堆栈使用而不是被丢弃。因此,下面涉及nftables 的任何部分都将假设这在客户端上已就位:已经处理了一种情况,
wg-quick
这也说明了rp_filter=1
必须将有效负载地址与信封地址区分开来,信封地址是使用默认路由的远程地址:当使用默认设置Table = auto
和时AllowedIPs = 0.0.0.0/0
,这在客户端部署中很常见。然后针对这种情况wg-quick
使用防火墙标记和附加nftables规则。它会看起来像这样:工作组为传出流量设置的防火墙标记允许在路由规则中区分(传出)信封流量和(传出)有效负载流量。
nftables部分用于处理信封的回复/传入流量:
按时间顺序,第一,它在postrouting挂钩中将conntrack流更新为 WG 为传出信封流量设置的标记。
然后,在预路由钩子中,从保存的conntrack流条目中检索该标记,以标记传入回复信封流量
早期的预路由钩子(
preraw
)是为了防止接收非WG流量到WG接口上设置的地址(不是为了路由,而是为了安全,下面不再保留)这些nftables规则最终允许将传入的信封流量视为路由规则中的信封流量。所有
src_valid_mark=1
这些努力都是为了让流量不会失败 SRPF。因为
wg-quick
的 bash 代码仅针对Table = auto
+触发它AllowedIPs = 0.0.0.0/0
,所以必须在客户端上手动调整和完成(这也是OP 链接的 Q/A 答案末尾评论的过滤规则部分:除非您设置了一些在您的客户端上使用奇特的数据包路由/过滤规则,而不是使用 WireGuard 客户端为您设置的默认值)。*
客户端和服务器上的配置
/etc/wireguard/wg0.nft
将从以下位置加载客户端wg0.conf
:客户的
/etc/wireguard/wg0.conf
(参考之前的文件):假设下面客户端主接口上的当前 IP 地址
eth0
是(NAT-ed...)192.168.1.2/24,网关为 192.168.1.1,以下是各种路由决策的结果:服务器设置要简单得多,因为它自己的端点是已知配置,并且 WG 内客户端的有效负载地址是 Internet 上不可路由的地址,不会与客户端的信封地址冲突。服务器上不涉及nftables 。
服务器的
/etc/wireguard/wg0.conf
:如果该服务器的主接口
eth0
地址为 1.2.3.4/24,网关为 1.2.3.1/24,远程 WG 对等方(客户端)在到达服务器时发现为 192.0.2.2:45678,则各种路由情况都很简单,是:没有添加地址
wg0
以防止常见的 UDP 多宿主并发症。如果添加了此地址,则到达 10.0.0.2 的源地址将被选择为 10.0.0.1,从而触发通过隧道应答的多宿主不感知 UDP 服务的问题:UDP 回复对 1.2.3.4 发出的查询将使用10.0.0.1 作为源,将被客户端应用程序拒绝(甚至在此之前,由于不允许使用 10.0.0.1,因此被其 WG 接口删除)。我在这些问答中做出了回答的其他详细信息:永远不会遇到 UDP 多宿主问题的最佳方法是实际上不处于多宿主情况并且不在 上添加 IP 地址
wg0
。当源地址选择算法无法从 中选择地址时,它将选择“主”IP 地址wg0
。如果服务器已经是多宿主的并且以某种方式选择了错误的源地址,那么可以通过wg-quick
服务器上的此附加条目来修复添加的路由wg0.conf
:这将提示地址选择算法使用 1.2.3.4 作为源来到达 10.0.0.2。这也可以允许设置 10.0.0.1,
wg0
即使它不会被使用,并更改整个 /24 的这种路由,然后在多个对等点的情况下,例如使用此而不是上面的:此路由更改不会保留或遵循影响实际 1.2.3.4 的某些内容(例如:主界面在管理上设置关闭然后打开)。实际上,只需在 上“再次”添加 1.2.3.4 即可
wg0
。例如,而不是上面的(确保它是 /32,这样它就不会触发创建任何导致网络中断的其他路由):这是针对作为端节点的服务器。如果它充当路由器和路由流量(例如:容器或虚拟机)而不是自己生成流量,则不存在 UDP 多宿主问题,但处理此路由器情况的设置很可能会丢失。
客户的极端情况
rp_filter=1
如果客户端上未使用 SRPF ( ),则与所有其他nftables设置一样,不需要应用以下修复。当绕过 WG 到达服务器时,客户端上存在一些极端情况,并且有足够的应用程序可以使用
setsockopt(sockfd, SOL_SOCKET, SO_MARK, ...)
跟踪路由(--udp)
需要通过实际的 Internet跟踪服务器的路由以找出发生了什么网络中断?
在显示目标之前,这仍然会超时,因为预期返回流量不是 UDP,而是相关的 ICMP 错误:未设置标记并被 SRPF 拒绝。可以通过添加标记相关流量的规则来修复:
ping、其他跟踪路由、socat 与 TCP...
还系统地标记和检索 conntrack 流的标记,而不仅仅是 UDP:
这使得上面的 3 个命令有效,而不是超时。