Saturday, July 27, 2013

GRE туннель Linux-Cisco. Когда нужна альтернативная адресация



Тут будет реализована немного извращенная, но таки достаточно интересная топология. Все изначально просто: есть сервер, выставленный в Интернет, и есть клиент, который по какой-то причине не может получить доступ до этого сервера. Забанил провайдер его по IP. Переживает бедный. А сервер то наш, нехорошо, когда клиенты доступ к нему получить не могут. Но мы серьезные люди, нас таким не напугаешь, мы и ход конем можем сделать. Например, арендовать сервер в облаке с двумя адресами, такие сейчас копейки стоят, по три рубля килограмм, и построить маршрутизацию через него. Точнее, построить GRE-туннель, а потом маршрутизацию через туннель. В DNS-записях, в свою очередь, будет фигурировать адрес вот этого самого арендованного сервера, а к нему то клиент доступ получить может. Топология этого извращения изображена на рисунке.
 

Для тех, кто не знал и забыл, напоминаю, что GRE-туннель, это такой туннель, когда данные не шифруются, а к пакету просто присоединятся заголовок третьего уровня с другими адресами и пакет отправляется дальше. При необходимости пакет можно фрагментировать. Остается настроить маршрутизатор на Linux и маршрутизатор на Cisco IOS.

Часть 1. Linux Router.

Итак, приступим, в первой части будем настраивать роутер на моем любимом Debian Linux. Система свежеустановленная. Адресация у нас будет выглядеть, как показано на рисунке.

 
Есть два публичных адреса, на один мы будем принимать соединения, а с другого построим туннель на нашу Циску. Внутренняя адресация, которая будет использоваться для туннеля, тоже показана на рисунке. Пусть у Linux будет 172.16.0.1, а у Cisco – 172.16.0.2

План у нас такой:
  1. Настраиваем интерфейсы
  2. Настраиваем туннель
  3. Настраиваем NAT
  4. Указываем маршруты
 1. Этот пункт гуглится за 3 с половиной минуты. Так что не будем тут задерживаться. Редактируем файл /etc/network/interfaces и приводим его к такому виду
auto lo
iface lo inet loopback

auto eth1
iface eth1 inet static
 address 91.29.21.2
 netmask 255.255.255.248
 gateway 91.29.21.1

auto eth2
iface eth2 inet static
 address 91.29.21.4
 netmask 255.255.255.248
 gateway 91.29.21.1
Коментариии тут излишни, этим мы устанавливаем интерфейсам адреса, маски и т.д.
Перезапускаем сеть, проверяем, что все работает.
root@POWERSERVER:~# service networking restart
 2. Открываем опять файл /etc/network/interfaces и теперь будем действовать хитро.

Удаленная локальная сеть с сервером у нас 10.1.0.0/24.
Создадим тунельный интерфейс с адресом 172.16.0.1. В действиях, которым положено выполняться в первую очередь перед поднятием интерфейса укажем командой создание GRE-туннеля к удаленному адресу из локального нашего интерфейса.

auto tun1
iface tun1 inet static
 address 172.16.0.1
 netmask 255.255.255.252
 up ifconfig tun1 multicast
 pre-up iptunnel add tun1 mode gre remote 144.43.21.2 local 91.29.21.4 ttl 20
 post-down iptunnel del tun1
 3. Тут мы будем использовать iptables. Создадим файл с правилами. В правилах будет указано, что все, что приходит на адрес интерфейса eth1 преобразовывалось с помощью NAT. Изменять будем адрес назначения с адреса интерфейса на локальный адрес удаленного сервера. Потом, чтобы это все успешно проходило маршрутизацию. В конечном итоге, чтобы все, что приходит с адреса удаленного сервера и уходит в Интернет через наш внешний интерфейс преобразовывалось обратно с через тот же NAT.

#!/bin/bash
iptables -F
iptables -X
iptables -P INPUT ACCEPT #accept all input packetes by default
iptables -F INPUT
iptables -P OUTPUT ACCEPT #accept all output packets by default
iptables -F OUTPUT
iptables -P FORWARD DROP #drop all forwarding packets by default
iptables -F FORWARD

iptables -t nat -F
iptables -t mangle -F
iptables -t nat -X
iptables -t mangle -X

iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i eth1 -j ACCEPT
iptables -A INPUT -i eth2 -j ACCEPT
iptables -A INPUT -i tun1 -j ACCEPT

iptables -t nat -A PREROUTING -i eth1 -d 91.29.21.2 -j DNAT --to-destination 10.1.0.4

iptables -A FORWARD -i eth1 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -s 10.1.0.0/24 -i tun1 -j ACCEPT
iptables -A FORWARD -d 10.1.0.4/32 -i eth1 -j ACCEPT
 
iptables -t nat -A POSTROUTING -o eth1 -s 10.1.0.4 -j SNAT --to-source 91.29.21.2

