Network, Security: Wireguard

Summary
  • Ключевые особенности/характеристики Wireguard:
    • Достоинства
      • Connection-less Protocol (based on UDP)
WireGuard only[9] uses UDP[4] and thus does not work in networks that block UDP traffic. This is unlike alternatives like OpenVPN because of the many disadvantages of TCP-over-TCP routing.
      • WireGuard supports only layer 3 for both IPv4 and IPv6 and can encapsulate v4-in-v6 and vice versa.
      • WireGuard supports multiple topologies: Point-to-point, Star (server/client) Mesh
      • WireGuard original code-base is less than 1% the size of a popular IPsec/OpenVPN implementation(s), making it easy for us to understand and secure.
      • Высокая производительность (ниже чем Ipsec с offload, но выше чем без offload)
      • Современный стек security протоколов
      • Быстрая установка соединений и меньшая задержка приложений за счет того, что полезные данные передаются в первом же пакете
Ars Technica reported that in testing, stable tunnels were easily created with WireGuard, compared to alternatives, and commented that it would be "hard to go back" to long reconnection delays, compared to WireGuard's "no nonsense" instant reconnections.
      • Поддержка связки ассиметричного (Curve25519)
        и симметричного шифрования (PSK) для большей безопаности
      • Один из сенаторов USA попросил NIST изучить протокол как замену IPsec/OpenVPN.
WireGuard aims to provide a simple and effective virtual private network implementation. A 2018 review by Ars Technica observed that popular VPN technologies such as OpenVPN and IPsec are often complex to set up, disconnect easily (in the absence of further configuration), take substantial time to negotiate reconnections, may use outdated ciphers, and have relatively massive code bases of over 400,000 and 600,000 lines of code, respectively, which hinders debugging.
By using versioning of cryptography packages, it focuses on ciphers believed to be among the most secure current encryption methods, and at the time of the Ars Technica review had a codebase of around 4000 lines of kernel code, about 1% of either OpenVPN or IPsec, making security audits easier.

Oregon senator Ron Wyden has recommended to the National Institute of Standards and Technology (NIST) that they evaluate WireGuard as a replacement for existing technologies like IPsec and OpenVPN.

Optional Pre-shared Symmetric Key Mode
WireGuard supports pre-shared symmetric key mode, which provides an additional layer of symmetric encryption to mitigate future advances in quantum computing. This addresses the risk that traffic may be stored until quantum computers are capable of breaking Curve25519; at which point traffic could be decrypted. Pre-shared keys are "usually troublesome from a key management perspective and might be more likely stolen", but in the shorter term, if the symmetric key is compromised, the Curve25519 keys still provide more than sufficient protection.
Wireguard was incorporated into the Linux 5.6 kernel

