пятница, 25 января 2013 г.

Site-to-site туннель GRE через IPSEC на маршрутизаторе Cisco 2911R с использованием модуля шифрования NME-RVPN


Первая схема

Казалось бы, обыденная задача - объединить два офиса шифрованным каналом. Всего-то нужно построить site-to-site VPN и зашифровать с помощью crypto map. Все так и есть, если речь идет не о государственной структуре. Нельзя использовать вражеские шифровальные алгоритмы и железо. Именно под эту задачу были выбраны маршрутизаторы ISR второго поколения 2911R. Буква R в конце названия говорит о том, что данные рутеры были произведены на территории РФ. Для шифрования трафика будем использовать модули для этих рутеров - NME RVPN, выполненные в качестве карты расширения для ISR. Они несут на борту русский софт от компании S-Terra и, конечно же, «Крипто про». По сути, платы представляют собой отдельную машинку под управлением redhat linux с несколькими кастомными софтинами. Имеет один внешний порт помимо общей коммутационной шины, которой подключаются все подобные модули в ISR.

Для тестов я решил собрать схему, которая изображена на первом рисунке.


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

Как добавить dot1.q интерфейс

Эта процедура описана в мануале к модулю, но после выполнения указанных действий пакеты через созданный интерфейс у меня не ходили. Они явно фильтровались процессом vpnserver. Еще раз, перечитав раздел мануала, обратил внимание на следующее:
"Если командой if_mgr add был зарегистрирован новый защищаемый интерфейс после конвертирования cisco-like конфигурации, то для этого интерфейса будет выполняться неявное правило Drop All, так как при конвертировании cisco-like конфигурации фильтры для каждого интерфейса прописываются в отдельности При следующем конвертировании cisco-like конфигурации новый интерфейс будет добавлен в эту конфигурацию и для него будут действовать общие правила, как и для остальных интерфейсов."
Итак, добавляем драйвер на интерфейс, заходим в shell коммандой cs_console, заходим в контекст интерфейса, делаем shutdown, выходим из режима конфигурирования. Тут-то и происходит "конвертирование cisco-like конфигурации". Опять заходим в режим конфигурирования, даем no shutdown, лип-ти-ти, пакеты ходят. Единственное, что нужно знать (на что я наткнулся) cs_console некорректно переписывает файл интерфейса, если интерфейс DOT1.Q. После проделывания данной операции исправьте файл /etc/sysconfig/network-scripts/ethX.X. В мануале написано, что ONBOOT должно быть равно FALSE. Я решил сделать true. После рубута интерфейс поднялся, но пакеты опять не ходили. Сделал по мануалу - добавил в /etc/rc.local строчку "/sbin/ifup ethX.X"

Как зашифровать (стандартный конфиг)

Конфигурацию для пробного запуска взял из "RVPN_Quick_Start_Guide.pdf".

В первой схеме я разбил маршрутизатор на 2 vrf: LAN и глобальный. Связующим звеном для них, как раз, являлся модуль RVPN. IPSEC туннель стартовал в модуле одного рутера, заканчивался, соответственно, в модуле другого. GRE туннель стартовал с внешних интерфейсов глобальной таблицы маршрутизации рутеров. Таким образом, получалось, что заголовки GRE не шифровались, а полезная нагрузка уже шла в виде ESP.


Получилось так:



Не самый подходящий вариант, поэтому я не стал на нем останавливаться.
Замечу, что в этой схеме IPSEC туннель строится без применения NAT, поэтому модуль без проблем заработал на конфиге из стартового мануала.

Вторая схема.

Главное отличие второй схемы от первой в том, что GRE туннель строится внутри шифрованного IPCES туннеля. IPSEC туннель строится с "внешних" для данной схемы интерфейсов платы RVPN. Из схемы видно, что эти интерфейсы являются внутренними для рутера и имеют private ip адреса. Таким образом, мы подошли к тому, что нужно использовать NAT для организации IPSEC туннеля.




И все было хорошо, пока не пришлось применить NAT.
Конфиг NAT на маршрутизаторе:

!
interface GigabitEthernet0/1.2141
 description WAN
 encapsulation dot1Q 2141
 ip address 10.199.1.2 255.255.255.252
 ip nat outside
 ip virtual-reassembly in
!
interface Special-Services-Engine1/0.33
 description RVPN-EXTERNAL
 encapsulation dot1Q 33
 ip address 192.168.252.254 255.255.255.0
 ip nat inside
 ip virtual-reassembly in
!
ip nat inside source list 99 interface GigabitEthernet0/1.2141 overload
ip nat inside source static udp 192.168.252.1 500 10.199.1.2 500 extendable
ip nat inside source static udp 192.168.252.1 4500 10.199.1.2 4500 extendable
access-list 99 permit 192.168.250.0 0.0.0.255
access-list 99 permit 192.168.252.0 0.0.0.255
access-list 99 permit 192.168.141.0 0.0.0.255

