GRE через IPSec (Libreswan + MikroTik)

Здравствуйте!

Данная статья рассматривает пример реализации GRE через IPSec на основе связки LibreSwan + MikroTik

Предполагается наличие предустановленного Linux дистрибутива, стека iproute2+NetFilter+IPTABLES и поддержки автозагрузки скриптов Runlevel Local

Техническое задание

  • Реализовать Split Tunneling и, как следствие, разрешить выход в Интернет как через локального ISP, так и через туннель

  • Минимум финансовых вложений

Топология

e8edb706143500f0bfde57f0517af609.png

  • Топология представлена двумя зонами: Zone1 и Zone2

  • Каждая из зон имеет подключение к сети Интернет со статическими публичными адресами

  • Клиентский доступ предполагает возможность выхода в сеть как через ISP1, так и через ISP2

  • Наличие GRE позволяет описать IPSec SAs одним правилом по IP Protocol 47

Подбор оборудования

Требования Zone1:

  • Обеспечить динамическую конфигурацию CE интерфейса средствами PPP/DHCP opt. 82

  • Обеспечить связь в локальной средствами IEEE 802.11

  • Поддержка GRE, IPSec, PBR, NAT, Traffic Filtering

  • Удобство администрирования предполагает наличие GUI

  • Минимальные финансовые вложения 

Требования Zone2:

  • Поддержка GRE, IPSec, NAT, Traffic Filtering

  • Минимальные финансовые вложения 

Выводы:

Исходя из требований выбор «железа» пал на MikroTik RouterOS и стек Libreswan + IPTABLES. MikroTik и IPTABLES объяснять, думаю, излишне, а вот выбор Libreswan основывался на сравнении характеристик Libreswan/strongSwan

Credits to www.researchgate.net

Credits to www.researchgate.net

GRE

MikroTik

1ced53514c1d9f4aa2502b10bc22aea7.png429d5e459fa969801b3befd9e9921db2.png05ea8d05db9d8f11e0d0c50164255f59.png

Debian

modprobe ip_gre
  • Проверяем

lsmod | grep gre
ip tunnel add gre1 mode gre local PubIP2 remote PubIP1 ttl 255
ip addr add 10.254.254.254/30 dev gre1
ip link set gre1 up
  • Выставляем MTU с учетом размера заголовков IP (20 байт), GRE (4 байта), IPSec (64 байта)

ip link set dev gre1 mtu 1412
  • Проверяем

ifconfig gre1
gre1: flags=209  mtu 1412
        inet 10.254.254.254  netmask 255.255.255.252  destination 10.254.254.254
nano -w /etc/rc.local
# GRE
modprobe ip_gre
ip tunnel add gre1 mode gre local PubIP2 remote PubIP1 ttl 255
ip addr add 10.254.254.254/30 dev gre1
ip link set dev gre1 mtu 1412
ip link set gre1 up
nano -w /etc/iptables/rc.firewall
# GRE
gre_iface="gre1"
remote_peer="121.221.241.236"
$ipt -A INPUT -i $iface -p 47 -m state --state NEW -s $remote_peer -j ACCEPT
$ipt -A OUTPUT -o $iface -p 47 -m state --state NEW -d $remote_peer -j ACCEPT
$ipt -A INPUT -i $gre_iface -p icmp --icmp-type echo-request -m state --state NEW -j ACCEPT
  • Проверяем

/etc/iptables/rc.firewall
iptables -nvL

Тестируем

[username@fw1] > ping address=10.254.254.254 src-address=10.254.254.253 size=1500
  SEQ HOST                                     SIZE TTL TIME       STATUS
    0 10.254.254.254                                               timeout
    1 10.254.254.254                           1500  64 2ms488us
    2 10.254.254.254                           1500  64 1ms829us
    3 10.254.254.254                           1500  64 1ms883us
    4 10.254.254.254                           1500  64 1ms931us
    5 10.254.254.254                           1500  64 1ms953us
    sent=6 received=5 packet-loss=16% min-rtt=1ms829us avg-rtt=2ms16us max-rtt=2ms488us

IPSec

MikroTik

8ff3e06a7568c1b11e3cbff11c958e8e.pngb5ef5bc1fe6157559bf1bdb238212791.png

> /certificate/
/certificate> add name=root_ca common-name=root_ca key-size=2048 key-usage=key-cert-sign,crl-sign days-valid=3650

/certificate> print

/certificate> sign 0
/certificate> add name=fw1_ike common-name=fw1_ike key-size=2048 days-valid=3650
/certificate> add name=fw2_ike common-name=fw2_ike key-size=2048 days-valid=3650

/certificate> print

/certificate> sign 1 ca=root_ca
/certificate> sign 2 ca=root_ca

