Стартиране на VPN-сървър зад провайдерски NAT’ом

Статия за това как успях да стартирам VPN сървър зад NAT на домашния провайдер (без публичен IP адрес). Сразу да уточня: че функционалността на тази реализация зависи пряко от типа NAT, използван от Вашия провайдер и рутера.
И така, възникна необходимостта да се свържа от своя Android смартфон към домашния компютър, като и двете устройства са свързани към интернет през провайдерските NAT, плюс компютърът е свързан през домашен рутер, който също NAT-ва връзките.
Класическата схема с нает VPS/VDS с публичен IP адрес и наемането на публичен IP адрес от провайдера не беше разглеждана по няколко причини.
С оглед опита от предишни статии, проведох няколко експеримента с STUN и NAT на провайдерите. Реших да направя малък експеримент, изпълнявайки командата на домашния рутер, работещ на OpenWRT:

$ stun stun.sipnet.ru

получих резултат:

STUN client version 0.97
Primary: Independent Mapping, Independent Filter, random port, will hairpin
Возвратната стойност е 0x000002

Дословен превод:
Independent Mapping — независимо картографиране
Independent Filter — независим филтър
random port — произволен порт
will hairpin — ще шплинтува
Изпълнявайки аналогична команда на компютъра си, получих:

STUN client version 0.97
Primary: Independent Mapping, Port Dependent Filter, random port, will hairpin
Возвратната стойност е 0x000006

Port Dependent Filter — филтър, зависим от порта
Разликата в резултатите от командите говори за това, че домашният рутер е внасял "своя дял" в процеса на транслация на пакетите от интернет, което се проявяваше в това, че при изпълнението на командата на компютъра:

stun stun.sipnet.ru -p 11111 -v

получих резултат:

…
MappedAddress = XX.1XX.1X4.2XX:4398
…

в този момент за кратко се отваряше UDP сесия, ако по това време изпратя UDP запитване (например: netcat XX.1XX.1X4.2XX 4398 -u), то запитването стигаше до домашния рутер, което потвърди TCPDump, стартиран на него, но запитването не достигаше до компютъра — IPtables в качеството си на NAT транслатор на рутера го блокираше.
Стартиране на VPN сървър зад провайдерски NAT
Но самият факт, че UDP запитването преминава през провайдерския NAT, даваше надежда за успех. Тъй като рутерът е в моя юрисдикция, реших проблема, пренасочвайки UDP/11111 порта към компютъра:

iptables -t nat -A PREROUTING -i eth1 -p udp -d 10.1XX.2XX.XXX --dport 11111 -j DNAT --to-destination 192.168.X.XXX

По този начин получих възможност да инициирам UDP сесия и да получавам заявки от интернет от всякакъв IP адрес. В този момент стартирах OpenVPN сървър (след предварителна конфигурация), слушащ UDP/11111 порт, като посочих външния IP адрес и порт (XX.1XX.1X4.2XX:4398) на смартфона и успешно се свързах от смартфона към компютъра. Но в тази реализация се появи проблем, трябваше по някакъв начин да поддържам UDP сесията до момента на свързването на OpenVPN клиента към сървъра; вариантът със периодично стартиране на STUN клиента не ми допадна — не исках излишно да натоварвам STUN сървърите.
Също така обърнах внимание на записа „will hairpin — ще шплинтува„, този режим

Hairpinning позволява на едно устройство в локалната мрежа зад NAT да получи достъп до друго устройство в същата мрежа по външния адрес на рутера.

Стартиране на VPN сървър зад провайдерски NAT
В крайна сметка реших проблема с поддръжката на UDP сесия просто — стартирах клиента на същия компютър със сървъра.
Работеше по следния начин:

  • стартирах STUN клиента с локален порт 11111
  • получавах отговор с външния IP адрес и порт XX.1XX.1X4.2XX:4398
  • изпращах данни с външния IP адрес и порт на електронната поща (възможен е и друг сервис), настроена на смартфона
  • стартирах OpenVPN сървър на компютъра, слушащ UDP/11111 порт
  • стартирах OpenVPN клиента на компютъра, посочвайки XX.1XX.1X4.2XX:4398 за свързване
  • по всяко време стартирах OpenVPN клиента на смартфона, посочвайки IP адреса и порта (в моя случай IP адресът не се променяше) за свързване

Стартиране на VPN сървър зад провайдерски NAT
По този начин получих възможност да се свързвам към компютъра си от смартфона. Тази реализация позволява свързване на всеки OpenVPN клиент.

Практика

Ще са необходими:

# apt install openvpn stun-client sendemail

Написвайки няколко скрипта, конфигурационни файлове, генерирайки необходимите сертификати (тъй като клиентът на смартфона работи само с сертификати), получих стандартна реализация на OpenVPN сървър.

Основен скрипт на компютъра

