Поднимаем WireGuard сервер на Fedora

Ранее на нашем сайте мы подробно рассматривали запуск и настройку сервера OpenVPN, но не так давно у него появился достойный соперник — WireGuard, который мы сегодня и разберём в данной статье.

Введение

WireGuard — это самый современный в настоящее время протокол для реализации виртуальных частных сетей (VPN).

Основные преимущества WireGuard:

  • реализован посредством модуля ядра, что значительно увеличивает производительность туннеля из-за отсутствия необходимости в постоянных переключениях между режимами ядра и пользовательским;
  • использует современные криптографические протоколы: Curve25519, ChaCha20, Poly1305 и т.д.;
  • имеет простую реализацию, что снижает вероятность возникновения ошибок и, как следствие, уязвимостей;
  • хорошо спроектирован и документирован.

Установка в Fedora

Начиная с версии ядра Linux 5.6.0, все необходимые для работы WireGuard модули ядра уже включены в его состав, поэтому установим лишь клиентскую утилиту настройки из основного репозитория Fedora:

sudo dnf install wireguard-tools

Настройка сервера

Создадим главный файл конфигурации сервера /etc/wireguard/wg0.conf:

[Interface]
Address = 10.8.0.1/24
PrivateKey = SERVER_PRIVATE_KEY
ListenPort = 27015

Сгенерируем секретный ключ для сервера в файл wg-srv-private и пропишем его содержимое вместо SERVER_PRIVATE_KEY:

touch wg-srv-private
chmod 0600 wg-srv-private
wg genkey > wg-srv-private

Вычислим на основе секретного ключа сервера публичный для передачи его клиентам:

wg pubkey < wg-srv-private > wg-srv-public

Зададим порт сервера при помощи директивы ListenPort. WireGuard работает только посредством протокола UDP. TCP не поддерживается.

Активируем сервер и настроим его автоматический запуск средствами systemd:

sudo systemctl enable --now [email protected]

Настройка брандмауэра

Для того, чтобы наш сервер начал принимать входящие соединения, необходимо настроить брандмауэр и правила маршрутизации.

Разрешим входящие подключения на порт сервера (в нашем примере применяется 27015):

sudo firewall-cmd --permanent --zone=public --add-port=27015/udp

Включим маскарадинг для зоны Firewalld:

sudo firewall-cmd --permanent --zone=public --add-masquerade

Разрешим перенаправление трафика между сетевыми интерфейсами:

sudo firewall-cmd --permanent --zone public --add-forward

Применим изменения в конфигурации Firewalld:

sudo firewall-cmd --reload

Разрешим перенаправление трафика как по протоколу TCP/IP версии 4, так и версии 6:

sudo sysctl -w net.ipv4.conf.all.forwarding=1
sudo sysctl -w net.ipv6.conf.all.forwarding=1

Сохраним настройки перенаправления так, чтобы они работали и после перезагрузки системы:

sudo bash -c "echo -e \"net.ipv4.conf.all.forwarding=1\nnet.ipv6.conf.all.forwarding=1\" > /etc/sysctl.d/99-wireguard.conf"

Настройка клиентов

Клиентская сторона

Теперь каждому клиенту необходимо самостоятельно сгенерировать ключевую пару. Принцип аналогичен GnuPG и SSH: секретная часть (private key) остаётся у клиента, а публичная (public key) передаётся администратору сервера.

Сгенерируем секретный ключ клиента 1:

touch wg-cli1-private
chmod 0600 wg-cli1-private
wg genkey > wg-cli1-private

Получим публичный ключ клиента 1:

wg pubkey < wg-cli1-private > wg-cli1-public

Создадим файл конфигурации клиента /etc/wireguard/wg0.conf (имя файла конфигурации на клиенте и сервере совпадают):

[Interface]
Address = 10.8.0.2/24
PrivateKey = CLIENT_PRIVATE_KEY
DNS = 1.1.1.1,8.8.8.8

[Peer]
PublicKey = SERVER_PUBLIC_KEY
AllowedIPs = 0.0.0.0/0
Endpoint = 1.2.3.4:27015
PersistentKeepalive = 20

