Туннелирование и частные сети

Туннелирование: использование некоторого потока данных для инкапсуляции (в общем случае — произвольного) сетевого трафика.

TODO вспомнить про SRv6 и вообще про ip route encap. Нужен пример encap/decap для Д/З.

Простейший туннель: IP over IP

TODO изобрести новый термин для «over» вместо «поверх»: «поверх» ассоциируется с «поверхностью» (обёрткой), хотя в действительности наоборот.

Использование

IP6 over IP6 — это как-то скучно! Ради большей наглядности пустим IP4 поверх IP6.

Обычная схема:

[root@router ~]# sysctl net.ipv{6,4}.conf.all.forwarding
net.ipv6.conf.all.forwarding = 1
net.ipv4.conf.all.forwarding = 0

Настроим передачу IPv4 в тоннеле:

[root@client ~]# ip -6 -br a show scope global
eth1             UP             2a00:f480:8:cc5:a00:27ff:fe1a:ffa/64 
[root@client ~]# ip link add name over0 type ip6tnl mode ipip6 local 2a00:f480:8:cc5:a00:27ff:fe1a:ffa remote 2a00:f480:8:cde:a00:27ff:fee3:f50e
[root@client ~]# ip link set over0 up
[root@client ~]# ip a add 10.50.0.1/24 dev over0
# это IPv4; здесь весь префикс on-link, и назначился маршрут на over0
[root@client ~]# ip -d link show over0
<...>

[root@srv ~]# ip -6 -br a
lo               UNKNOWN        ::1/128 
eth1             UP             2a00:f480:8:cde:a00:27ff:fee3:f50e/64 fe80::a00:27ff:fee3:f50e/64 
[root@srv ~]# ip tunnel add over0 mode ipip6 local 2a00:f480:8:cde:a00:27ff:fee3:f50e remote 2a00:f480:8:cc5:a00:27ff:fe1a:ffa
[root@srv ~]# ip link set over0 up
[root@srv ~]# ip a add 10.50.0.2/24 dev over0 
# это IPv4; здесь весь префикс on-link, и назначился маршрут на over0
[root@srv ~]# ip -d link show over0
<...>

Ядро Linux приписывает к внешнему заголовку destination option "Tunnel Encap Limit" rfc2473, равный 4.

TODO Даже tshark тянет over 120 Мб собственной библиотеки. Предложить скачать результат запуска tcpdump -w и посмотреть на хосте с помощью хостового wireshark?

Паста из wireshark:

Frame 1: Packet, 146 bytes on wire (1168 bits), 146 bytes captured (1168 bits)
Ethernet II, Src: PCSSystemtec_1a:0f:fa (08:00:27:1a:0f:fa), Dst: PCSSystemtec_d7:92:2a (08:00:27:d7:92:2a)
    Destination: PCSSystemtec_d7:92:2a (08:00:27:d7:92:2a)
    Source: PCSSystemtec_1a:0f:fa (08:00:27:1a:0f:fa)
    Type: IPv6 (0x86dd)
Internet Protocol Version 6, Src: 2a00:f480:8:cc5:a00:27ff:fe1a:ffa, Dst: 2a00:f480:8:cde:a00:27ff:fee3:f50e
    0110 .... = Version: 6
    .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT)
    .... 0001 1011 0001 1000 1110 = Flow Label: 0x1b18e
    Payload Length: 92
    Next Header: Destination Options for IPv6 (60)
    Hop Limit: 64
    Source Address: 2a00:f480:8:cc5:a00:27ff:fe1a:ffa
    Destination Address: 2a00:f480:8:cde:a00:27ff:fee3:f50e
    [Source SLAAC MAC: PCSSystemtec_1a:0f:fa (08:00:27:1a:0f:fa)]
    [Destination SLAAC MAC: PCSSystemtec_e3:f5:0e (08:00:27:e3:f5:0e)]
    Destination Options for IPv6
        Next Header: IPIP (4)
        Length: 0
        [Length: 8 bytes]
        Tunnel Encapsulation Limit
            Type: Tunnel Encapsulation Limit (0x04)
            Length: 1
            Tunnel Encapsulation Limit: 4
        PadN
            Type: PadN (0x01)
            Length: 1
            PadN: 00
Internet Protocol Version 4, Src: 10.50.0.1, Dst: 10.50.0.2
Internet Control Message Protocol

TODO добавить сюда короткое толкование нужных для темы «туннели» опций из пасты, а остальные, если надо, просто снабдить короткими ссылками (в частности, текст ниже — это оверкилл)

   There are two padding options which are used when necessary to align
   subsequent options and to pad out the containing header to a multiple
   of 8 octets in length.  These padding options must be recognized by
   all IPv6 implementations:

   Pad1 option  (alignment requirement: none)

      +-+-+-+-+-+-+-+-+
      |       0       |
      +-+-+-+-+-+-+-+-+

      NOTE! the format of the Pad1 option is a special case -- it does
            not have length and value fields.

      The Pad1 option is used to insert one octet of padding into the
      Options area of a header.  If more than one octet of padding is
      required, the PadN option, described next, should be used, rather
      than multiple Pad1 options.

   PadN option  (alignment requirement: none)

      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - -
      |       1       |  Opt Data Len |  Option Data
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - -

      The PadN option is used to insert two or more octets of padding
      into the Options area of a header.  For N octets of padding, the
      Opt Data Len field contains the value N-2, and the Option Data
      consists of N-2 zero-valued octets.

