Найти в Дзене
Linux | Network | DevOps

Open VPN и хитрый роутинг

Оглавление

Рассмотрим задачу. Исходные данные.

Существует внутренняя сеть 192.168.1.0/24. Она выходит в Интернет через роутер с внутренним интерфейсом 192.168.1.1 и внешним интерфейсом 120.3.5.8. Этот и все другие IP адреса взяты совершенно случайно и никакого отношения к реальным серверам не имеют.

Где то «в замке у шефа» в буржуинском сегменте Интернет стоит сервер с IP 110.45.45.8, который тоже принадлежит нашей компании.

Задача 1.

-2

Необходимо весь трафик, предназначенный на WEB сервера (80 порт) отправлять только через сервер 110.45.45.8. Трафик между нашей сетью и этим сервером должен быть зашифрован. Весь остальной трафик из нашей сети должен идти обычным образом.

Задача 2.

-3

Необходимо весь исходящий трафик нашей сети, предназначенный для Интернет, оправлять через роутер 110.45.45.8. Трафик между нашей сетью и этим роутером должен быть зашифрован.

Что тут сказать, параноидальные задачи, но выполнимые. Итак, будем играть в Штирлица и шифроваться.

Настройка VPN.

Материал, описанный в этом разделе необходим для решения обеих задач.

Для шифрования трафика меду двумя серверами мы будем использовать Open VPN. Сервер, выводящий нашу компанию в Интернет, будет работать как VPN клиент. Сервер в Интернет всегда включен, поэтому он будет работать в качестве VPN сервера.

Open VPN настраивается так же как и в предыдущей главе, поэтому не буду повторять материалы этой главы. Просто покажу готовые конфигурационные файлы клиента и сервера.

Конфигурационный файл VPN сервера.

dev tap0
proto udp
mode server
comp-lzo
log-append /var/log/openvpn.log
daemon
ifconfig-pool 192.168.240.2 192.168.240.12
ifconfig 192.168.240.1 255.255.255.0
tls-server
dh /etc/openvpn/dh1024.pem
ca /etc/pki/CA/CA.crt
cert /etc/pki/tls/certs/server.pem
key /etc/pki/tls/private/server.key
port 5000
user nobody
group nobody
persist-tun
persist—key
verb 0

Необходимо подставить реальные файлы ключей и сертификатов.

Что изменилось в файле конфигурации сервера, по сравнению с предыдущей главой? Во-первых, используется 5000 порт, а не 1194. За время, прошедшее с момента написания первой главы, создатели программы стали рекомендовать использовать порт 5000. На самом деле номер порта может быть любой, но мы будем следовать рекомендациям отцов-основателей.

Конфигурационный файл Linux клиента.

remote 110.45.45.8 5000
dev tap
proto udp
ca /etc/openvpn/certs/CA.crt
cert /etc/openvpn/certs/client.pem
key /etc/openvpn/keys/client.key
client
tls-client
comp-lzo
user nobody
group nobody
ping 30
ping-restart 120
ping-timer-rem
persist-key
persist-tun
verb 0

В этом файле мы тоже заменили порт, куда будет подключаться клиент на 5000.

Посмотрим, что получится после настройки такого решения.

-4

Таким образом, мы обеспечили шифрование при передаче данных между первым и вторым серверами. Но этого мало! Надо сделать так, что бы VPN сервер мог доставлять пакеты в сеть 192.168.1.0/24. Поэтому в конфигурации VPN клиента добавим команду push, которая внесет изменения в таблицу маршрутизации VPN сервера.

push "route 192.168.1.0 255.255.255.0 192.168.240.2"

В результате конфигурационный файл клиента будет выглядеть так:

remote 110.45.45.8 5000
dev tap
proto udp
ca /etc/openvpn/certs/CA.crt
cert /etc/openvpn/certs/client.pem
key /etc/openvpn/keys/client.key
client
tls-client
comp-lzo
user nobody
group nobody
push «route 192.168.1.0 255.255.255.0 192.168.240.2»
ping 30
ping-restart 120
ping-timer-rem
persist-key
persist—tun
verb 0

Теперь внимательно приглядимся к нашей схеме. У нас получилось два сегмента внутренних сетей:

  • 192.168.1.0/24
  • 192.168.240.0/24

И два! Целых два выхода в Интернет! Через роутер 192.168.1.1 и роутер 192.168.240.1.

Господа, как только у вас появляется больше чем один выход в Интернет, необходимо использовать дополнительные возможности, предоставляемые ядром Linux в области маршрутизации. Эти возможности очень хорошо описаны в документе Linux Advanced Routing & Traffic Control HOWTO:

Настоятельно рекомендую в дальнейшее подробно изучить данный HOWTO!

А теперь займёмся решением задач.

Решение задачи 1.

Напомню, что требуется сделать.

-5

Нам необходимо весь трафик на WEB сервера (порт 80) отправлять в Интернет через удаленный сервер, через интерфейс с IP адресом 110.45.45.8.

Весь остальной трафик из нашей сети должен выходит в Интернет через локальный сервер, через интерфейс с IP адресом 120.3.5.88.

