Классические туннели, такие как GRE и IPIP, знакомы каждому админу. Однако Linux не ограничивается ими. Малоизвестные опции классических туннелей и более новые протоколы могут существенно упростить решение задач. В этой статье мы рассмотрим несколько не самых распространенных протоколов и научимся управлять ими с помощью iproute2, стандартного инструмента для работы с сетевым стеком Linux.

INFO

Здесь и далее в качестве условных публичных адресов IPv4 я использую сети 192.0.2.0/24, 198.51.100.0/24 и 203.0.113.0/24, которые в RFC 5737 зарезервированы для примеров и документации.

 

Dual stack GRE

Для передачи IPv4 поверх IPv4 часто используют IPIP, для передачи IPv6 поверх IPv4 — SIT, а для передачи IPv6 поверх IPv6 есть IP6IP6, хотя случаи его применения мне неизвестны. Недостаток в том, что для сети с dual stack потребовалось бы больше одного туннеля.

GRE может решить обе задачи одновременно. В Linux достаточно добавить на туннельный интерфейс адреса из обоих протоколов.

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

Создаем туннель.

$ ip tunnel add tun0 mode gre local 203.0.113.10 remote 198.51.100.20
$ ip link set dev tun0 up

Добавляем адреса.

$ ip address add 10.10.10.1/24 dev tun0
$ ip address add 2001:db8:1::1/64 dev tun0

Важно помнить, что туннели в Linux создаются в выключенном (down) состоянии. Не забывай добавлять в скрипты ip link set dev ... up.

 

gretap

Классический GRE инкапсулирует пакеты IP. Однако протокол не просто так называется generic routing encapsulation. Он вполне может передавать и кадры протоколов канального уровня.

В заголовках GRE для протокола инкапсулированного пакета есть отдельное поле, куда пишется EtherType нагрузки, и пакет помещается в полезную нагрузку целиком. А сам GRE — отдельный протокол IP с номером 47. Детали можно узнать из RFC 2784.

Команды для настройки несколько отличаются от обычного GRE:

$ ip link add tun0 type gretap local 192.0.2.10 remote 203.0.113.20
$ ip link set dev tun0 up

Если мы просто присвоим туннелю адрес и будем маршрутизировать через него трафик, особой пользы от того, что он работает на канальном уровне, мы не увидим. Зато его можно объединить в мост с физическим интерфейсом и отправить весь трафик из сегмента L2 на другую сторону туннеля.

Объединим интерфейсы eth2 и tun0 в мост br0:

$ ip link add br0 type bridge
$ ip link set dev br0 up

$ ip link set dev eth2 master br0
$ ip link set dev tun0 master br0
 

Несколько туннелей GRE к одному хосту

Обычно между двумя маршрутизаторами настраивают по одному туннелю. Что, если нужно больше, например для тестов? У GRE есть на это ответ. Можно указать «ключ» и создать своего рода кодовое разделение доступа. Если между хостами уже настроен обычный туннель, никаких трудностей это не вызовет.

$ ip tunnel add tun2 mode gre local 198.51.100.10 remote 203.0.113.20 key 1234
$ ip address add 10.10.10.1/28 dev tun2

$ ip tunnel add tun3 mode gre local 198.51.100.10 remote 203.0.113.25 key 3456
$ ip address add 10.10.20.1/28 dev tun3

Несмотря на название, к шифрованию эта опция не имеет никакого отношения — «ключ» передается в открытом виде и служит только для идентификации туннелей.

Продолжение доступно только подписчикам

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

Подпишись на «Хакер» по выгодной цене!

Подписка позволит тебе в течение указанного срока читать ВСЕ платные материалы сайта. Мы принимаем оплату банковскими картами, электронными деньгами и переводами со счетов мобильных операторов. Подробнее о подписке

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

  1. Аватар

    aandrusha

    17.05.2019 at 15:24

    «В отличие от L2TPv2, он может как работать прямо поверх IP (протокол 115), так и инкапсулироваться в UDP. Первый вариант лучше по производительности, но второй лучше проходит через NAT.»
    Мне кажется, что тут должно быть наоборот.

Оставить мнение

Check Also

Внутри x86-64 SystemV ABI. Как говорить с ядром Linux на его языке

Абстракция — основа программирования. Многие вещи мы используем, не задумываясь об их внут…