Андрей Кишкин
Подключаем несколько локальных сетей с пересекающейся адресацией к одному компьютеру
В вашу квартиру или офис проведено несколько локальных сетей, но их одновременному подключению к компьютеру мешают пересекающиеся адресные пространства. Сети можно «подружить», если вы используете ОС Linux.
Локальные пользовательские сети стихийно появляются и исчезают повсюду, они могут охватывать как целые городские районы, так и соединять лишь пару компьютеров в квартире.
Ситуация, когда компьютер подключен одновременно к нескольким сетям, нередка. Но часто одновременной работе во всех этих сетях препятствует объективная причина – пересекающаяся, а чаще всего и вовсе одинаковая адресация. Что же делать?
Одни эту проблему решают физическим подключением только одной из «проблемных» сетей к компьютеру и «перетыкая» кабели по мере необходимости.
Другие устанавливают для каждой сети отдельную плату в системный блок и «переключают» сети на уровне операционной системы, активизируя нужный сетевой интерфейс и выключая все ненужные.
Третьи используют для управления сетевым «зоопарком» дополнительное оборудование, благо простенький маршрутизатор стоит сейчас совсем недорого, кроме того, в его роли можно использовать старый никому не нужный компьютер.
Последний подход универсален, но при всех своих плюсах требует, во-первых, дополнительное «железо», а во вторых – умения это «железо» настраивать.
Я расскажу о том, как к своему компьютеру с операционной системой Linux подключить несколько локальных сетей с произвольной адресацией, и о том, как работать со всеми подключенными сетями одновременно, не испытывая при этом почти никаких проблем.
Для начала рекомендую ознакомиться с материалами [1, 2].
Эти материалы можно найти и на русском языке, но найденные мной переводы несколько устарели.
Требования к системе:
- Ядро Linux 2.6 (я использовал 2.6.17.9), собранное с поддержкой следующих опций netfilter:
CONFIG_NETFILTER
CONFIG_IP_NF_CONNTRACK
CONFIG_IP_NF_IPTABLES
CONFIG_IP_NF_MATCH_MARK
CONFIG_IP_NF_NAT
В большинстве ядер из дистрибутивов нужные опции уже включены, но для их работы требуется подгрузить нужные модули ядра.
- IPTables 1.2.9 и выше (я использовал 1.3.3).
При тестировании работы схемы использовался дистрибутив Slackware Linux 10.2, но вы можете работать с другими дистрибутивами, так как схема универсальна.
Команды, приведенные в статье, можно просто набирать с консоли, но лучше оформить их в качестве командного файла, запускаемого при старте системы, я для этих целей использую /etc/rc.local.
Итак, мы решили подключить компьютер к двум локальным сетям с пересекающейся адресацией. Исходные данные для подключений смотрите в таблице.
Исходные данные для подключений
|
Интерфейс
|
Адрес
|
Маска
|
Шлюз
|
DNS-сервер
|
Сеть 1
|
Eth0
|
192.168.0.10
|
255.255.255.0
|
192.168.0.1
|
192.168.0.2
|
Сеть 2
|
Eth1
|
192.168.0.10
|
255.255.255.0
|
192.168.0.1
|
192.168.0.2
|
Схематично это они представлены на рисунке.
Схема соединения
Алгоритм решения поставленной задачи состоит в замене неуникальных адресов на уникальные, таким образом можно «обмануть» систему маршрутизации, заставив ее «плясать под нашу дудку».
О том, какими критериями нужно пользоваться при выборе сети, адреса которой мы будем подменять, читайте в конце статьи, пока же для простоты выберем в качестве «подопытной» сеть, подключенную к интерфейсу Eth1.
Задачу конфигурирования системы можно разбить на три, более мелкие:
- Идентификация и инициализация входящего трафика.
- Инициализация и маршрутизация ответного трафика.
- Инициализация и маршрутизация собственного трафика системы.
Под идентификацией трафика подразумевается определение сети источника, а под инициализацией – придание идентифицированным пакетам неких специфических черт, разговор о которых пойдет дальше.
Идентификация и инициализация входящего трафика
Инициализацию будем производить в зависимости от интерфейса, с которого трафик пришел. Неуникальный адрес хоста назначения (нашего компьютера) (в общем случае не уникальна адресация сетевых сегментов, подключенных к компьютеру, но так как из каждого сегмента нашей системе принадлежит только один адрес, будем именно его называть неуникальным, хотя это может быть и не так, т.е. адреса разные, но принадлежат одному сетевому пространству) будем заменять уникальным. Это поможет нам решить и еще одну задачу – задачу маршрутизации обратного трафика, но об этом позже.
Мы выбрали в качестве «подопытной» сеть, подключенную к интерфейсу eth1, поэтому назначаем дополнительный уникальный адрес на этом интерфейсе:
ip address add 192.168.1.10/32 dev eth1
Адрес можно выбирать любой удобный, особой роли он не играет, важно, чтобы он не входил в сети, подключенные к другим сетевым интерфейсам.
Обратите внимание на маску сети, в общем случае она может быть любой, но так как адрес не участвует в реальном сетевом взаимодействии, то лучше ее сделать как в нашем примере.
Далее заменяем адрес хоста назначения в пакетах, приходящих с интерфейса eth1:
iptables –t NAT –A PREROUTING –i eth1 –s 192.168.0.0/24 –j DNAT -–to-destination 192.168.1.10
Инициализация и маршрутизация ответного трафика
Маршрутизацию обратного трафика будем производить «от источника», т.е. в зависимости от адреса отправителя, т.к. он уникальный.
Создадим в системе дополнительную таблицу маршрутизации для каждой сети. Из консоли дайте следующие команды:
echo /etc/iproute2/rt_tables >> 10 TO_ETH0
echo /etc/iproute2/rt_tables >> 20 TO_ETH1
или добавьте в файл /etc/iproute2/rt_tables строки соответствующие «10 TO_ETH0», «20 TO_ETH1» вручную. В скрипт эти команды добавлять не нужно, достаточно запустить их один раз.
Добавляем маршрут по умолчанию в эти таблицы:
ip route add default dev eth1 table TO_ETH1
ip route add default dev eth0 table TO_ETH0
А теперь создаем правила, в соответствии с которыми все пакеты, у которых в поле «От» указан адрес 192.168.1.10, нужно маршрутизировать в соответствии с таблицей TO_ETH1, т.е. передавать через интерфейс eth1, а все пакеты у которых в поле «От» указан адрес 192.168.0.10, передавать через интерфейс eth0.
Маркируем пакеты:
iptables –t mangle –A OUTPUT –s 192.168.0.10/24 –j MARK -–set-mark 0
iptables –t mangle –A OUTPUT –s 192.168.1.10/24 –j MARK -–set-mark 1
Маршрутизируем в зависимости от метки:
ip rule add fwmark 1 table TO_ETH1
ip rule add fwmark 0 table TO_ETH0
Теперь осталось заменить адрес, и пакет может отправляться в путешествие по сети:
iptables –t nat –A OUTPUT –s 192.168.1.10 –j DNAT -–to 192.168.0.10
Теперь наш компьютер может отвечать на запросы (например, DNS или ICMP) из обеих подключенных сетей. Можно попробовать его «попинговать» и насладиться полученным эффектом.
Инициализация и маршрутизация собственного трафика системы
Описанных действий достаточно для организации работы сервера в двух сетях, отвечающего на запросы, приходящие из обеих сетей, но не генерирующего собственного трафика.
В реальности такую ситуацию представить сложно, поэтому займемся трафиком, который генерирует сам хост.
Логика работы такова: при обращении к хосту из сети, подключенной к интерфейсу eth1, заменяем адрес сети хоста с 192.168.0.0 на 192.168.1.0, например, пишем не:
ping 192.168.0.5
а
ping 192.168.1.5
При обращении к сети, подключенной к интерфейсу eth0 все остается по-старому.
Существует один не очень приятный момент: невозможность работы с DNS-сервером сети, подключенной к интерфейсу eth1 (распространяется только на подменяемые нами адреса, т.е. все нелокальные для этой сети имена (например, интернет-имена) будут разрешаться корректно). То есть посылать DNS-запросы вы, конечно, можете, но ответы сервера теперь будут «некорректными», эта проблема решается занесением нужных, но уже откорректированных записей в файл /etc/hosts. То есть если в сети, подключенной к интерфейсу eth1, имеется хост с именем server.local и адресом 192.168.0.1, то файл /etc/hosts следует прописать server.local 192.168.1.1.
Для реализации схемы, описанной выше, нам требуется только заменить адрес сети на выходе:
iptables –t nat –A POSTROUTING –d 192.168.1.0/24 –j NETMAP –to 192.168.0.0
И все. Пакеты будут корректно отмаршрутизированы при помощи правил, созданных нами выше.
Теперь несколько слов о том, как следует подходить к выбору сети, в которой будем «подменять» адреса.
Во-первых, подменять адреса нужно в более «простой» сети, т.е. в той, где меньше сервисов (выделенные серверы и т. д.).
Во-вторых, не стоит выбирать сеть, адреса в которой выдаются по DHCP. Для гарантированной работы конфигурации следует в стартовом скрипте каждый раз выяснять свой адрес, например, через «ip link sh».
Будьте предельно внимательны при наборе правил, т.к. даже малейшие ошибки могут привести к серьезным проблемам, поэтому перед подключением к реальным сетям работоспособность конфигурации настоятельно рекомендую проверить на «испытательном стенде»: вашем ПК и нескольких подключенных к нему.
- Advanced Linux Routing – http://lartc.org/howto.
- IPTables 1.2.2 Tutorial – http://iptables-tutorial.frozentux.net/iptables-tutorial.html.