如何从 Mulvad VPN 的“本地网络共享”阻止中排除 libvirt 使用的 dnsmasq

如何从 Mulvad VPN 的“本地网络共享”阻止中排除 libvirt 使用的 dnsmasq

我不使用本地网络,除了 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 inputtable inet mullvad所在位置ct mark 0x00000f41 accept)之前设置。

与我所知道/记得的相反,您似乎不需要设置正确的meta markfwmark)来根据需要路由回复,至少不需要从主机本身到“本地”网络的回复。 (令人惊讶的是,实际行为似乎是特定于应用程序的。当我使用 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" acceptchain 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用作其上游服务器,正如我最初怀疑的那样......

相关内容