В данной заметке я расскажу вам про то, как раскатать свой собственный VPN сервер на VDS. В качестве VPN будет использоваться WireGuard, потому что это самая передовая технология VPN которая даёт наибольшую производительность в условиях ограниченных ресурсов. Данная статья не ставит целью разобраться с работой с WireGuard, лишь установить максимально быстро и просто.
Вот что обещает производитель моего мобильного роутера:
Поиск vds
Первое, что нужно сделать, это найти подходящего хостера для покупки VDS. В этом могут помочь специальные сервисы, такие как:
Когда-то давно, когда я выбирал себе хостера, я наткнулся на следующий список компаний принимающих к оплате BTC. Я предпочел использовать HostSailor
.
Установка
-
Берем самый дешёвый vps с приемлемым количеством трафика, тут важный момент, для корректной работы сервиса нужно будет работать с модулями ядра линукса это значит что подайдёт не любой тип виртуализации.
OpenVZ
- не подходит так как это виртуализация на уровне ядра, нам нужна -KVM
, это полноценная виртуалка которая позволит нам запустить хоть шиндус на сервере. -
Ставим debian 11.
Все шаги между этими 2мя пунктами я пропущу, т.к. у любого хостера навалом подобной информации в справке.
Настройка сервера (Debian)
- Подключится через ssh под рутом (
ssh root@<YOU IP>
) и обновить систему.
apt update
apt dist-upgrade
apt install net-tools sudo wireguard-tools mawk grep iproute2 qrencode iptables
Если сервер с очень маленьким количеством ОЗУ, например 256 или 512 мб, то попытка обновления системы может повалить ее, так что не вводим apt upgrade
, выбора все равно нет.
- Создать нового пользователя.
Это необходимо для того чтобы, было невозможно подключится к серверу из под рута.
useradd -m -s /bin/bash admin
passwd admin
usermod -aG sudo admin
- Проверить какие сервисы висят на портах.
Хостеры часто любят поставить какой-то софт при установке, например Apache. Наша задача удалить его весь, т.к. он потенциальная дыра в безопасности. В результате должен остаться только sshd.
netstat -tulpn
Для отключения лишних сервисов необходимо сделать следующее:
/etc/init.d/apache2 stop
update-rc.d apache2 disable
- Для увелечения безопасности настроить ssh:
nano /etc/ssh/sshd_config
- Сменить порт:
#Port 22 # ---> раскомментировать, сменить на любое число (1024 до 64000)
- Ищем параметр
PermitRootLogin
и ставимno
- Ищем параметр
PermitEmptyPasswords
и ставимno
- Запретить доступ по ssh всем кроме user: добавить внизу
AllowUsers admin
- Перезапускаем sshd и реконектимся.
service sshd restart
Здесь нужно быть крайне внимательным, в случае ошибки в предыдущих пунктах или утери пароля, вы не сможете больше получить доступ к северу. Для коннекта нужно сделать следующее:
ssh -p <PORT> admin@<YOU IP>
Установка WIREGUARD
Здесь не большое отступление. Мы бы, конечно, могли бы установить VPN с нуля и настроить все ручками, как например тут и тут, но сегодня наша задача получить готовое, а главное удобное для использования решение, а не преисполниться в своем познании, поэтому воспользуемся готовым скриптом, который разрулит всю рутину за нас.
- Скачиваем и запускаем скрипт:
wget https://raw.githubusercontent.com/burghardt/easy-wg-quick/master/easy-wg-quick
chmod +x easy-wg-quick
./easy-wg-quick user_1
sudo wg-quick up ./wghub.conf
Ввод предпоследний команды настроит конфиг для первого клиента с именем user_1
. Конфиг будет доступен в виде:
- конфиг файла -
wgclient_user_1.conf
. - qr код -
wgclient_user_1.qrcode.txt
, его можно вывести в терминале командойcat wgclient_user_1.qrcode.txt
- uci -
wgclient_user_1.uci.txt
После добавления нового клиента нужно обязательно перезагрузить интерфейс:
sudo wg-quick down ./wghub.conf
sudo wg-quick up ./wghub.conf
Для автоматического старта при запуске системы нужно сделать следующее:
sudo cp wghub.conf /etc/wireguard/wghub.conf
sudo systemctl enable wg-quick@wghub
sudo systemctl start wg-quick@wghub
systemctl status wg-quick@wghub
UDP: Дальнейшее было на debian 10, на Debian 11 проблема не воспроизвелась.
После чего я столкнулся с проблемой, при попытки запустится выдавалось такое сообщение:
admin@my-vpn:~$ sudo wg-quick up ./wghub.conf
[#] ip link add wghub type wireguard
RTNETLINK answers: Operation not supported
Unable to access interface: Protocol not supported
[#] ip link delete dev wghub
Cannot find device "wghub"
Также попытка подгрузить модуль wireguard
, тоже не успешна:
admin@my-vpn:~$ sudo modprobe wireguard
modprobe: FATAL: Module wireguard not found in directory /lib/modules/4.19.0-6-amd64
Решение подсмотрел тут:
sudo apt install linux-headers-$(uname -r|sed 's/[^-]*-[^-]*-//')
sudo wg-quick up ./wghub.conf
После установки хедеров, вводим команду запуска сервера и наши конфиги начинают работать.
Клиенты
Linux
Первое, что нужно сделать - это установить клиент под Linux:
sudo apt install wireguard
После чего создаем конфиги для клиентов. Как правило, у меня из несколько, поэтому я называю их в формате wg_<название страны>
. Например, конфиг для нидерландов будет такой - /etc/wireguard/wg_nl.conf
. Содержимое самого конфига берется с сервера, что описано выше.
sudo nano /etc/wireguard/wg_nl.conf
Для запуска или остановки клиента достаточно сделать следующее:
sudo wg-quick up wg_nl
sudo wg-quick down wg_nl
Для автоматического старта при старте системы нужно сделать:
sudo systemctl enable wg-quick@wg_nl
В случае возникновения следующей проблемы:
/usr/bin/wg-quick: line 32: resolvconf: command not found
Тут дело в том что в systemd resolvconf
это часть команды resolvectl
. Для решения проблемы достаточно просто сделать ссылку:
sudo ln -s /usr/bin/resolvectl /usr/local/bin/resolvconf
# ИЛИ
sudo apt install openresolv
Также в случае появления данной ошибки:
Failed to set DNS configuration: Unit dbus-org.freedesktop.resolve1.service not found.
Нужно включить недостающий сервис:
sudo systemctl start systemd-resolved.service
sudo systemctl enable systemd-resolved.service
Для работы скрипта нужно разрешить запуск wg
и wg-quick
от нашего юзера. Для этого в /etc/sudoers
добавим в конец следующую строку (вместо user ваш пользователь):
user ALL=(ALL:ALL) NOPASSWD: /usr/bin/wg, /usr/bin/wg-quick
Switch
Если конфиг один, то для включения и выключения VPN можно использовать простенький обнострочник:
if ip l dev wg_nl | grep -q UP; then; sudo wg-quick down wg_nl; else; sudo wg-quick up wg_nl; fi
Если конфигов больше одного, то можно использовать скрипт, который позволяет их циклически переключать:
#! /bin/bash
vpns=$(ls /etc/wireguard/)
flag=0
for vpn in $vpns
do
vpnname="${vpn%.*}"
if [ $flag == 1 ] || ! $(ip l | grep wg | grep -q UP)
then
sudo wg-quick up $vpnname
notify-send -i online "Wireguard" "Enable $vpnname VPN."
exit 0
fi
if ip l | grep -q $vpnname
then
sudo wg-quick down $vpnname
flag=1
fi
done
notify-send -i offline "Wireguard" "Disable VPN!"
exit 0
Для отображения уведомлений в данном скрипте необходимы пакеты dunst
, libnotify-bin
, papirus-icon-theme
. Теперь данный скрипт можно повесть на комбинацию клавиш, например в BSPWM
.
Polybar
В Polybar
или любой другой бар, можно добавить виджет показывающий статус соединения. Я предлагаю создать 2 таких виджета, первый будет показывать факт соединение, второй-же будет отображать внешний IP и страну соединения.
Первый блок. Показывает щит с замком (из Nerd Fonts) когда запущен любой VPN.
[module/vpn]
type = custom/script
exec-if = ip l | grep wg | grep -q UP
interval = 3
exec = echo " "
format-prefix = " "
format-prefix-foreground = ${colors.foreground-alt}
format-underline = ${colors.orange}
Второй же запрашивает внешний ip адрес.
[module/vpn_check]
type = custom/script
interval = 1
exec = cat /tmp/vpn_state
click-left = touch /tmp/vpn_check
format-prefix = " "
format-prefix-foreground = ${colors.foreground-alt}
format-underline = ${colors.orange}
Однако тут все сложнее. Чтобы не есть лишний трафик и не засорять канал, опрос ip адреса проходит раз в минуту или по нажатию на виджет на панели. Однако обновить виджет просто по нажатию нельзя, поэтому мы создаем файл в /tmp
, наличие которого проверяет скрипт. Если он существует, скрипт создает документ с данными, которые уже читает док раз в секунду.
#! /bin/bash
counter=0
echo ------ > /tmp/vpn_state
while [ true ]
do
if [ -f /tmp/vpn_check ]
then
addr=$(curl -4 -s ifconfig.net/json)
ip=$(echo $addr | jq -r '.ip')
con=$(echo $addr | jq -r '.country_iso')
echo $con $ip > /tmp/vpn_state
rm /tmp/vpn_check
counter=0
else
if [[ $counter == 60 ]]
then
addr=$(curl -4 -s ifconfig.net/json)
ip=$(echo $addr | jq -r '.ip')
con=$(echo $addr | jq -r '.country_iso')
echo $con $ip > /tmp/vpn_state
counter=0
else
counter=$((counter + 1))
fi
fi
sleep 1
done
Данный скрипт необходимо пихнуть в автозагрузку, а также для его работы нужен пакет jq
.
Интересные ссылки: