Предисловие
В статье будут рассмотрены четыре независимых варианта прохождения трафика транзитом с помощью:
У меня провайдер заблокировал мой openvpn. Сначала обычный провайдер, а потом и мобильный тоже. Это был обычный vds сервер за рубежом с openvpn. Использовался исключительно в личных целях. После блокировки я просто решил проверить, а будет ли работать doublevpn, так как у меня был сервер еще и в России. Оказалось, что все отлично работает с помощью double. Суть этой технологии в том, что интернет‑трафик проходит через два сервера вместо одного. Об этом хорошо забытом инструменте и пойдет речь в статье, возможно, кому‑то это будет полезно. Так же я в статье на всякий случай рассмотрел варианты туннелировать трафик и с помощью vtun или socks5 прокси.
Вариант I. DoubleVPN
Конечно, первое, что пришло в голову - это просто соединить два сервера в России и в другой стране с помощью openvpn. И это получилось без проблем. Вот ниже мое решение:
Шаг первый. Установка openVPN на обоих серверах
Все, что я пишу, подходит так или иначе для любых *nix серверов, будь то ubuntu, centos, fedora, rocky и т.д.
Установить можно openvpn готовым скриптом, например, вот таким:
https://github.com/Nyr/openvpn-install
После того как вы запустили скрипт на обоих серверах, можно перейти к настройкам каждого из них.
Шаг два. Настройка на зарубежном VDS
На сервере в стране Х настройка очень простая. После того как вы запустили вышеуказанный скрипт и openvpn установился, все что нужно сделать - это отредактировать файл конфигурации, замените его следующим содержимым.
/etc/openvpn/server/server.conf
port XXXX # Порт на котором у вас работает openvpn
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key
dh dh.pem
tls-crypt tc.key
remote-cert-tls client
server 10.100.39.0 255.255.255.0
keepalive 10 120
persist-key
persist-tun
verb 3
sndbuf 0
rcvbuf 0
push "route 10.100.39.0 255.255.255.0"
Далее сделайте рестарт опенвпн сервера:
systemctl restart openvpn-server@server.service
И скопируйте клиентский ключ, который был создан при установке на российский VDS. Например, с помощью scp
.
На этом всё. Настройка зарубежного сервера завершена.
Шаг три. Настройка российского VDS.
На российском vds после установки openvpn из скрипта уже работает впн-сервер (10.8.0.0/24). Мы его трогать не будем. Все что нам надо сделать - это запустить на российском vds еще и зарубежного open-vpn клиента.
Редактируем /etc/sysctl.conf
Втыкаем следующие строки:
net.ipv4.ip_forward=1
net.ipv4.conf.tun0.rp_filter=0
net.ipv4.conf.tun1.rp_filter=0
Строки net.ipv4.conf.tun0.rp_filter=0
и net.ipv4.conf.tun1.rp_filter=0
отключают проверку reverse path filtering для интерфейсов tun0 и tun1 соответственно. Можно ребутнуть сервер или ввести соответствующие команды.
Редактируем файл:
/etc/iproute2/rt_tables
И добавляем в него строку:
150 vpn_net
Здесь подробное объяснение зачем и что мы делаем (можно не читать)
Файл /etc/iproute2/rt_tables служит для определения имен пользовательских таблиц маршрутизации в Linux-системах.
Таблицы маршрутизации: Представьте, что у вас есть несколько маршрутов, по которым пакеты данных могут перемещаться в вашей сети. Таблицы маршрутизации позволяют организовать эти маршруты в группы, что упрощает управление и настройку сетевых соединений.
Зачем нужны пользовательские таблицы:
Разделение трафика: Вы можете направить разные типы трафика по разным маршрутам. Например, весь трафик VPN можно отправить через определенную таблицу, а остальной трафик — через другую.
Управление политиками: Таблицы могут использоваться для реализации различных сетевых политик, таких как маршрутизация на основе качества обслуживания (QoS) или балансировка нагрузки.
Управление несколькими сетевыми интерфейсами: Если у вас несколько сетевых интерфейсов, вы можете использовать разные таблицы для каждого из них.
Что значит число 150 и строка 150 vpn_net?
Число: Это просто уникальный номер, который вы присваиваете своей таблице. Вы можете выбрать любое число, кроме тех, которые уже зарезервированы системой (например, 255, 254, 253, 0).
Строка: Строка в формате "число имя_таблицы" связывает числовой идентификатор с понятным именем. В данном случае, вы создаете таблицу с именем "vpn_net" и присваиваете ей номер 150.
Зачем добавлять такую строку?
Предположим, у вас есть VPN-соединение, и вы хотите, чтобы весь трафик, направленный в VPN, проходил через это соединение. Вы можете создать отдельную таблицу маршрутизации для VPN-трафика и добавить в нее соответствующие маршруты. Затем, используя правила iptables или другие механизмы, вы можете перенаправлять весь трафик, предназначенный для VPN, в эту таблицу.
Теперь нам надо создать два скрипта, которые будут выполняться при старте зарубежного openvpn клиента и при остановке.
/etc/openvpn/server1_up.sh
/sbin/ip rule add from 10.8.0.0/24 table vpn_net
/sbin/ip route add default dev tun1 table vpn_net
/etc/openvpn/server1_down.sh
/sbin/ip rule del from 10.8.0.0/24 table vpn_net
/sbin/ip route del default dev tun1 table vpn_net
На оба скрипта вешаем
chmod +x /etc/openvpn/server1_up.sh
и chmod +x /etc/openvpn/server1_down.sh
Теперь нам надо взять клиентский конфиг, который мы взяли на зарубежном сервере. Сменить ему расширение: вместо .ovpn написать .conf
mv my_client.ovpn my_client.conf
Положить в папку: /etc/openvpn/client
и отредактировать примерно таким образом:
/etc/openvpn/client/my_client.conf
client
dev tun
proto udp
remote XX.XX.XX.XX YY YY # IP и порт зарубежного VDS
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
auth SHA512
cipher AES-256-CBC
verb 3
script-security 2
up "/etc/openvpn/server1_up.sh"
down /etc/openvpn/server1_down.sh
# До этого место. Дальше не трогаем.
<ca>
-----BEGIN CERTIFICATE-----
wIBAgIJAL0WnyzV8N87MA0
......
Указываем, что у нас будут стартовать скрипты при запуске и остановке клиента.
Запускаем опенвпн-клиент
systemctl start openvpn-client@my_client
Добавляем новое правило iptables
iptables -t nat -I POSTROUTING -s 10.8.0.0/24 -o tun1 -j MASQUERADE
А старое nat правило, которое добавил установщик Nyr/openvpn-install, удаляем. Сохраняем iptables тем способом, которые есть в вашем *nix, так чтобы они сработали после загрузки. И делаем автостарт нашего клиента:
systemctl enable openvpn-client@my_client
Проверяем, что все работает, с помощью команд
ip route show table all|grep vpn_net
ip rule list| grep vpn_net
ip address
С помощью openvpn-install создаем необходимое кол-во опенвпн ключей.
Вариант II. OpenVPN + Vtun
В первом варианте у нас был openvpn + openvpn, но нам ничего не мешает соединить, например, российский VDS и зарубежный с помощью старого и доброго vtun. И точно так же туннелировать трафик
Шаг первый. Установка vtun на обоих серверах
Vtun можно собрать из исходников. Будем считать, что вы на обоих серверах vtun и openvpn поставили. Форвард пакетов разрешили, см. настройки у варианта № 1.
Шаг второй. Запуск vtun сервера на зарубежном сервере
Для сервера можно взять примерно такой конфиг и положить его в файл /etc/vtund.conf
:
/etc/vtund.conf
options {
port 5000;
ifconfig /sbin/ifconfig;
}
# Default session options
default {
proto tcp; # TCP protocol
compress no; # Compression is off
encrypt no; # ssh does the encryption
speed 0; # By default maximum speed
keepalive yes;
stat yes;
}
my_tunnel {
passwd MY_STRONG_PASS; # Password
type tun; # IP tunnel
proto tcp; # TCP protocol
up {
ifconfig "%% 10.3.0.2 pointopoint 10.3.0.1 mtu 1500";
};
down{
ifconfig "%% down";
};
}
Открываем порт 5000 и добавляем SNAT правила, где to-source XX.XX.XX.XX
это белый IP в стране Х.
-A INPUT -p tcp -m tcp --dport 5000 -j ACCEPT
-A POSTROUTING -s 10.3.0.0/24 -j SNAT --to-source XX.XX.XX.XX
Запускаем:
vtund -s
Проверяем, должен появиться интерфейс tun и ip.
ip address
Шаг три. Запуск vtun клиента и openvpn в России
Openvpn ставим как обычно, см. вариант 1.
А вот настройки vtun на российском сервере
/etc/vtund.conf
options {
port 5000;
# Path to various programs
ifconfig /sbin/ifconfig;
ip /sbin/ip;
}
# Default session options
default {
compress no;
encrypt no;
speed 0;
keepalive yes;
stat yes;
}
my_tunnel {
passwd PASS; # Password
type tun; # IP tunnel
proto udp; # TCP protocol
up {
# 10.3.0.1 локальный ip
# 10.3.0.2 удаленный ip
ifconfig "%% 10.3.0.1 pointopoint 10.3.0.2 mtu 1500";
ip "rule add from 10.8.0.0/24 table vpn_net";
ip "route add default dev %% table vpn_net";
};
down{
ip "rule del from 10.8.0.0/24 table vpn_net";
ip "route del default dev %% table vpn_net";
ifconfig "%% down";
};
}
Запускаем командной:
vtund my_tunnel ip_адрес_вашего_зарубежного_сервера
Точно так же как и с опенвпн маскарадим трафик:
iptables -t nat -I POSTROUTING -s 10.8.0.0/24 -o tun1 -j MASQUERADE
После этого все должно заработать. Если не работает, то убедитесь, что пинги проходят между 10.3.0.1 и 10.3.0.2 и смотрите логи.
Конфигурация vtun дана для примера. Там по желанию можно и трафик передавать по udp, шифровать, сжимать и т.д.
Но самое интересное - это то, что vtun можно засунуть в ssh-туннель, после чего его фильтрация и блокировка станет делом невероятно хлопотным.
Can I use vtun over SSH ?
Yes, via the port forwarding feature of ssh. Don't enable vtun's encryption as ssh does its own encryption. Also, make sure to select the TCP protocol as SSH can forward TCP but not UDP. An example session might look something like this
home$ ssh -L 5000:localhost:5000 work.megacorp.com
(authenticate if necessary)
work$ vtund -s home_tunnel_config
...
home$ vtund home_tunnel_config localhost
https://vtun.sourceforge.net/faq.html
Вариант III. OpenVPN + tun2proxy
В третьем варианте мы закинем openvpn трафик в socks5 и так же выпустим наружу. Хотя с помощью tun2proxy можно туннелировать и в http прокси, поэтому даже зарубежный VDS не обязателен, достаточно иметь ssh доступ в стране Х или какую-нибудь http-проксю.
https://github.com/tun2proxy/tun2proxy
Tun2proxy - это туннельный интерфейс для HTTP- и SOCKS-прокси на Linux, Android, macOS, iOS и Windows:
HTTP‑прокси (без аутентификации, базовая и дайджест‑аутентификация)
Поддержка SOCKS4 и SOCKS5 (без аутентификации, аутентификация по имени пользователя и паролю)
Поддержка SOCKS4a и SOCKS5h (через функцию виртуального DNS)
Минимальная настройка конфигурации для маршрутизации всего трафика
Поддержка IPv4 и IPv6
Механизм обхода GFW для определенных случаев использования
Поддержка SOCKS5 UDP
Встроенная поддержка проксирования DNS через TCP
Установка и настройка
Вся установка и настройка делается на сервере в России. На первом сервере. На втором (зарубежном сервере) лишь нужен ssh аккаунт для создания socks5 прокси.
Я поставил rust последнюю версию
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
И далее запустил установку
$HOME/.cargo/bin/cargo install tun2proxy
И он благополучно установился, проверил что все ок:
$HOME/.cargo/bin/tun2proxy --help
Почитал справку по использованию. Дальше я создал для проверки ssh socks5 tcp динамическую проксю такой командой:
ssh -D 14017 -q -C -N my-socks5-user@my-remote-server.com
Повесил на порт 14017. По хорошему, надо было бы udp socks5 делать (но мы же не ищем легких путей), и для теста так интереснее.
Далее запустил tun2proxy командой:
$HOME/.cargo/bin/tun2proxy --tun tun1 --proxy "SOCKS5://127.0.0.1:14017"
Потом поднял сетевой интерфейс, т.к. по умолчанию он отключен:
ifconfig tun1 up
Это и есть фишка tun2roxy, что он создает сетевой интерфейс. То есть если набрать, например ifconfig, то при включенном tun2roxy можно увидеть еще одну "сетевую карту", которую он создал на основе прокси. А если есть tun1, то можно уже делать все, что мы захотим, почти так же как и в предыдущих вариантах.
Проверил, что все работает такой командой:
curl --interface tun1 ifconfig.me
В ответ получил IP адрес своего зарубежного сервера. Все окей, трафик завернулся в tun1 и вышел из-за рубежа.
Теперь надо заставить openVPN ходить таким же макаром, чтобы выпустить наружу трафик openVPN через tun1 & socks5.
/etc/sysctl.conf
net.ipv4.ip_forward=1
net.ipv4.conf.tun0.rp_filter=0
net.ipv4.conf.tun1.rp_filter=0
net.ipv4.conf.all.route_localnet=1
В файл:
/etc/iproute2/rt_tables
Добавил строчку:
150 vpn_net
И ввел команды:
/sbin/ip rule add from 10.8.0.0/24 table vpn_net
/sbin/ip route add default dev tun1 table vpn_net
И дальше прикол, если просто замаскарадить трафик командой iptables -t nat -I POSTROUTING -s 10.8.0.0/24 -o tun1 -j MASQUERADE
, то работать не будут DNS запросы, ведь они идут не по TCP. Как я и писал выше, обычный socks5 tcp прокси не очень-то и подходит. Так что перед тем как маскарадить, мне пришлось поставить dnsproxy и запустить его командой:
./dnsproxy -u 8.8.8.8:53
И сам tun2proxy на этот раз запустил командой, что указана выше, но с доп. ключом --dns direct
и так же изменил настройку клиентского опенвпн, чтобы он с DNS запросами шел ко мне локально на сервер.
После этого все заработало и openvpn клиент вышел наружу через этот туннель.
Вариант IV. GO Simple Tunnel (GOST) + openVPN
Этот вариант предложили ребята в комментариях: 1, 2.
И этот вариант очень простой.
GOST (GO Simple Tunnel) - это инструмент с открытым исходным кодом, созданный на языке Go. Он предназначен для создания безопасных и надежных туннелей для передачи данных между различными устройствами и сетями. Почитать справку на английском можно здесь.
На западный сервер я поставил только openvpn.
А в России, на старенький Centos 7 я поставил GOST таким образом:
yum install epel-release
yum install snapd
systemctl enable --now snapd.socket
ln -s /var/lib/snapd/snap /snap
snap install gost
Далее создал службу: vim /usr/lib/systemd/system/gostopenvpn.service
[Unit]
Description=My GOST Service
After=network.target
[Service]
Type=simple
ExecStart=/путь_к/gost -L=udp://:1194/XX.XX.XX.XX:1194
[Install]
WantedBy=multi-user.target
XX.XX.XX.XX:1194
- это IP зарубежного сервера и порт, на котором на зарубежном сервере запущен openVPN.
Далее открыл порт в iptables на российском сервере, где установлен GOST, и запустил службу:
iptables -I INPUT -p udp --dport 1194 -j ACCEPT
systemctl enable gostopenvpn.service
systemctl start gostopenvpn.service
Отредактировал зарубежный клиентский конфиг опенвн, указал на нем IP российского сервера с gost вместо зарубежного. И всё заработало. Клиенты openvpn подключаются к российскому IP, проходят через туннель и выходят в интернет с зарубежного IP.