← Home

[f44] kvm qemu vm 直通宿主机的 tailscale exit-node

05 Sep, 2026 10:17 PM +08:00

全文由 Gemini 3.8 Flash 生成。

将虚拟机流量通过宿主机的 Tailscale Exit-Node 导出,最稳定、免维护的方案是在宿主机侧完成所有转发与 MSS 钳制。这样无论新建多少台虚拟机,虚拟机内部无需安装 Tailscale,也不需要每次手动修改 MTU。

核心架构

第一步:宿主机内核与系统参数(永久生效)

在宿主机上创建 sysctl 配置文件,放行数据转发并防止路由非对称丢包:

sudo tee /etc/sysctl.d/99-tailscale-kvm.conf << 'EOF'
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
net.ipv4.conf.all.rp_filter = 2
net.ipv4.conf.default.rp_filter = 2
EOF

# 立即应用配置
sudo sysctl --system

第二步:宿主机防火墙策略(firewalld)

在宿主机配置 firewalld,完成网卡分配、NAT 伪装、跨区域放行和 MTU 钳制:

# 1. 将 tailscale0 划入 trusted 区域并开启 NAT 伪装
sudo firewall-cmd --permanent --zone=trusted --add-interface=tailscale0
sudo firewall-cmd --permanent --zone=trusted --add-masquerade

# 2. 建立转发策略:允许 libvirt 网桥 (virbr0) 流量流向 trusted 区域 (tailscale0)
sudo firewall-cmd --permanent --new-policy=libvirt-to-tailscale
sudo firewall-cmd --permanent --policy=libvirt-to-tailscale --add-ingress-zone=libvirt
sudo firewall-cmd --permanent --policy=libvirt-to-tailscale --add-egress-zone=trusted
sudo firewall-cmd --permanent --policy=libvirt-to-tailscale --set-target=ACCEPT

# 3. 核心:开启 TCP MSS 钳制,自动将数据包限制在 Tailscale 的 1280 MTU 内(防止 TLS 握手卡死)
sudo firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

# 4. 重载防火墙
sudo firewall-cmd --reload

第三步:宿主机 Tailscale 启动参数

宿主机连接 Exit-Node 时,必须带上 --exit-node-allow-lan-access=true,否则 Tailscale 会阻断一切局域网/网桥的转发流量:

# 将 <EXIT_NODE_NAME_OR_IP> 替换为你的目标出口节点(例如 mdev)
sudo tailscale up --exit-node=<EXIT_NODE_NAME_OR_IP> --exit-node-allow-lan-access=true --accept-routes=true

如果更倾向于直接固定虚拟机的 MTU,Fedora 虚拟机通过 NetworkManager 管理网络:

在虚拟机执行:

# 查看当前活跃连接名(通常如 'Wired connection 1' 或网卡名)
nmcli connection show --active

# 将其 MTU 设为 1280 并重新连接(替换 "Wired connection 1" 为实际名字)
sudo nmcli connection modify "Wired connection 1" 802-3-ethernet.mtu 1280
sudo nmcli connection up "Wired connection 1"

验证:运行 ip link show,确认虚拟机重启或重连后网卡 MTU 依然保持为 1280。

第四步:虚拟机内配置(只需处理 DNS)

得益于宿主机开启了 MSS 钳制,虚拟机网卡保持默认的 1500 MTU 即可正常通信。但由于宿主机启用了全局出口节点,虚拟机的默认 DNS 可能无法解析,建议将虚拟机 DNS 改为公共 DNS:

Bash

# 在虚拟机内执行:配置为公共 DNS(以实际网卡名 enp1s0 为准)
sudo resolvectl dns $(ip -o -4 route show to default | awk '{print $5}') 1.1.1.1 8.8.8.8

# 验证网络与外网出口
curl -I https://www.google.com
curl -s https://ifconfig.me   # 应显示 Exit-Node 的公网 IP

快速排错清单