In the previous article we've looked how to deploy OpenVPN DCO on a Rocky Linux 9 system and about new technology in general. Here I'd like to describe how to do the same, but for 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 процесс. Как это сделать – смотрите в конце предыдущей статьи.
Приятного пользования!