Uruchamianie serwera VPN za NAT-em dostawcy

Artykuł o tym, jak udało mi się uruchomić serwer VPN za NAT-em domowego dostawcy (bez publicznego adresu IP). Od razu zaznaczam, że funkcjonalność tej realizacji bezpośrednio zależy od typu NAT używanego przez Twojego dostawcę oraz router..
Otóż, pojawiła się u mnie potrzeba podłączenia się z mojego smartfona z Androidem do domowego komputera, oba urządzenia są połączone z Internetem przez NAT-y dostawcy, dodatkowo komputer jest podłączony przez domowy router, który również NAT-uje połączenia.
Klasyczny schemat z wykorzystaniem wynajmowanego VPS/VDS z publicznym adresem IP, a także wynajem publicznego adresu IP od dostawcy nie był brany pod uwagę z kilku powodów.
Biorąc pod uwagę doświadczenia z poprzednich artykułów, przeprowadzając kilka eksperymentów ze STUN-ami i NAT-ami dostawców. Postanowiłem zrealizować mały eksperyment, wykonując polecenie na domowym routerze działającym na oprogramowaniu OpenWRT:

$ stun stun.sipnet.ru

otrzymałem wynik:

STUN client version 0.97
Primary: Independent Mapping, Independent Filter, random port, will hairpin
Wartość zwrotna to 0x000002

Dosłowne tłumaczenie:
Independent Mapping — niezależne mapowanie
Independent Filter — niezależny filtr
random port — losowy port
will hairpin — będzie pinować
Wykonując analogiczne polecenie na swoim komputerze, otrzymałem:

STUN client version 0.97
Primary: Independent Mapping, Port Dependent Filter, random port, will hairpin
Wartość zwrotna to 0x000006

Port Dependent Filter — filtr zależny od portu
Różnica w wynikach poleceń wskazywała na to, że domowy router wnosił "swoją cegiełkę" w proces translacji pakietów z Internetu, objawiało się to tym, że po wykonaniu polecenia na komputerze:

stun stun.sipnet.ru -p 11111 -v

otrzymywałem wynik:


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

w tym momencie na chwilę otwierała się sesja UDP, jeśli w tym momencie wysłać zapytanie UDP (na przykład: netcat XX.1XX.1X4.2XX 4398 -u), to zapytanie przychodziło na domowy router, co potwierdził TCPDump uruchomiony na nim, ale zapytanie nie docierało do komputera — IPtables jako NAT-traslator na routerze odrzucał je.
Uruchomienie serwera VPN za NAT'em dostawcy
Jednak sam fakt przejścia zapytania UDP przez NAT dostawcy dawał nadzieję na sukces. Ponieważ router znajduje się w mojej kompetencji, rozwiązałem problem przekierowując port UDP/11111 na komputer:

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

W ten sposób uzyskałem możliwość nawiązania sesji UDP i odbierania żądań z Internetu z dowolnego adresu IP. W tym momencie uruchomiłem serwer OpenVPN (wcześniej go konfigrując), nasłuchując na porcie UDP/11111, wskazałem na smartfonie zewnętrzny adres IP i port (XX.1XX.1X4.2XX:4398) i pomyślnie połączyłem się z komputera. Jednak w tej realizacji pojawił się problem, ponieważ trzeba było jakoś utrzymać sesję UDP do momentu połączenia klienta OpenVPN z serwerem; nie podobała mi się opcja z okresowym uruchamianiem klienta STUN — nie chciałem bez potrzeby obciążać serwerów STUN.
Zwróciłem również uwagę na zapis «will hairpin — będzie pinować«, tryb ten

Hairpinning pozwala jednej maszynie w lokalnej sieci za NAT uzyskać dostęp do innej maszyny w tej samej sieci pod zewnętrznym adresem routera.

Uruchomienie serwera VPN za NAT'em dostawcy
Ostatecznie problem utrzymania sesji UDP rozwiązałem prosto — uruchomiłem klienta na tym samym komputerze co serwer.
Działało to w ten sposób:

  • uruchamiałem klienta STUN z lokalnym portem 11111
  • otrzymywałem odpowiedź z zewnętrznym adresem IP i portem XX.1XX.1X4.2XX:4398
  • wysyłałem dane z zewnętrznym adresem IP i portem na e-mail (można użyć dowolnej innej usługi), ustawioną na smartfonie
  • uruchamiałem serwer OpenVPN na komputerze nasłuchującego na porcie UDP/11111
  • uruchamiałem klienta OpenVPN na komputerze, wskazując XX.1XX.1X4.2XX:4398 do połączenia
  • o każdej porze uruchamiałem klienta OpenVPN na smartfonie, wskazując adres IP i port (w moim przypadku adres IP nie zmieniał się) do połączenia

Uruchomienie serwera VPN za NAT'em dostawcy
W ten sposób uzyskałem możliwość łączenia się z moim komputerem ze smartfona. Ta realizacja pozwala na podłączenie dowolnego klienta OpenVPN.

Praktyka

Będziesz potrzebować:

# apt install openvpn stun-client sendemail

Napisawszy kilka skryptów, parę plików konfiguracyjnych, generując niezbędne certyfikaty (ponieważ klient na smartfonie działa tylko na certyfikatach), otrzymałem standardową realizację serwera OpenVPN.

Główny skrypt na komputerze

# 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

Skrypt wysyłania danych na e-mail:

# 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"

Plik konfiguracyjny serwera:

# 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

Plik konfiguracyjny klienta:

# 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

Generowanie certyfikatów było realizowane przez w tym artykule.
Uruchamianie skryptu:

# ./vpn11.sh

Wcześniej nadając mu uprawnienia do uruchomienia

# chmod +x vpn11.sh

Po stronie smartfona

Instalując aplikację OpenVPN dla Androida, skopiowawszy plik konfiguracyjny, certyfikaty i konfigurując go, wyszło tak:
Na smartfonie sprawdzam pocztęUruchomienie serwera VPN za NAT'em dostawcy
Koryguję numer portu w ustawieniachUruchomienie serwera VPN za NAT'em dostawcy
Uruchamiam klienta i łączę sięUruchomienie serwera VPN za NAT'em dostawcy

W trakcie pisania artykułu przeniosłem konfigurację z komputera na Raspberry Pi 3 i próbowałem uruchomić to wszystko na modemie LTE, ale nie udało się! Wynik polecenia

# stun stun.ekiga.net -p 11111

STUN client version 0.97
Primary: Independent Mapping, Port Dependent Filter, random port, will hairpin
Wartość zwrotna to 0x000006

wartość Filtr zależny od portu nie pozwolił na uruchomienie systemu.
Ale domowy dostawca bez problemu umożliwił uruchomienie systemu na Raspberry Pi 3.
W połączeniu z kamerą internetową, z VLC dla
tworzenia strumienia RTSP z kamery internetowej

$ 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

i VLC na smartfonie do oglądania (strumień rtsp://10.2.0.1:8554/), powstał niezły system monitoringu wideo na odległość, można również uruchomić Sambę, routować ruch przez VPN, zdalnie zarządzać komputerem i wiele więcej…

Wnioski

Jak pokazuje praktyka, do zorganizowania serwera VPN można obejść się bez zewnętrznego adresu IP, za który trzeba płacić, tak samo jak za wynajmowany VPS/VDS. Ale wszystko zależy od dostawcy. Oczywiście chciałbym uzyskać więcej informacji o różnych dostawcach i typach używanych NAT'ów, ale to dopiero początek…
Dziękuję za uwagę!

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster