Повесть о Linux и NAT (Network address translation)

  Автор: (С) Иван Н. Песин


 

Повесть о Linux и NAT (Network address translation)

Не то что бы давным-давно, пришлось заняться мне проблемой маскарада (masquerading) и трансляции ip-адресов на Линуксе. Техническое задание и описание проекта было достаточно сложным, и весьма нестандартным, потому я решил ознакомиться с молвой народа по данной теме. Проведя неделю в дебрях РуНЕТа и пограничных областях, я с ужасом обнаружил, что данные, касательно маскарада, похоже, хранятся за семью печатями и никто не обнародовал основные мысли и постулаты.

Потому я решил, что стоит сообщить, хотя бы "что там можно, что нельзя" дабы народ не терялся в разных домыслах. Начнем, пожалуй, с определений.

1. Маскарад (masquerade) и трансляция адресов (NAT) являются синонимами.
2. Маскарад - это замена в исходящем пакете адреса источника на другой адрес.
3. В мире Линукс, хотя это и неправильно, слова "маскарад" и "трансляция адресов" понимают как разные понятия; а именно
4. Маскарад - замена адреса на адрес машины, выполняющей маскарад.
5. Трансляция адресов - замена адреса на любой указанный.
6. Далее по тексту, слова "маскарад" и "NAT", будем понимать в смысле мира Линкус (т.е. как разные понятия).

Решение проблемы маскарада, на ядрах разных версий отличается, и потому мы разделим нашу повесть на две части, ядра версии от, если не ошибаюсь, 2.0.29 до 2.2.9ас, и от 2.2.10 до 2.4.0. Ядра версии 2.4.х я обсуждать не буду, потому как там имеется вполне сносное описание. Итак,

Ядра версий 2.0.29 - 2.2.9

Для функции маскарада в этих версиях необходим пакет ipfwadm либо ipchains, зависит от версии. Установив их можно приступать к осмысленным действиям. Очень тривиальная задача решается следующим образом:

ipchains -A forward -i ethX -s 192.168.1.0/24 -j MASQ

результатом этой команды будет замена исходных адресов пакетов из сети 192.168.1.0 класса С, при маршрутизации их через интерфейс ethX, на адрес машины на которой выполнены команды.

Перейдем теперь к более сложным случаям. Допустим, вам необходимо, в зависимости от адреса источника/назначения маскарадить под разными адресами. Как же это выполнить? Тут нам придется обратиться к нестандартным средствам.

Для начала посмотрим урл http://www.suse.de/~mha/HyperNews/get/linux-ip-nat.html. Хотя там написано не очень много, зато содержательно. После прочтения остается лишь вытащить соответствующий архив с программой и патчем ядра. Пропатчив ядро, его надо перекомпилировать (прочитать почитайки обязательно!) с соответствующими изменениями в конфигурации. Устанавливаем скомпилированное ядро, при этом не забываем про "ядро, на всякий случай" (рабочее ядро, которое вы будете загружать, если новое ядро не загрузится). После перезагрузки станет возможным использование команды ipnatadm. Название говорит само за себя ;). Теперь легко можно изобразить команды вроде:

ipnatadm -O -i -b -S 192.168.1.1/24 -M 207.46.230.219
ipnatadm -O -i -b -S 192.168.1.2/24 -M 207.46.230.229

ну и так далее, думаю, разобраться можно. Есть еще полезная опция -W, позволяющая задавать интерфейс. Да, не забудьте, что псевдонимы интерфейсов не понимаются ни ipchains, ни ipfwadm, ни ipnatadm. Перейдем теперь к теме

Ядра версий 2.2.10 - 2.4.0

На этих версиях, к сожаленью, программа ipnatadm предательски перестает функционировать. Почему предательски? Потому что удается пропатчить ядро, скомпилировать, загрузиться и даже приконнектиться с помощью telnet, например. Но при попытке выполнить, допустим, даже вышеописанные команды, интерфейс подвисает. Ну что ж, значит нужно искать другие ходы. Если нужно, значит надо.

Внимательно прочитав информацию, размещенную на сайте с ipnatadm, можно обнаружить любопытный факт. А именно то, что один наш земляк Алексей Кузнецов, пишет часть ядра, которая, в том числе, ведает маршрутизацией и маскарадом. Из этого прямо следует, что функциональность этого кода огромна, а документация - м-да, хромает, мягко выражаясь. Сам Кузнецов советует разбирать исходники ядра - для тех, кто сможет, захочет, имеет время, и т.д. и т.п.

Ну а я попробую, насколько это возможно, сжато рассмотреть стандартный и нестандартные методы маскарада, и NAT'а. Стандартный случай: необходимо маскарадить исходящие пакеты хоста 192.168.1.1 в 207.46.230.219. Подход к решению этой задачи полностью аналогичен случаю с более ранними ядрами. Необходимо лишь учесть, что в системах с этими ядрами утилиты ipfwadm нет, вместо нее используется ipchains. Сразу перейдем к рассмотрению более сложных случаев. Допустим, как и в предыдущем примере, пакеты с разных машин, необходимо транслировать в разные адреса.

Тут придется прибегнуть к утилите ip из пакета iproute. Изобразим следующие команды:

ip rule add from 192.168.1.1 nat 207.46.230.219
ip rule add from 192.168.1.2 nat 207.46.230.229

кроме того:

ip route add nat 207.46.230.219 via 192.168.1.1
ip route add nat 207.46.230.229 via 192.168.1.2

Результатом этих действий будет маскарад и демаскарад адресов 192.168.1.1 и 192.168.1.2, соответственно в 207.46.230.219 и 229.

Вот такие пирожки. Это все теория и стандартные случаи, давайте рассмотрим более интересный и совсем реальный пример. Имеется сеть на ~250 машин, линукс красная шапочка версии 6.2, в роли маршрутизатора, и выполняющий маскарад внутренних машин под адрес, допустим, 207.46.230.219. Линукс включен в машину провайдера витой парой, из сетевой в сетевую. Кроме того, провайдер, естественно, не желает тратить отдельный ip-адрес на сетевую в которую включен наш линукс. Другими словами (рисунком) ситуация следующая:

  ________________           +----------------------+
 /                \          | Линукс               |
/ Внутренняя сеть  \ _______ | eth0:192.168.1.254   |
\   192.168.1.x    /         |                      |
 \ _______________/          | eth1:207.46.230.219  | 
                             +----------------------+
                                    | 192.168.100.1
                                +-----------+
                                |  Our ISP  |
                                |  Machine  |
+-----------+

Вопрос: как это реализовать на линуксе? Вообще-то весьма просто. Для начала объясним линуксу, как посылать пакеты на машину провайдера. Она находиться не в одной логической сети с нами, а потому изначально линукс не знает как туда попасть. Для этого укажем:

route add -host 192.168.100.1 eth1

что означает: машина 192.168.100.1 подсоединена непосредственно к интерфейсу eth1. Далее, укажем, что все пакеты, предназначенные для интернета отсылать через машину провайдера:

route add default gw 192.168.100.1

и остается лишь прописать правила маскарада. Допустим, я хочу, что бы машины с адресами 192.168.1.101-105 ходили в интернет, а другие нет:

ipchains -A forward -s 192.168.1.101 -j MASQ
ipchains -A forward -s 192.168.1.102 -j MASQ
ipchains -A forward -s 192.168.1.103 -j MASQ
ipchains -A forward -s 192.168.1.104 -j MASQ
ipchains -A forward -s 192.168.1.105 -j MASQ

ipchains -A forward -j REJECT -l

Ну вот, в общем, на сегодня и все.

 


Copyright © 2001, Иван Песин.
Лицензия http://www.linuxgazette.com/copying.html
Опубликовано на http://gazette.linux.ru.net, Июль 2001

Вернуться на главную страницу