На удаленном сервере нам надо сделать только NAT преобразование. Все пакеты, пришедшие из сети 192.168.1.0/24 или 192.168.240.0/24 (а вдруг у вас на клиентском сервере работает прокси сервер Squid?) пропускать через SNAT.

Поэтому в firewall удаленного сервера надо добавить следующие правила:

iptables –t nat –A POSTROUTING –o eth0 –s 192.168.1.0/24 -j SNAT --to-source 110.45.45.8

iptables –t nat –A POSTROUTING –o eth0 –s 192.168.240.0/24 -j SNAT --to-source 110.45.45.8

Не забудьте разрешить прохождение этих пакетов через firewall.

iptables –A FORWARD –p tcp --dport 80 –i tap0 –j ACCEPT

Не забудьте разрешить перенос пакетов с одного сетевого интерфейса на другой.

echo 1 > /proc/sys/net/ipv4/ip_forward

В файле /etc/sysctl.conf отредактируйте строку.

net.ipv4.ip_forward = 1

C удаленным сервером все. Займемся локальным сервером. Наша задача отправлять пакеты предназначенные на 80 порт в Интернет через машину 192.168.240.1.

Добавить маршрут в таблицу маршрутизации? Не поможет, в таблице маршрутизации нельзя указывать порты.

Сделать DNAT? Тоже не поможет, нам нельзя менять IP назначения.

SNAT? Тоже ничего не даст.

-6

Во всех случаях, перечисленных выше, пакет с локального сервера будет уходить по маршруту по умолчанию через интерфейс eth0.

-7

Для решения нашей проблемы мы добавим еще одну таблицу маршрутизации.

В этой таблице сделаем маршрут по умолчанию на машину 192.168.240.1 через интерфейс tap0.

Все пакеты, приходящие на наш сервер на 80 порт из внутренней сети, а также все пакеты, которые генерируют программы, работающие на нашем сервере на 80 порт, будем передавать в новую таблицу маршрутизации. А там уровень IP все сделает сам.

Создадим новую таблицу маршрутизации с именем www.

echo 430 www >> /etc/iproute2/rt_tables

Таким образом, мы создали таблицу номер 430 с именем www. Номер и имя можно использовать любые. Главное, что бы они уже не использовались в вашей системе. Вы можете сначала посмотреть содержимое файла rt_tables при помощи программы cat.

cat /etc/iproute2/rt_tables

Добавим в таблицу www маршрут по умолчанию.

ip route add default via 192.168.240.1 dev tap0 table www

Таблица создана. Как заставить необходимые нам пакеты попадать именно в неё? Тут следует сделать два действия:

  1. При помощи iptables и действия MARK пометить пакет. Присвоить ему номер от 1 до 64.
  2. При помощи программы ip, все помеченные нужным нам номером пакеты перенаправить в таблицу www.

iptables –t mangle –A PREROUTING –i eth1 –p tcp --dport 80 -j MARK --set-mark 1

iptables –t mangle –A OUTPUT –p tcp --dport 80 –d ! 192.168.1.0/24 -j MARK --set-mark 1

Обратите внимание на то, что метки мы ставим в таблице mangle в цепочках PREROUTING (для пакетов, пришедших из внутренней сети) и OUTPUT (для пакетов, которые генерирует программное обеспечение, работающее на нашей машине), до того, как пакеты попадут в таблицу маршрутизации.

ip rule add fwmark 1 table www

Можете посмотреть какие пакеты, каким таблицам будут передаваться.

ip rule show

После перезагрузки компьютера, привязка к таблице и маршруты пропадут. Поэтому мы должны сделать так, что бы при старте они появились снова. Тут все зависит от дистрибутива. Самый простой способ воспользоваться файлом /etc/rc.d/rc.local (или /etc/rc.d/rc.local.local, зависит от системы, которую вы используете). В этом файле надо дописать правила:

ip route add default via 192.168.240.1 dev tap0 table www

ip rule add fwmark 1 table www

Сама таблица www создается только один раз.

Теперь займемся firewall.

Разрешаем хождение пакетов на 80 порт, через интерфейс tap0.

iptables –A FORWARD –p tcp --dport 80 –o tap0 –j ACCEPT

Остальными правилами разрешаете то, что должно выходить через интерфейс eth0. Я не буду писать эти правила. Посмотрите, как это делалось в разделе, посвященном firewall. Единственное добавление — теперь надо явно указывать output интерфейс при помощи параметра –o.

Последнее замечание — NAT преобразования. Нам необходимо делать NAT только на интерфейсе eth0. На интерфейсе tap0 ничего делать не надо. Там пакеты идут без преобразования.

Решение задачи 2.

А тут я поступлю немного хитрее. Я хочу, что бы вы сами решили эту задачу. Если все заработает, значит, вы все поняли правильно. Если не заработает, присылайте мне ваше решение. У нас будет тема для обсуждения.

Единственная подсказка — трафик на 22 порт удаленного сервера не пускайте через VPN. Если вдруг не получится, вы хоть сможете подключиться к удаленному серверу. И вторая причина — в этом соединении уже итак все зашифровано J.