C каждым днем все больше и больше людей узнают, что такое VPN, и начинают им пользоваться, но зачастую все сталкиваются с такой проблемой, что включая VPN мы получаем доступ к заблокированным ресурсам, но в тоже время теряем доступ к ресурсам, которые закрывают свой доступ из других локаций по тем или иным причинам. По этой причине приходится постоянно выключать VPN. В данном мане я расскажу, как поднять свой VPN сервис, который позволит получать доступ ко всем ресурсам в интернете не отключаясь от VPN‑сервера.
Для создания нам надо два сервера VPN1 и VPN2.
VPN1 в идеале должен находиться в той же стране, что и пользователь по двум причинам:
Для ускорения сигнала и минимизации задержек.
Многие ресурсы запрещают доступ из других локаций.
VPN2 может находиться в стране, где нет тех ограничений, которые необходимо обойти. Чем ближе к локации пользователя он будет находиться, тем лучше по той же первой причине выше.
Для дальнейшего понимания что и куда "втыкать" определимся с данными серверов:
VPN1:
IP1 - 11.11.11.11
ip1_gateway - 11.11.11.1
IP_VPN1 - 192.168.11.1
ip_gateway_vpn1 - 192.168.11.1
VPN2:
IP2 - 12.12.12.12
ip2_gateway - 12.12.12.1
IP_VPN2 - 192.168.12.1
ip_gateway_vpn2 - 192.168.12.1
На сервере VPN1 мы подключаем пользователей с перенаправлением всего трафика, а на сервер VPN2 подключаем сервер VPN1 с «локальным» подключением. «Локальное» подключение — подключение при котором между серверами создается только туннель и в него идет определенный трафик, а весь трафик по умолчанию идет в обход туннеля.
Приступим к настройке сервера VPN1.
Для начала установим необходимые утилиты:
apt update && apt upgrade
apt install sudo vim shorewall curl wget openvpn dnsutils -y
Включаем пересылку пакетов на сервере. Находим строку и приводим ее к следующему виду:
vim /etc/sysctl.conf
net.ipv4.ip_forward=1
sysctl -p
cd /etc/shorewall/
Далее нам надо взять шаблоны необходимых файлов, чтобы не писать их с нуля:
cp /usr/share/doc/shorewall/examples/two-interfaces/{interfaces,policy,rules,snat,zones} /etc/shorewall/
cp /usr/share/shorewall/configfiles/{tunnels,routes} /etc/shorewall/
mkdir {local,routes.d}
Теперь приводим шаблоны к нашей ситуации. На сервере VPN1 у нас будет три интерфейса:
ens3 – физический интерфейс с внешним статическим IP,
tun1u – виртуальный интерфейс vpn1.server,
tun2u – виртуальный интерфейс vpn2.client.
Сервер VPN1 находится в зоне ru, значит так ее и назовем, а VPN2 находится в зоне nl:
vim zones
fw firewall
net ipv4
ru ipv4
nl ipv4
Обращаем внимание на названия интерфейсов!
vim interfaces
net ens3 dhcp,tcpflags,nosmurfs,routefilter,logmartians,sourceroute=0
ru tun1u optional,tcpflags,nosmurfs,routefilter,logmartians
nl tun2u optional,tcpflags,nosmurfs,routefilter,logmartians
В следующем файле мы прописываем настройки для пересылки трафика VPN, где указываем свои протокол и порт vpn сервера:
vim tunnels
openvpnserver:udp:11443 net 0.0.0.0/0
Нам надо включить маскардинг, для этого в файле snat убираем дефолтные настройки и прописываем свои с подстановкой своих подсетей:
vim snat
MASQUERADE 192.168.11.0/24 ens3
MASQUERADE 192.168.11.0/24 tun2u
vim policy
$FW net ACCEPT
$FW ru ACCEPT
$FW nl ACCEPT
ru $FW ACCEPT
ru net ACCEPT
ru nl ACCEPT
net all DROP $LOG_LEVEL
# THE FOLOWING POLICY MUST BE LAST
all all REJECT $LOG_LEVEL
vim rules
?SECTION ALL
?SECTION ESTABLISHED
?SECTION RELATED
?SECTION INVALID
?SECTION UNTRACKED
?SECTION NEW
# Don't allow connection pickup from the net
#
Invalid(DROP) net all tcp
#
# Accept DNS connections from the firewall to the network
#
DNS(ACCEPT) $FW net
#
# Accept SSH connections from the local network for administration
#
SSH(ACCEPT) net $FW
SSH(ACCEPT) nl $FW
SSH(ACCEPT) ru $FW
SSH(ACCEPT) $FW net
SSH(ACCEPT) $FW nl
SSH(ACCEPT) $FW ru
#
# Allow Ping from the local network
#
Ping(ACCEPT) nl $FW
Ping(ACCEPT) ru $FW
#
# Drop Ping from the "bad" net zone.. and prevent your log from being flooded..
#
Ping(DROP) net $FW
ACCEPT $FW nl icmp
ACCEPT $FW ru icmp
ACCEPT $FW net icmp
Настраиваем vpn сервер, запускаем. Так же перезапускаем shorewall:
systemctl restart shorewall
systemctl enable shorewall
Можем выпустить уже пользовательский сертификат с оборотом всего трафика и проверить работоспособность. Проверить можно на сайте https://2ip.ru ну или на том, который больше нравится. Если подключение пошло, на сайте мы увидели IP сервера, тогда все сделали верно.
Начинаем настраивать VPN2.
Для начала установим необходимые утилиты:
apt update && apt upgrade
apt install sudo vim shorewall curl wget openvpn dnsutils -y
Включаем пересылку пакетов на сервере. Находим строку и приводим ее к следующему виду:
vim /etc/sysctl.conf
net.ipv4.ip_forward=1
sysctl -p
cd /etc/shorewall/
Далее нам надо взять шаблоны необходимых файлов, чтобы не писать их с нуля:
cp /usr/share/doc/shorewall/examples/two-interfaces/{interfaces,policy,rules,snat,zones} /etc/shorewall/
cp /usr/share/shorewall/configfiles/tunnels /etc/shorewall/
Теперь приводим шаблоны к нашей ситуации. На сервере VPN2 у нас будет два интерфейса:
ens3 – физический интерфейс с внешним статическим IP,
tun2u – виртуальный интерфейс vpn2.server.
Сервер VPN2 находится в зоне nl, значит так ее и назовем:
vim zones
fw firewall
net ipv4
nl ipv4
Обращаем внимание на названия интерфесов!
vim interfaces
net ens3 dhcp,tcpflags,nosmurfs,routefilter,logmartians,sourceroute=0
nl tun2u optional,tcpflags,nosmurfs,routefilter,logmartians
В следующем файле мы прописываем настройки для пересылки трафика VPN где указываем свои протокол и порт vpn сервера:
vim tunnels
openvpnserver:udp:12443 net 0.0.0.0/0
Далее нам надо включить маскардинг, для этого в следующем файле убираем дефолтные настройки и прописываем свои с подстановкой своих подсетей:
vim snat
MASQUERADE 192.168.0.0/16 ens3
vim policy
$FW net ACCEPT
$FW nl ACCEPT
nl net ACCEPT
net all DROP $LOG_LEVEL
# THE FOLOWING POLICY MUST BE LAST
all all REJECT $LOG_LEVEL
vim rules
?SECTION ALL
?SECTION ESTABLISHED
?SECTION RELATED
?SECTION INVALID
?SECTION UNTRACKED
?SECTION NEW
# Don't allow connection pickup from the net
#
Invalid(DROP) net all tcp
#
# Accept DNS connections from the firewall to the network
#
DNS(ACCEPT) $FW net
#
# Accept SSH connections from the local network for administration
#
SSH(ACCEPT) net $FW
SSH(ACCEPT) nl $FW
SSH(ACCEPT) $FW net
SSH(ACCEPT) $FW nl
#
# Allow Ping from the local network
#
Ping(ACCEPT) nl $FW
Ping(ACCEPT) nl nl
#
# Drop Ping from the "bad" net zone.. and prevent your log from being flooded..
#
Ping(DROP) net $FW
ACCEPT $FW nl icmp
ACCEPT $FW net icmp
Настраиваем vpn сервер, запускаем. Так же перезапускаем shorewall
systemctl restart shorewall
systemctl enable shorewall
Теперь можем создать пользовательский сертификат, но без оборачивания всего трафика в vpn, который только создаст туннель между VPN1 сервером и VPN2, локальный. Сертификат отправляем на VPN1 сервер, включаем и добавляем в автозагрузку.
Теперь начинаем делать то, ради чего все и затевалось. Нам надо настроить маршрутизацию трафика по зонам (да, мы делаем только два сервера, но можно сделать и больше). Первое, что мы должны сделать, это создать список адресов локации.
Сложный, нудный, но веселый вариант
Для этого мы идем на сайт и выбираем для какой страны (страна, где мы находимся).
Мы получаем список сетей с начальным и конечным адресами и в таком виде мы не можем их использовать, нам надо привести их к следующему виду xx.xx.xx.xx/xx, а для этого нужно правльно высчитать маску каждой сети из таблицы. Можно вручную считать на бумажке или в уме, а можно пойти сюда и считать с помощью калькулятора сетей. Нужно быть очень внимательным при пересчете, ведь допущенные ошибки могут привести к тому, что трафик будет перенаправляться не так, как нам надо или система совсем не заведется.
И так, считаем сети и сразу записываем в файл /etc/shorewall/local/ru на сервере VPN1 в колонку в виде:
xx.xx.xx.xx/xx
xx.xxx.xx.xx/xx
и т.д.
Работа достаточно большая, особенно если страна большая)
Простой и скучный вариант
Идем на тот же сайт, но чуть дальше, выбираем страну и формат CIDR и скачиваем архив со списком адресов в нужном нам формате, однако в списке есть первые лишние строки, удаляем их и сохраняем в файл /etc/shorewall/local/ru на сервере VPN1.
Закончили? Идем дальше. Теперь нам надо сделать так, чтобы данные адреса в нужном формате попали в конфигурационный файл, плюс включить пересылку трафика на VPN2, для этого нам надо создать скрипт (можно не паниковать, я уже давно все написал, нам надо только скопировать и вставить, подставляя свои значения):
cd /etc/shorewall/
vim auto.sh
#!/bin/bash
input=local/ru
output=routes.d/ru
localnet="<ip1_gateway>"
interface=ens3
tun2=tun2u
ip2="<IP2>"
ip_gateway_vpn2="<ip_gateway_vpn2>"
echo "#provider dest gateway device" > $output
echo "#provider dest gateway device
main 0.0.0.0/0 $ip_gateway_vpn2 $tun2
main $ip2 $localnet $interface #connect nl
main 195.201.201.32 $localnet $interface #check 2ip.ru
INCLUDE /etc/shorewall/routes.d/ru" > routes
while IFS= read -r network
do
echo "main $network $localnet $interface" >> $output
done < $input
Важное замечание
Данная схема будет работать только в том случае, если и клиент подключатся из той же зоны, где сервер VPN1, в противном случае доступа к серверу не будет. Однако если есть желание дать другу из Турции сертификат к своему vpn, то надо взять его IP адрес и добавить в файл routes:
vim /etc/shorewall/routes
...
main <IP_of_friend> <localnet> <interface>
...
Теперь делаем файл исполняемым:
chmod +x auto.sh
Запускаем скрипт и перезапускаем shorewall:
./auto.sh
shorewall restart
Теперь у нас практически все готово, сначала проверим работу. Подключаемся к vpn и идем проверять. Переходим на сайт 2ip.ru и видим адрес VPN1, так как мы прописали пересылку пакетов на этот сайт через VPN1. Теперь идем на сайт 2ip.ua или любой другой, но который точно не находится в зоне ru (в примере я делал для нее) и видим адрес VPN2. Если все так, тогда поздравляю, если нет, тогда стоит проверить все еще раз по шагам.
Остался последний шаг на сервере VPN1, если конечно не хотим делать все вручную каждый раз после перезагрузки (при чем доступ по ssh будет закрыт). Нам надо настроить условие автозагрузки shorewall. Для этого мы редактируем файл /usr/lib/systemd/system/shorewall.service и меняем строчку «After=network-online.target» на «After=openvpn@cli002008.service», где cli002008 имя моего сертификата:
vim /usr/lib/systemd/system/shorewall.service
Проблемное место
На свежей версии debian shorewall не хочет запускаться после openvpn, что мы указывали выше. Я не разобрался пока в проблеме, если у кого-то есть ответ, то пишите в комментариях. Пока предложу другое решение, запускать через cron:
crontab -e
...
@reboot sleep 10; systemctl restart shorewall
...
Теперь все готово!
Сервера брал тут, можно купить "вечный сервер". Еще использую сервера здесь, данный хостинг имеет большое разнообразие локаций по приемлемым ценам.
Можно настроить обновление данных в автоматическом режиме. Через крон будет скачиваться файл с адресами и записываться в shorewall, но данный способ является платным. Надо купить подписку и получить ссылку и токен для скачивания в следующем формате:
curl -o firewall.gz 'https://dl.ip2location.com/v1/firewall?token=mOdUlMdh0nK9Oap3iHaJxFrX0koqVahHX9Е9gfZhP9nURa126U4xnS9vKlbU3gry&country=RU|BY&format=cidr'
Реклама
Для облегчения жизни предлагаю собственный скрипт для создания vpn сервера и клиентских сертификатов. Всем желающим добро пожаловать в ЛС.
Благодарности за помощь
Благодарю за редакторские правки Дарью.
Комментарии (16)
ivankudryavtsev
27.06.2023 12:11Эх, ребята, веселый вариант был бы подключением сетевой пробы на ip dest и решением добавлять ли его в локальную таблицу или отправлять в remote по geoip или иному списку. Между прочим, в сетях шпд это уже лет 5 как применяется в разных формах. А вы "скачиваем список, добавляем в маршруты"...
Базы GeoIP, списки РКН вкупе с iptables, tcpdump+простой скрипт на питоне решают вопросик легко.
net_racoon
27.06.2023 12:11А почему нельзя пушить клиенту специфик маршруты?
dumasti Автор
27.06.2023 12:11+1потому что если пушить будет VPN1, то клиент будет ходить на эти адреса через VPN сервер, но на остальные будет ходить мимо туннеля. А VPN2 должен пушить все адреса не входящие в список.
net_racoon
27.06.2023 12:11Ну получается адреса, которые не в списке, пойдут через локальный Инет. Или не понимаю задачи.
aborouhin
27.06.2023 12:11+2Эта проблема как раз легко решается. Инвертировать список CIDR, так, чтобы пушить "все, кроме" - задача тривиальная. А вот какое количество маршрутов сможет переварить OpenVPN-клиент на среднем смартфоне (и с т.зр. использования им ресурсов, и с т.зр. времени установки соединения) - вопрос интересный.
P.S. У меня самогó схема похожая - VPN в РФ для пользователей и на нём маршрутизация по настраиваемым правилам, но эти правила посложнее (используются не только GeoIP, но и списки РКН, и вручную добавленные исключения, это настраивается индивидуально под разных клиентов, да и точек выхода в сумме 4 - собственно VPN-сервер, роутер в офисе в РФ для тех сайтов, которые блокируют доступ с IP дата-центров, сервер в Голландии, роутер в Турции).
dumasti Автор
27.06.2023 12:11+1Это вторая проблема, пушить столько маршрутов на конечное устройство - многие устройства просто не потянут. Но инвертировать список это уже сложнее. Для примера нам надо чтобы по стране нашего местонахождения трафик выходил с первого сервера, а весь остальной мир со второго. А теперь считаем: в IPv4 - 4 294 967 296 адресов, в условной стране их пусть будет 200 000. Вопрос: что легче и быстрее обработать (в том числе и серверу) 200 000 адресов, а все остальное пересылать на другой сервер или оставшиеся 4 294 767 296 адресов?
aborouhin
27.06.2023 12:11Ну мы же не индивидуально каждый адрес с маской /32 пушить будем :) После суммаризации большой разницы не будет (количество "дырок" в списке всех возможных адресов равно количеству промежутков между этими "дырками" +/- 1, а что там округлится до ровных масок, а что придётся делить на несколько диапазонов - уж точно не на порядок будет разница)
aborouhin
27.06.2023 12:11+1P.S. Посчитал сейчас по GeoIP базе от Maxmind. Все российские сети - 12138 префиксов, все сети, кроме российских - 47310 префиксов. Разница в 4 раза, да, как раз за счёт дробления "промежутков" между российскими диапазонами, - но вряд ли это будет сильно критично для каких-либо применений.
NikaLapka
27.06.2023 12:11-1Позвольте подать идею, только не топите её сразу, можно же просто, до времени положить на полочку и иногда возвращаться к ней:
Почти год я платил условные 5$ за VPS\VPN хостинг, причина проста, например, купил новый ноутбук, нужно загрузить обычный intel wifi драйвер.. и так и сяк - не получается, эмоции, гнев, или очередные изменения у провайдера и то что работало вчера, сегодня уже не работает.. и однажды, коллега по работе на моё возмущение ответил, - "а я просто в "популярном" веб браузере, установил "популярное" дополнение и всё работает, смотри..", я посмотрел, и оно действительно работает. Начал искать, а какие ещё есть бесплатные варианты. Потом сел и задал себе вопрос, - "я собираю разные конструкторы в Linux.. разве не смогу я сделать, тот же прокси, VPN, маршрутизацию.. через данные бесплатные аналоги? конечно смогу!", но что лучше 5$ или бесплатно. Для кого-то это бигмак и кола, а для меня два обеда. А в год.. но самая главная причина: я не хочу платить даже такие деньги за такой сервис различных хостинг провайдеров, т.к. они врут, обманывают, предоставляют не грамотный сервис. Почему-то у меня не возникает отторжения, когда я пополняю счёт на 5$ в том же DO, Vultr, Hetzner,.. т.к. на мой взгляд их товар стоит этих денег, но то что рекомендуют, как пример в см выше - это уровень 3-4$ за год.
oller
27.06.2023 12:11Главная проблема openvpn, это блокирование его как зарубежном, так и в РФ
dumasti Автор
27.06.2023 12:11Это бесконечный цикл: одни блокируют, другие ищут новые способы это обойти. А блокируют не только OpenVPN трафик, но и Wireguard, strongswang, softeather и другие. Вопрос в том, как замаскировать свой трафик так, чтобы его сложнее было распознать.
anzay911
Если статья начинается с установки vim, хорошо бы если в ней было описано, как из него выйти. Шутка.
dumasti Автор
с долей правды)