Здесь вместо CLIENT_PRIVATE_KEY укажем секретный ключ клиента (содержимое файла wg-cli1-private), а SERVER_PUBLIC_KEY — публичный ключ сервера (содержимое wg-srv-public).

Директива Address содержит желаемый внутренний IP-адрес на сервере, а Endpoint — доменное имя или IP адрес сервера WireGuard, а также его порт.

Сторона сервера

Клиент любым способом передаёт администратору сервера свой публичный ключ (содержимое файла wg-cli1-public), затем администратор прописывает его в главный конфигурационный файл /etc/wireguard/wg0.conf:

[Peer]
PublicKey = CLIENT1_PUBLIC_KEY
AllowedIPs = 10.8.0.2/32

Здесь CLIENT1_PUBLIC_KEY — публичный ключ, переданный клиентом, а AllowedIPs — IP-адрес или подсеть, из которой клиенту будет выдан внутренний IP-адрес на сервере WireGuard.

Если клиентов несколько, то все действия следует повторить для каждого из них.

Подключение к серверу

Существует два основных способа настройки подключения к серверу. Рассмотрим каждый из них более подробно.

Современный способ

Network Manager имеет встроенную поддержку WireGuard, поэтому воспользуемся им для быстрой настройки соединения.

Импортируем созданную ранее конфигурацию:

nmcli connection import type wireguard file /etc/wireguard/wg0.conf

Запустим автоматически созданное соединение с именем wg0:

nmcli connection up wg0

При необходимости настроим автоматическое подключение к VPN-серверу при загрузке системы:

nmcli connection modify wg0 connection.autoconnect yes

Классический способ

Запустим туннель и настроим его автоматическое поднятие при помощи wg-quick:

sudo systemctl enable --now [email protected]

Если всё сделано верно, то подключение будет успешно установлено.

Приложение

Пример файла конфигурации сервера для двух клиентов:

# Главные настройки сервера: его внутренний IP-адрес,
# секретный ключ и порт, который он будет слушать.
[Interface]
Address = 10.8.0.1/24
PrivateKey = SERVER_PRIVATE_KEY
ListenPort = 27015

# Настройки клиентов. Каждый отдельным блоком.
# Клиент №1
[Peer]
PublicKey = CLIENT1_PUBLIC_KEY
AllowedIPs = 10.8.0.2/32

# Клиент №2
[Peer]
PublicKey = CLIENT2_PUBLIC_KEY
AllowedIPs = 10.8.0.3/32

