Настройка OpenVPN с поддержкой Data Channel Offload (DCO) на Fedora 38

В прошлой статье мы рассмотрели в целом, что такое DCO в OpenVPN и как его запустить на Rocky Linux 9. Здесь же я расскажу, как проделать то же самое, только для Fedora 38.

Итак, имеем систему на Fedora 38, которая бежит на ядре 6.4.14-200.fc38.x86_64, установлен openvpn из стандартных репозиториев Fedora:

# dnf info openvpn
Last metadata expiration check: 1:12:41 ago on Sun 10 Sep 2023 03:31:03 PM MSK.
Installed Packages
Name         : openvpn
Version      : 2.6.6
Release      : 1.fc38
Architecture : x86_64
Size         : 1.7 M
Source       : openvpn-2.6.6-1.fc38.src.rpm
Repository   : @System
From repo    : updates
Summary      : A full-featured TLS VPN solution (beta release)
URL          : https://community.openvpn.net/
License      : GPLv2
Description  : OpenVPN is a robust and highly flexible tunneling application that uses all
             : of the encryption, authentication, and certification features of the
             : OpenSSL library to securely tunnel IP networks over a single UDP or TCP
             : port.  It can use the Marcus Franz Xaver Johannes Oberhumers LZO library
             : for compression.

Для того, чтобы включить поддержку DCO, необходимо установить модуль ядра ovpn-dco. Сделать это можно через copr репозиторий openvpn3, либо из исходников, взяв последние из репозитория на GitHub или GitLab.

Установка через copr

Подключаем репозиторий и ставим пакет kmod-ovpn-dco.

# dnf copr enable dsommers/openvpn3
Enabling a Copr repository. Please note that this repository is not part
of the main distribution, and quality may vary.
...
Do you really want to enable copr.fedorainfracloud.org/dsommers/openvpn3? [y/N]: y
Repository successfully enabled.

Ставим пакет:

# dnf install -y kmod-ovpn-dco

Во время установки на систему приедет пакет kmod-ovpn-dco с исходниками модуля ядра и запустится его сборка при помощи DKMS.

Однако, на момент написания этого поста установка заканчивалась неудачей.

Ошибка во время dnf install
Running transaction
  Preparing        :                                                                                                                                                                                                                      1/1
  Installing       : kernel-devel-matched-6.4.14-200.fc38.x86_64                                                                                                                                                                          1/3
  Installing       : dkms-3.0.11-1.fc38.noarch                                                                                                                                                                                            2/3
  Running scriptlet: dkms-3.0.11-1.fc38.noarch                                                                                                                                                                                            2/3
Created symlink /etc/systemd/system/multi-user.target.wants/dkms.service → /usr/lib/systemd/system/dkms.service.

  Installing       : kmod-ovpn-dco-0-20220905git3ba6c07.fc38.noarch                                                                                                                                                                       3/3
  Running scriptlet: kmod-ovpn-dco-0-20220905git3ba6c07.fc38.noarch                                                                                                                                                                       3/3
Loading new ovpn-dco-0.20220905git3ba6c07.fc38 DKMS files...
Deprecated feature: REMAKE_INITRD (/usr/src/ovpn-dco-0.20220905git3ba6c07.fc38/dkms.conf)
Building for 6.4.14-200.fc38.x86_64
Building initial module for 6.4.14-200.fc38.x86_64
Deprecated feature: REMAKE_INITRD (/var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/source/dkms.conf)
Error! Bad return status for module build on kernel: 6.4.14-200.fc38.x86_64 (x86_64)
Consult /var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/build/make.log for more information.
warning: %post(kmod-ovpn-dco-0-20220905git3ba6c07.fc38.noarch) scriptlet failed, exit status 10

Error in POSTIN scriptlet in rpm package kmod-ovpn-dco
  Verifying        : kmod-ovpn-dco-0-20220905git3ba6c07.fc38.noarch                                                                                                                                                                       1/3
  Verifying        : dkms-3.0.11-1.fc38.noarch                                                                                                                                                                                            2/3
  Verifying        : kernel-devel-matched-6.4.14-200.fc38.x86_64                                                                                                                                                                          3/3

Installed:
  dkms-3.0.11-1.fc38.noarch                                         kernel-devel-matched-6.4.14-200.fc38.x86_64                                         kmod-ovpn-dco-0-20220905git3ba6c07.fc38.noarch

