У меня просто проблема на сервере с несколькими сетевыми картами и IP-адресами. Я настроил свой сервер Cent OS 7 с дополнительным общедоступным IP-адресом, принадлежащим eth1. Когда iptables source NAT включен, нельзя использовать только дополнительный IP-адрес.
В этом посте два общедоступных IP-адреса обозначены 99.0.1.100 (eth0) и 99.0.2.100 (eth1). Маска подсети 99.0.2.100 - 255.255.254.0, шлюз по умолчанию установлен правильно (99.0.1.1 для 99.0.1.100, 99.0.2.1 для 99.0.2.100).
ниже содержание /etc/sysconfig/network-scripts/ifcfg-eth1
. (HWADDR подвергается цензуре)
DEVICE=eth1
TYPE=Ethernet
HWADDR=**:**:**:**:**:**
ONBOOT=yes
NM_CONTROLLED=no
BOOTPROTO=static
IPADDR=99.0.2.100
NETMASK=255.255.254.0
ниже вывод ip route
.
default via 99.0.1.1 dev eth0 proto static metric 100
99.0.1.0/23 dev eth0 proto kernel scope link src 99.0.1.100 metric 100
99.0.2.0/23 dev eth1 proto kernel scope link src 99.0.2.100
ниже вывод ip rule
.
0: from all lookup local
32765: from 99.0.2.100 lookup subroute-eth1
32766: from all lookup main
32767: from all lookup default
ниже содержание /etc/sysconfig/network-scripts/route-eth1
.
default via 99.0.2.1 table subroute-eth1
ниже содержание /etc/sysconfig/network-scripts/rule-eth1
.
from 99.0.2.100 table subroute-eth1
затем следующий запрос был отправлен правильно и ответил правильный IP-адрес в виде строки для каждого общедоступного IP-адреса.
# curl --interface eth0 api.ipify.org # outputs 99.0.1.100
# curl --interface eth1 api.ipify.org # outputs 99.0.2.100
здесь я хочу, чтобы каждый пользователь системы использовал свой публичный IP-адрес. Итак, применил следующий исходный NAT iptables. Где uid = 1000 - это A, uid = 1001 - это B соответственно.
# iptables -t nat -m owner --uid-owner 1000 -A POSTROUTING -j SNAT --to-source 99.0.1.100
# iptables -t nat -m owner --uid-owner 1001 -A POSTROUTING -j SNAT --to-source 99.0.2.100
в этой ситуации eth0 работает правильно, но время ожидания eth1 истекло.
# curl api.ipify.org # outputs 99.0.1.100
# sudo -u A curl api.ipify.org # outputs 99.0.1.100
# sudo -u B curl api.ipify.org # **time out**
Я понятия не имею, что не так, из-за отсутствия опыта работы в сети. Если у кого-то есть идеи, помогите, пожалуйста. Обратите внимание, что в этой ситуации ssh root@99.0.2.100
из Интернета все еще работает нормально.
редактировать: ниже вывод ip route show table subroute-eth1
default via 99.0.2.1 dev eth1
Uid должен вызвать изменение маршрутизации для использования eth1
вместо того eth0
. nat/POSTROUTING
SNAT (хотя он все еще необходим) приходит слишком поздно для этого, потому что, как следует из названия POSTROUTING, это происходит после решения о маршрутизации: сетевой интерфейс выбран и больше не будет меняться.
Для локального трафика правило должно выполняться в mangle/OUTPUT
цепь, чтобы изменить маршрут, используя метки, которые могут вызвать ip rule
уважать:
# iptables -t mangle -A OUTPUT -m owner --uid-owner 1000 -j MARK --set-mark 1000
# iptables -t mangle -A OUTPUT -m owner --uid-owner 1001 -j MARK --set-mark 1001
Затем информация повторно используется через ip rule
. Следует учитывать даже 1000 (для конкретного случая uid1000$ curl --interface eth1 http://api.ipify.org/
который не должен использовать запись 32765):
ip rule add fwmark 1000 lookup main
ip rule add fwmark 1001 lookup subroute-eth1
Обратите внимание, что исходный IP-адрес по умолчанию был выбран раньше: SNAT все еще необходим, чтобы исправить его на новый правильный. Зачем использовать этот знак, если уже есть правило с from 99.0.2.100 lookup subroute-eth1
затем? Опять же, это из-за порядка различных вычислений в сетевом стеке, как показано ниже. Поток пакетов в схемах Netfilter и General Networking: только изменение mangle/OUTPUT
может вызвать проверка маршрута видно на схеме, и к этому времени IP не был исправлен до 99.0.2.100.
В обратном пути некоторые элементы сети все равно не узнают об этих таблицах маршрутизации вовремя, необходимо установить свободный режим. eth1
с rp_filter или возвратные пакеты будут отброшены:
# echo 2 > /proc/sys/net/ipv4/conf/eth1/rp_filter
То же самое для eth0
для обработки конкретного случая для uid 1000 выше (uid1000$ curl --interface eth1 http://api.ipify.org/
):
# echo 2 > /proc/sys/net/ipv4/conf/eth0/rp_filter
При этом следует в основном работай. Но на самом деле несколько пакетов не принадлежат uid 1001: TCP RST
, последний ACK
после завершения процесса или для UDP связанные ошибки ICMP ... принадлежат только ядру. Они не будут соответствовать uid 1001, будут отправлены на неправильный интерфейс (с неправильным IP-адресом на этом неправильном интерфейсе), и это приведет к возникновению тайм-аутов в конце соединений, более вероятно, на удаленной стороне, а не локально. Это можно увидеть, выполнив kill -KILL
на клиенте с измененным соединением с пользователем 1001 через eth1
, и наблюдаем несколько повторных попыток ACK
пакеты с источником 99.0.2.100, отправленные через eth0
(вместо того eth1
) признавая FIN
с пульта получено несколько раз на eth1
.
Так что все это нужно переработать с помощью CONNMARK
выслеживать потоки инициированный пользователем, вместо пакеты инициирован пользователем (некоторые пояснения Вот). nat
не нужно менять, так как только 1-й пакет в NEW
state все равно проходит через правила iptables и уже отслеживает потоки. Давай начнем сначала:
# iptables -t mangle -F
# iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark
# iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark
# iptables -t mangle -A OUTPUT -m owner --uid-owner 1000 -j MARK --set-mark 1000
# iptables -t mangle -A OUTPUT -m owner --uid-owner 1001 -j MARK --set-mark 1001
# iptables -t mangle -A OUTPUT -j CONNMARK --save-mark
Теперь все должно вести себя правильно.
Последнее замечание: хотя в ваших настройках этого не требовалось, локальный маршрут ссылки для eth1 должен быть продублирован в таблице. subroute-eth1
, иначе доступ eth1
LAN из uid 1001 даст странные результаты, потому что правило 32765 читается перед правилом 32766, поэтому локальный маршрут ссылки никогда не будет определен, поскольку результат этой команды показывает:
# ip route get 99.0.2.55 mark 1001
99.0.2.55 via 99.0.2.1 dev eth1 table subroute-eth1 src 99.0.2.100 mark 0x3e9 uid 0 \ cache
Это может предотвратить доступ ко всей ЛВС, кроме шлюза.
Вы должны добавить (или поместить, если необходимо, в файлы конфигурации системы):
ip route add table subroute-eth1 99.0.2.0/23 dev eth1 scope link src 99.0.2.100
А потом предыдущий ip route get
команда выдаст вместо этого правильный:
99.0.2.55 dev eth1 table subroute-eth1 src 99.0.2.100 mark 0x3e9 uid 0 \ cache