Bash-скрипт для установки WireGuard на Linux-сервере и управления VPN-клиентами. Это форк angristan/wireguard-install, дополненный режимом самостоятельного управления межсетевым экраном — например, через nftables.
Клиент направляет выбранный трафик через зашифрованный туннель на сервер. При использовании masquerade сайты видят внешний адрес сервера. Скрипт создаёт конфигурации IPv4 и IPv6.
Нужен доступ root. Скрипт предусматривает следующие дистрибутивы (этот список не означает, что все версии проверены в данном форке):
- AlmaLinux >= 8
- Alpine Linux
- Arch Linux
- CentOS Stream >= 8
- Debian >= 10
- Fedora >= 32
- Oracle Linux
- Rocky Linux >= 8
- Ubuntu >= 18.04
Скачайте все три файла в один каталог и запустите установщик от root. Меню использует соседние файлы для бэкапа и восстановления:
curl -fO https://raw.githubusercontent.com/rmtshnik/wireguard-install/master/wireguard-install.sh
curl -fO https://raw.githubusercontent.com/rmtshnik/wireguard-install/master/wireguard-backup.sh
curl -fO https://raw.githubusercontent.com/rmtshnik/wireguard-install/master/wireguard-restore.py
chmod +x wireguard-install.sh
./wireguard-install.shОтветьте на вопросы установщика. Он установит WireGuard и необходимые инструменты, создаст конфигурацию сервера, настроит службу systemd (OpenRC на Alpine) и предложит создать первого клиента.
Сеть VPN выбирайте самостоятельно: она не должна пересекаться с сетями сервера, клиентов и другими сетями, к которым нужен доступ. Текущий скрипт использует маску /24 для IPv4 и /64 для IPv6. Для совместимости с выдачей клиентских адресов используйте адрес сервера вида X.Y.Z.1 и IPv6-адрес вида fdXX:XXXX:XXXX::1.
Например, для выбранной сети 10.66.66.0/24 адрес сервера будет 10.66.66.1. Это только пример, а не обязательная сеть.
Повторный запуск открывает меню:
1) Добавить клиента
2) Показать клиентов
3) Отозвать клиента
4) Создать резервную копию
5) Восстановить из резервной копии
6) Удалить WireGuard
7) Выход
Если /etc/wireguard/params ещё нет, доступны установка, восстановление и выход. Восстановление не запускает установку пакетов: заранее установите WireGuard, Python 3.8+ и службу wg-quick. Например, для Debian 11+/Ubuntu 20.04+: sudo apt update && sudo apt install wireguard python3. Для Alpine заранее подготовьте OpenRC-службу wg-quick.ИМЯ_ИНТЕРФЕЙСА. Пункт восстановления сообщает о недостающих инструментах; зависимости автоматически не скачиваются.
При установке введите номер режима: 1 или 2. Нажатие Enter выбирает 1 (auto).
1) auto— режим по умолчанию. Скрипт добавляет команды firewalld либо iptables вPostUp/PostDown: правила создаются при запуске интерфейса и удаляются при его остановке.2) external— правилами управляете вы. Скрипт не добавляет firewall-хуки и не запрашивает установку iptables. Используйте этот режим, если уже настраиваете nftables самостоятельно.
В обоих режимах скрипт включает маршрутизацию IPv4 и IPv6 через /etc/sysctl.d/wg.conf. Выбор сохраняется в /etc/wireguard/params. Добавление и отзыв клиентов не меняют правила firewall. При удалении установки в режиме external ваши правила nftables сохраняются.
Не забудьте добавить разрешающие правила в ваш nftables перед подключением клиентов. Нужны:
- Входящий UDP на порт WireGuard.
- Пересылка трафика из VPN во внешний интерфейс.
- Пересылка ответного трафика обратно в VPN.
- Masquerade для выбранной частной IPv4-сети, если у неё нет отдельной маршрутизации в интернете.
Замените параметры примера своими значениями. Порт должен совпадать с ListenPort в конфигурации сервера: установщик предлагает случайный порт, не обязательно 51820.
# Параметры в начале вашего файла nftables
define WAN_IF = "ens3"
define WG_IF = "wg0"
define WG_PORT = 51820
define WG_NET4 = 10.66.66.0/24
Ниже показаны фрагменты существующих цепочек, а не готовая замена вашего firewall. Вставьте правила в соответствующие цепочки перед подходящими правилами drop/reject. Не создавайте повторно таблицы и цепочки, если они уже есть, и не добавляйте дубли существующих правил.
table inet filter {
# ============================================================
# ЦЕПОЧКА INPUT — ВХОДЯЩИЙ ТРАФИК К СЕРВЕРУ
# ============================================================
chain input {
# В существующей цепочке сохраняются hook, policy и остальные правила
iifname $WAN_IF udp dport $WG_PORT accept
}
# ============================================================
# ЦЕПОЧКА FORWARD — ТРАФИК МЕЖДУ ИНТЕРФЕЙСАМИ
# ============================================================
chain forward {
iifname $WG_IF oifname $WAN_IF ip saddr $WG_NET4 accept
iifname $WAN_IF oifname $WG_IF ip daddr $WG_NET4 ct state established,related accept
}
}
Правило NAT поместите в существующую цепочку postrouting. Если таблицы и цепочки NAT ещё нет, её структура может выглядеть так:
table ip nat {
# ============================================================
# ЦЕПОЧКА POSTROUTING — ПОДМЕНА АДРЕСА ПРИ ВЫХОДЕ В ИНТЕРНЕТ
# ============================================================
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
ip saddr $WG_NET4 oifname $WAN_IF masquerade
}
}
Пример предполагает, что остальные правила вашего firewall разрешают необходимый служебный трафик и исходящий трафик сервера. Правила доступа к сервисам самого сервера через VPN добавляются отдельно в input.
Сохраните изменения в постоянной конфигурации вашей системы. Для проверки полного файла без применения можно использовать nft -c -f /etc/nftables.conf, если ваша конфигурация находится по этому пути. Проверка синтаксиса не заменяет проверку соединения и порядка правил. Не очищайте действующий набор правил командой flush ruleset ради добавления VPN.
Отдельного переключателя «включить/выключить IPv6» в текущем установщике нет. Он всегда запрашивает IPv6-адрес, добавляет IPv6 в конфигурации сервера и клиентов и включает net.ipv6.conf.all.forwarding = 1.
Параметр клиента AllowedIPs определяет, какой трафик направляется в туннель:
| Значение | Маршрутизация |
|---|---|
0.0.0.0/0,::/0 |
Весь IPv4 и IPv6 через VPN |
0.0.0.0/0 |
Только IPv4 через VPN; IPv6 может идти напрямую через сеть клиента |
Необходимы следующие условия:
- На сервере работает выход в IPv6-интернет: есть глобальный IPv6-адрес и маршрут по умолчанию.
- IPv6 включён в сетевом стеке клиента и сервера; на интерфейсах WireGuard назначены IPv6-адреса.
- У клиента в
[Peer]указанAllowedIPs = 0.0.0.0/0,::/0. - На сервере включена IPv6-маршрутизация и разрешена пересылка в firewall.
- Для частной ULA-сети VPN настроен NAT66 (masquerade). Альтернатива — выделенный провайдером глобальный префикс с маршрутом к VPN-клиентам; тогда NAT66 не нужен. Одного наличия глобального адреса на сервере для маршрутизации клиентского префикса недостаточно.
Для ULA-сети добавьте параметр, соответствующий вашей IPv6-сети WireGuard:
define WG_NET6 = fd42:42:42::/64
Дополните существующую цепочку forward таблицы inet filter:
# IPv6: из VPN в интернет и ответный трафик
iifname $WG_IF oifname $WAN_IF ip6 saddr $WG_NET6 accept
iifname $WAN_IF oifname $WG_IF ip6 daddr $WG_NET6 ct state established,related accept
Для ULA-адресов добавьте masquerade в IPv6 NAT:
table ip6 nat {
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
ip6 saddr $WG_NET6 oifname $WAN_IF masquerade
}
}
IPv6 также требует служебного ICMPv6, включая обнаружение соседей и сообщения об ошибках/MTU. Не блокируйте его целиком. Если ваш firewall ещё не разрешает ICMPv6, простой вариант для существующей цепочки input таблицы inet filter:
meta l4proto ipv6-icmp accept
При ограничивающей политике output разрешите необходимый исходящий ICMPv6 и UDP WireGuard; также проверьте прохождение связанных ICMPv6-ошибок в forward. Подробности: пример nftables для IPv4/IPv6, документация nftables.
Если сервер получает маршрут IPv6 через Router Advertisement, включение forwarding может изменить приём RA. Для такого внешнего интерфейса может потребоваться net.ipv6.conf.ens3.accept_ra = 2 (замените ens3 своим интерфейсом). При статической настройке маршрутов это обычно не требуется.
При установке введите 0.0.0.0/0 в поле AllowedIPs. Для существующих клиентов измените AllowedIPs в их конфигурациях и переподключите VPN. Чтобы это значение использовалось при создании новых клиентов, установите ALLOWED_IPS=0.0.0.0/0 в /etc/wireguard/params; уже выданные файлы автоматически не обновляются.
Это не отключает IPv6 на устройстве. Если сеть клиента предоставляет IPv6, приложения могут обращаться к сайтам напрямую, вне VPN. Если нужен VPN только с IPv4 без обхода через IPv6, дополнительно отключите IPv6 на клиенте либо заблокируйте его вне туннеля средствами клиентского firewall. Точный способ зависит от ОС клиента.
Полного отключения IPv6 на сервере через меню скрипта нет. Одно изменение AllowedIPs не удаляет IPv6-адреса, маршрутизацию или NAT. Не отключайте IPv6 системно на сервере ради этого параметра: его могут использовать другие службы. Для текущего режима external можно не добавлять IPv6-правила VPN, если IPv6 через туннель не используется.
Да. Адрес Endpoint определяет, как клиент связывается с сервером, а внутренний трафик туннеля может быть IPv4 или IPv6 независимо от этого. WireGuard поддерживает обе версии IP.
Например: клиент с IPv4-интернетом → WireGuard по UDP/IPv4 → сервер → сайт по IPv6. Нативное IPv6-подключение у провайдера клиента для этого не требуется, но IPv6 в ОС клиента должен быть включён. На сервере должны выполняться условия из раздела выше. Сам по себе WireGuard не создаёт IPv6-доступ, если его нет у сервера.
Проверяйте не только handshake: отдельно проверьте доступ к IPv4- и IPv6-ресурсам с подключённого клиента. Например, curl -6 https://www.wireguard.com/ проверяет IPv6-доступ к этому сайту, если он доступен по IPv6 и на клиенте установлен curl.
Остановка интерфейса отключит VPN-клиентов, поэтому используйте доступ к серверу, не зависящий от этого туннеля.
- Сделайте защищённую резервную копию
/etc/wireguard— в ней есть приватные ключи. Подготовьте постоянные правила nftables для выбранных сетей, UDP-порта, пересылки и NAT. - До редактирования хуков остановите WireGuard:
systemctl stop wg-quick@wg0. На Alpine:rc-service wg-quick.wg0 stop. Заменитеwg0именем своего интерфейса. Так прежние командыPostDownсмогут снять правила, добавленные при запуске. - Проверьте результат остановки и действующие правила. Если правила установщика остались, удалите только их соответствующим инструментом firewall, не очищая весь набор.
- Удалите из
/etc/wireguard/wg0.confтолько созданные установщиком firewall-командыPostUp/PostDown. Сохраните собственные хуки и настройки интерфейса и клиентов. - Добавьте или измените строку
FIREWALL_MODE=externalв/etc/wireguard/params. - Запустите WireGuard:
systemctl start wg-quick@wg0; на Alpine:rc-service wg-quick.wg0 start. Проверьте handshake и доступ клиента в интернет.
Автоматическая миграция не выполняется. Изменение только /etc/wireguard/params не удаляет прежние хуки.
В репозитории есть отдельный скрипт wireguard-backup.sh. Запускайте его от root; нужны Bash, tar с поддержкой gzip и стандартные утилиты Linux.
В основном меню выберите 4. Укажите каталог назначения (Enter — /root/wireguard-backups) и при необходимости дополнительный каталог с клиентскими файлами. Бэкап также можно запустить отдельно из каталога скачанных скриптов:
sudo bash wireguard-backup.shПо умолчанию архив создаётся в /root/wireguard-backups. Его имя содержит время UTC и случайный суффикс. Можно указать свой каталог назначения, а затем дополнительные каталоги поиска клиентских файлов:
sudo bash wireguard-backup.sh /var/backups/wireguard /srv/vpn-clientsВ архив попадают:
- Весь каталог
/etc/wireguard: конфигурации интерфейсов, серверные ключи, записи клиентов и файлparamsустановщика. /etc/sysctl.d/wg.conf, если он существует.- Обычные файлы
*-client-*.conf, найденные рекурсивно в/root,/homeи дополнительных каталогах. Пути сохраняются относительно корня системы.
Если клиентские файлы переименованы и больше не соответствуют шаблону, сохраните их отдельно. Символические ссылки при поиске клиентов не обходятся; ссылки внутри /etc/wireguard сохраняются как ссылки, без копирования внешних целей. Файлы, оставшиеся только на устройствах клиентов, с сервера скопировать невозможно. Серверная конфигурация содержит публичные ключи клиентов, но не позволяет восстановить их утраченные приватные ключи.
Скрипт не останавливает VPN и копирует состояние файлов на диске. Не добавляйте и не отзывайте клиентов и не меняйте конфигурацию во время копирования. Изменения, внесённые только через wg set и не сохранённые в файлы, в архив не попадут.
Архив проверяется на возможность чтения и получает права 600; рабочий каталог создаётся с доступом только для root. При ошибке временные файлы удаляются, а готовый архив не публикуется. Это проверка целостности упаковки, а не полноценный тест восстановления.
Архив содержит приватные ключи и не зашифрован. Храните каталог назначения под управлением root, а копию архива — в защищённом хранилище вне сервера. Старые архивы автоматически не удаляются: контролируйте свободное место и срок хранения. Бэкап в режиме external не включает nftables, сетевые настройки провайдера и пользовательские службы или хуки за пределами /etc/wireguard; сохраните их отдельно, включая файлы, подключаемые через include.
Используйте доверенный архив и SSH-подключение, не зависящее от восстанавливаемого VPN. Запустите sudo ./wireguard-install.sh, выберите 5 в меню установленного сервера или 2 в начальном меню нового сервера. Введите полный путь к архиву .tar.gz.
Восстановление выполняет модуль wireguard-restore.py на Python 3.8+ без сторонних библиотек. Его можно запустить напрямую:
sudo python3 wireguard-restore.py /root/wireguard-backups/ИМЯ-АРХИВА.tar.gzПорядок работы:
- Проверка и распаковка. Архив читается в закрытый временный каталог. Отклоняются абсолютные пути,
.., повторяющиеся пути, символические и жёсткие ссылки, специальные и неожиданные файлы. Лимиты — 10 000 записей и 256 МиБ суммарного размера файлов после распаковки. Проверка структуры не доказывает доверенность архива. - Проверка конфигурации. Нужны
paramsданного установщика и соответствующая конфигурация интерфейса. Параметры разбираются как данные, а не выполняются как shell-код. Разрешены только известные параметры и настройки forwarding. Проверяются имена интерфейсов, наличие внешнего интерфейса, инструменты WireGuard и службы. Интерфейс, запущенный вне службы, необходимо предварительно остановить вручную. - Предварительный просмотр. Выводятся имена всех восстанавливаемых интерфейсов, количество peers и shell-хуков. Ключи не выводятся. Восстанавливаются все конфигурации
*.confверхнего уровня/etc/wireguardиз архива; одноимённые действующие конфигурации будут заменены. Другие действующие интерфейсы не удаляются. Старый архив может вернуть отозванных клиентов. - Подтверждение. Для продолжения нужно ввести
RESTORE. Если архив содержитPreUp/PostUp/PreDown/PostDown, эти команды могут выполняться от root при управлении интерфейсами. Проверяйте их до подтверждения. Не используйте чужие архивы. - Страховочная копия. Если
/etc/wireguardсуществует, вызывается скрипт бэкапа. При его ошибке восстановление прекращается до остановки VPN. Дополнительно создаётся закрытый каталог/root/wireguard-backups/restore-recovery-…с предыдущими версиями заменяемых файлов. Путь выводится до изменений. - Клиентские и дополнительные файлы. Они сохраняются в
restore-recovery-…/recovered-files/с исходной структурой путей и правами600. Домашние каталоги пользователей автоматически не перезаписываются. Отсюда можно забрать клиентские конфигурации или вручную перенести их на исходные места с нужными владельцами. Прочие файлы из/etc/wireguard, помимо конфигураций верхнего уровня иparams, также восстанавливаются сюда; если хуки ссылаются на такие файлы, подготовьте их вручную до запуска восстановления. - Замена и запуск. Останавливаются затронутые активные службы. Восстанавливаются конфигурации,
paramsи, если присутствует в архиве,/etc/sysctl.d/wg.conf. Применяется forwarding, запускаются восстановленные интерфейсы, проверяются состояние службы иwg show. - При ошибке. Скрипт пытается остановить новые службы, вернуть заменённые файлы и прежние значения forwarding, запустить ранее активные службы. Если откат неполный, он явно сообщает об этом. Страховочный архив и каталог восстановления сохраняются. Изменения, сделанные shell-хуками в firewall или других службах, могут потребовать ручного исправления. Прерывание питания или принудительное завершение процесса также требует ручного восстановления.
- Проверка клиентом. Проверьте handshake, DNS и интернет, отдельно IPv4/IPv6 при их использовании. Запуск службы сам по себе не подтверждает работоспособность VPN. Автозапуск не меняется: на новом сервере после проверки выполните
sudo systemctl enable wg-quick@wg0(Alpine:sudo rc-update add wg-quick.wg0), подставив своё имя интерфейса.
Правила nftables не восстанавливаются автоматически. Подготовьте их отдельно. В режиме auto восстановленные firewall-хуки будут выполняться как часть запуска службы. При переносе проверьте имя внешнего интерфейса, порт, доступность IPv6 и публичный адрес сервера. Если публичный адрес изменился, обновите SERVER_PUB_IP в params и Endpoint в уже выданных клиентских конфигурациях.
Архивы со ссылками или нестандартными параметрами требуют ручного восстановления после проверки. Сначала проверьте процедуру на тестовом сервере. Сохранённые ключи позволяют существующим клиентам подключаться без перевыпуска конфигураций, если внешний адрес и остальные параметры остаются прежними.
Ошибки и предложения для форка можно оставить в Issues. Перед крупными изменениями желательно обсудить подход. Историю исходного проекта можно найти в его Issues и обсуждениях.
Для проверки кода используются ShellCheck и shfmt. Настройки CI находятся в .github/workflows/lint.yml.
bash -n wireguard-install.sh
bash -n wireguard-backup.sh
shellcheck -e SC1091,SC1117,SC2001,SC2034 wireguard-install.sh wireguard-backup.sh
shfmt -d wireguard-install.sh wireguard-backup.sh
python3 -B -m unittest discover -s tests -vЭти проверки не подтверждают работоспособность VPN: установку, firewall и передачу трафика нужно дополнительно проверять в тестовой Linux-системе.
Основано на проекте angristan/wireguard-install. Лицензия — MIT. Автору исходного проекта можно сказать спасибо.