Вопрос или проблема
Я уже видел другие ответы на этом сайте, прочитал статью и посмотрел видео на эту тему, но все равно не могу подключить свой сетевой неймспейс к внешнему миру.
Настройка
Я создал неймспейс под названием “foo” и пару интерфейсов veth
, один из которых переместил в неймспейс.
ip netns add foo
ip link add veth-foo type veth peer name veth-out
ip link set dev veth-foo netns foo
Я назначил каждому интерфейсу IP-адрес и убедился, что они оба активны.
ip -n foo addr add 192.168.15.1 dev veth-foo
ip addr add 192.168.15.2 dev veth-out
ip -n foo link set dev veth-foo up
ip link set dev veth-out up
# На всякий случай я убедился, что и интерфейсы loopback тоже активны, хотя они все равно показывают "UNKNOWN".
ip link set dev lo up
ip -n foo link set dev lo up
Я добавил записи в таблицы маршрутизации как глобального, так и “foo” неймспейсов, чтобы они могли общаться друг с другом.
ip route add 192.168.15.1 via 192.168.15.2
ip -n foo route add default via 192.168.15.1
Теперь я могу достичь “foo” из глобального неймспейса и глобальный неймспейс из “foo”.
$ traceroute -n 192.168.15.1
traceroute to 192.168.15.1 (192.168.15.1), 30 hops max, 60 byte packets
1 192.168.15.1 0.257 ms 0.209 ms 0.194 ms
$ ip netns exec foo traceroute -n 192.168.15.2
traceroute to 192.168.15.2 (192.168.15.2), 30 hops max, 60 byte packets
1 192.168.15.2 0.046 ms 0.009 ms 0.008 ms
Я также могу достичь ethernet-интерфейса, который подключает VM к внешнему миру изнутри “foo”.
# Я выполнил это после настройки IP forwarding, packet forwarding,
# и IP masquerading, так что не уверен, сработает ли это на данном этапе.
$ ip netns exec foo traceroute -n 10.0.2.15
traceroute to 10.0.2.15 (10.0.2.15), 30 hops max, 60 byte packets
1 10.0.2.15 0.065 ms 0.010 ms 0.008 ms
Наконец, я настроил IP forwarding, packet forwarding, и IP masquerading.
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -A FORWARD -o enp1s0 -i veth-out -j ACCEPT
iptables -A FORWARD -i enp1s0 -o veth-out -j ACCEPT
iptables -t nat -A POSTROUTING -s 192.168.15.1/24 -o enp1s0 -j MASQUERADE
В результате моя система выглядит так:
$ sysctl -a | grep ip_forward
net.ipv4.ip_forward = 1
net.ipv4.ip_forward_update_priority = 1
net.ipv4.ip_forward_use_pmtu = 0
$ iptables -t nat -L -v
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 102 packets, 6816 bytes)
pkts bytes target prot opt in out source destination
0 0 MASQUERADE all -- any enp1s0 192.168.15.0/24 anywhere
$ ip addr
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 noprefixroute
valid_lft forever preferred_lft forever
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 52:54:00:c3:cd:ac brd ff:ff:ff:ff:ff:ff
inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic noprefixroute enp1s0
valid_lft 83383sec preferred_lft 83383sec
inet6 fec0::11b8:4b3b:59ba:bae4/64 scope site dynamic noprefixroute
valid_lft 86026sec preferred_lft 14026sec
inet6 fe80::f3fd:90f2:d15f:d570/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: veth-out@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether da:a2:13:05:c4:f5 brd ff:ff:ff:ff:ff:ff link-netns foo
inet 192.168.15.2/32 scope global veth-out
valid_lft forever preferred_lft forever
inet6 fe80::d8a2:13ff:fe05:c4f5/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
$ ip -n foo addr
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 proto kernel_lo
valid_lft forever preferred_lft forever
4: veth-foo@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 7e:84:e6:16:92:8e brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.15.1/32 scope global veth-foo
valid_lft forever preferred_lft forever
inet6 fe80::7c84:e6ff:fe16:928e/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
$ ip route
default via 10.0.2.2 dev enp1s0 proto dhcp src 10.0.2.15 metric 100
10.0.2.0/24 dev enp1s0 proto kernel scope link src 10.0.2.15 metric 100
192.168.15.1 via 192.168.15.2 dev veth-out
$ ip -n foo route
default via 192.168.15.1 dev veth-foo
Тестирование
На этом этапе я рассчитываю, что смогу достичь внешнего мира, но нет.
$ ip netns exec foo traceroute -n 8.8.8.8
traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets
1 192.168.15.1 3067.680 ms !H 3067.655 ms !H 3067.650 ms !H
$ sudo ip netns exec foo ping -c 3 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
From 192.168.15.1 icmp_seq=1 Destination Host Unreachable
From 192.168.15.1 icmp_seq=2 Destination Host Unreachable
From 192.168.15.1 icmp_seq=3 Destination Host Unreachable
--- 8.8.8.8 ping statistics ---
3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2077ms
Конечно, сама виртуальная машина подключена к Интернету.
$ traceroute -n 8.8.8.8
traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets
1 10.0.2.2 0.719 ms 0.691 ms 0.676 ms
2 192.168.100.1 1.913 ms 2.593 ms 5.264 ms
3 31.146.255.37 18.493 ms 18.740 ms 19.041 ms
4 188.123.128.85 19.384 ms 19.658 ms 19.925 ms
5 188.123.128.96 20.275 ms 21.787 ms 188.123.128.84 21.773 ms
6 192.178.69.213 47.953 ms 53.145 ms 53.127 ms
7 192.178.69.212 53.116 ms 51.893 ms 188.123.128.33 51.293 ms
8 192.178.107.87 48.513 ms 192.178.107.135 43.582 ms 192.178.107.203 43.391 ms
9 72.14.237.137 43.195 ms 8.8.8.8 43.207 ms 43.200 ms
$ ping -c 3 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=255 time=40.2 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=255 time=37.9 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=255 time=38.0 ms
--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 37.859/38.698/40.205/1.067 ms
Tcpdump
Вот вывод tcpdump -n -i veth-out icmp
. Он зафиксировал пакеты, когда я нацелился на 192.168.15.2
и 10.0.2.15
, но ничего не поймал, когда я нацелился на 8.8.8.8
.
listening on veth-out, link-type EN10MB (Ethernet), snapshot length 262144 bytes
# Это вывод, когда я запускал `traceroute -n 192.168.15.2` (адрес
# "veth-out") в другом терминальном окне (разумеется, из "foo").
12:44:19.172007 IP 192.168.15.2 > 192.168.15.1: ICMP 192.168.15.2 udp port traceroute unreachable, length 68
12:44:19.172029 IP 192.168.15.2 > 192.168.15.1: ICMP 192.168.15.2 udp port mtrace unreachable, length 68
12:44:19.172046 IP 192.168.15.2 > 192.168.15.1: ICMP 192.168.15.2 udp port 33436 unreachable, length 68
12:44:19.172063 IP 192.168.15.2 > 192.168.15.1: ICMP 192.168.15.2 udp port 33437 unreachable, length 68
12:44:19.172102 IP 192.168.15.2 > 192.168.15.1: ICMP 192.168.15.2 udp port 33438 unreachable, length 68
12:44:19.172119 IP 192.168.15.2 > 192.168.15.1: ICMP 192.168.15.2 udp port 33439 unreachable, length 68
# А это когда я выполнял ту же команду, но адресовал её на 10.0.2.15 (ethernet
# интерфейс для внешнего мира).
12:44:35.305689 IP 10.0.2.15 > 192.168.15.1: ICMP 10.0.2.15 udp port traceroute unreachable, length 68
12:44:35.305715 IP 10.0.2.15 > 192.168.15.1: ICMP 10.0.2.15 udp port mtrace unreachable, length 68
12:44:35.305733 IP 10.0.2.15 > 192.168.15.1: ICMP 10.0.2.15 udp port 33436 unreachable, length 68
12:44:35.305750 IP 10.0.2.15 > 192.168.15.1: ICMP 10.0.2.15 udp port 33437 unreachable, length 68
12:44:35.305766 IP 10.0.2.15 > 192.168.15.1: ICMP 10.0.2.15 udp port 33438 unreachable, length 68
12:44:35.305783 IP 10.0.2.15 > 192.168.15.1: ICMP 10.0.2.15 udp port 33439 unreachable, length 68
^C
12 packets captured
12 packets received by filter
0 packets dropped by kernel
Ни tcpdump -n -i lo icmp
, ни tcpdump -n -i enp1s0 icmp
не зафиксировали никакие пакеты, независимо от цели traceroute
— да, даже когда “foo” успешно достиг интерфейса “enp1s0” (адресованного 10.0.2.15
).
Информация о системе
Это было выполнено внутри VM (GNOME Boxes), в Fedora 41, версия ядра 6.11.4-301.fc41.x86_64.
Моя хостовая машина также работает на Fedora 41, хотя ядро на версии 6.13.5-200.fc41.x86_64.
Редактирование: На случай, если это была проблема Fedora, я протестировал это в Mint VM, и произошло то же самое.
Ответ или решение
Связь сетевых неймспейсов с внешним Интернетом часто является сложной задачей, особенно когда речь идет о наладке маршрутизации и конфигурации NAT (Network Address Translation). Давайте рассмотрим основные аспекты, теорию, примеры и реализацию, чтобы понять, почему ваш сетевой неймспейс "foo" не может подключиться к Интернету, и как это исправить.
Теория
Сетевые неймспейсы позволяют изолировать сетевые стеки, позволяя работать нескольким независимым сетевым конфигурациям на одном устройстве. Таким образом можно запускать изолированные сервисы или приложения, которые не взаимодействуют друг с другом напрямую. Однако, сама по себе изоляция несёт в себе определенные сложности при необходимости доступа к глобальной сети Интернет.
Для доступа сетевого неймспейса в Интернет важно правильно настроить маршрутизацию и обеспечить трансляцию сетевых адресов (NAT). В частности, необходимо:
- Обеспечить, чтобы пакеты данных из неймспейса попадали на интерфейс, связанный с глобальной сетью.
- Настроить бриджинг или маршрутизацию между виртуальным и физическим интерфейсом.
- Применить IP-маскарадинг, чтобы пакеты, выходящие из неймспейса, могли получить обратную связь от адресатов в Интернете.
Пример
На практике вы уже создали пару виртуальных Ethernet-устройств veth
, с одной стороной в неймспейсе "foo". Настроили IP-адреса и подняли интерфейсы, что позволило взаимодействовать между главным пространством имён и "foo". Тем не менее, когда вы пытаетесь достичь внешних адресов, как например, 8.8.8.8, вы сталкиваетесь с проблемой: "Destination Host Unreachable".
Реализация
Давайте разберемся, в чем может быть причина.
-
IP-маскарад: Вы правильно задали команду для маскарадинга:
iptables -t nat -A POSTROUTING -s 192.168.15.1/24 -o enp1s0 -j MASQUERADE
Однако, возможно, стоит проверить сам NAT-тэйбл для других правил, которые могут блокировать доступ.
-
Маршрутизация: Проверьте маршруты, особенно маршрут по умолчанию в неймспейсе "foo".
ip -n foo route
Ваш маршрут по умолчанию должен правильно указывать на интерфейс, через который обеспечивается доступ к внешним сетям.
-
IP-адресация: Обратите внимание на формат ваших IP-адресов. На устройстве
veth-out
у вас адрес:inet 192.168.15.2/32 scope global veth-out
<prefix>/32
здесь может ограничивать адрес совокупности, так как используется одиночный хостовой адрес. Попробуйте изменить на/24
.ip addr add 192.168.15.2/24 dev veth-out
-
Корректное сетевое соединение между
veth-out
и физическим интерфейсомenp1s0
. Проверьте, что маршруты на физическом интерфейсе корректны и интерфейс видит внешние сети:ip route
Убедитесь, что ваш основной интерфейс может отправлять и получать пакеты из внешнего мира. Отладкой этого может помочь
tcpdump
для интерфейсаenp1s0
. -
Проутинг и трансляция. Проверьте, что интерфейс
enp1s0
настраивает внешнюю маршрутизацию и соединение работает правильно через стек TCP/IP. -
Диагностика через
tcpdump
позволяет мониторить попытки пакетов ICMP, что может указать на проблемы в самой маршрутизации. Поскольку данные не достигалиenp1s0
, необходимо попробовать иные варианты отладки.
Заключение
Корректная настройка сети — важный и тонкий процесс. В вашем случае, возможно, проблема с маршрутизацией либо маскарадом. Проверьте индивидуальные компоненты и взаимодействие между ними. Возможно, ошибка лежит в классе IP-адресов или распределении маски.
Надеюсь, этот детальный разбор поможет вам в поиске и устранении проблемы.