Проверим, что туннель работает

зарежем TCP на router:

Какой-нибудь date | netcat 10.50.0.242 80 должен продолжать работать (потому что через router проходит не TCP, а IP)

Недостатки

TODO разъяснить: ipip0 — «не совсем настоящий» интерфейс (только p2p, без MAC и т. п.)

IP6 over TCP «на скорую руку» с socat

TODO переделать на TUN:/ipv6

В socat есть работа с tun/tap устройствами. Буквально в одну строку из них делается полноценный тоннель:

[root@srv ~]# socat TCP6-LISTEN:1337,fork,reuseaddr TUN:192.168.255.1/24,up </dev/null &

и

[root@client ~]# socat TCP:сервер:1337 TUN:192.168.255.27/24,up </dev/null &

Результат:

[root@client ~]# ip -4 r
192.168.200.0/24 dev tun0 proto kernel scope link src 192.168.200.2

[root@client ~]# ping -c2 192.168.200.1
PING 192.168.200.1 (192.168.200.1) 56(84) bytes of data.
64 bytes from 192.168.200.1: icmp_seq=1 ttl=64 time=3.64 ms
64 bytes from 192.168.200.1: icmp_seq=2 ttl=64 time=3.16 ms

--- 192.168.200.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 3.159/3.399/3.639/0.240 ms

* посмотреть tcpdump на router

l2tp — фреймы в IP или UDP

TODO В идеале — вообще не использовать IP-адреса, а прокинуть что-то, чему нужен непосредственно L2. Если не получится — всё-таки заменить IP4 на IP6.

Можно туннелировать не IP-пакеты, а фреймы — например, при помощи L2TP.

Всё по документации — скажем, с инкапсуляцией не в IP, а в UDP; и для простоты — без bridge

Особенности:

Виртуальный интерфейс l2tpeth можно добавить в bridge c локальным интерфейсом — тогда абоненты из туннелей окажутся в одном сегменте с абонентами локальной сети

WireGuard

Сайт, и конечно Arch-вики

TODO Переделать grep "" … в cat …

Начальная настройка:

[root@srv ~]# grep -r "" /etc/systemd/network*
/etc/systemd/network/50-intnet.network:[Match]
/etc/systemd/network/50-intnet.network:Name = eth1
/etc/systemd/network/50-intnet.network:
/etc/systemd/network/50-intnet.network:[Network]
/etc/systemd/network/50-intnet.network:Address=2a00:f480:8:e50::918/64
/etc/systemd/network/50-intnet.network:
/etc/systemd/network/50-intnet.network:[Route]
/etc/systemd/network/50-intnet.network:Destination=2a00:f480:8:e60::/64
/etc/systemd/network/50-intnet.network:Gateway=_ipv6ra

TODO Пояснения относительно Gateway=_ipv6ra

[root@router ~]# grep -r "" /etc/systemd/network*
/etc/systemd/network/50-intnet.network:[Match]
/etc/systemd/network/50-intnet.network:Name = eth1
/etc/systemd/network/50-intnet.network:
/etc/systemd/network/50-intnet.network:[Network]
/etc/systemd/network/50-intnet.network:Address=2a00:f480:8:e50::919/64
/etc/systemd/network/60-deepnet.network:[Match]
/etc/systemd/network/60-deepnet.network:Name=eth2
/etc/systemd/network/60-deepnet.network:
/etc/systemd/network/60-deepnet.network:[Network]
/etc/systemd/network/60-deepnet.network:Address=2a00:f480:8:e60::919/64
/etc/systemd/networkd.conf:[Network]
/etc/systemd/networkd.conf:IPv6Forwarding=yes

[root@client ~]# grep -r "" /etc/systemd/network*
/etc/systemd/network/60-deepnet.network:[Match]
/etc/systemd/network/60-deepnet.network:Name=eth1
/etc/systemd/network/60-deepnet.network:
/etc/systemd/network/60-deepnet.network:[Network]
/etc/systemd/network/60-deepnet.network:Address=2a00:f480:8:e60::91a/64
/etc/systemd/network/60-deepnet.network:
/etc/systemd/network/60-deepnet.network:[Route]
/etc/systemd/network/60-deepnet.network:Destination=2a00:f480:8:e50::/64
/etc/systemd/network/60-deepnet.network:Gateway=_ipv6ra

Ручная настройка

Лайфхак для копипасты:

# wg genkey | tee /dev/stderr | wg pubkey

Для настройки вручную на сервере нужно

На клиенте:

TODO добавить конкретный пример (хотя бы на уровне ip a / wg showconf)

Настройка средствами networkd

TODO Перейти на PrivateKeyFile

Для systemd-networkd:

Сервер:

Клиент:

Д/З

wg — route encap/decap — наблюдатель — route encap/decap — wg

LecturesCMC/LinuxNetwork2026/Six/11_TunnelingVPN (последним исправлял пользователь FrBrGeorge 2026-06-01 22:05:10)