d4c2a5758aa718ab56ec2acbc7b2de8c.png

Несколько слов о Notrack Chain:

Все дело в том, что у MikroTik (впрочем у меня есть подозрение что это проблема netfilter) есть серьезные проблемы с трекингом IPSec (желающие попробовать вернуться в Dial-Up эру могут прогнать через FastTrack:)) Поэтому будем отключать в дальнейшем.

7f40fd19bf6b69c7bc28e4166665b066.png68b350e8bade8cb84da0d5fdccd2fdb8.png1902f015b1476fc50127e318bc683d01.png4bd06ee2689b4ef1c835c1b78b22cef9.png

Libreswan

apt install libreswan
ipsec initnss
certutil -W -d sql:/var/lib/ipsec/nss

Несколько слов о NSS:

NSS есть ничто иное как пользовательская библиотека используемая Libreswan IKE демоном pluto. NSS не обрабатывает IPSec криптографию внутри ядра; за это отвечают NETKEY или KLIPS модули.

Основной плюс использования NSS в том, что для pluto нет необходимости знать о том как работает криптографический шлюз. Pluto не требует доступа к ключам или данным, вместо этого используя PK11 wrapper API независимо от криптографического шлюза. Вся обработка осуществляется через доступ к NSS средствами PK11 интерфейса, тем самым избегая необходимости прямого доступа к ключам шифрования. Все IKE операции осуществляются с использованием NSS. RSA ключи (как чистые RSA, так и X.509 ключи) хранятся внутри NSS и не упоминаются напрямую в /etc/ipsec.secrets. X.509 ключи и сертификаты описываются при помощи их «никнеймов» (вместо их реальных имен) в /etc/ipsec.conf

touch /etc/ipsec.d/nsspassword
nano -w /etc/ipsec.d/nsspassword
NSS Certificate DB:secret
systemctl enable ipsec
systemctl status ipsec
  • Выгружаем сертификаты из MikroTik (System >> Certificates) На выходе получатся 3 PEM пары с защищенными паролем ключами

  • Загружаем на Libreswan сервер и снимаем защиту

openssl rsa -in root_ca.key_encr -out root_ca.key
openssl rsa -in fw1_ike.key_encr -out fw1_ike.key
openssl rsa -in fw2_ike.key_encr -out fw2_ike.key
openssl pkcs12 -export -in fw1_ike.crt -inkey fw1_ike.key -certfile root_ca.crt -out fw1_ike.p12 -name fw1_ike
openssl pkcs12 -export -in fw2_ike.crt -inkey fw2_ike.key -certfile root_ca.crt -out fw2_ike.p12 -name fw2_ike
certutil -A -a -i /home/username/certs/root_ca.crt -d sql:/var/lib/ipsec/nss -n "RootCA" -t 'CT,,'
ipsec import /home/username/certs/fw1_ike.p12
ipsec import /home/username/certs/fw2_ike.p12
touch /etc/ipsec.d/fw1-fw2.conf
nano -w /etc/ipsec.d/fw1-fw2.conf
conn fw1-fw2
        # Peers
        left=PubIP2
        right=PubIP1
        # Phase 1 Settings
        keyexchange=ike
        ikev2=insist
        ike=aes256-sha256;dh21
        ikelifetime=24h
        dpddelay=8s
        dpdtimeout=32s
        dpdaction=clear
        fragmentation=yes
        # IKEv2 Auth
        authby=rsasig
        leftcert=fw2_ike
        leftid=%fromcert
        leftsendcert=always
        leftrsasigkey=%cert
        rightcert=fw1_ike
        rightid=%fromcert
        rightca=%same
        rightrsasigkey=%cert
        # Phase 2 Settings
        type=tunnel
        phase2=esp
        phase2alg=aes256-sha256;dh21
        salifetime=12h
        rekey=yes
        pfs=yes
        # SAs
        leftsourceip=PubIP2
        leftprotoport=gre
        rightsourceip=PubIP1
        rightprotoport=gre
        # Auto Start During Bootup
        auto=start
  • Указываем интерфейс на котором будем слушать трафик (аргумент interfaces оказался устаревшим, работаем через listen) В том же файле при необходимости можно включить дебаги.

nano -w /etc/ipsec.conf
listen=PubIP2
systemctl restart ipsec
systemctl status ipsec
nano -w /etc/iptables/rc.firewall
# IPSec
$ipt -A INPUT -i $iface -p udp -m state --state NEW -s $remote_peer --dport 500 -j ACCEPT
$ipt -A OUTPUT -o $iface -p udp -m state --state NEW -d $remote_peer --dport 500 -j ACCEPT
$ipt -A INPUT -i $iface -p 50 -m state --state NEW -s $remote_peer -j ACCEPT
$ipt -A OUTPUT -o $iface -p 50 -m state --state NEW -d $remote_peer -j ACCEPT
  • Проверяем

/etc/iptables/rc.firewall
iptables -nvL

Тестируем

[username@fw1] > ping address=10.254.254.254 src-address=10.254.254.253 size=1500
  SEQ HOST                                     SIZE TTL TIME       STATUS
    0 10.254.254.254                                               timeout
    1 10.254.254.254                           1500  64 3ms69us
    2 10.254.254.254                           1500  64 2ms865us
    3 10.254.254.254                           1500  64 2ms861us
    4 10.254.254.254                           1500  64 2ms918us
    5 10.254.254.254                           1500  64 2ms944us
    sent=6 received=5 packet-loss=16% min-rtt=2ms861us avg-rtt=2ms931us max-rtt=3ms69us
ipsec whack --trafficstatus

Маршрутизация и NAT

MikroTik

516d394401170dd0bd45d7104238ea6d.png623327339fbfa0bd70da39dfbdb82842.pngcba9be77c0ff4105467856e7a70b4447.pngf49dd20fadb1d5e966949ac1511c48bc.pngf2460236596369ca3a90df0ba58acc96.png250395c74fdb58b4d0f80ba283518e54.png9f67d2b07624a88d868df44264761ef4.png888f22de765bb779f657d5320e6d3a0f.png

Тестируем

ping 10.254.254.254 -l 1500

Pinging 10.254.254.254 with 1500 bytes of data:
Reply from 10.254.254.254: bytes=1500 time=2ms TTL=63
Reply from 10.254.254.254: bytes=1500 time=2ms TTL=63
Reply from 10.254.254.254: bytes=1500 time=3ms TTL=63
Reply from 10.254.254.254: bytes=1500 time=3ms TTL=63

Ping statistics for 10.254.254.254:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 2ms, Maximum = 3ms, Average = 2ms

Заключение

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

Закончить хотелось бы выходом «наружу» :) Тем более у нас с вами остался нерассмотренным вопрос проблемы FastTrack.

Приступим !

nano -w /etc/sysctl.conf
net.ipv4.ip_forward=1
sysctl -p
# Stateful rules
$ipt -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

#
# FORWARD
#

# GRE FWD
$ipt -A FORWARD -i $gre_iface -m state --state NEW -j ACCEPT

#
# NAT
#

# OB MASQUERADE
$ipt -t nat -A POSTROUTING -o $iface ! -p 47 -j MASQUERADE
$ipt -t nat -A POSTROUTING -o $iface -p udp ! --dport 500 -j MASQUERADE
$ipt -t nat -A POSTROUTING -o $iface ! -p 50 -j MASQUERADE
  • Проверяем

iptables -nvL
iptables -nvL -t nat

ab54271d8d437f806115d5f52e378738.png103b4fc3eb523b70d2aa7f7fc29d73e5.pngddebbd721c583661b2c887caf67d8dcc.pngba38bf9518fd382eb6adcc46eb37923d.pnge9419d8f6ae874146af409b09713b813.png

tracert -d 8.8.8.8

Tracing route to 8.8.8.8 over a maximum of 30 hops

  1    <1 ms    <1 ms    <1 ms  10.10.10.10
  2     7 ms     2 ms    11 ms  58.162.26.204
  3     1 ms     1 ms     1 ms  203.50.60.72
  4     2 ms     2 ms     3 ms  203.50.61.144
  5     2 ms     2 ms     1 ms  203.50.11.195
  6     3 ms     2 ms     2 ms  142.250.162.28
  7     2 ms     2 ms     2 ms  142.250.234.217
  8     3 ms     3 ms     2 ms  216.239.59.109
  9     2 ms     2 ms     1 ms  8.8.8.8

Trace complete.
tracert -d null.somedomain.name

Tracing route to null.somedomain.name [45.32.236.11]
over a maximum of 30 hops:

  1    <1 ms    <1 ms    <1 ms  10.10.10.10
  2     2 ms     2 ms     2 ms  10.254.254.254
  3     *        *        *     Request timed out.
  4     2 ms     2 ms     2 ms  100.100.200.1
  5    11 ms    10 ms    31 ms  10.91.0.1
  6     2 ms     2 ms     2 ms  10.91.0.17
  7     2 ms     2 ms     2 ms  10.91.0.1
  8    80 ms     9 ms     7 ms  67.199.141.33
  9   244 ms   244 ms   244 ms  141.136.106.174
 10     *        *        *     Request timed out.

На этом все:) Спасибо всем, кто дочитал до конца и по традиции ссылка на внешний ресурс  — заглядывайте иногда.

Буду рад ответить на вопросы по теме.

© Habrahabr.ru