30 комментариев к записи

  1. Если кто-то вместо Network Manager использует systemd-networkd, то он поддерживает WireGuard «из коробки»:

    Листинг файла /etc/systemd/network/10-wg0.netdev:

    [NetDev]
    Name = wg0
    Kind = wireguard
    Description = WireGuard
    
    [WireGuard]
    PrivateKey = CLIENT_PRIVATE_KEY
    
    [WireGuardPeer]
    PublicKey = SERVER_PUBLIC_KEY
    AllowedIPs = 0.0.0.0/0
    Endpoint = 1.2.3.4:27015
    PersistentKeepalive = 20

    Листинг файла /etc/systemd/network/10-wg0.network:

    [Match]
    Name = wg0
    
    [Network]
    Address = 10.8.0.2/32
    DNS = 1.1.1.1,8.8.8.8
    
    [Route]
    Gateway = 10.8.0.1
    Destination = 10.8.0.1/24
  2. Отсутствуют совпадения для аргумента: hernel-headers
    Ошибка: Совпадений не найдено

  3. Также можно добавить, что для усиления безопасности существует возможность добавить слой симметричного шифрования для рукопожатия — общий ключ между клиентом и сервером — pre-shared key (PSK).

    Создание PSK:

    wg genpsk > wg-psk

    Далее в конфиг сервера и клиента нужно добавить строку:

    PresharedKey = PSK_KEY

    Здесь вместо PSK_KEY — содержимое файла wg-psk.

    Разумеется, для каждого клиента в файле конфигурации сервера, в блоке Peer, должен быть указан свой общий ключ. Этот же ключ должен быть прописан и на самом клиенте.

  4. При создании файла 99-wireguard не указано значение для второго параметра

  5. Статья обновлена. WireGuard теперь входит в состав ядра Linux версии 5.6.0 и выше.

  6. Может кто-нибудь знает как защитить конфиг на стороне клиента? Если я угнал клиентский конфиг, то могу без проблем конектится к серверу. Парольная аутентификация как я понял не предусмотрена в самом протоколе. PresharedKey тоже непонятно зачем нужен — если я могу просто скопировать конфиг у клиента

    1. Да, в случае кражи клиентского конфига, им смогут пользоваться злоумышленники до тех пор, пока публичный ключ не будет удалён на стороне сервера из разрешённых.

      На Reddit и в баг-трекере WireGuard эта тема неоднократно поднималась, но разработчики отказываются добавлять поддержку парольной защиты для закрытых ключей.

  7. Начиная с 33 версии федора использует systemd-resolved. А wg-quick, ничего об этом не знает и пытается использовать resolvconf. Это приводит к ошибкам связанным с резолвингом имён.

    Инструкция как пофиксить есть в арчивики (статья про wireguard), но хорошо эту инструкцию тоже обновить бы.

    1. Да, поэтому WireGuard подключение сейчас лучше поднимать при помощи Network Manager, который корректно интегрируется с systemd-resolved.

      Обновил статью. Спасибо.

    2. Там можно просто не указывать «DNS=х.х.х.х», тогда проблем не будет

      1. Если не указывать DNS для соединения, может произойти утечка DNS (dns leak).

        1. Да, поэтому в systemd-resolved надо указать свои DNS и включить DoT

          1. Активация DNS-over-TLS не требуется ибо DNS-трафик и так будет перенаправляться целиком внутрь WireGuard интерфейса.

  8. Там даже будет что-то типа шифрования DNS трафика?

    1. WireGuard шифрует весь проходящий через него трафик, в т.ч. и DNS.

    1. Начиная с Linux версии 5.6, все необходимые модули ядра WireGuard входят в комплект его поставки. Отдельно устанавливать их больше не требуется.

    1. Пропишите выделенную серверу IPv6 /128 подсеть и WireGuard будет выдавать клиентам адреса из неё.

  9. Добрый день. Никак не могу понять взаимодействие между клиентами возможно?

    Т.е между Клиент №1 — Клиент №2 через сервер.

  10. Подскажите, пожалуйста, какие настройки нужно сделать, чтобы можно было использовать почтового клиента на клиенте wireguard?

    Если подключаюсь к vpn — почта не принимается / не отправляется.

    1. Ответ на этот вопрос зависит от того, где находится WireGuard сервер.

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

      Если во внешней сети и WireGuard экспортирует основной шлюз, то всё должно работать автоматически в штатном режиме.

      1. Если во внешней сети и WireGuard экспортирует основной шлюз, то всё должно работать автоматически в штатном режиме.

        Почтовый сервер находится во внешней сети. Если не сложно, можете кратко указать что нужно проверить в этом случае? (Может быть порты открыть и т.п.)

        1. Почтовый сервер находится во внешней сети.

          Если сервер находится во внешней сети, то он должен быть доступен по своему основному IP-адресу, т.к. в наших примерах соединение WireGuard становится основным шлюзом.

          Если не сложно, можете кратко указать что нужно проверить в этом случае?

          Проверьте, что выдаётся действительный внешний IP-адрес и он пингуется:

          dig mail.example.org
          ping -c 4 mail.example.org

          Может быть порты открыть и т.п.

          Открывать порты для интерфейса WireGuard необходимо только если требуется подключаться к серверу по его внутреннему IP.

  11. Прикольно бы запихнуть wireguard в сеть yggdrasil, тут даже статика не нужна.

    1. В таком случае потеряется весь смысл использования WireGuard — скорость и работа исключительно в режиме ядра.

Комментарии закрыты