Для автозапуска вместе с сетью положим его в папку /etc/network/if-up.d/
и не забываем добавить права на выполнение
root@POWERSERVER:~# chmod +x /etc/network/if-up.d/iptables_rules
4.Первым делом необходимо разрешить роутинг во всей системе. По-умолчанию это запрещено. Проверить можно с помощью чтения значения из файла
root@POWERSERVER:~# cat /proc/sys/net/ipv4/ip_forward
0
Если там 0, то роутинг запрещен, если 1 – разрешен. Установим 1:
root@POWERSERVER:~# echo 1 > /proc/sys/net/ipv4/ip_forward
Чтобы не делать этого каждый раз после перезагрузки открываем файл /etc/sysctl.conf и раскоментируем там строку
net.ipv4.ip_forward=1
Дальше нам надо указать маршрут в удаленную сеть с сервером, пакеты будут перенаправляться на туннельный адрес Cisco-маршрутизатора.
root@POWERSERVER:~# ip route add 10.1.0.0/24 via 172.16.0.2 metric 10
Метрику тут я задал потому что в будущем еще планирую донастроить балансировку через двух провайдеров. В данном случае она не обязательна. Дабы не повторять это каждый раз, можно создать файл /etc/network/if-up.d/route и внести туда эту команду. Что-то вроде того, что было сделано с правилами iptables. Итак, создаем файл, делаем его исполняемым и вносим туда следующие строки
#!/bin/bash
ip route add 10.1.0.0/24 via 172.16.0.2 metric 10
Перезагружаемся и проверяем таблицу маршрутизации
root@POWERSERVER:~# ip route
default via 91.29.21.1 dev eth1
10.1.0.0/24 via 172.16.0.2 dev tun1  metric 10
91.29.21.0/29 dev eth1  proto kernel  scope link  src 91.29.21.2
91.29.21.0/29 dev eth2  proto kernel  scope link  src 91.29.21.4
172.16.0.2 dev tun1  proto kernel  scope link  src 172.16.0.1
root@POWERSERVER:~#


Все маршруты на месте. Можно переходить к настройке Cisco.

Что же у нас получилось. Пакеты, которые приходят на адрес 91.29.21.2 попадают под правила iptables и там изменяется адрес получателя на адрес удаленного сервера 10.1.0.4, потом этот пакет проходит цепочку роутинга, а согласно таблице маршрутизации он должен направляться на адрес 172.16.0.2, а это адрес доступен через тунельный интерфейс. Таким образом пакет с адресом назначения удаленного сервера отправляется через GRE-туннель.

Часть 2. Роутер Cisco

И вот когда у нас настроен наш Linux-роутер перейдем к Cisco. Тут мы будем использовать технологию policy based routing. Суть технологии проста, пакеты, которые отвечают определенным критериям маршрутизируются по отдельным правилам вне зависимости от того, что написано в таблице маршрутизации. Это для того, чтоб остальные товарищи, которые ходят в Интернет через этот же роутер не затрагивались.

1. Настроим туннельный интерфейс. Внешние интерфейсы имеют вид
 
interface FastEthernet0/0
 ip address 144.43.21.2 255.255.255.248
 duplex auto
 speed auto
end
interface FastEthernet0/1
 ip address 10.1.0.1 255.255.255.0
 duplex auto
 speed auto
end

Как видно из адресации, интерфейс FastEthernet0/0 у нас смотрит в мир, а FastEthernet0/1 является внутренним интерфейсом. Перейдем к созданию туннеля.
Router(config)#interface Tunnel0
Router(config-if)# ip address 172.16.0.2 255.255.255.0
Router(config-if)# tunnel source 144.43.21.2
Router(config-if)# tunnel destination 91.29.21.4
Router(config-if)#
Указывем адрес его (припоминаем, что этот адрес у нас использовался при конфигурировании linux-маршрутизатора), тут же указаны адреса откуда и куда он должен стоиться.

2. Настоим политики маршрутизации. Первым делом создадим список доступа для фильтрации адресов. В данном случае я использую всю подсеть, хотя можно указать конкретный адрес нашего сервера.
Router(config)#ip access-list extended SERVER
Router(config-ext-nacl)# permit ip 10.1.0.0 0.0.0.255 any
Router(config-ext-nacl)#
Теперь создадим карту маршрутизации.
Router(config)#route-map From-server permit 10
Router(config-route-map)# match ip address SERVER
Router(config-route-map)# set ip next-hop 172.16.0.1
Router(config-route-map)#
Этим мы указываем, что траффик, который попадает под созданный нами спосок доступа должен перенаправляться на алрес 172.16.0.1. А это, как мы помним, адрес тунельного интерфейса Linuxa. Теперь эту политику нужно применить к интерфейсу. Конечно же к внутреннему.
Router(config)#interface fastEthernet 0/1
Router(config-if)# ip policy route-map From-server
Router(config-if)#
Что мы тут получили. Трафик, который будет приходит от linuxa будет успешно перенаправляться на сервер, так как пакеты имеют его адрес. Пакеты, которые идут от сервера попадают под правило, которое перенаправляет их через туннель обратно на linux, а там они проходят обратное правило NAT и адрес источника заменяется из адреса сервера на публичный адрес linux-маршрутизатора и уходят в мир.

Вот такая нехитрая но рабочая схема.

No comments:

Post a Comment