Для того, чтобы понять, что вообще происходит на модуле RVPN, нужно в режиме cisco-like дать комманду "logging trap debugging". С этого момента все происходящее можно смотреть в файле "/tmp/cspvpngate.log".
Первое, с чем пришлось столкнуться на второй схеме - проблема с идентификацией пира.

Проблема с идентификацией.

Jan 16 15:19:48 cspgate  vpnsvc: Partner's VPN Agent info: product: Gate; build: 3.1.10330; OS: Linux-RHEL5; CPU: i386
Jan 16 15:19:48 cspgate  vpnsvc: IKE proposals received from 10.199.1.2:500:
Jan 16 15:19:48 cspgate  vpnsvc:    Transform #1: Auth:Pre-Shared Key, Cipher:(65534), Hash:(65534), Group:MODP_1024, Life Time:86400
Jan 16 15:19:48 cspgate  vpnsvc: Check proposal #1, Protocol ISAKMP, Transform #1 for Rule "IKE_CMAP_1", Proposal #1, Protocol ISAKMP, Transform #1 - match
Jan 16 15:19:48 cspgate  vpnsvc: IKE proposals sent to 10.199.1.2:500:
Jan 16 15:19:48 cspgate  vpnsvc:    Transform #1: Auth:Pre-Shared Key, Cipher:(65534), Hash:(65534), Group:MODP_1024, Life Time:86400
Jan 16 15:19:48 cspgate  vpnsvc: [ISAKMP]: NAT detected on remote side, Partner: 10.199.1.2:500
Jan 16 15:19:48 cspgate  vpnsvc: [ISAKMP]: NAT detected on local side, Partner: 10.199.1.2:500
Jan 16 15:19:48 cspgate  vpnsvc: Using preshared key "cs_key_10_199_1_2" for partner 10.199.1.2:500
Jan 16 15:19:48 cspgate  vpnsvc: [ISAKMP]: Identity "192.168.252.1" is received from partner 10.199.1.2:4500
Jan 16 15:19:48 cspgate  vpnsvc: Unable to choose authentication rule for partner 10.199.1.2:500
Jan 16 15:19:48 cspgate  vpnsvc: [ISAKMP]: Incoming connection FAILED. [Main Mode, Responder, Packets 5,6, Pre-Shared Key] Check IDii ERROR, Partner: 10.199.1.2:4500

Смысл в том, что изначально он видит внешний адрес пира (в нашем случае 10.199.1.2 считаем внешним), видит привязанный к нему ключ, применяет его. Позже пир сообщает ему, что его настоящий адрес 192.168.252.1 и он за NAT. Этот ищет как авторизовать адрес 192.168 и не находит, в результате отвечая "Unable to choose authentication rule for partner". Вот как я это понял.
Поискал на форуме S-terra подобные ошибки, нашел решение.
Необходимо в cisco_like конфиге заменить строку "crypto isakmp identity address" на "crypto isakmp identity hostname", обозначить hostname пира двумя адресами (внешним и внутренним) строчками "ip host gw1 10.199.1.2", "ip host gw1 additional 192.168.252.1", поменять строчку ключа с "crypto isakmp key hMV21m4H hostname 10.199.1.2" на "crypto isakmp key hMV21m4H hostname gw1".
В результате решение выглядит так:

Было:
crypto isakmp identity address
crypto isakmp key hMV21m4H hostname 10.199.1.2

Стало:
crypto isakmp identity hostname
ip host gw1 10.199.1.2
ip host gw1 additional 192.168.252.1
crypto isakmp key hMV21m4H hostname gw1

Более он не ругался на идентификацию, но четко дал понять, что протокол AH не работает через NAT.

Проблема с натом (AH не натится):

Jan 16 16:04:47 gw2  vpnsvc: [ISAKMP]: Connection request FAILED. [Quick Mode, Initiator, Packet 1] [Get Local Policy] ERROR, Partner: 10.199.1.2:4500, Identity: gw1
Jan 16 16:04:47 gw2  vpnsvc: Connection request FAILED, Reason: AH and NAT are not compatible, ip: 10.199.1.2, Protocol: IPsec, Stopped at: [Quick Mode, Initiator, Packet 1] [Get Local Policy]
Jan 16 16:04:49 gw2  vpnsvc: Connection request, packet: 192.168.142.2->192.168.141.2, proto 1, FilteringRule: "Filter_nil_acl_CMAP_1"
Jan 16 16:04:49 gw2  vpnsvc: [ISAKMP]: Connection request FAILED. [Quick Mode, Initiator, Packet 1] [Get Local Policy] ERROR, Partner: 10.199.1.2:4500, Identity: gw1
Jan 16 16:04:49 gw2  vpnsvc: Connection request FAILED, Reason: AH and NAT are not compatible, ip: 10.199.1.2, Protocol: IPsec, Stopped at: [Quick Mode, Initiator, Packet 1] [Get Local Policy]
Jan 16 16:04:51 gw2  vpnsvc: Connection request, packet: 192.168.142.2->192.168.141.2, proto 1, FilteringRule: "Filter_nil_acl_CMAP_1"

