Подробная инструкция, как арендовать и настроить свой выделенный сервер - для защиты своего сетевого трафика от анализа третьими лицами (прослушки) и прочих нежелательных сетевых активностей. Коротко, о чём гайд:
- Сервер Linux Debian 11
- Виртуальная частная сеть Wireguard
- Мониторинг Grafana
- Спасательный круг: backups & snapshots
- Базовая защита от взлома перебором fali2ban
- Фильтр нежелательного контента, приоритезация трафика QoS
Шаг 1: Выбрать хостинг
Воспользоваться поисковым запросом "список самых дешёвых VPS хостингов" и выбрать, какой больше нравится. Конфигурации и цены бывают разные, самые дешёвые начинаются от двух евро в месяц. Например - hip.hosting
Шаг 2: Выбрать локацию, операционную систему и оплатить аренду сервера
Локацию сервера выбираем из доступных, исходя из своих предпочтений. Обычно - чем ближе локация, тем ниже задержка. Операционную систему я советую Debian.
Шаг 3: Настройка операционной системы
Используя программу Putty и предоставленные IP адрес и пароль, нужно войти на сервер и обновиться:
sudo apt update && apt upgrade -y
sudo apt-get install iptables net-tools vim rsync parted -y
В файле системной конфигурации нужно убрать знак комментария "#" в начале строки "net.ipv4.ip_forward=1", чтобы разрешить нашему серверу выполнять роль прокси:
vim /etc/sysctl.conf
vim, vi - самый распространённый текстовый редактор linux. Режим редактирования включается кнопкой i, выход из редактирования кнопка esc. Чтобы выйти без сохранения надо ввести ":q!" (без кавычек), выход с сохранением - ":wq!"
Установим бесплатный клиент с открытым исходным кодом Wireguard:sudo apt install wireguard -y
Переходим в папку приложения:cd /etc/wireguard/
Генерируем и записываем ключи:wg genkey | tee privatekey | wg pubkey | tee publickey
Приватный ключ надо записать в конфиг Wireguard; здесь Address = это адрес сервера в виртуальной сети, а ListenPort = порт, по которому будут подключаться клиенты (адрес и порт можно задать произвольно):echo "[Interface]
PrivateKey = $(cat privatekey)
Address = 10.0.0.1/24
ListenPort = 51820" > wg0.conf
в Putty текст вставляется правой кнопкой мыши. В vim через Putty - клавиша shift+правая кнопка мыши. А для переноса больших объёмов текста в веб-консоль, у меня есть пара удобных инструментов - typewriter и infill.
Далее - надо добавить в этот файл информацию о сетевом адаптере:INTERFACE=$(ip route | grep default | awk '{print $5}' | head -n1); sudo tee -a wg0.conf <<EOF
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o $INTERFACE -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o $INTERFACE -j MASQUERADE
EOF
После этого, в конфигурационный файл добавляются клиенты:[Peer]
PublicKey = uJWPI0zpKSB7C4G9LLdy4VMX2bPXs33g7nfdo2CVanw=
AllowedIPs = 10.10.10.30/32
PublicKey - публичный ключ клиента, которому принадлежит виртуальный адрес AllowedIPs, а маска /32 говорит о том, что это одиночный адрес хоста.
В итоге, конфигурационный файл wg0.conf должен иметь вид типа такого:
[Interface]
Address = 10.10.10.1/24ListenPort = 21212
PrivateKey = qPSUFPcGiHUQkOo2RHPGWeb3XmSjfiSWqSMuPd3SnCs=
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o ens3 -j MASQUERADE[Peer]
PublicKey = uJWPI0zpKSB7C4G9LLdy4VMX2bPXs33g7nfdo2CVanw=
AllowedIPs = 10.10.10.30/32[Peer]
PublicKey = YXnyogyq5930eFdueaFivCqpJCRMEmawJrpP1lcGEDc=
AllowedIPs = 10.10.10.20/32
где
PrivateKey - приватный ключ сервера
Address - виртуальный адрес сервера
ListenPort - порт сервера
PublicKey - публичный ключ клиента, которому принадлежит виртуальный адрес AllowedIPs из его секции [Peer]
Публичный ключ клиента можно получить в приложении клиента (например, Wireguard для Windows), где он будет случайно сгенерирован при добавлении нового "пустого" туннеля.
Добавляем туннель в автозагрузку и перезагружаемся:sudo systemctl enable wg-quick@wg0
sudo reboot
Готово! Минимальная настройка завершена,
теперь введя в клиент публичный ключ сервера, внутренний IP-адрес клиента и внешний IP=адрес сервера с портом - можно пользоваться сетью. Теперь установим и настроим мониторинг Grafana для отслеживания сетевой активности по клиентам:sudo tee /etc/apt/sources.list.d/grafana.list <<'EOF'
deb [signed-by=/etc/apt/keyrings/grafana.gpg]
https://apt.grafana.com
stable main
EOF
sudo mkdir -p /etc/apt/keyrings/
apt-get install gpg
wget -q -O - https://apt.grafana.com/gpg.key
| gpg --dearmor | sudo tee /etc/apt/keyrings/grafana.gpg > /dev/null
sudo apt install -y prometheus grafana
sudo iptables -A INPUT -i wg0 -j ACCEPT
sudo iptables -A OUTPUT -o wg0 -j ACCEPT
curl https://sh.rustup.rs
-sSf | sh
source $HOME/.cargo/env
sudo apt install cargo build-essential -y
cargo install clap --version 4.0.26
exec bash
cargo install prometheus_wireguard_exporter
vim /etc/prometheus/prometheus.yml
Заполнить файл следующим содержанием, строгое количество пробелов в началах строк!scrape_configs:
- job_name: 'wireguard'
scrape_interval: 10s
static_configs:
- targets: ['localhost:9586']
Чтобы мониторинг запускался со стартом системы, создадим systemd-сервис:vim /etc/systemd/system/wireguard-exporter.service
[Unit]
Description=Prometheus WireGuard Exporter
After=network-online.target
[Service]
ExecStart=/usr/bin/prometheus_wireguard_exporter --interfaces wg0
Restart=on-failure
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now grafana-server
sudo systemctl enable --now wireguard-exporter.service
prometheus_wireguard_exporter --interfaces wg0 &>> /var/log/wireguard-exporter.log &
Проверка что всё работает:jobs -l
Теперь можно зайти на веб-панель мониторинга, используя адрес своего сервера и порт 3000: http://your-server-ip:3000
Для первого входа используются стандартные логин и пароль admin
Мониторинг можно настроить в разделе "Dashboards". В режиме "edit" - включается сверху справа - выбираем Add - visualisation. Выбираем prometheus, адрес сервера вставляем дефолтный (http://localhost:9090) и save. Сохраняем дашборд под каким-нибудь названием и заходим в него через меню Dashboards. Удаляем все query и создаём новую, по кнопке + Add query. В поле Data source должен быть выбран prometheus. Справа - переключаемся в режим Code, если вдруг выбран Builder. Далее - в поле "Enter a PromQL query..." вставляем следующий запрос:rate(wireguard_received_bytes_total[1m])
Нажимаем кнопку Run queries и сверху должен появиться график. Сохраняем дашборд справа сверху. Дальнейшая настройка вполне интуитивна. Чтобы переименовать графики - нужно прокрутить Panel options вниз до кнопки + Add field override, нажав на неё выбрать нужный график и переименовать его.
Для базовой защиты сервера от взлома - рекомендую утилиту fail2ban:sudo apt install fail2ban -y
vim /etc/fail2ban/jail.local
Пример настройки файла конфигурации /etc/fail2ban/jail.local
:
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 7
bantime = 1h
sudo systemctl start fail2ban
sudo systemctl enable fail2ban
Далее - продвинутая конфигурация: переход на другую файловую систему, резервное копирование и моментальные снимки, восстановление из резервной копии, фильтрация нежелательного контента и правила для разных типов трафика.
Этап 1: Смена файловой системы и резервное копирование
Иногда случаются различные казусы, после которых возникает острое желание откатиться на некоторое время назад. В большинстве приложений - такой откат на одно последнее действие происходит комбинацией клавиш CTRL+Z, однако не всегда и не везде. В некоторых случаях - полезно иметь полную резервную копию всех данных. Лучше, когда она есть и не нужна, чем когда нужна и её нет.
Базовая файловая система Linux, EXT4 - не обладает функционалом снимков файловой системы - поэтому в первую очередь мы выполним переход на более продвинутую BTRFS
Смотрим сколько есть места на сервере командой df -h. В моём примере сервер с 10ГБ диском.
Свободное место делим чуть меньше чем пополам и с помощью parted создаём логический том под резервную копию
sudo apt install parted btrfs-progs -y
sudo parted /dev/sda
resizepart 1 → указываем новый размер: 4.8GB.
mkpart primary btrfs 4.8GB 100% → создаем /dev/sda2 из оставшегося места.
print → проверяем, что получилось.
q
sudo mkdir /mnt/btrfs_backup
sudo mount /dev/sda2 /mnt/btrfs_backup
Синхронизируем содержимое корневого раздела и резервного, без лишних каталогов (и удаляя всё лишнее в целевой директории): sudo rsync -aAXv --delete --exclude={"/dev/","/proc/","/sys/","/tmp/","/run/","/mnt/","/media/*","/lost+found"} / /mnt/btrfs_backup/
sudo mkdir /mnt/btrfs_backup/{dev,proc,sys,tmp,run,mnt,media}
Подменяем разделы для загрузки с бэкапа - редактируем fstab:sudo sed -i "| / |c UUID=$(sudo blkid -s UUID -o value /dev/sda2) / btrfs defaults,compress=zstd,noatime 0 1" /mnt/btrfs_backup/etc/fstab
И загрузчик grub:
sudo mount --bind /dev /mnt/btrfs_backup/dev
sudo mount --bind /proc /mnt/btrfs_backup/proc
sudo mount --bind /sys /mnt/btrfs_backup/sys
sudo chroot /mnt/btrfs_backup
update-grub
grub-install /dev/sda
exit
Теперь при следующей загрузке сервер запустится из резервной копии в разделе с файловой системой BTRFS.sudo reboot
После перезагрузки, убедимся, что корень (/) находится на /dev/sda2 командой df -h, затем преобразуем /dev/sda1 в BTRFS: sudo mkfs.btrfs -f /dev/sda1
sudo mkdir /mnt/sda1
sudo mount /dev/sda1 /mnt/sda1
mkfs преобразует файловую систему, не конвертируя данные, поэтому нам надо вернуть их обратно из резервной копии:sudo rsync -aAXv --delete --exclude={"/dev/","/proc/","/sys/","/tmp/","/run/","/mnt/","/media/*","/lost+found"} / /mnt/sda1/
Снова правим GRUB, для загрузки в sda1:
sudo mount --bind /dev /mnt/sda1/dev
sudo mount --bind /proc /mnt/sda1/proc
sudo mount --bind /sys /mnt/sda1/sys
sudo chroot /mnt/sda1
update-grub
grub-install /dev/sda
exit
Перезагружаемся и актуализируем fstabsudo reboot
sudo sed -i "s/^UUID=[^ ]* / btrfs/UUID=(blkid -s UUID -o value(findmnt -n -o SOURCE /)") / btrfs/" /etc/fstab
Восстановление из загрузочного меню GRUB RESCUE
Если по какой-то случайности система оказалась в нерабочем состоянии, разбираться в котором нет никакого желания - можно загрузиться в резервную копию через меню загрузчика GRUB.
Смотрим список доступных разделов:ls
Проверяем список на наличие загрузочного сектора:ls (hd0,gpt2)/boot/
Если вывод команды показывает файлы типа vmlinuz и initrd.img, значит, это корневой раздел. Для успешного восстановления - нужно выбрать корневой раздел с резервной копией.
Обычно, нумерация разделов такая же, как в операционке, а hd - это номер физического диска (нумерация с нуля)
Загрузка из этого раздела:set root=(hd0,gpt2)
set prefix=(hd0,gpt2)/boot/grub
insmod normal
normal
После загрузки в резервный раздел - нужно вернуться к действию 5) и копировать резервную копию на основной раздел, а затем перезагрузиться в него (и fstab обновить).
Работа с моментальными снимками
Создадим первый:sudo mkdir /snapshots
sudo btrfs subvolume snapshot / /snapshots/root_$(date +%Y-%m-%d_%H-%M)
Просмотр списка "быстрых сохранений":sudo btrfs subvolume list /
Откат системы к моментальному снимку
sudo btrfs subvolume set-default $(sudo btrfs subvolume list / | sort -n -k2 | tail -1 | awk '{print $2}') / && sudo reboot
- Эта команда выполняет откат к последнему снапшоту, после чего перезагружает систему.
Этап 2: Настройка конфигурации клиента и блокировка рекламы на уровне DNS
На стороне устройств, включённых в виртуальную частную сеть, (на стороне клиентов) выполняется следующая настройка конфигурации Wireguard:
Секция [Interface] относится к виртуальному интерфейсу клиента; ему нужно присвоить (или сгенерировать) приватный ключ подходящего формата (wireguard), публичный отпечаток которого вводится в конфигурацию на стороне сервера. Адрес - во внутренней сети, то бишь в VPN. А DNS - указываем от AdGuard, с блокировкой рекламы и вредоносных сайтов, и запасной от Google, как самый надёжный - к нему сервер будет обращаться только в случае недоступности первого (чего обычно тоже никогда не случается).
В секции [Peer] указывается публичный ключ нашего сервера, Endpoint - это IP-адрес сервера и его listenport; PersistentKeepalive - это время в секундах когда будет повторно выполнено рукопожатие для поддержания активного статуса подключения, а AllowedIPs - это список сетевых адресов, трафик до которых будет перенаправлен через VPN. Иными словами - если какой-то адрес не входит в диапазоны указанные в этом списке - то трафик до этого адреса не будет идти через VPN. Это может быть полезно, например, для внутренних ресурсов, доступ к которым может быть ограничен с удалённых серверов, или для минимизации задержки в онлайн-играх.
Чтобы "ограничить влияние" VPN на какие-либо сервисы, делаются три действия:
определение сетевого адреса, используемого сервисом - проще всего это сделать с помощью поиска в Сети, поскольку разработчики обычно публикуют информацию о используемых адресах, либо с помощью анализаторов типа WireShark
с помощью специального калькулятора (https://www.procustodibus.com/blog/2021/03/wireguard-allowedips-calculator/) нужно составить корректную строку для AllowedIPs
ввести эту строку в секцию AllowedIPs в конфиге клиента (пира)
Пример конфигурации для клиента, с блокировкой рекламы и исключением сети 11.7.0.0/16:
[Interface]
PrivateKey = e3rmxdsBWO5pcHR4wRaQSiOJ9lrz7w8dALNIKeMUc0M=
Address = 10.10.10.99/24
DNS = 94.140.14.14, 8.8.8.8[Peer]
PublicKey = Hp3gn3oQOHO2QBWSL0jlYVhrCSNh/HW3a/e+O1jR2Ts=
AllowedIPs = 0.0.0.0/5, 8.0.0.0/7, 10.0.0.0/8, 11.0.0.0/14, 11.4.0.0/15, 11.6.0.0/16, 11.8.0.0/13, 11.16.0.0/12, 11.32.0.0/11, 11.64.0.0/10, 11.128.0.0/9, 12.0.0.0/6, 16.0.0.0/4, 32.0.0.0/3, 64.0.0.0/2, 128.0.0.0/1
Endpoint = 2.21.189.131:33444
PersistentKeepalive = 60
Этап 3: фильтр HTTP рекламы Privoxy
Установим Privoxy и скачаем расширенные листы блокировок:
sudo apt update && sudo apt install privoxy -y
sudo wget -O /etc/privoxy/easylist
https://easylist.to/easylist/easylist.txt
&& echo "filterfile easylist" | sudo tee -a /etc/privoxy/config && sudo systemctl restart privoxy && sudo systemctl enable privoxy
Для фильтрации всей остальной рекламы - рекомендую приложение uBlock в браузере клиента
Этап 4: правила для разных типов трафика (QoS)
Установим политики по умолчаниюsudo iptables -P INPUT ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -P FORWARD DROP
Разрешить форвард только для клиентов Wireguard:sudo iptables -A FORWARD -i wg0 -o ens3 -j ACCEPT
sudo iptables -A FORWARD -i ens3 -o wg0 \ -m state --state RELATED,ESTABLISHED -j ACCEPT
Включить NAT для выхода в Интернет:sudo iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE
Смарт-фильтр CAKE настраиваем на пропускную способность сети сервера (с указанием названия адаптера):sudo tc qdisc replace dev ens3 root cake bandwidth 100mbit nat
Правила для игрового трафика:sudo iptables -t mangle -A PREROUTING -i wg0 -p udp -m multiport --dports 27000:27100,3478:3479,4379:4380,3724,4000,5060:5062,6112:6119,6250,12000:64000 -j DSCP --set-dscp-class EF
sudo iptables -t mangle -A PREROUTING -i wg0 -p tcp -m multiport --dports 27015:27050,1119:1120,3074,3724,4000,6112:6120 -j DSCP --set-dscp-class EF
Голосовые и видеозвонки:sudo iptables -t mangle -A PREROUTING -i wg0 -p udp --dport 3478:3481 -j DSCP --set-dscp-class EF
Видео-стриминг:sudo iptables -t mangle -A PREROUTING -i wg0 -p tcp --dport 443 -m string --string "youtube" --algo bm -j DSCP --set-dscp-class AF21
Веб-трафик:sudo iptables -t mangle -A PREROUTING -i wg0 -p tcp --dport 80,443 -j DSCP --set-dscp-class BE
Низкий приоритет для всего остального (например, торренты):sudo iptables -t mangle -A PREROUTING -i wg0 -j DSCP --set-dscp-class CS1
команды iptables и tc не сохраняются при перезагрузке по умолчанию; чтобы конфигурация не потерялась при выключении сервера, используем дополнительные инструменты:
sudo apt-get install iptables-persistent -y
sudo iptables-save > /etc/iptables/rules.v4
vim /usr/local/bin/apply_
qos.sh
sudo chmod +x /usr/local/bin/apply_
qos.sh
vim /etc/systemd/system/qos.service
[Unit]
Description=Apply QoS rules
After=network-online.target
Wants=network-online.target[Service]
Type=oneshot
ExecStart=/usr/local/bin/apply_qos.sh
RemainAfterExit=yes[Install]
WantedBy=multi-user.target
sudo systemctl enable qos.service
После успешной настройки - сделаем снапшот системы и выполним перезагрузку сервера, чтобы убедиться, что система устойчива к перезапускам:sudo btrfs subvolume snapshot / /snapshots/root_$(date +%Y-%m-%d_%H-%M) && sudo reboot
Комментарии (14)
Mirzapch
25.06.2025 12:08Сервер Linux Debian 11
Актуальная версия дебиана - 12.11.0 на данный момент.
CPUBug
25.06.2025 12:08Зачем использовать Debian 11? Debian 12 выпущен около 2-х лет назад.
Aremys Автор
25.06.2025 12:08Дома у себя - согласен. Но на хостингах обычно идут не самые последние релизы ОС.
CPUBug
25.06.2025 12:08Это легко решается редактированием sources.list с последующим apt update && apt dist-upgrade
Aremys Автор
25.06.2025 12:08зачем? чем 11 дебиан плох? какого функционала нам не хватает? зачем нам тратить своё время на лишние действия?
CPUBug
25.06.2025 12:08Дело не в нехватке функционала. Использование актуальной версии дистрибутива сделало бы инструкцию актуальной на более долгое время. Насколько я помню до конца поддержки Debian 11 осталось около года.
alexs963
25.06.2025 12:08Давно уже iptables заменили на nftables
Для конвертации ext4 в btrfs есть btrfs-convert
Почему не использовать юнит systemd для запуска мониторинга? после перезагрузки предлагаете вручную снова запускать?
Рекомендую использовать снимки в режиме только для чтения:
btrfs subvolume snapshot -r
Aremys Автор
25.06.2025 12:08про мониторинг - вот это хорошо подмечено, пропустил его автозапуск, добавляю в гайд
lea
25.06.2025 12:08По настройке fail2ban пара комментариев:
Желательно заигнорить айпишник станции, с которой ходим на vps.
Производительность может очень сильно отличаться в зависимости от способа бана. У меня fail2ban стартовал минут 5 при 1500 забаненных айпишниках с близкой к вашей конфигурацией и банами по-дефолту через rich rules, переключил на ipset - время запуска сократилось до пары секунд.
sudo dnf install fail2ban sudo vi /etc/fail2ban/jail.local # приводим к виду: [DEFAULT] bantime = 1mo findtime = 3600 maxretry = 2 ignoreip = 127.0.0.0/8 ::1 $MY_IP [sshd] enabled = true filter = sshd mode = aggressive port = 22 # переключаем на баны через ipset sudo vi /etc/fail2ban/jail.d/00-firewalld.conf # конфиг, который был у меня по-умолчанию: [DEFAULT] banaction = firewallcmd-rich-rules banaction_allports = firewallcmd-rich-rules # приводим к виду: [DEFAULT] banaction = firewallcmd-ipset banaction_allports = firewallcmd-ipset # названия действий для iptables/nftables можно подсмотреть где-то тут: # sudo ls -la /etc/fail2ban/action.d/ # чтобы не слетало правило фильтрации по ipset при # выполнении sudo firewall-cmd --reload sudo vi /etc/firewalld/firewalld.conf # находим строку FlushAllOnReload=yes # заменяем на FlushAllOnReload=no sudo systemctl restart firewalld sudo systemctl enable --now fail2ban sudo iptables -L # тут увидим новое правило: Chain INPUT (policy ACCEPT) target prot opt source destination REJECT tcp -- anywhere anywhere multiport dports ssh match-set f2b-sshd src reject-with icmp-port-unreachable sudo fail2ban-client status sshd sudo ipset list f2b-sshd # два способа посмотреть список банов
(это на centos9 stream, но идея должна быть понятна)
+ добавил бы про отключение логина по ssh для пользователя root (как минимум)
Vadimio
25.06.2025 12:08Гайд - это, я так понимаю, от английского guide (руководство)
т.е. статья называется:
"руководство на виртуальный частный сервер (VPS) с нуля"
Это вообще по-русски написано?Давайте тогда, как сегодня модно:
"Обзор на VPS с нуля"
ValdikSS
И все начинают маршрутизировать трафик через ваш сервер, без ограничений. Запрещающих правил у вас не вижу.
Aremys Автор
Отличное замечание! сейчас поправлю гайд