Как пересылать трафик между пространствами имен в 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 или пространство имен для пересылки трафика из глобального пространства имен в пространство имен vpn?

Во-первых: я не думаю, что вы можете добиться этого, используя 127.0.0.0/8 и / или интерфейс loopback (например, lo). Вы должны использовать некоторые другие IP-адреса и интерфейсы, потому что для 127.0.0.0/8 и для loopback существуют конкретные вещи.

Тогда есть, конечно, несколько методов, но вот пример:

 # 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 

Первая команда создает из воздуха пару виртуальных интерфейсов Ethernet, подключенных виртуальным кабелем Ethernet. Вторая команда перемещает один из этих интерфейсов в netns vpn. Считайте это эквивалентом таких вещей, как socketpair (2) или pipe (2): процесс создает пару, затем вилки, и каждый процесс поддерживает только один конец пары, и они могут общаться.

Обычно (LXC, virt-manager, …) есть также мост, который должен поместить все в одну и ту же ЛВС, когда у вас много нетнов.

Как только это будет установлено, для хоста это похоже на любой маршрутизатор. Включите переадресацию 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, чтобы все было видно как исходящее из 10.0.0.1 внутри vpn.

 # 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 

Теперь это даже будет работать, если вы подключаетесь от хоста к себе, если вы не используете loopback ip, а любой другой IP, принадлежащий хосту, с правилом nat, как указано выше. Допустим, ваш 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