Нет, так нет. Убираем AH. Заменяем строку "crypto ipsec transform-set gost ah-md5-hmac esp-des" строкой "crypto ipsec transform-set gost esp-des".
Решение:

Было:
crypto ipsec transform-set gost ah-md5-hmac esp-des

Стало:
crypto ipsec transform-set gost esp-des

После этого IPSEC туннель поднялся, но не поднялся GRE. Я упустил небольшой нюанс при создании туннеля из vrf. Я указал, что после создание интерфейс tu33 помещается в vrf LAN, а вот то, что создается он из этого же vrf, я не указал, и IOS пытался строить этот туннель из глобальной таблицы маршрутизации. После добавления строчки "tunnel vrf LAN" все завелось.
!
interface Tunnel33
 ip vrf forwarding LAN
 ip address 10.199.4.1 255.255.255.0
 ip mtu 1476
 ip tcp adjust-mss 1436
 ip ospf network broadcast
 ip ospf hello-interval 30
 tunnel source 192.168.250.254
 tunnel destination 192.168.249.254
 tunnel vrf LAN
!

Вторая схема дебаг:
C2911-RND-INT#ping vrf AVIA-LAN-R1 192.168.142.2
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.168.142.2, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 4/4/4 ms
C2911-RND-INT#ping vrf AVIA-LAN-R1 10.199.2.2
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 10.199.2.2, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/2/4 ms

--

C2911-RND-INT#traceroute vrf AVIA-LAN-R1
Protocol [ip]:
Target IP address: 10.199.2.2
Source address: 192.168.141.2
Numeric display [n]:
Resolve AS number in (G)lobal table, (V)RF or(N)one [G]:
Timeout in seconds [3]:
Probe count [3]:
Minimum Time to Live [1]:
Maximum Time to Live [30]:
Port Number [33434]:
Loose, Strict, Record, Timestamp, Verbose[none]:
Type escape sequence to abort.
Tracing the route to 10.199.2.2
VRF info: (vrf in name/id, vrf out name/id)
  1 192.168.141.1 0 msec 4 msec 0 msec
  2 192.168.250.1 0 msec 0 msec 0 msec
  3 192.168.252.254 4 msec 4 msec 0 msec
  4 10.199.1.1 4 msec 4 msec 0 msec

C2911-RND-INT#traceroute vrf AVIA-LAN-R1
Protocol [ip]:
Target IP address: 192.168.142.2
Source address: 192.168.141.2
Numeric display [n]:
Resolve AS number in (G)lobal table, (V)RF or(N)one [G]:
Timeout in seconds [3]:
Probe count [3]:
Minimum Time to Live [1]:
Maximum Time to Live [30]:
Port Number [33434]:
Loose, Strict, Record, Timestamp, Verbose[none]:
Type escape sequence to abort.
Tracing the route to 192.168.142.2
VRF info: (vrf in name/id, vrf out name/id)
  1 192.168.141.1 0 msec 4 msec 0 msec
  2 10.199.4.2 4 msec 4 msec 4 msec
  3 192.168.142.2 4 msec *  4 msec
 
Теперь получилось так:


На этом можно было бы остановиться, но мне не понравились два лишних хопа при направлении пакета в интернет. В интернет пакеты летят через модуль RVPN. Можно было сделать линк между vrf вланами через коммутатор и два интерфейса рутера, либо рут мапом перекинуть пакеты куда нужно, но у клиента коммутатор не поддерживает вланы, а рут мапом тоже не очень красиво получается из-за NAT. Итак, в данном случае нет никакой нужды использовать разбиение на vrf.

Третья схема.
После всех проб и ошибок образовалась простая и понятная схема. Как оказалось, именно она рассматривается первой в одном из мануалов по настройке site_to_site туннеля между рутерами с использованием модуля RVPN.


Но и тут небольшая проблемка. Падает ospf сессия в туннеле. Долго думать не пришлось. Приходит маршрут на сеть, в которой лежит адрес назначения туннеля, из-за чего ospf ругается на петлю "looped chain attempting to stack" и кладет сессию. Все решилось добавлением запрета на аннонс этой сети посредством использования distribute-list.

Проблема с падением ospf.

looped chain attempting to stack
Решение: не анонсировать маршрут назначения туннеля в сам туннель.

QOS

Остался последний штрих - настроить QOS. В одном офисе подключение 5 mbps, в другом adsl 8/1 (1 mbps исходящий). Используем политику для классификации на входе и иерархический шедулер на выходе.

Router1:

class-map match-all GW1TOGW2TUN
 match access-group name RVPN-IN
!
class-map match-all TUNNEL-INET-OUT-CLASS
 match access-group name TUNNEL-INET-OUT
!
policy-map mark-input
 class GW1TOGW2TUN
  set ip precedence 4
!
policy-map GW1-OUT
 class TUNNEL-INET-OUT-CLASS
  bandwidth percent 70
 class class-default
  fair-queue 32
policy-map GW1-OUT-PARENT
 class class-default
  shape average 5000000
   service-policy GW1-OUT
!
ip access-list extended RVPN-IN
 permit udp any any eq isakmp
 permit udp any any eq non500-isakmp
 permit esp any any
!
ip access-list extended TUNNEL-INET-OUT
 permit ip any any precedence flash-override
!
!
interface GigabitEthernet0/1.2141
 description WAN
 encapsulation dot1Q 2141
 ip address 10.199.1.2 255.255.255.252
 ip nat outside
 ip virtual-reassembly in
 service-policy output GW1-OUT-PARENT
!

Debug:
C2911-GW1#show policy-map interface gigabitEthernet 0/1.2141
 GigabitEthernet0/1.2141

  Service-policy output: GW1-OUT-PARENT

    Class-map: class-default (match-any)
      15112 packets, 6977168 bytes
      5 minute offered rate 163000 bps, drop rate 0 bps
      Match: any
      Queueing
      queue limit 64 packets
      (queue depth/total drops/no-buffer drops) 0/0/0
      (pkts output/bytes output) 15112/6977168
      shape (average) cir 5000000, bc 20000, be 20000
      target shape rate 5000000

      Service-policy : GW1-OUT

        Class-map: TUNNEL-INET-OUT-CLASS (match-all)
          15112 packets, 6977168 bytes
          5 minute offered rate 163000 bps, drop rate 0 bps
          Match: access-group name TUNNEL-INET-OUT
          Queueing
          queue limit 64 packets
          (queue depth/total drops/no-buffer drops) 0/0/0
          (pkts output/bytes output) 15112/6977168
          bandwidth 70% (3500 kbps)

        Class-map: class-default (match-any)
          0 packets, 0 bytes
          5 minute offered rate 0 bps, drop rate 0 bps
          Match: any
          Queueing
          queue limit 64 packets
          (queue depth/total drops/no-buffer drops/flowdrops) 0/0/0/0
          (pkts output/bytes output) 0/0
          Fair-queue: per-flow queue limit 16
                      Maximum Number of Hashed Queues 32


C2911-GW1#show policy-map interface Special-Services-Engine 1/0
 Special-Services-Engine1/0

  Service-policy input: mark-input

    Class-map: GW1TOGW2TUN (match-all)
      15171 packets, 6923154 bytes
      5 minute offered rate 0 bps, drop rate 0 bps
      Match: access-group name RVPN-IN
      QoS Set
        precedence 4
          Packets marked 15171

    Class-map: class-default (match-any)
      12079 packets, 6262861 bytes
      5 minute offered rate 0 bps, drop rate 0 bps
      Match: any                                                                   

C2911-GW1#show ip access-lists
Standard IP access list 99
    10 permit 192.168.35.0, wildcard bits 0.0.0.255 (8 matches)
    20 permit 10.199.5.252, wildcard bits 0.0.0.3 (2 matches)
Extended IP access list RVPN-IN
    10 permit udp any any eq isakmp (3365 matches)
    20 permit udp any any eq non500-isakmp (30482 matches)
    30 permit esp any any
Extended IP access list TUNNEL-INET-OUT
    10 permit ip any any precedence flash-override (15168 matches)


Router2:
class-map match-all GW2TOGW1TUN
 match access-group name RVPN-IN
!
class-map match-all TUNNEL-INET-OUT-CLASS
 match access-group name TUNNEL-INET-OUT
!
policy-map mark-input
 class GW2TOGW1TUN
  set ip precedence 4
!
policy-map GW2-OUT
 class TUNNEL-INET-OUT-CLASS
  bandwidth percent 70
 class class-default
  fair-queue 32
policy-map GW2-OUT-PARENT
 class class-default
  shape average 1000000
   service-policy GW2-OUT
!
ip access-list extended RVPN-IN
 permit udp any any eq isakmp
 permit udp any any eq non500-isakmp
 permit esp any any
!
ip access-list extended TUNNEL-INET-OUT
 permit ip any any precedence flash-override
!
interface GigabitEthernet0/1.2142
 description WAN
 encapsulation dot1Q 2142
 ip address 10.199.2.2 255.255.255.252
 ip nat outside
 ip virtual-reassembly in
 service-policy output GW1-OUT-PARENT
!

Вот и всё.










1 комментарий: