я получил lo
(127.0.0.1
) и eth0
(172.17.0.8
). Я хочу перенаправить пакеты, которые попадают в 127.0.0.1:80
к 172.17.42.1:80
(маршрут от eth0
).
Я попытался
iptables -t nat -A OUTPUT -p tcp --dport 80 -d 127.0.0.1 -j DNAT --to 172.17.42.1:80
Но когда я сделаю curl localhost:80
Я не получаю ответа, когда делаю curl 172.17.42.1:80
это просто работает.
Когда вы пытаетесь связаться с localhost, ваш исходный адрес - 127.0.0.1, как и ваш конечный адрес. Итак, пакет выглядит примерно так:
| SRC | DST |
| 127.0.0.1 | 127.0.0.1 |
Поскольку пакеты, которые генерируются локально, сначала проходят цепочку OUTPUT, вы изменяете пакет правилом DNAT:
iptables -t nat -A OUTPUT \
-d 127.0.0.1 \
-p tcp --dport 80 \
-j DNAT \
--to 172.17.42.1:80
После цепочки OUTPUT пакет выглядит так:
| SRC | DST |
| 127.0.0.1 | 172.17.42.1 |
Итак, первая ошибка, которую вы видите, заключается в том, что даже если этот пакет маршрутизируется за пределы исходного устройства, пункт назначения не знает, как правильно его вернуть. Таким образом, вам также необходимо добавить дополнительное правило SNAT:
iptables -t nat -A POSTROUTING \
-d 172.17.42.1 \
-p tcp --dport 80 \
-j SNAT \
--to-source <your_ip_addr>
Теперь пакет будет выглядеть довольно корректно для выхода из сети (адрес источника будет публичным адресом этого устройства, а не адресом localhost).
Но это пока не решит вашу боль.
Решения о маршрутизации пакетов, сгенерированных на локальной машине, принимаются в двух местах.
Решение для этого пакета будет принято на втором этапе, до того, как IP-адрес источника будет перезаписан в цепочке POSTROUTING ...
Таким образом, механизм безопасности ядра отбрасывает пакет, потому что по умолчанию ядро отказывается маршрутизировать пакеты с src 127.0.0.1. Значит, даже mangle вместе с fwmark нам здесь не поможет. Для этого нужно включить route_localnet. Это индивидуальная переменная, которая позволяет использовать 127/8 для целей локальной маршрутизации (по умолчанию 0 - он же отключен).
sysctl -w net.ipv4.conf.all.route_localnet=1
В вашем случае вы можете смело заменить «все» на имя исходящего интерфейса.
Теперь пакеты будут маршрутизироваться в соответствии с предыдущими правилами в таблице, и, поскольку у нас есть POSTROUTING SNAT, мы исправим исходный ip 127.0.0.1 и перепишем его.
Надеюсь это поможет.
PS. извините перед 2-3 правками, здесь 5 утра, а я все еще не сплю :)
Прежде чем сразу перейти к правилам брандмауэра, следует также выполнить простую проверку пересылки. Скорее, как когда проверяют, подключен ли шнур питания, прежде чем разбирать оборудование.
Бегать:
cat /proc/sys/net/ipv4/ip_forward
Если вы получите ноль, IPv4 не будет пересылать. Вам нужно будет включить это.
Чтобы включить его немедленно и временно для проверки поведения:
echo 1 > /proc/sys/net/ipv4/ip_forward
Вышеупомянутое включает его для машины, но просто изменяет настройку ядра на лету и не будет "сохранен".
Отредактируйте файл sysctl.conf, чтобы внести правильные постоянные изменения и обеспечить следующие настройки:
net.ipv4.ip_forward = 1