
У меня есть серверы за двумя разными публичными IP-адресами, и я использую DNAT для отправки трафика на разные внутренние серверы в зависимости от порта.
------------------------- -----------------------
| server a (port 80/tcp)| | router A |
| (eth0) 192.168.1.123|..................|192.168.1.1 (eth1) |
------------------------- : | (eth0) 1.2.3.4|............
: ----------------------- :
: :
: ----------------------- :.... INTERNET
------------------------- : | router B | :
| server a (port 25/tcp)| : | (eth0) 2.3.4.5|...........:
| (eth0) 192.168.1.234|..................|192.168.1.2 (eth1) |
------------------------- -----------------------
На маршрутизаторах A и BI включена переадресация и следующие iptables:
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE
iptables -t nat -A PREROUTING -d ${externalIP} -i eth0 -p tcp --dport 25 -j DNAT --to 192.168.1.234
iptables -t nat -A PREROUTING -d ${externalIP} -i eth0 -p tcp --dport 80 -j DNAT --to 192.168.1.123
На самом деле у меня на серверах A и B добавлен следующий маршрут:
route add default gw 192.168.1.1
Таким образом, весь внутренний трафик в Интернет проходит через маршрутизатор A, а весь трафик на порты 25 и 80 корректно отправляется на серверы A и B, но соединения работают только в том случае, если трафик проходит через маршрутизатор A. Действительно, трафик через маршрутизатор B поступает на серверы, но возвращается через маршрутизатор A вместо B, поэтому соединения не работают.
Я добавил новый маршрут на серверах:
route add default fw 192.168.1.2
route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 eth0
0.0.0.0 192.168.1.2 0.0.0.0 UG 0 0 0 eth0
192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
Но связь по-прежнему не работает.
Как мне это сделать?
Не так уж важно балансировать трафик Внутренний -> Внешний, но хочется, чтобы все входящие соединения из Интернета на внешние IP-адреса устанавливались корректно.
ПРИМЕЧАНИЕ: Я также пытался выполнить DNAT на одном из маршрутизаторов по внешнему IP-адресу другого маршрутизатора, но они находятся в разных сетях, и это не сработало:
iptables -t nat -I PREROUTING -p tcp --dport 25 -d ${ExternalIPA} -i eth0 -j DNAT --to ${ExternalIPB}
решение1
Ваша текущая настройка не будет работать так, как задумано. Вам нужен виртуальный IP, который будет плавать над Router-A
и Router-B
. Это также позволит сбалансировать нагрузку между двумя маршрутизаторами с простотой. В этом примере я буду использовать отраслевой стандартВРРПна маршрутизаторе Linux (Ubuntu-16).
Вот процедура:
В Linux Router-A
и Router-B
выполните следующие команды:
$ sudo echo "net.ipv4.ip_nonlocal_bind=1" >> /etc/sysctl.conf
$ sudo sysctl -p
Установить keepalived на обоих маршрутизаторах
$ sudo apt-get update
$ sudo apt-get install keepalived -y
Затем перейдите к Router-A
тому, что будет действовать как MASTER
. Создайте новый файл конфигурации /etc/keepalived/keepalived.conf
со следующими записями:
vrrp_instance VI_1 {
interface eth1
state MASTER
virtual_router_id 50
priority 101
authentication {
auth_type AH
auth_pass pass123
}
virtual_ipaddress {
192.168.1.99
}
}
Затем перейдите к Router-B
тому, что будет действовать как BACKUP
, и сделайте то же самое с новым файлом конфигурации /etc/keepalived/keepalived.conf
:
vrrp_instance VI_1 {
interface eth1
state BACKUP
virtual_router_id 50
priority 100
authentication {
auth_type AH
auth_pass pass123
}
virtual_ipaddress {
192.168.1.99
}
}
Объяснение:
net.ipv4.ip_nonlocal_bind=1
сообщает ядру, что виртуальный IP-адрес НЕ должен быть привязан к какому-либо физическому интерфейсу.
vrrp_instance VI_1
должны совпадать на обоих маршрутизаторах. Это идентификатор, поскольку на одном маршрутизаторе может работать несколько VRRP.
interface eth1
— это интерфейс, обращенный к локальной сети (к внутренним серверам).
state MASTER
Router-A
и так state BACKUP
далее , Router-B
это говорит само за себя.
virtual_router_id 50
должны совпадать на обоих маршрутизаторах. Это идентификатор.
priority 101
Router-A
и так priority 100
далее Router-B
(в этом случае маршрутизатор A имеет более высокий приоритет).
authentication
должны совпадать на обоих маршрутизаторах. В этом случае я использовал общий ключpassw123
virtual_ipaddress
плавающий IP-адрес, который будет использовать VRRP. Этот IP-адрес должен совпадать на обоих маршрутизаторах. Этот IP-адрес не должен использоваться ни одним устройством в сегменте LAN. В этом случае я выбрал192.168.1.99
Включить службу keepalived
$ sudo systemctl enable keepalived
Запустить службу поддержки активности
$ sudo systemctl start keepalived
Пришло время изменить правила iptables на обоих маршрутизаторах.
Очистите все правила NAT с обоих маршрутизаторов (избавьтесь от неисправных правил NAT)
$ sudo iptables -t nat -F
$ sudo iptables -t mangle -F
Затем добавьте правильные правила NAT:
Маршрутизатор-А
$ sudo iptables -t nat -A POSTROUTING -o eth0 -s 192.168.1.0/24 -j SNAT --to 192.168.1.99
$ sudo iptables -t nat -A PREROUTING -d ${externalIP} -i eth0 -p tcp --dport 25 -j DNAT --to 192.168.1.234
Маршрутизатор-B
$ sudo iptables -t nat -A POSTROUTING -o eth0 -s 192.168.1.0/24 -j SNAT --to 192.168.1.99
$ sudo iptables -t nat -A PREROUTING -d ${externalIP} -i eth0 -p tcp --dport 80 -j DNAT --to 192.168.1.123
Это все, что вам нужно со стороны маршрутизатора. Теперь перейдите на серверы (Server-A и Server-B), удалите существующий шлюз по умолчанию ( 192.168.1.1
) и назначьте новый шлюз ( 192.168.1.99
)
$ sudo ip route del 0/0
$ sudo route add default gw 192.168.1.99
При установлении соединений из Интернета два сервера (Сервер-A и Сервер-B) будут возвращать трафик на виртуальный IP-адрес ( 192.168.1.99
), который находится выше Router-A
иRouter-B
решение2
Наконец мне удалось заставить это работать без использования виртуального IP, по сути, используя CONNNMARK и добавляя различные маршруты:
ПРИМЕЧАНИЕ:
- Маршрутизатор A eth1 MAC = AA:AA:AA:AA:AA:AA
- Маршрутизатор B eth1 MAC = BB:BB:BB:BB:BB:BB
Мне нужно добавить следующие маршруты и iptables на все серверы, использующие асимметричные маршруты:
# add the two routing tables
ip route add to default table 11 via 192.168.1.1 dev eth0
ip route add to default table 33 via 192.168.1.2 dev eth0
# add the mark to the routing tables
ip rule add priority 99 table 11 fwmark 11
ip rule add priority 99 table 33 fwmark 33
# mark the packets that came from the different routes
iptables -t mangle -A OUTPUT ! -d 192.168.1.0/24 -m addrtype --dst-type UNICAST -j CONNMARK --restore-mark
iptables -A INPUT -i eth0 ! -s 192.168.1.0/24 -m addrtype --src-type UNICAST -m mac --mac-source AA:AA:AA:AA:AA:AA -j CONNMARK --set-mark 33
iptables -A INPUT -i eth0 ! -s 192.168.1.0/24 -m addrtype --src-type UNICAST -m mac --mac-source BB:BB:BB:BB:BB:BB -j CONNMARK --set-mark 11
Теперь все работает нормально. Все соединения из интернета к любому из внешних IP-адресов маршрутизируются через маршрутизатор, который управляет соединением DNAT.