WireGuard was praised by Linux kernel creator Linus Torvalds who stated that it is a "work of art" in contrast to OpenVPN and IPsec.[
Linus Torvalds merged David Miller's net-next tree, and WireGuard entered the mainline Linux kernel tree.
Android developers added native kernel support for WireGuard in their Generic Kernel Image.
FreeBSD-based pfSense Community Edition (CE) 2.5.0 and pfSense Plus 21.02 removed kernel-based WireGuard as well.
The official package repositories for both pfSense CE 2.5.2 and pfSense Plus 21.05 included the WireGuard package.
  • Wireguard поддерживает post-up/post-down скрипты (так же, как ipsec), это позволяет реализовать множество различных сценариев, напр. некую аналогию IPSec RRI в виде добавления маршрута в RIB при поднятии туннеля и удаления после падения или прописывание определенных DNS записей
[Interface] 
PostUp = resolvectl dns %i 10.0.0.1 10.0.0.2; resolvectl domain %i ~fakedomain.com
[Interface]
PostUp = /etc/wireguard/postup.shp

 

Практика

Для remote-access VPN в сравнении с IPSec + L2TP Wireguard это просто сказка – поднятие VPN (а это не только первичное подключение, а любые переподключения) в тысячи раз быстрее, говорю на практике. Поднимал как чистый сервис, так и docker image контейнер от LinuxServer.io.

IOS

Приложение простейшее и удобное – конфиг клиента можно прочитать из файла, отсканировать QR (самое удобное чаще всего) или настоить вручную. Так же есть опции по включению on-demand (только в зависимости от среды LTE/WiFi, но это самые частые кейсы).

Zyxel Keenetic

На Zyxel при настройке обращает внимание IP MTU – 1324, заведомо низкий  MTU под который подстраиваются кадры с помощью adjust-mss.

Кстати, полученный конфиг peer_<name>.conf из Docker Image Wireguard (о нем ниже) не распарсился корректно GUI keenetic – пришлось подставлять IP/port вручную, только после этого заработало.
interface Wireguard0
description reverse-tunnel-for-camera-WG
security-level public
ip address <ip> 255.255.255.0
ip mtu 1324
ip tcp adjust-mss pmtu
wireguard listen-port 51820
wireguard peer <key> !weril.me
endpoint weril.me:51820
keepalive-interval 30
preshared-key <psk>
allow-ips 0.0.0.0 0.0.0.0
!
up
ManualConfiguration

Установка в Linux с ядра 5.6 не требуется – код уже в ядре.

Для генерации PSK ключей 32 байта, которые использует Wireguard, проще всего использовать OpenSSL.

$ openssl rand -base64 32
9+0ljeeUlKM47DPhxIcWBmsRfuj8wtEAjBq6ePPJ5Lw=

Ключи конфигурации:

    • PrivateKey – наш приватный ключ
    • ListenPort – на каком порту слушаем мы
    • Address –  наш адрес в туннеле
    • peer
      • PublicKey – публичный ключ peer
      • PresharedKey – разделяемый ключ, необязательный, но потенциально это доп защита от атак типо квантового шифрования
      • AllowedIPs – работает как таблица маршрутизации при приеме пакета вне туннеля и как фильтр при приеме пакета из определенного туннеля
      • Endpoint – адрес endpoint (IP:PORT), можно указать только с одной стороны (напр. spoke или remote access)
    • PersistentKeepalive – указываем как часто будут отправлятся keepalive пакеты для поддержания сессий nat/fw на промежуточных устройствах. По умолчанию отключено, обычно при включении настраивается PersistentKeepalive = 25

Пример простейшего соединения одного клиента с сервером (проверено, работает).

#Server Config
[Interface]
PrivateKey = #Replace with server private key#
ListenPort = 51820
Address = 192.168.200.1/24
[Peer]
#Client 1
PublicKey = #Replace with client public key#
PresharedKey = #Replace with pre-shared key#
AllowedIPs = 192.168.200.2/32

#Client Config
[Interface]
PrivateKey = #Replace with client private key#
Address = 192.168.200.2/24
DNS = 1.1.1.1, 8.8.8.8
[Peer]
PublicKey = #Replace with server public key#
PresharedKey = #Replace with pre-shared key#
AllowedIPs = 0.0.0.0/0
Endpoint = #Replace with server domain name or ip address#:51820

Docker Image от LinuxServer.io

Использовал популярный docker img от LinuxServer.io (50 млн openvpn и 10 млн загрузок wireguard).

docker pull linuxserver/wireguard
По конфигу и особенностям работы:
  • осторожно с именами PEERS – во первых должны содержать только символы (напр. использование тире недопустимо), во вторых не должны иметь пробелов между ними.
  • для добавления пиров или удаления пересоздаем контейнер, не нужно переживать, что пиры получат другие ключи – они генерируются от имени, если имя пира сохранить старым, будет ему в новом контейнере сгенерирован старый ключ. Если очень переживаем, никто не мешает не удалять исходный контейнер до проверки работы:
sudo docker stop weril-wireguard
sudo docker rename weril-wireguard weril-wireguard-old
  • так же изменение SERVERPORT на 443 по факту не сработало – Wireguard в контейнере был настроен на прослушивание стандратного 51820! Пришлось это траблшутить (wg status) и настраивать дефолтно (перегенериррорвать контейнер и QR код)
  • сам конфиг wireguard при этом продолжает находится в стандартном месте /etc/wireguard/wg0.conf – его можно использовать для идентификации peer (проще всего по выделенному для него IP)
  • так же работает стандартный просмотр статистики по пирам через команду wg
**** Peer <some_example_name> contains non-alphanumeric characters and thus will be skipped. No config for peer <some_example_name> will be generated. ****
sudo docker run -d \
--name=weril-wireguard \
--cap-add=NET_ADMIN \
--cap-add=SYS_MODULE \
-e PUID=1000 \
-e PGID=1000 \
-e TZ=Europe/London \
-e SERVERURL=weril.me `#optional` \
-e SERVERPORT=51820 `#optional` \
-e PEERS=X1,X2,X3,X4,X5 `#optional` \
-e PEERDNS=1.1.1.1,8.8.8.8 `#optional` \
-e INTERNAL_SUBNET=10.13.13.0 `#optional` \
-e ALLOWEDIPS=0.0.0.0/0 `#optional` \
-e LOG_CONFS=true `#optional` \
-p 51820:51820/udp \
-v /path/to/appdata/config:/config \
-v /lib/modules:/lib/modules `#optional` \
--sysctl="net.ipv4.conf.all.src_valid_mark=1" \
--restart unless-stopped \
linuxserver/wireguard
QR код можно найти в логах docker контейнера. Либо можно вызвать QR code через утилиту /app/show-peer. По технике для генерации QR скрипт делает поиск пира в /etc/wireguard/wg0.conf и делается вывод о наличии пира, а по отдельному файлу пира генерируется QR с использованием утилиты qrencode (принимает на входе обычный текст и генерирует QR).
The peer/client config qr codes will be output in the docker log. They will also be saved in text and png format under /config/peerX in case PEERS is a variable and an integer or /config/peer_X in case a list of names was provided instead of an integer. 

sudo docker logs weril-wireguard 

sudo docker exec -it weril-wireguard /app/show-peer <peer_name>

cat /app/show-peer
if grep -q "# ${PEER_ID}" /config/wg0.conf; then
  echo "PEER ${i} QR code:"
  qrencode -t ansiutf8 < /config/${PEER_ID}/${PEER_ID}.conf
else
  echo "PEER ${i} is not active"
fi
Файлы с конфигами (напр. для Desktop клиентов или Keenetic) можно забрать из контейнера из папки /config/.
sudo docker exec -it weril-wireguard cat /config/peer_<peer_name>/peer_<peer_name>.conf

# либо проваливаемся в контейнер
sudo docker exec -it weril-wireguard bash
cat /config/peer_<peer_name>/peer_<peer_name>.conf
Ошибки
Для Centos7 потребовалась установка kernel модуля. Без него была ошибка ниже.
sudo docker logs weril-wireguard
E: Sub-process returned an error code
**** No kernel headers found in the Ubuntu or Debian repos!! Will try the headers from host (if mapped), may or may not work ****
**** Kernel headers don't seem to be available in Ubuntu, Debian and Raspbian repos, or shared from the host; therefore can't compile the module. Sleeping now. . . ****
Установка на “гипервизоре” docker:
https://www.wireguard.com/install/
Method 2: users wishing to stick with the standard kernel may use ELRepo's pre-built module:
$ sudo yum install epel-release elrepo-release
$ sudo yum install yum-plugin-elrepo
$ sudo yum install kmod-wireguard wireguard-tools
Далее удаляем docker и создаем новый, должно все работать:
sudo docker rm -f weril-wireguard
sudo docker logs weril-wireguard

Leave a Reply