Стартиране на 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
Return value is 0x000002

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

STUN client version 0.97
Primary: Independent Mapping, Port Dependent Filter, random port, will hairpin
Return value is 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
client
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
Return value is 0x000006

стойността Port Dependent Filter не позволи на системата да стартира.
Но домашният доставчик без проблем разреши на системата да стартира на 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 адрес, за който трябва да се плаща, както и наеман VPS/VDS. Но всичко зависи от доставчика. Разбира се, бих искал да получа повече информация за различни доставчици и типовете използвани NAT, но това е само началото...
Благодаря за вниманието!

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

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