Articol despre cum am reușit să lansez un server VPN în spatele NAT-ului furnizorului meu de internet (fără IP public). Aș dori să menționez că funcționalitatea acestei implementări depinde direct de tipul de NAT folosit de furnizorul dumneavoastră, dar și de routerul.
Astfel, am avut nevoie să mă conectez de pe telefonul meu Android la computerul de acasă, ambele dispozitive fiind conectate la Internet prin NAT-uri ale furnizorului, plus că computerul este conectat printr-un router de acasă, care, de asemenea, a NAT-uit conexiunile.
Schema clasică cu utilizarea unui VPS/VDS închiriat cu IP public, precum și închirierea unui IP public de la furnizor nu a fost luată în considerare din mai multe motive.
Având în vedere experiența articolelor anterioare, și având în vedere mai multe experimente cu STUN-uri și NAT-uri ale furnizorilor. Am decis să fac un mic experiment, rulând comanda pe routerul de acasă care funcționează pe firmware OpenWRT:
$ stun stun.sipnet.ruam obținut rezultatul:
Versiunea clientului STUN 0.97
Primary: Independent Mapping, Independent Filter, random port, will hairpin
Valoarea de returnare este 0x000002
Traducere literală:
Independent Mapping — mapare independentă
Independent Filter — filtrul independent
random port — port aleator
will hairpin — va înfinge
Executând o comandă similară pe PC-ul meu, am obținut:
Versiunea clientului STUN 0.97
Primary: Independent Mapping, Port Dependent Filter, random port, will hairpin
Valoarea de returnare este 0x000006
Port Dependent Filter — filtru dependent de port
Diferența în rezultatele comenzilor indica faptul că routerul de acasă a adus «contribuția sa» în procesul de traducere a pachetelor din Internet, acest lucru manifestându-se prin faptul că, la executarea comenzii pe computer:
stun stun.sipnet.ru -p 11111 -vam obținut rezultatul:
…
MappedAddress = XX.1XX.1X4.2XX:4398
…
în acel moment se deschidea temporar o sesiune UDP, dacă în acel moment se trimitea o cerere UDP (de exemplu: netcat XX.1XX.1X4.2XX 4398 -u), cererea ajungea la routerul de acasă, ceea ce a fost confirmat de TCPDump rulând pe acesta, dar cererea nu ajungea la computer — IPtables, ca traductor NAT pe router, o dropa.

Dar faptul că cererea UDP a trecut prin NAT-ul furnizorului dădea speranțe de succes. Deoarece routerul se află sub jurisdicția mea, am rezolvat problema prin redirecționarea portului UDP/11111 către computer:
iptables -t nat -A PREROUTING -i eth1 -p udp -d 10.1XX.2XX.XXX --dport 11111 -j DNAT --to-destination 192.168.X.XXXAstfel, am obținut posibilitatea de a iniția o sesiune UDP și de a primi cereri din Internet de la orice adresă IP. În acest moment, am pornit serverul OpenVPN (după ce l-am configurat) ascultând pe portul UDP/11111, am specificat pe smartphone adresa IP externă și portul (XX.1XX.1X4.2XX:4398) și m-am conectat cu succes de pe smartphone la computer. Însă, în această implementare a apărut o problemă, trebuia să mențin sesiunea UDP până la conectarea clientului OpenVPN la server, varianta cu pornirea periodică a clientului STUN nu mi-a plăcut — nu voiam să încarc inutil serverele STUN.
De asemenea, am observat înregistrarea „will hairpin — va înfinge«, acest mod
Hairpinning permite unei mașini din rețeaua locală în NAT să acceseze o altă mașină din aceeași rețea folosind adresa externă a routerului.

În cele din urmă, problema menținerii sesiunii UDP a fost rezolvată simplu — am pornit clientul pe același computer cu serverul.
Funcționa astfel:
- pornind clientul STUN cu portul local 11111
- primeam un răspuns cu adresa IP externă și portul XX.1XX.1X4.2XX:4398
- trimiteam date cu adresa IP externă și portul către e-mail (orice alt serviciu este posibil), configurat pe smartphone
- pormind serverul OpenVPN pe computer cu ascultare pe portul UDP/11111
- pornind clientul OpenVPN pe computer cu specificarea XX.1XX.1X4.2XX:4398 pentru conectare
- în orice moment, porneam clientul OpenVPN pe smartphone cu specificarea adresei IP și a portului (în cazul meu, adresa IP nu s-a schimbat) pentru conectare

Astfel, am obținut posibilitatea de a mă conecta la computerul meu de pe smartphone. Această implementare permite conectarea oricărui client OpenVPN.
Practică
Va fi nevoie de:
# apt install openvpn stun-client sendemailScriind câteva scripturi, câteva fișiere de configurație și generând certificatele necesare (deoarece clientul de pe smartphone funcționează doar pe bază de certificate) s-a obținut o implementare standard a serverului OpenVPN.
Scriptul principal pe computer
# 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
doneScriptul de trimitere a datelor pe 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"Fișierul de configurație a serverului:
# cat server.confproto 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 20Fișierul de configurație a clientului:
# cat client.confclient
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 30Generarea certificatelor a fost efectuată prin această articole.
Lansarea scriptului:
# ./vpn11.shDupă ce l-am făcut executabil
# chmod +x vpn11.shPe telefonul mobil
Instalând aplicația OpenVPN pentru Android, am copiat fișierul de configurare, certificatele și l-am configurat, a rezultat așa:
Pe telefon verific e-mailul
Corectez numărul portului în setări
Lansez clientul și mă conectez
În procesul de scriere a articolului, am transferat configurația de pe computer pe Raspberry Pi 3 și am încercat să pornesc totul pe un modem LTE, dar nu a funcționat! Rezultatul comenzii
# stun stun.ekiga.net -p 11111Versiunea clientului STUN 0.97
Primary: Independent Mapping, Port Dependent Filter, random port, will hairpin
Valoarea de returnare este 0x000006
valoarea Filtru dependent de port nu a permis sistemului să pornească.
Dar furnizorul de acasă a permis fără probleme sistemului să pornească pe Raspberry Pi 3.
Împreună cu camera web, cu VLC pentru
crearea fluxului RTSP de la camera web
$ 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 pe telefon pentru vizionare (flux rtsp://10.2.0.1:8554/), am obținut un sistem decent de supraveghere video la distanță, de asemenea, se poate ridica Samba, rutează traficul prin VPN, gestionează computerul de la distanță și multe altele...
Ieșire
Așa cum a demonstrat practica, pentru a organiza un server VPN, se poate face și fără un IP extern pentru care trebuie să plătești, la fel ca și pentru un închiriat VPS/VDS. Dar totul depinde de furnizor. Sigur că mi-ar fi plăcut să primesc mai multe informații despre diferiți furnizori și tipurile de NAT-uri utilizate, dar acesta este doar începutul...
Vă mulțumesc pentru atenție!
Sursa: habr.com