# cat vpn11.sh
#!/bin/bash
until [[ -n "$iftosrv" ]]; do echo "$(date) Определяю сетевой интерфейс"; iftosrv=`ip route get 8.8.8.8 | head -n 1 | sed 's|.*dev ||' | awk '{print $1}'`; sleep 5; done
ABSOLUTE_FILENAME=`readlink -f "$0"`
DIR=`dirname "$ABSOLUTE_FILENAME"`
localport=11111
until [[ $a ]]; do
	address=`stun stun.sipnet.ru -v -p $localport 2>&1 | grep "MappedAddress" | sort | uniq | head -n 1 | sed 's/:/ /g' | awk '{print $3" "$4}'`
        ip=`echo "$address" | awk {'print $1'}`
        port=`echo "$address" | awk {'print $2'}`
	srv="openvpn --config $DIR/server.conf --port $localport --daemon"
	$srv
	echo "$(date) Сервер запущен с внешним адресом $ip:$port"
	$DIR/sendemail.sh "OpenVPN-Server" "$ip:$port"
	sleep 1
	openvpn --config $DIR/client.conf --remote $ip --port $port
	echo "$(date) Cоединение клиента с сервером разорвано"
	for i in `ps xa | grep "$srv" | grep -v grep | awk '{print $1}'`; do
		kill $i && echo "$(date) Завершен процесс сервера $i ($srv)"
		done
	echo "Жду 15 сек"
	sleep 15
	done

Скрипт за изпращане на данни по електронна поща:

# cat sendemail.sh 
#!/bin/bash
from="От кого"
pass="Пароль"
to="Кому"
theme="$1"
message="$2"
server="smtp.yandex.ru:587"
sendEmail -o tls=yes -f "$from" -t "$to" -s "$server" -xu "$from" -xp "$pass" -u "$theme" -m "$message"

Конфигурационен файл на сървъра:

# cat server.conf
proto udp
dev tun
ca      /home/vpn11-srv/ca.crt
cert    /home/vpn11-srv/server.crt
key     /home/vpn11-srv/server.key
dh      /home/vpn11-srv/dh2048.pem
server 10.2.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
tls-server
tls-auth /home/vpn11-srv/ta.key 0
tls-timeout 60
auth    SHA256
cipher  AES-256-CBC
client-to-client
keepalive 10 30
comp-lzo
max-clients 10
user nobody
group nogroup
persist-key
persist-tun
log /var/log/vpn11-server.log
verb 3
mute 20

Конфигурационен файл на клиента:

# cat client.conf
клиент
dev tun
proto udp
ca      "/home/vpn11-srv/ca.crt"
cert    "/home/vpn11-srv/client1.crt"
key     "/home/vpn11-srv/client1.key"
tls-client
tls-auth "/home/vpn11-srv/ta.key" 1
auth SHA256
cipher AES-256-CBC
auth-nocache
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
log /var/log/vpn11-clent.log
verb 3
mute 20
ping 10
ping-exit 30

Генерирането на сертификати се проведе с помощта на тази статия.
Стартиране на скрипта:

# ./vpn11.sh

Предварително задавайки му права за изпълнение

# chmod +x vpn11.sh

На смартфона

Инсталирайки приложението OpenVPN за Android, като копирах конфигурационния файл, сертификатите и го настроих, получи се следното:
На смартфона проверявам имейлаСтартиране на VPN сървър зад провайдерски NAT
Коригирам номера на порта в настройкитеСтартиране на VPN сървър зад провайдерски NAT
Стартирам клиента и се свързвамСтартиране на VPN сървър зад провайдерски NAT

В процеса на писане на статията прехвърлих конфигурацията от компютъра на Raspberry Pi 3 и опитах да стартирам всичко това на LTE модем, но не успях! Резултатът от командата

# stun stun.ekiga.net -p 11111

STUN client version 0.97
Primary: Independent Mapping, Port Dependent Filter, random port, will hairpin
Возвратната стойност е 0x000006

стойността Филтър, зависим от порта не позволи на системата да стартира.
Но домашният доставчик без проблеми позволи на системата да стартира на Raspberry Pi 3.
В комбинация с уеб камера, с VLC за
създаване на RTSP поток от уеб камерата

$ cvlc v4l2:///dev/video0:chroma=h264 :input-slave=alsa://hw:1,0 --sout '#transcode{vcodec=x264,venc=x264{preset=ultrafast,profile=baseline,level=31},vb=2048,fps=12,scale=1,acodec=mpga,ab=128,channels=2,samplerate=44100,scodec=none}:rtp{sdp=rtsp://10.2.0.1:8554/}' --no-sout-all --sout-keep

и VLC на смартфона за гледане (поток rtsp://10.2.0.1:8554/), получи се добра система за видеонаблюдение на разстояние, също така може да бъде настроена Samba, да се маршрутизира трафик през VPN, да се управлява компютъра отдалечено и много други неща...

Извод

Както показа практиката, за организиране на VPN сървър може да се мине и без външен IP адрес, за който трябва да се плаща, така и за наемания посветени сървъри. Но всичко зависи от доставчика. Разбира се, исках да получа повече информация за различните доставчици и типовете използвани NAT, но това е само началото...
Благодаря за вниманието!

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster