У меня есть два сервера под управлением CentOS 7 с общедоступными IP-адресами, которые также подключены к одной локальной сети. На сервере A есть несколько виртуальных машин, на одну из которых я пытаюсь перенаправить порт 80. Я делаю это используя firewall-cmd
, и моя сетевая карта WAN присоединена к внешней зоне в обоих случаях (LAN - внутренняя зона). Это, конечно, означает, что маскарад включен (так как это значение по умолчанию для внешнего). Я также проверил (как минимум дюжину раз), чтобы убедиться, что ip_forwarding
установлен в 1, и что настройка сохраняется после перезагрузки.
Вот результат firewall-cmd --list-all
на сервере A:
external (active)
target: default
icmp-block-inversion: no
interfaces: em1
sources:
services:
ports:
protocols:
masquerade: yes
forward-ports: port=80:proto=tcp:toport=80:toaddr=192.168.11.1
source-ports:
icmp-blocks:
rich rules:
Насколько мне известно, это должно работать, но это не так. Чтобы проверить, я бегу nc -vl 80
на виртуальной машине и nc -v [external IP] 80
на стороннем сервере. Время ожидания соединения истекло.
Та же самая конфигурация на сервере B работает отлично. Я могу отправлять и получать текст с помощью netcat без проблем.
Вот схема сети для некоторых дополнительных деталей:
WAN
|
_____Switch_____
/ \
em1 enp1s0
| | zone: external
+----------+ +----------+ ---------------
| Server A | | Server B |
+----------+ +----------+ ---------------
| | zone: internal
bridge1 bridge1
| | |
| em2 enp3s0
| \____Switch_____/
|
vnet0
+--------+
| Web VM |
+--------+
Конфигурация сети выполняется с помощью скриптов с NM_CONTROLLED=no
на всех интерфейсах для обоих серверов. Оба сервера также имеют одинаковую конфигурацию (очевидное различие - IP-адреса).
Установка SELinux на разрешающий режим ничего не меняет (он включен на сервере B без проблем, и сервер A в любом случае не имеет соответствующих отказов, отображаемых в журналах аудита)
Я могу перенаправить трафик через netcat, как на сервере A: nc -vl 80 | nc -v 192.168.11.1 80
, и он отлично работает. Я также могу просто открыть порт 80 на сервере A и без проблем слушать оттуда. Так что проблема здесь строго в пересылке.
Я побежал iptables -t nat -S
чтобы просмотреть загруженные правила, и я вижу следующее:
-A PRE_external_allow -p tcp -m mark --mark 0x66 -j DNAT --to-destination 192.168.11.1:80
Когда я бегу iptables -t nat -vnL | grep :80
Я вижу, что счетчик пакетов увеличивается, когда я пытаюсь подключиться (хотя опять же, время ожидания соединения истекает), поэтому я знаю, что правило сработало.
Я попытался перенаправить порт на другое устройство в сети, не находящееся ни на одном сервере, с теми же результатами (сервер B работает, сервер A не работает).
Сервер A только сейчас впервые подключается к глобальной сети, поэтому я не знаю, работала ли пересылка в прошлом.
Что касается основных различий, я могу думать только о следующем:
На обоих серверах работают разные версии ядра (сервер A включен. 3.10.0-693.11.1.el7.x86_64
, Сервер B включен 3.10.0-514.26.2.el7.x86_64
). Однако я попытался запустить старое ядро на сервере A, и это не решило проблему (поэтому я относительно уверен, что это не ошибка ядра, если только она не связана с драйверами сетевой карты, хотя это все равно было бы странно. ).
На сервере A работает firewalld v0.4.4.4, а на сервере B - v0.4.3.2. Я еще не пробовал откатиться до v0.4.3.2 на сервере A (yum не может найти эту версию пакета).
Как вы уже догадались, на сервере B не было крупных обновлений с августа. Как бы мне ни хотелось, я не решаюсь обновлять его сейчас из опасения, что пересылка тоже прервется (будьте уверены, я обновлюсь в конце концов. Надеюсь, что скоро). К сожалению, это означает, что существует чрезвычайно большое количество пакетов с более новыми версиями на сервере A. Простое сравнение версий пакетов приведет к тому, что нужно будет просмотреть много информации.
Я также заметил, что некоторые правила iptables были немного другими:
Сервер А
-A POSTROUTING_ZONES -o em1 -g POST_external
-A POSTROUTING_ZONES -o bridge1 -g POST_internal
-A POSTROUTING_ZONES -o em2 -g POST_internal
-A POSTROUTING_ZONES -g POST_external
-A PREROUTING_ZONES -i em1 -g PRE_external
-A PREROUTING_ZONES -i bridge1 -g PRE_internal
-A PREROUTING_ZONES -i em2 -g PRE_internal
-A PREROUTING_ZONES -g PRE_external
Сервер B
-A POSTROUTING_ZONES -o enp1s0 -g POST_external
-A POSTROUTING_ZONES -o bridge1 -j POST_internal
-A POSTROUTING_ZONES -o enp3s0 -j POST_internal
-A POSTROUTING_ZONES -g POST_external
-A PREROUTING_ZONES -i enp1s0 -g PRE_external
-A PREROUTING_ZONES -i bridge1 -j PRE_internal
-A PREROUTING_ZONES -i enp3s0 -j PRE_internal
-A PREROUTING_ZONES -g PRE_external
Сервер B использует jump
для внутренней зоны, а сервер A использует goto
. Это может быть связано с разницей в версии firewalld, и это единственное, о чем я могу думать на данный момент, что может вызвать эту проблему (хотя я все еще считаю это маловероятным, поскольку это связано с внутренней зоной).
На обоих серверах установлен и настроен докер. Контейнеры на сервере A предназначены только для внутреннего использования. Некоторые контейнеры на сервере B имеют переадресацию портов в Интернет (настроенную через docker run
). На сервере B также работает OpenVPN.
Единственное, что я могу придумать, это отметить, что аппаратное обеспечение серверов сильно различается (сервер A - это Dell T420, сервер B - это кастомный LGA 775, поэтому просто настольное оборудование).
Я уже начинаю сойти с ума. Я даже пробовал включить маскировку во внутренней зоне, как я видел в другом месте (что не имеет абсолютно никакого смысла и, к удивлению, не устранило проблему).
Что мне здесь не хватает?
Обновить
Пытался перенаправить локально на другой порт на сервере A (т.е. firewall-cmd --zone=external --add-forward-port=port=80:proto=tcp:toaddr=192.168.11.3:toport:81
). Я могу подключиться к порту 80 при прослушивании с помощью netcat на сервере A на порту 81, поэтому локальная переадресация работает нормально. Просто не могу пересылать на другие IP-адреса.
Установка цели для внутренней зоны на ПРИНЯТЬ устранила эту проблему для меня.
I.E. firewall-cmd --permanent --zone=internal --set-target=ACCEPT
Признаюсь, я как-то пропустил эту настройку на сервере B. Тем не менее, мне кажется немного странным, что исходящие соединения не принимаются по умолчанию в default
цель.
Очевидно, необходимо убедиться, что ваш WAN-маршрутизатор, каким бы он ни был, отправляет входящий трафик порта 80 на нужный сервер.