如何在 Linux 網路命名空間之間轉發流量?
我能夠設置一個網路命名空間並啟動一個在命名空間內偵聽 127.0.0.1 的伺服器:
# ip netns add vpn # ip netns exec vpn ip link set dev lo up # ip netns exec vpn nc -l -s 127.0.0.1 -p 80 & # ip netns exec vpn netstat -tlpn Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.1:80 0.0.0.0:* LISTEN 5598/nc
之後,我可以連接到命名空間內的伺服器:
# ip netns exec vpn nc 127.0.0.1 80 -zv localhost [127.0.0.1] 80 (http) open
但我無法連接到命名空間外的伺服器:
# nc 127.0.0.1 80 (UNKNOWN) [127.0.0.1] 80 (http) : Connection refused
如何配置 iptables 或 namespace 將流量從全域命名空間轉發到 vpn 命名空間?
第一:我認為您無法通過使用 127.0.0.0/8 和/或環回介面(如 lo)來實現這一點。您必須使用其他一些 IP 和介面,因為 127.0.0.0/8 和環回有一些特定的東西硬連線。
那麼肯定有不止一種方法,但這裡有一個例子:
# ip netns add vpn # ip link add name vethhost0 type veth peer name vethvpn0 # ip link set vethvpn0 netns vpn # ip addr add 10.0.0.1/24 dev vethhost0 # ip netns exec vpn ip addr add 10.0.0.2/24 dev vethvpn0 # ip link set vethhost0 up # ip netns exec vpn ip link set vethvpn0 up # ping 10.0.0.2 PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data. 64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.134 ms 64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.100 ms
第一個命令憑空創建了一對由虛擬乙太網電纜連接的虛擬乙太網介面。第二個命令將這些介面之一移動到 netns vpn。將其視為類似於 socketpair(2) 或 pipe(2) 之類的東西:一個程序創建一對,然後分叉,每個程序只保留一對的一端,它們可以通信。
通常(LXC,virt-manager,…)當您有許多 netns 時,還需要一個橋接器將所有內容放在同一個 LAN 中。
一旦到位,對於主機來說,它就像任何路由器一樣。啟用 ip 轉發(如果可以,請限制更多:至少 vethhost0 和主界面需要它):
# echo 1 > /proc/sys/net/ipv4/conf/all/forwarding
添加一些 DNAT 規則,例如:
# iptables -t nat -A PREROUTING ! -s 10.0.0.0/24 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.0.2
現在您可以在 vpn 中添加預設路由:
# ip netns exec vpn ip route add default via 10.0.0.1
或者,相反,添加一條 SNAT 規則,讓所有內容都被視為來自 vpn 內的 10.0.0.1。
# iptables -t nat -A POSTROUTING -d 10.0.0.2/24 -j SNAT --to-source 10.0.0.1
有了這個,您可以從任何其他主機進行測試,但不能從主機本身進行測試。為此,還要添加一個類似於之前 DNAT 的 DNAT 規則,但在 OUTPUT 中並更改(否則任何傳出的 http 連接也會更改)為您自己的 IP。假設您的 IP 是 192.168.1.2:
# iptables -t nat -A OUTPUT -d 192.168.1.2 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.0.2
現在,如果您不使用環回 ip,而是使用上述 nat 規則屬於主機的任何其他 IP,那麼它甚至可以從主機連接到自身。假設您的 IP 是 192.168.1.2:
# ip netns exec vpn nc -l -s 10.0.0.2 -p 80 & [1] 10639 # nc -vz 192.168.1.2 80 nc: myhost (192.168.1.2) 80 [http] open # [1]+ Done ip netns exec vpn nc -l -s 10.0.0.2 -p 80