Я заметил странное поведение в Linux:
Сначала я очищаю все маршруты и правила iptables:
ip route flush table main
ip route flush table default
ip route flush table local
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
iptables -t nat -F
iptables -t mangle -F
iptables -F
iptables -X
ip6tables -P INPUT ACCEPT
ip6tables -P FORWARD ACCEPT
ip6tables -P OUTPUT ACCEPT
ip6tables -t nat -F
ip6tables -t mangle -F
ip6tables -F
ip6tables -X
Затем я добавляю локальный маршрут:
ip route add local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1 table local
Затем на терминале я открываю порт с помощью nc -lp 12345
, а на другом терминале я подключаюсь к это с nc 127.0.0.1 12345
, и я могу отправлять и получать данные между сервером netcat и клиентом.
Так что пока все в порядке.
Теперь, после того, как я убил предыдущий сервер и клиент netcat, если я запустил:
iptables -t nat -A POSTROUTING -j MASQUERADE
и перезапускаю сервер netcat, клиент не сможет подключиться . Вы знаете, почему?
Я заметил, что добавление ip route add local 192.168.0.10 dev wlan0 proto kernel scope host src 192.168.0.10 table local
заставляет соединение netcat снова работать. Однако я не понимаю, почему интерфейс wlan0 (IP-адрес которого 192.168.0.10) может влиять на интерфейс обратной связи?
Для информации я использую ArchLinux
Я не знаю если это ошибка или намеренный откат, но, как я могу видеть здесь, это не имеет ничего общего ни с упомянутым вами локальным маршрутом wlan0
, ни со всем шлюзом по умолчанию, бла-бла (без обид, но для меня это почти не имеет смысла) сказано в другом / "правильном" ответе.
Обычно MASQUERADE
работает так: он выбирает адрес, настроенный на исходящем интерфейсе (который определяется маршрутизацией, следовательно, POSTROUTING
) для исходный NAT, который он выполняет.(Если на интерфейсе назначено несколько адресов, он, вероятно, выберет первый или тот, который установлен в качестве предпочтительного исходного адреса в соответствующем маршруте; я не очень знаком с этим, и это выходит за рамки здесь в любом случае). Это не имеет ничего общего с адресом следующего магазина / шлюза маршрута по умолчанию. (В любом случае NAT работает по-другому.)
Однако, когда дело доходит до интерфейса lo
, все становится немного сложнее. Точнее, похоже, это как-то связано не с самим интерфейсом (помимо того факта, что это будет исходящий интерфейс, потому что местом назначения является локальный адрес), а скорее с тем фактом, что адреса в 127.0 Блок .0.0 / 8
не входит в область global
. Хотя я понятия не имею, что происходит за кулисами, кажется, что трафик не может «проявиться», если хост не имеет настроенного IP-адреса области global
, но пытается MASQUERADE
.
Я вижу здесь, даже если вы просто настроите адрес, действительный для области global
(например, 192.168.0.10/32
) на любом интерфейсе (включая ] lo
), вы увидите, что он снова работает. (Упомянутый вами локальный маршрут будет добавлен автоматически. Но я не вижу, чтобы здесь работало добавление только маршрута.)
Как бы то ни было, адреса и интерфейсы не сильно связаны друг с другом в Linux (не прямым способом, например, он будет отвечать на трафик только в том случае, если их адрес назначения совпадает с настроенным адресом на входящем интерфейсе, даже если когда переадресация IP не имеет значения). Так что это может иметь какое-то отношение к этому: в случае, если MASQUERADE
не может выбрать адрес области глобальный
из того, что настроено на исходящем интерфейсе, он просто выбирает один из любого (я сомневаюсь, что хотя приоритет имеет какое-то отношение к маршруту по умолчанию), если все еще нет, он просто отказывается работать каким-то образом.
Если вам действительно нужно правило, которое включает MASQUERADE
на всех интерфейсах, кроме lo
, вы можете иметь:
iptables -t nat -A POSTROUTING ! -o lo -j MASQUERADE
В дополнение к другим ответам я провел еще несколько экспериментов. Пожалуйста обратите внимание, что это только мои выводы, я не искал внутри исходного кода ядра (но если у вас есть документация, поделитесь).
Действительно, похоже, что интерфейс lo
и 127.0.0.1
подчиняются своим собственным правилам.
Для других интерфейсов, вот как я считаю, что исходный IP-адрес назначается пакету (не говоря уже о MASQUERADE или таких вещах, как сырые сокеты):
Когда кто-то пытается отправить пакет на целевой IP-адрес, Linux будет поиск подходящего правила маршрутизации добавлен, например:
ip route add <NETWORK>/<PREFIX> dev <INTERFACE_XX> [src <SRC_IP>]
Если указан параметр src
(это, кажется, подразумевает добавление правила типа ip route add local
]. Обратите внимание, что INTERFACE_XX и INTERFACE_YY не должны совпадать, что удивительно), тогда пакет отправляется на интерфейс INTERFACE_XX
с SRC_IP
в качестве IP-адреса источника.
Если параметр src
не указан, он будет отправлять пакет на INTERFACE_XX
, а адрес источника выбирается путем поиска первого действительного IP-адреса на интерфейсе от первого запущенного до последний (за исключением lo). Если IP-адрес не найден, IP-адрес источника устанавливается на 0.0.0.0. Если у интерфейса несколько IP-адресов, выбирается первый. Как ни странно, это означает, что пакет не обязательно имеет IP-адрес выходного интерфейса, на который он отправляется.
Думаю, MASQUERADE выбирает IP-адрес источника аналогичным образом.
Пожалуйста, поправьте меня, если вы думаете, что что-то не так.
Это обоснованное предположение. Параметр MASQUERADE
заменяет исходный IP-адрес в IP-пакетах на адрес, который он решает использовать. Я думаю, что в этом случае он заменяет исходный адрес адресом интерфейса, по которому доступен шлюз по умолчанию.
Итак, если ваш шлюз по умолчанию - 192.168.0.1
, адрес источника пакета заменяется на 192.168.0.1
. Назначение - 127.0.0.1
, и это не работает должным образом.
Вы должны ограничить MASQUERADE
только пакетами, в которых исходящий интерфейс является интерфейсом к шлюзу по умолчанию.
Вы можете сделать это с помощью следующей команды:
iptables -t nat -A POSTROUTING -o <if> -j MASQUERADE