Complete!

Из лога видно, что во время сборки модуля ядра произошла ошибка и указан файл, в котором можно посмотреть логи сборки модуля для получения подробностей.

Лог сборки
# cat /var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/build/make.log
DKMS make.log for ovpn-dco-0.20220905git3ba6c07.fc38 for kernel 6.4.14-200.fc38.x86_64 (x86_64)
Sun Sep 10 03:31:13 PM MSK 2023
make: Entering directory '/var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/build'
/var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/build/gen-compat-autoconf.sh /var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/build/compat-autoconf.h
make -C /lib/modules/6.4.14-200.fc38.x86_64/build M=/var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/build PWD=/var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/build REVISION=copr:0.20220905git3ba6c07.fc38 CONFIG_OVPN_DCO=m INSTALL_MOD_DIR=updates/ modules
make[1]: Entering directory '/usr/src/kernels/6.4.14-200.fc38.x86_64'
CC [M] /var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/build/drivers/net/ovpn-dco/main.o
CC [M] /var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/build/drivers/net/ovpn-dco/bind.o
CC [M] /var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/build/drivers/net/ovpn-dco/crypto.o
CC [M] /var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/build/drivers/net/ovpn-dco/ovpn.o
/var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/build/drivers/net/ovpn-dco/ovpn.c: In function ‘ovpn_net_xmit’:
/var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/build/drivers/net/ovpn-dco/ovpn.c:468:28: error: implicit declaration of function ‘skb_gso_segment’; did you mean ‘skb_gso_reset’? [-Werror=implicit-function-declaration]
468 | segments = skb_gso_segment(skb, 0);
| ^~~~~~~~~~~~~~~
| skb_gso_reset
/var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/build/drivers/net/ovpn-dco/ovpn.c:468:26: warning: assignment to ‘struct sk_buff *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
468 | segments = skb_gso_segment(skb, 0);
| ^
CC [M] /var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/build/drivers/net/ovpn-dco/peer.o
cc1: some warnings being treated as errors
make[3]: *** [scripts/Makefile.build:252: /var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/build/drivers/net/ovpn-dco/ovpn.o] Error 1
make[3]: *** Waiting for unfinished jobs....
/var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/build/drivers/net/ovpn-dco/peer.c: In function ‘ovpn_peer_create’:
/var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/build/drivers/net/ovpn-dco/peer.c:91:9: error: implicit declaration of function ‘netif_tx_napi_add’; did you mean ‘netif_napi_add’? [-Werror=implicit-function-declaration]
91 | netif_tx_napi_add(ovpn->dev, &peer->napi, ovpn_napi_poll,
| ^~~~~~~~~~~~~~~~~
| netif_napi_add
cc1: some warnings being treated as errors
make[3]: *** [scripts/Makefile.build:252: /var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/build/drivers/net/ovpn-dco/peer.o] Error 1
make[2]: *** [scripts/Makefile.build:497: /var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/build/drivers/net/ovpn-dco] Error 2
make[1]: *** [Makefile:2050: /var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/build] Error 2
make[1]: Leaving directory '/usr/src/kernels/6.4.14-200.fc38.x86_64'
make: *** [Makefile:52: all] Error 2
make: Leaving directory '/var/lib/dkms/ovpn-dco/0.20220905git3ba6c07.fc38/build'

Ключевая ошибка здесь в следующем: implicit declaration of function ‘skb_gso_segment’; did you mean ‘skb_gso_reset’?

На эту тему как раз есть давно закрытый issue в github: https://github.com/OpenVPN/ovpn-dco/issues/42. Почему автор, после того как поправил ошибку, не обновил пакет в copr – загадка, которую попробую выяснить.

В общем, пока из copr не получится установить на современные ядра (если у вас более старое ядро, можно попробовать установить из copr), ставить как и в случае с Rocky Linux, из исходников.

Установка ovpn-dco из исходников

Для того, чтобы поставить все из исходников, нам понадобятся следующие пакеты:

  • gcc
  • git
  • kernel-devel
  • kernel-headers
  • make

Ставим их: dnf install -y git gcc kernel-headers kernel-devel make

Далее клонируем репозиторий с исходниками, заходим в него и запускаем сборку:

# git clone https://github.com/openvpn/ovpn-dco.git
# cd ovpn-dco
# make

В результате вы должны увидеть примерно следующий лог сборки make:

# make
/root/ovpn-dco/gen-compat-autoconf.sh /root/ovpn-dco/compat-autoconf.h
make -C /lib/modules/6.4.14-200.fc38.x86_64/build M=/root/ovpn-dco PWD=/root/ovpn-dco REVISION=0.2.20230426-1-gdba96d2 CONFIG_OVPN_DCO_V2=m INSTALL_MOD_DIR=updates/ modules
make[1]: Entering directory '/usr/src/kernels/6.4.14-200.fc38.x86_64'
CC [M] /root/ovpn-dco/drivers/net/ovpn-dco/main.o
CC [M] /root/ovpn-dco/drivers/net/ovpn-dco/bind.o
CC [M] /root/ovpn-dco/drivers/net/ovpn-dco/crypto.o
CC [M] /root/ovpn-dco/drivers/net/ovpn-dco/ovpn.o
CC [M] /root/ovpn-dco/drivers/net/ovpn-dco/peer.o
CC [M] /root/ovpn-dco/drivers/net/ovpn-dco/sock.o
CC [M] /root/ovpn-dco/drivers/net/ovpn-dco/stats.o
CC [M] /root/ovpn-dco/drivers/net/ovpn-dco/netlink.o
CC [M] /root/ovpn-dco/drivers/net/ovpn-dco/crypto_aead.o
CC [M] /root/ovpn-dco/drivers/net/ovpn-dco/pktid.o
CC [M] /root/ovpn-dco/drivers/net/ovpn-dco/tcp.o
CC [M] /root/ovpn-dco/drivers/net/ovpn-dco/udp.o
LD [M] /root/ovpn-dco/drivers/net/ovpn-dco/ovpn-dco-v2.o
MODPOST /root/ovpn-dco/Module.symvers
CC [M] /root/ovpn-dco/drivers/net/ovpn-dco/ovpn-dco-v2.mod.o
LD [M] /root/ovpn-dco/drivers/net/ovpn-dco/ovpn-dco-v2.ko
BTF [M] /root/ovpn-dco/drivers/net/ovpn-dco/ovpn-dco-v2.ko
Skipping BTF generation for /root/ovpn-dco/drivers/net/ovpn-dco/ovpn-dco-v2.ko due to unavailability of vmlinux
make[1]: Leaving directory '/usr/src/kernels/6.4.14-200.fc38.x86_64'

В логе не видно никаких ошибок, значит можно попробовать установить модуль ядра в систему:

# make install
/root/ovpn-dco/gen-compat-autoconf.sh /root/ovpn-dco/compat-autoconf.h
make -C /lib/modules/6.4.14-200.fc38.x86_64/build M=/root/ovpn-dco PWD=/root/ovpn-dco REVISION=0.2.20230426-1-gdba96d2 CONFIG_OVPN_DCO_V2=m INSTALL_MOD_DIR=updates/ modules_install
make[1]: Entering directory '/usr/src/kernels/6.4.14-200.fc38.x86_64'
INSTALL /lib/modules/6.4.14-200.fc38.x86_64/updates//drivers/net/ovpn-dco/ovpn-dco-v2.ko
SIGN /lib/modules/6.4.14-200.fc38.x86_64/updates//drivers/net/ovpn-dco/ovpn-dco-v2.ko
At main.c:167:
- SSL error:FFFFFFFF80000002:system library::No such file or directory: crypto/bio/bss_file.c:67
- SSL error:10000080:BIO routines::no such file: crypto/bio/bss_file.c:75
sign-file: ./certs/signing_key.pem
DEPMOD /lib/modules/6.4.14-200.fc38.x86_64
make[1]: Leaving directory '/usr/src/kernels/6.4.14-200.fc38.x86_64'
depmod -a

Не смотря на ошибки SSL, модуль установился нормально и виден в системе. Даже нормально загружается и выгружается:

# modinfo ovpn-dco-v2
filename: /lib/modules/6.4.14-200.fc38.x86_64/updates/drivers/net/ovpn-dco/ovpn-dco-v2.ko
alias: net-pf-16-proto-16-family-ovpn-dco-v2
alias: rtnl-link-ovpn-dco
version: 0.2.20230426-1-gdba96d2
license: GPL
author: (C) 2020-2023 OpenVPN, Inc.
description: OpenVPN data channel offload (ovpn-dco)
rhelversion: 9.99
srcversion: 045BF0F4AB0BEC5963517E6
depends: udp_tunnel,ip6_udp_tunnel
retpoline: Y
name: ovpn_dco_v2
vermagic: 6.4.14-200.fc38.x86_64 SMP preempt mod_unload
# modprobe ovpn-dco-v2
# rmmod ovpn-dco-v2

В dmesg видим следующие сообщения, о том, что модуль был установлен отдельно от ядра, успешно загрузился, однако не прошёл проверку подписи. Автор утверждает, что в этом нет ничего страшного.

[ 2332.779985] ovpn_dco_v2: loading out-of-tree module taints kernel.
[ 2332.780013] ovpn_dco_v2: module verification failed: signature and/or required key missing - tainting kernel
[ 2332.781283] OpenVPN data channel offload (ovpn-dco) 0.2.20230426-1-gdba96d2 -- (C) 2020-2023 OpenVPN, Inc.

Включаем DCO

Итак, модуль ядра ovpn-dco мы собрали и установили, теперь самое время проверить конфигурационные параметры OpenVPN, чтобы они не мешали включению DCO. А именно (повторим из прошлой статьи):

Требования

Версия openvpn. Поддержка DCO в openvpn появилась в версии 2.6. Значит openvpn должен быть этой или более высокой версии. Также можно проверить, что поддержка DCO была включена при сборке:

# openvpn --version | grep DCO
OpenVPN 2.6.6 x86_64-redhat-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] [DCO]
DCO version: N/A

