Вопрос или проблема
Я пытаюсь настроить два сетевых пространства имен для взаимодействия друг с другом. Я создал два пространства имен, ns0
и ns1
, у каждого из которых есть пара veth, где не-национальная сторона veth подключена к мосту.
Я настроил это так:
ip link add veth0 type veth peer name brveth0
ip link set brveth0 up
ip link add veth1 type veth peer name brveth1
ip link set brveth1 up
ip link add br10 type bridge
ip link set br10 up
ip addr add 192.168.1.11/24 brd + dev br10
ip netns add ns0
ip netns add ns1
ip link set veth0 netns ns0
ip link set veth1 netns ns1
ip netns exec ns0 ip addr add 192.168.1.20/24 dev veth0
ip netns exec ns0 ip link set veth0 up
ip netns exec ns0 ip link set lo up
ip netns exec ns1 ip addr add 192.168.1.21/24 dev veth1
ip netns exec ns1 ip link set veth1 up
ip netns exec ns1 ip link set lo up
ip link set brveth0 master br10
ip link set brveth1 master br10
Как и ожидалось, я могу пинговать интерфейс в ns0
из ns1
.
$ sudo ip netns exec ns1 ping -c 3 192.168.1.20
PING 192.168.1.20 (192.168.1.20) 56(84) bytes of data.
64 bytes from 192.168.1.20: icmp_seq=1 ttl=64 time=0.099 ms
64 bytes from 192.168.1.20: icmp_seq=2 ttl=64 time=0.189 ms
Но я не могу подключиться между ними по TCP.
Например, запуская сервер в ns0
:
$ sudo ip netns exec ns0 python3 -m http.server 8080
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
Я ожидал, что смогу выполнить curl из ns1
, но это приводит к ошибке:
$ sudo ip netns exec ns1 curl 192.168.1.20:8080
curl: (7) Не удалось подключиться к 192.168.1.20 порт 8080: Нет маршрута к хосту
Почему это происходит?
Я столкнулся с похожей ситуацией:На хостах k8s, использующих flannel, podA может пинговать podB на том же хосте, но tcp соединение сбрасывалось ICMP сбросом от cni0.
iptables-save
показывает правила о k8s, и ни одно из них не выглядит неправильно.
nft list ruleset
показывает правила созданные firewalld:
table inet firewalld {
chain filter_FORWARD {
type filter hook forward priority filter + 10; policy accept;
ct state { established, related } accept
ct status dnat accept
iifname "lo" accept
ip6 daddr { ::/96, ::ffff:0.0.0.0/96, 2002::/24, 2002:a00::/24, 2002:7f00::/24, 2002:a9fe::/32, 2002:ac10::/28, 2002:c0a8::/32, 2002:e000::/19 } reject with icmpv6 addr-unreachable
jump filter_FORWARD_ZONES
ct state invalid drop
reject with icmpx admin-prohibited
}
Все работает отлично после остановки службы firewalld:
systemctl stop firewalld
Поэтому, пожалуйста, проверьте, есть ли другие службы или модули ядра, которые также могут использовать netfilter.
Ответ или решение
Проблема с подключением TCP между пространствах имен в Linux
Ваша проблема заключена в том, что, несмотря на успешное выполнение команды ping между пространствами имен, вы не можете установить TCP-соединение. Давайте подробно разберем возможные причины и шаги по их устранению.
1. Общая схема настройки
На основании приведенной вами информации, вы успешно настроили два пространства имен ns0
и ns1
, которые используют пары виртуальных Ethernet (veth) и подключены к мосту (bridge). У вас есть следующие IP-адреса:
ns0
: 192.168.1.20ns1
: 192.168.1.21- Мост
br10
: 192.168.1.11
Вы можете успешно использовать ICMP (ping), что говорит о том, что уровень сетевой конфигурации работает корректно. TCP же является более сложным протоколом, который требует проверки дополнительных настроек.
2. Настройки брандмауэра
Наиболее вероятной причиной ошибки "No route to host" при попытке подключения TCP является брандмауэр. Вы уже упомянули о iptables
и nftables
, которые могут блокировать трафик. Рекомендуется проверить следующие настройки:
-
Правила iptables: Используйте команду
sudo iptables -L -v -n
. Убедитесь, что в правилах нет блокировок, касающихся трафика между вашими пространствами имен. -
Правила firewalld: Если вы используете firewalld, убедитесь, что в конфигурации нет правил, которые могли бы блокировать ваш TCP-трафик. Остановка firewalld, как вы уже сделали, подтверждает, что именно он мог быть проблемой.
3. Прослушивание на всех интерфейсах
Ваша команда для запуска сервера HTTP (python3 -m http.server 8080
) по умолчанию настроена на прослушивание на всех интерфейсах (0.0.0.0
). Убедитесь, что сервер действительно запущен в ns0
и работает без ошибок.
Попробуйте выполнить следующие команды для проверки:
sudo ip netns exec ns0 netstat -tuln | grep 8080
Эта команда покажет, прослушивает ли ваш сервер порт 8080 и на каких интерфейсах.
4. Проверка соединения с помощью telnet
Для более детального анализа попробуйте использовать утилиту telnet
для тестирования TCP-соединения:
sudo ip netns exec ns1 telnet 192.168.1.20 8080
Если соединение установлено, то проблема не в сетевой конфигурации. Если нет, то это может указывать на то, что пакет не достигает нужного места назначения.
5. Проблемы с MTU
Если используется слишком малый размер MTU, это тоже может привести к ошибкам подключения, особенно для протоколов, чувствительных к фрагментации. Проверьте MTU для всех интерфейсов, особенно для veth и моста, и убедитесь, что они совпадают:
ip link show
6. Повторная проверка маршрутизации
Убедитесь, что маршрутизация настроена корректно. Для каждой сетевой namespace убедитесь, что есть доступ к маршруту по умолчанию и трафик направляется через нужные интерфейсы:
sudo ip netns exec ns0 ip route
sudo ip netns exec ns1 ip route
Заключение
Сложности с TCP-подключением между пространствами имен, несмотря на успешные ping-запросы, чаще всего возникают из-за проблем с брандмауэром, ошибками конфигурации маршрутизации или проблемами с прослушиванием серверных приложений. Рекомендуется проверять настройки брандмауэра и маршрутизации, а также убедиться в работоспособности приложения на всех требуемых интерфейсах.
Если указанные шаги не приведут к успеху, возможно, стоит подумать о других системных настройках или обратиться к документации для вашей операционной системы.