![是否可以使用 UFW 从连接到 ZeroTier VPN 并位于 LAN 上的机器转发到 LAN 上的另一台机器?](https://linux22.com/image/785545/%E6%98%AF%E5%90%A6%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%20UFW%20%E4%BB%8E%E8%BF%9E%E6%8E%A5%E5%88%B0%20ZeroTier%20VPN%20%E5%B9%B6%E4%BD%8D%E4%BA%8E%20LAN%20%E4%B8%8A%E7%9A%84%E6%9C%BA%E5%99%A8%E8%BD%AC%E5%8F%91%E5%88%B0%20LAN%20%E4%B8%8A%E7%9A%84%E5%8F%A6%E4%B8%80%E5%8F%B0%E6%9C%BA%E5%99%A8%EF%BC%9F.png)
我正在尝试使连接到我的 VPN 的任何机器都能够访问我服务器上的容器内的服务。
为此,我使用 PROXMOX 设置了一个服务器并订阅了一个免费的 ZeroTier VPN 帐户。
目前,我的 PROXMOX 机器上运行着一组 LXC 容器,还有一个连接到 VPN 的 VM。选择 VM 而不是容器是因为 VM 可以访问 TUN 设备,而非特权容器则不能。
总体思路如下:
(Some Machine running ZeroTier) -> (ZeroTier VPN) -> (Linux VM running ZeroTier) -> (Container)
当然,(运行 Zero Tier 的某台机器)和(运行 ZeroTier 的 Linux VM)都在同一个 ZeroTier 网络上。
我想要的是能够交换 UDP 和 TCP 流量。
到目前为止,我已经完成的是运行一个 netcat 实例,在(运行 ZeroTier 的 Linux VM)上监听 UDP,并让(运行 Zero Tier 的某台机器)通过 ZeroTier vpn 连接并交换消息,或者通过 VPN 连接到 Linux 机器上的 SSH。
我无法完成的是让(运行零层的某台机器)使用 UFW 配置连接到(容器)上的服务。
这些是(运行 ZeroTier 的 Linux VM 上的接口):
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 96:a8:af:d9:7f:99 brd ff:ff:ff:ff:ff:ff
altname enp0s18
inet 192.168.1.104/24 brd 192.168.1.255 scope global ens18
valid_lft forever preferred_lft forever
inet6 fe80::94a8:afff:fed9:7f99/64 scope link
valid_lft forever preferred_lft forever
3: ztyouvjg5f: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 2800 qdisc fq_codel state UNKNOWN group default qlen 1000
link/ether 96:47:56:a9:29:3a brd ff:ff:ff:ff:ff:ff
inet 10.xx.xx.163/24 brd 10.xx.xx.255 scope global ztyouvjg5f
valid_lft forever preferred_lft forever
inet6 fexx::xxxx:xxxx:xxxx:xxd7/64 scope link
valid_lft forever preferred_lft forever
其中 ens18 是我的虚拟机与 LAN 通信的接口,ztyouvjg5f 是虚拟机连接到 ZeroTier 网络的接口。
同时,UFW 配置为允许以下连接通过:
Status: active
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
9993/udp ALLOW Anywhere
27960/udp ALLOW Anywhere
22/tcp (v6) ALLOW Anywhere (v6)
9993/udp (v6) ALLOW Anywhere (v6)
27960/udp (v6) ALLOW Anywhere (v6)
192.168.1.103 27960/udp ALLOW FWD Anywhere on ztyouvjg5f
现在,为了更清楚一点,我使用 22/tcp 通过 ssh 连接到虚拟机。端口 9993/udp 是 ZeroTier VPN 端口。端口 27960/udp 是我的服务的端口。地址 192.168.1.103 是我 LAN 上容器的 IP 地址,该容器上有一个监听端口 27960/udp 的服务。
这里的目的是允许从 VPN 到 192.168.1.103:27960 的端口 27960/udp 上的任何内容。
为了在我的系统上启用端口转发,我修改了虚拟机上的以下文件:
/etc/default/ufw
在 FORWARD POLICY 上设置 ACCEPT:
DEFAULT_FORWARD_POLICY="ACCEPT"
并且
/etc/ufw/sysctl.conf
取消注释以下几行:
net/ipv4/ip_forward=1
net/ipv6/conf/default/forwarding=1
net/ipv6/conf/all/forwarding=1
最后,里面:
/etc/ufw/before.rules
我添加了以下规则(我仅手动插入了*nat 块):
#
# rules.before
#
# Rules that should be run before the ufw command line added rules. Custom
# rules should be added to one of these chains:
# ufw-before-input
# ufw-before-output
# ufw-before-forward
#
# PORT FORWARDING
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -i ens18 -p udp --dport 27960 -j DNAT --to-destination 192.168.1.103
-A POSTROUTING -s 192.168.1.0/24 -o ens18 -j MASQUERADE
# don't delete the 'COMMIT' line or these nat table rules won't be processed
COMMIT
# Don't delete these required lines, otherwise there will be errors
*filter
:ufw-before-input - [0:0]
:ufw-before-output - [0:0]
:ufw-before-forward - [0:0]
:ufw-not-local - [0:0]
# End required lines
# allow all on loopback
-A ufw-before-input -i lo -j ACCEPT
-A ufw-before-output -o lo -j ACCEPT
# quickly process packets for which we already have a connection
-A ufw-before-input -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-output -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-forward -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# drop INVALID packets (logs these in loglevel medium and higher)
-A ufw-before-input -m conntrack --ctstate INVALID -j ufw-logging-deny
-A ufw-before-input -m conntrack --ctstate INVALID -j DROP
# ok icmp codes for INPUT
-A ufw-before-input -p icmp --icmp-type destination-unreachable -j ACCEPT
-A ufw-before-input -p icmp --icmp-type time-exceeded -j ACCEPT
-A ufw-before-input -p icmp --icmp-type parameter-problem -j ACCEPT
-A ufw-before-input -p icmp --icmp-type echo-request -j ACCEPT
# ok icmp code for FORWARD
-A ufw-before-forward -p icmp --icmp-type destination-unreachable -j ACCEPT
-A ufw-before-forward -p icmp --icmp-type time-exceeded -j ACCEPT
-A ufw-before-forward -p icmp --icmp-type parameter-problem -j ACCEPT
-A ufw-before-forward -p icmp --icmp-type echo-request -j ACCEPT
# allow dhcp client to work
-A ufw-before-input -p udp --sport 67 --dport 68 -j ACCEPT
#
# ufw-not-local
#
-A ufw-before-input -j ufw-not-local
# if LOCAL, RETURN
-A ufw-not-local -m addrtype --dst-type LOCAL -j RETURN
# if MULTICAST, RETURN
-A ufw-not-local -m addrtype --dst-type MULTICAST -j RETURN
# if BROADCAST, RETURN
-A ufw-not-local -m addrtype --dst-type BROADCAST -j RETURN
# all other non-local packets are dropped
-A ufw-not-local -m limit --limit 3/min --limit-burst 10 -j ufw-logging-deny
-A ufw-not-local -j DROP
# allow MULTICAST mDNS for service discovery (be sure the MULTICAST line above
# is uncommented)
-A ufw-before-input -p udp -d 224.0.0.251 --dport 5353 -j ACCEPT
# allow MULTICAST UPnP for service discovery (be sure the MULTICAST line above
# is uncommented)
-A ufw-before-input -p udp -d 239.255.255.250 --dport 1900 -j ACCEPT
# don't delete the 'COMMIT' line or these rules won't be processed
COMMIT
通过此配置,端口 27960 上的 UDP 流量应转发到监听端口 27960 的(容器)。容器没有安装 ufw,但 PROXMOX 防火墙配置为让 27960 上的 udp 流量通过。
我可以从我的局域网内连接到容器。但是,如果我尝试通过 VPN 连接到容器,流量却无法到达容器。
我是否遗漏了什么?
谢谢。
答案1
因此,经过两天的努力,我终于解决了我的问题。
不知何故,即使我记得编辑过,我的 Linux VM 上也没有启用 IP 转发/etc/sysctl.conf
。启用后,我能够在 LAN 上转发流量,但仍然无法通过 VPN 发送流量。
我从 ZeroTier 文档中获得的最大技巧是配置托管路由并设置 iptable 规则。
首先,我添加了管理路线(这不是我的图片,是我从 github 帖子中取的):
之后我编辑/etc/sysctl.conf
并取消了评论net.ipv4.ip_forward
然后我添加了这些 iptable 规则:
sudo iptables -t nat -A POSTROUTING -o $PHY_IFACE -j MASQUERADE
sudo iptables -A FORWARD -i $PHY_IFACE -o $ZT_IFACE -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i $ZT_IFACE -o $PHY_IFACE -j ACCEPT
最后我还是坚持了规则:
sudo apt install iptables-persistent
sudo bash -c iptables-save > /etc/iptables/rules.v4
这是文档的链接:
我把这些信息带到这里以防它被删除。