[DCO] в первой строчке указывает, что openvpn бинарный файл был собран со включенной поддержкой DCO – то, что нам надо.

Наличие модуля ядра ovpn-dco. Наличие присутствует. Мы только что его собрали и установили.

Совместимые режимы шифрования. DCO поддерживается только при использовании AEAD режиме шифра. А именно, поддерживаются AES-***-GCM и ChaCha20-Poly1305.

Драйвер. Для разгрузки поддерживается только tun (L3) драйвер. Если у вас режим работы tap (L2), то можете закрывать эту заметку, либо подумать о переходе на L3 VPN (tun).

В любом случае, если какие-то из настроек не подходят для активации режима DCO, openvpn вам об этом скажет в логах. Поэтому обязательно читайте их!

Перезапускаем openvpn и смотрим логи:

# systemctl restart openvpn-server@<config_name>
# journalctl -u openvpn-server@<config_name>

В логах сразу после старта сервиса вы можете увидеть, например, такие сообщения:

  • Note: cipher 'AES-256-CBC' in --data-ciphers is not supported by ovpn-dco, disabling data channel offload. – такая ошибка появляется, когда в конфиге не указаны data-ciphers и туда по умолчанию попадают все поддерживаемые системой шифры. В т.ч. неподдерживаемые режимом DCO.
  • Note: Kernel support for ovpn-dco missing, disabling data channel offload. – это можно увидеть в случае, если модуль ядра не установлен в системе.

Нужно устранить причины появления ошибок. Обратите внимание, что если вы будете на рабочей системе менять набор шифров, то убедитесь, что все ваши клиенты поддерживают новые шифры, а также что в конфигах клиентов не указан какой-то конкретный, например, AES-***-CBC, который перестанет работать после явного перечисления AES-***-GCM шифров на сервере. Иначе клиент просто не сможет подключиться из-за несовпадающих шифров.

После устранения всех несовместимых с DCO параметров настроек, в логах вы увидите следующее:

DCO version: 0.2.20230426-1-gdba96d2
...
DCO device tun0 opened

Также, можно проверить, что tun# устройство работает под собранным нами драйвером ovpn-dco:

# ethtool -i tun0
driver: ovpn-dco
version: 0.2.20230426-1-gdba96d2
firmware-version:
expansion-rom-version:
bus-info: ovpn
supports-statistics: no
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: no

Останется лишь проверить наличие связи, подняв соединение с VPN-сервером. Также можно проверить, что при передаче трафика не используется openvpn процесс. Как это сделать – смотрите в конце предыдущей статьи.

Приятного пользования!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Оптимизировано Optimole
ru_RUРусский