В прошлой статье мы рассмотрели в целом, что такое 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 процесс. Как это сделать – смотрите в конце предыдущей статьи.
Приятного пользования!