Магия iptables. Необычные виды преобразований сетевых адресов

Настраивать проброс портов и общий доступ к интернету через один публичный адрес умеют все, но не все знают, что возможности NAT в netfilter гораздо шире. Сегодня я продемонстрирую тебе эти возможности с помощью синтаксиса команды iptables.

Самые новые версии некоторых дистрибутивов уже используют nftables, но до ухода iptables в прошлое еще далеко. Поскольку популярные ОС маршрутизаторов, даже проприетарные, сейчас основаны на Linux, многое из этой статьи можно применить и к ним, при условии что их интерфейс не ограничивает формат опций искусственно, а просто передает их в правила iptables.

1:1 NAT

Все, кто использовал Amazon EC2, online.net и другие облачные платформы, наверняка с ним уже сталкивались. Публичные адреса для виртуалок настроить в админке можно, но самой виртуалке при этом выдается частный адрес.

Чтобы это сделать, нужно всего лишь указать по одному адресу вместо целой сети в --source/--destination и --to-destination/--to-source соответственно.

Вот команды для сопоставления частного адреса 10.0.0.10 публичному 102.0.2.10:

$ sudo iptables -t nat -I PREROUTING -d 192.0.2.10 -j DNAT --to-destination 10.0.0.10
$ sudo iptables -t nat -I POSTROUTING -s 10.0.0.10 -j SNAT --to-source 192.0.2.10

INFO

Если нет необходимости подключаться к внутреннему адресу из интернета, достаточно одного правила SNAT — об ответах позаботится модуль conntrack, если он не выключен.

NETMAP

Что делать, если нужно транслировать не один адрес, а целую сеть? Нередко одной компании бывает нужно подключиться к сети другой — например, к поставщику технической поддержки или иных услуг. Проблемы начинаются, если у поставщика уже есть клиент с такой же сетью, как у тебя.

Здесь на помощь приходит опция NETMAP, которая транслирует одну сеть в другую.

INFO

Полезно знать, что сети для частного использования из RFC 1918 на самом деле очень большого размера. Вот они:

  • 10.0.0.0/8 (до 10.255.255.255);
  • 172.16.0.0/12 (до 172.31.255.255);
  • 192.168.0.0/16 (до 192.168.255.255).

Если выбрать менее популярные адреса, чем 192.168.(0|1).0 или 10.0.0.0, с конфликтом можно не столкнуться никогда.

Предположим, в компании-клиенте используется сеть 192.168.0.0/24, а в компании-поставщике — 10.85.0.0/24. Мы сделаем вид, что в нашей компании сеть не 192.168.0.0/24, а 172.17.18.0/24:

$ sudo iptables -t nat -I POSTROUTING -s 192.168.0.0/24 -d 10.85.0.0/24 -j NETMAP --to 172.17.18.0/24
$ sudo iptables -t nat -I PREROUTING -s 10.85.0.0/24 -d 172.17.18.0/24 -j NETNAP --to 192.168.0.0/24

В отличие от SNAT и DNAT, она заменяет не весь адрес источника или назначения, а только адрес хоста — ту часть, где в маске сети нули. Адрес 192.168.0.10 всегда транслируется в 172.17.18.10, так что этот метод отлично подходит для двусторонней работы.

Продолжение доступно только участникам

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», увеличит личную накопительную скидку и позволит накапливать профессиональный рейтинг Xakep Score! Подробнее

Вариант 2. Открой один материал

Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.


Даниил Батурин: @dmbaturin Координатор проекта VyOS (https://vyos.io), «языковед», функциональщик, иногда сетевой администратор

Комментарии (8)

  • Относительно Hairpin:

    "Остается одно: пропускать весь трафик из сети в нее саму через маршрутизатор:
    sudo iptables -t nat -I POSTROUTING -s 10.0.0.0/24 -d 10.0.0.0/24 -j MASQUERADE"

    А) Если -I - то указывать позицию, куда вставляется правило. Если добавляем в конец списка правил - то -A.

    Б) Плохой совет - маскарадить ВЕСЬ локальный трафик через роутер, особенно если у вас сегментированная сеть %). По разным причинам.

    Тут всё проще - если у вас сервер сидит в своей DMZ (как это должно быть) - то скорее всего ничего делать и не нужно (разве что в фаерволе правила-разрешения для доступа с локалки прописать), так как путь туда и обратно будет одинаков. Если же у вас всё в одном сегменте (не есть хорошо), то путь туда и обратно будет разным - туда через роутер, обратно сервер ответит напрямую клиенту (так как они в одном широковещательном сегменте в пределе прямой видимости). Потому на помощь и приходит костыль в виде маскарадинга (в данном случае именно костыль), чтобы сервер ответил обратно на роутер, а роутер уже клиенту.

    Если для доступа снаружи у нас правило prerouting:

    $ sudo iptables -t nat -A PREROUTING -p tcp -d 203.0.113.10:80 -j DNAT --to-destination 10.0.0.20

    то для доступа изнутри к этому же ресурсу ставим симметричное postrouting (10.0.0.0/24 - локальные клиенты, которым даем доступ к ресурсу 10.0.0.20:80 через глобальный ип, выдавая клиентов за роутер):

    sudo iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -d 10.0.0.20:80 -j MASQUERADE

    То есть маскарадим только избранный трафик - в данном случае HTTP на 10.0.0.20. Не маскарадьте весь трафик через роутер - это зло %)

    Ну и всегда смотрим цепочку активных правил, чтобы не сделать мессиво из правил %) :

    iptables -S (ну или iptables -L)
    iptables -t nat -S

    Если намесили и нужно очистить, к примеру, правила nat:

    iptables -t nat -F

  • В коммандах для 1:1 Nat очепятка: 192.0.2.10 -> 10.0.2.10

  • Порадовало: "10.0.0.0/8 (до 10.255.255.255.255)"
    Поправьте, пожалуйста.

  • Полезно знать, что сети для частного использования из RFC 1918 на самом деле очень большого размера. Вот они:
    10.0.0.0/8 (до 10.255.255.255.255);

    Мне кажется, одна 255 - лишняя :-)

    • Это не лишняя, это запасные байтики... Двойная точность :)

  • Как помимо всего зашифровать трафик между двумя компами...?

    • всё зависит от целей, самый простой вариант - ssh туннель, а там и разные vpn-ы и куча туннелей с разным уровнем шифрования и вложенности