对于表示抱歉,但我认为这应该在这里…
我创建了一个 veth 对,该对的一端位于网络命名空间中。我将地址 10.1.2.50/24 分配给命名空间内的对端,将地址 10.1.2.1/24 分配给根命名空间内的对端。我设置了一个 iptables 规则来伪装来自与 veth 对关联的子网的流量:
sudo iptables -t nat -A POSTROUTING -s 10.1.2.0/24 ! -o my-veth -j MASQUERADE
这听起来合理吗?我可以伪装通过 veth 对的流量而不创建桥接吗?
在命名空间外部,我可以 ping 10.1.2.50;在命名空间内部,我可以 ping 10.1.2.1 和主机的公共 IP。但在命名空间内部,我无法 ping 互联网上的公共 IP(它会一直挂起,等待响应)。我该如何调试?
我的设置如下。我像这样创建了配对:
ip link add my-veth type veth peer name my-ceth
我将该对的一端放在命名空间中:
ip link set my-ceth netns my-ns
我在命名空间内部和外部分配了 IP 地址:
ip addr add 10.1.2.1/24 dev my-veth
nsenter --net=/run/netns/my-ns ip addr add 10.1.2.50/24 dev my-ceth
我调出了命名空间内部和外部的设备:
ip link set my-veth up
nsenter --net=/run/netns/my-ns ip link set my-ceth up
我在命名空间内设置了默认路由:
nsenter --net=/run/netns/my-ns ip route add default via 10.1.2.1
我在命名空间外创建了一个 iptables 规则,以对来自命名空间的流量进行 NAT:
iptables -t nat -A POSTROUTING -s 10.1.2.0/24 ! -o my-veth -j MASQUERADE
我的ip addr
样子是这样的:
133: my-veth@if132: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether f6:b9:cb:fe:44:4a brd ff:ff:ff:ff:ff:ff link-netns my-ns
inet 10.1.2.1/24 scope global my-veth
valid_lft forever preferred_lft forever
inet6 fe80::f4b9:cbff:fefe:444a/64 scope link
valid_lft forever preferred_lft forever
在命名空间内:
132: my-ceth@if133: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether e2:c6:18:68:c8:14 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.1.2.50/24 scope global my-ceth
valid_lft forever preferred_lft forever
我的ip route
样子是这样的:
default via 192.168.88.1 dev wlo1 proto dhcp metric 600
10.1.2.0/24 dev my-veth proto kernel scope link src 10.1.2.1
在命名空间内:
default via 10.1.2.1 dev my-ceth
10.1.2.0/24 dev my-ceth proto kernel scope link src 10.1.2.50
我的iptables -t nat --list-rules
命名空间外部如下所示:
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N DOCKER
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 10.1.2.0/24 ! -o my-veth -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
但我无法从命名空间内部 ping 通公共 IP:
$ sudo ip netns exec my-ns ping 93.184.215.14
PING 93.184.215.14 (93.184.215.14) 56(84) bytes of data.
任何帮助都非常感谢!
1
最佳答案
1
这一切看起来都大体正确。我已将您的步骤浓缩为以下脚本,其中我做了一些不会对操作产生影响的更改:
- 我已将您使用的 替换
nsenter
为更简单的替代方法,即ip -n <namespace>
在适当的地方,或ip netns exec
。 netns
我使用选项将“创建 veth 对”步骤和“将对的一端添加到网络命名空间”步骤合并为一个步骤ip link add
。- 我
LOG
在规则之前添加了一条规则MASQUERADE
只是为了在内核日志中看到匹配的流量。
#!/bin/bash
set -e
# make sure we haven't already run this script
if ip netns exec my-ns true > /dev/null 2>&1; then
echo "ERROR: namespace already exists" >&2
exit 1
fi
ip netns add my-ns
ip link add my-veth type veth peer name my-ceth netns my-ns
ip addr add 10.1.2.1/24 dev my-veth
ip link set my-veth up
ip -n my-ns addr add 10.1.2.50/24 dev my-ceth
ip -n my-ns link set my-ceth up
ip -n my-ns route add default via 10.1.2.1
iptables -t nat -A POSTROUTING -s 10.1.2.0/24 -j LOG
iptables -t nat -A POSTROUTING -s 10.1.2.0/24 ! -o my-veth -j MASQUERADE
运行此脚本后,我可以从网络命名空间 ping 外部地址:
# ip netns exec my-ns ping -c1 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=58 time=16.9 ms
--- 8.8.8.8 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 16.853/16.853/16.853/0.000 ms
4
-
“它对我有用”实际上并不能解决任何问题。
– -
@larsks 这很有帮助,也很慷慨。感谢您对使用 ip 命令的指点。iptables 日志行对我特别有用。我将尝试在安装了 ubuntu 的 VM 上执行相同操作。我现在的猜测是,我的问题与 docker 在我的系统上安装的 iptables 规则存在某种冲突。
– -
@TomYan 它至少与尖刻的评论一样有用,甚至可能更有用。
–
-
@AlexFlint 您可以研究启用跟踪功能以识别哪些规则与您的流量匹配。如何做到这一点取决于您使用的是旧版 iptables 还是 iptables-nft(或直接使用 nft)。
–
|
–
|