![如何从 Mulvad VPN 的“本地网络共享”阻止中排除 libvirt 使用的 dnsmasq](https://linux22.com/image/227175/%E5%A6%82%E4%BD%95%E4%BB%8E%20Mulvad%20VPN%20%E7%9A%84%E2%80%9C%E6%9C%AC%E5%9C%B0%E7%BD%91%E7%BB%9C%E5%85%B1%E4%BA%AB%E2%80%9D%E9%98%BB%E6%AD%A2%E4%B8%AD%E6%8E%92%E9%99%A4%20libvirt%20%E4%BD%BF%E7%94%A8%E7%9A%84%20dnsmasq.png)
我不使用本地网络,除了 libvirt 的 dnsmasq 之外。由于本地网络被阻止,我的虚拟机上没有 DNS。因此,我想使用本指南将 dnsmasq 从具有分割隧道的本地网络共享块中排除:https://mullvad.net/en/help/split-tunneling-with-linux-advanced
。
据我了解,在我的情况下,dnsmasq 不解析我的主机的 DNS,而仅解析特定 NIC(虚拟机一)的 DNS。有关 libvirt dnsmasq 的信息https://www.whonix.org/wiki/KVM#DHCP
我想禁用本地网络共享以获得最大的安全性,但允许 dnsmasq 使用 Mulvad 指南中的 netfilter 规则,而不打开本地网络上其他计算机/路由器的端口。
我需要工作的唯一本地连接是 dnsmasq
Proto Recv-Q Send-Q Local Address Foreign Address State Program name
tcp 0 0 192.168.122.1:53 0.0.0.0:* LISTEN dnsmasq
也许我也需要这些连接才能工作
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
udp UNCONN 0 0 192.168.122.1:53 0.0.0.0:* users:(("dnsmasq",pid=1695,fd=5))
udp UNCONN 0 0 0.0.0.0%virbr0:67 0.0.0.0:* users:(("dnsmasq",pid=1695,fd=3))
我nft list ruleset
使用 VPN + Killswitch + 本地网络共享(关闭):
$ sudo /usr/sbin/nft list ruleset
table inet filter {
chain input {
type filter hook input priority filter; policy accept;
}
chain forward {
type filter hook forward priority filter; policy accept;
}
chain output {
type filter hook output priority filter; policy accept;
}
}
# Warning: table ip filter is managed by iptables-nft, do not touch!
table ip filter {
chain LIBVIRT_INP {
iifname "virbr0" udp dport 53 counter packets 0 bytes 0 accept
iifname "virbr0" tcp dport 53 counter packets 0 bytes 0 accept
iifname "virbr0" udp dport 67 counter packets 0 bytes 0 accept
iifname "virbr0" tcp dport 67 counter packets 0 bytes 0 accept
}
chain INPUT {
type filter hook input priority filter; policy accept;
counter packets 60942 bytes 62002672 jump LIBVIRT_INP
}
chain LIBVIRT_OUT {
oifname "virbr0" udp dport 53 counter packets 0 bytes 0 accept
oifname "virbr0" tcp dport 53 counter packets 0 bytes 0 accept
oifname "virbr0" udp dport 68 counter packets 0 bytes 0 accept
oifname "virbr0" tcp dport 68 counter packets 0 bytes 0 accept
}
chain OUTPUT {
type filter hook output priority filter; policy accept;
counter packets 50614 bytes 29575202 jump LIBVIRT_OUT
}
chain LIBVIRT_FWO {
iifname "virbr0" ip saddr 192.168.122.0/24 counter packets 0 bytes 0 accept
iifname "virbr0" counter packets 0 bytes 0 reject
}
chain FORWARD {
type filter hook forward priority filter; policy accept;
counter packets 0 bytes 0 jump LIBVIRT_FWX
counter packets 0 bytes 0 jump LIBVIRT_FWI
counter packets 0 bytes 0 jump LIBVIRT_FWO
}
chain LIBVIRT_FWI {
oifname "virbr0" ip daddr 192.168.122.0/24 ct state related,established counter packets 0 bytes 0 accept
oifname "virbr0" counter packets 0 bytes 0 reject
}
chain LIBVIRT_FWX {
iifname "virbr0" oifname "virbr0" counter packets 0 bytes 0 accept
}
}
# Warning: table ip nat is managed by iptables-nft, do not touch!
table ip nat {
chain LIBVIRT_PRT {
ip saddr 192.168.122.0/24 ip daddr 224.0.0.0/24 counter packets 1 bytes 40 return
ip saddr 192.168.122.0/24 ip daddr 255.255.255.255 counter packets 0 bytes 0 return
meta l4proto tcp ip saddr 192.168.122.0/24 ip daddr != 192.168.122.0/24 counter packets 0 bytes 0 masquerade to :1024-65535
meta l4proto udp ip saddr 192.168.122.0/24 ip daddr != 192.168.122.0/24 counter packets 1 bytes 635 masquerade to :1024-65535
ip saddr 192.168.122.0/24 ip daddr != 192.168.122.0/24 counter packets 0 bytes 0 masquerade
}
chain POSTROUTING {
type nat hook postrouting priority srcnat; policy accept;
counter packets 396 bytes 23131 jump LIBVIRT_PRT
}
}
# Warning: table ip mangle is managed by iptables-nft, do not touch!
table ip mangle {
chain LIBVIRT_PRT {
oifname "virbr0" udp dport 68 counter packets 0 bytes 0 xt target CHECKSUM
}
chain POSTROUTING {
type filter hook postrouting priority mangle; policy accept;
counter packets 50620 bytes 29575670 jump LIBVIRT_PRT
}
}
table ip6 filter {
chain LIBVIRT_INP {
}
chain INPUT {
type filter hook input priority filter; policy accept;
counter packets 4 bytes 256 jump LIBVIRT_INP
}
chain LIBVIRT_OUT {
}
chain OUTPUT {
type filter hook output priority filter; policy accept;
counter packets 18 bytes 1064 jump LIBVIRT_OUT
}
chain LIBVIRT_FWO {
}
chain FORWARD {
type filter hook forward priority filter; policy accept;
counter packets 0 bytes 0 jump LIBVIRT_FWX
counter packets 0 bytes 0 jump LIBVIRT_FWI
counter packets 0 bytes 0 jump LIBVIRT_FWO
}
chain LIBVIRT_FWI {
}
chain LIBVIRT_FWX {
}
}
table ip6 nat {
chain LIBVIRT_PRT {
}
chain POSTROUTING {
type nat hook postrouting priority srcnat; policy accept;
counter packets 2 bytes 136 jump LIBVIRT_PRT
}
}
table ip6 mangle {
chain LIBVIRT_PRT {
}
chain POSTROUTING {
type filter hook postrouting priority mangle; policy accept;
counter packets 18 bytes 1064 jump LIBVIRT_PRT
}
}
table inet mullvad {
chain prerouting {
type filter hook prerouting priority -199; policy accept;
iif != "wg-mullvad" ct mark 0x00000f41 meta mark set 0x6d6f6c65
ip saddr 138.199.15.146 udp sport 57632 meta mark set 0x6d6f6c65
}
chain output {
type filter hook output priority filter; policy drop;
oif "lo" accept
ct mark 0x00000f41 accept
udp sport 68 ip daddr 255.255.255.255 udp dport 67 accept
ip6 saddr fe80::/10 udp sport 546 ip6 daddr ff02::1:2 udp dport 547 accept
ip6 saddr fe80::/10 udp sport 546 ip6 daddr ff05::1:3 udp dport 547 accept
ip6 daddr ff02::2 icmpv6 type nd-router-solicit icmpv6 code no-route accept
ip6 daddr ff02::1:ff00:0/104 icmpv6 type nd-neighbor-solicit icmpv6 code no-route accept
ip6 daddr fe80::/10 icmpv6 type nd-neighbor-solicit icmpv6 code no-route accept
ip6 daddr fe80::/10 icmpv6 type nd-neighbor-advert icmpv6 code no-route accept
ip daddr 138.199.15.146 udp dport 57632 meta mark 0x6d6f6c65 accept
oif "wg-mullvad" udp dport 53 ip daddr 10.64.0.1 accept
oif "wg-mullvad" tcp dport 53 ip daddr 10.64.0.1 accept
udp dport 53 reject
tcp dport 53 reject with tcp reset
oif "wg-mullvad" accept
reject
}
chain input {
type filter hook input priority filter; policy drop;
iif "lo" accept
ct mark 0x00000f41 accept
udp sport 67 udp dport 68 accept
ip6 saddr fe80::/10 udp sport 547 ip6 daddr fe80::/10 udp dport 546 accept
ip6 saddr fe80::/10 icmpv6 type nd-router-advert icmpv6 code no-route accept
ip6 saddr fe80::/10 icmpv6 type nd-redirect icmpv6 code no-route accept
ip6 saddr fe80::/10 icmpv6 type nd-neighbor-solicit icmpv6 code no-route accept
icmpv6 type nd-neighbor-advert icmpv6 code no-route accept
ip saddr 138.199.15.146 udp sport 57632 ct state established accept
iif "wg-mullvad" accept
}
chain forward {
type filter hook forward priority filter; policy drop;
udp sport 68 ip daddr 255.255.255.255 udp dport 67 accept
udp sport 67 udp dport 68 accept
ip6 saddr fe80::/10 udp sport 546 ip6 daddr ff02::1:2 udp dport 547 accept
ip6 saddr fe80::/10 udp sport 546 ip6 daddr ff05::1:3 udp dport 547 accept
ip6 saddr fe80::/10 udp sport 547 ip6 daddr fe80::/10 udp dport 546 accept
ip6 daddr ff02::2 icmpv6 type nd-router-solicit icmpv6 code no-route accept
ip6 saddr fe80::/10 icmpv6 type nd-router-advert icmpv6 code no-route accept
ip6 saddr fe80::/10 icmpv6 type nd-redirect icmpv6 code no-route accept
ip6 daddr ff02::1:ff00:0/104 icmpv6 type nd-neighbor-solicit icmpv6 code no-route accept
ip6 daddr fe80::/10 icmpv6 type nd-neighbor-solicit icmpv6 code no-route accept
ip6 saddr fe80::/10 icmpv6 type nd-neighbor-solicit icmpv6 code no-route accept
ip6 daddr fe80::/10 icmpv6 type nd-neighbor-advert icmpv6 code no-route accept
icmpv6 type nd-neighbor-advert icmpv6 code no-route accept
oif "wg-mullvad" udp dport 53 ip daddr 10.64.0.1 accept
oif "wg-mullvad" tcp dport 53 ip daddr 10.64.0.1 accept
udp dport 53 reject
tcp dport 53 reject with tcp reset
oif "wg-mullvad" accept
iif "wg-mullvad" ct state established accept
reject
}
chain mangle {
type route hook output priority mangle; policy accept;
oif "wg-mullvad" udp dport 53 ip daddr 10.64.0.1 accept
oif "wg-mullvad" tcp dport 53 ip daddr 10.64.0.1 accept
meta cgroup 5087041 ct mark set 0x00000f41 meta mark set 0x6d6f6c65
}
chain nat {
type nat hook postrouting priority srcnat; policy accept;
oif "wg-mullvad" ct mark 0x00000f41 drop
oif != "lo" ct mark 0x00000f41 masquerade
}
}
我的 dnsmasq conf 由 libvirtd 管理。请参阅下面的conf
##WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
##OVERWRITTEN AND LOST. Changes to this configuration should be made using:
## virsh net-edit default
## or other application using the libvirt API.
##
## dnsmasq conf file created by libvirt
strict-order
pid-file=/run/libvirt/network/default.pid
except-interface=lo
bind-dynamic
interface=virbr0
dhcp-range=192.168.122.2,192.168.122.254,255.255.255.0
dhcp-no-override
dhcp-authoritative
dhcp-lease-max=253
dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
答案1
下面提到的链应该包含在一个单独的表中,例如:
table inet allowedLocal {
...
}
这取决于您希望允许的具体流量。如果您希望仅允许来自虚拟机的 DNS 请求(以及来自主机的回复),那么您应该使用如下链:
chain input {
type filter hook input priority mangle; policy accept;
ip saddr 192.168.122.0/24 meta l4proto { tcp, udp } th dport 53 ct mark set 0x00000f41
}
设置了 (conntrack mark)后ct mark
,您不需要任何hook output
来自主机的回复链,因为它们将属于相应请求的相同“连接”,因此会ct mark
自动获得相同的连接。priority mangle
将确保ct mark
在流量进入chain input
(table inet mullvad
所在位置ct mark 0x00000f41 accept
)之前设置。
与我所知道/记得的相反,您似乎不需要设置正确的meta mark
(fwmark
)来根据需要路由回复,至少不需要从主机本身到“本地”网络的回复。 (令人惊讶的是,实际行为似乎是特定于应用程序的。当我使用 systemd-resolved 存根额外侦听器进行测试时,回复会从请求发出的接口中发出,即使我消除了任何路由,包括但不限于前缀路由,当我使用 dnsmasq 进行测试时,回复始终按照路由main
表进行路由,而忽略所有 ip 规则/备用表。)
如果您想允许所有“连接”由VM发起那是(L3-)目的地为主机,您可以删除meta l4proto { tcp, udp } th dport 53
:
chain input {
type filter hook input priority mangle; policy accept;
ip saddr 192.168.122.0/24 ct mark set 0x00000f41
}
请注意,上述链不会建立“连接”由主机发起那是(L3-) 发往 VM允许。如果你想允许这样的“连接”,你需要这样:
chain output {
type route hook output priority filter; policy accept;
ip daddr 192.168.122.0/24 ct mark set 0xf41 meta mark set 0x6d6f6c65
}
附带说明一下,ct mark
该链中的设置主要是为了允许来自虚拟机的回复。真正让来自主机的发起流量被允许的是oif "wg-mullvad" accept
中chain output
的规则table inet mullvad
。流量似乎是type route
在稍后阶段遍历链的,因此即使在做出新的路由决策之前(因为meta mark
),也必须允许原始路由。换句话说,我想如果一个人想要(进一步)过滤已被一条type route
链“更改”的流量,他们将不得不使用另一条type route
链(而不是一条type filter
链)。(如果你不关心细节,可以忽略这一段。无论如何,这些信息可能并不完全正确。)
编辑:我只是注意到,chain prerouting
实际上table inet mullvad
设置了ct mark
所有iif != "wg-mullvad"
流量所需的流量,这意味着您不需要我上面给出的任何链来仅允许 DNS 为虚拟机工作。您可以尝试它们,看看它们是否有帮助,但现在我觉得问题可能是由于dnsmasq
某种原因没有10.64.0.1
用作其上游服务器,正如我最初怀疑的那样......