Článok o tom, ako sa mi podarilo spustiť VPN server za NATom domáceho providera (bez verejnej IP adresy). Hneď na úvod poviem, že funkčnosť tejto realizácie priamo závisí od typu NAT, ktorý váš provider používa, a taktiež od smerovača.
Takže, vznikla potreba pripojiť sa zo svojho Android smartfónu na domáci počítač, pričom oba zariadenia sú pripojené na Internet cez providera NAT, navyše je počítač pripojený cez domácu router, ktorý tiež NATuje spojenia.
Klasická schéma s využitím prenajatého VPS/VDS s verejnou IP adresou a taktiež prenájom verejnej IP adresy od providera nebola z viacerých dôvodov zvažovaná.
S ohľadom na skúsenosti z predchádzajúcich článkov, vykonaním niekoľkých experimentov so STUN-ami a NAT-ami providerov. Rozhodol som sa na malý experiment, vykonávajúc príkaz na domácom routeri, ktorý pracuje na firme OpenWRT:
$ stun stun.sipnet.rudostal som výsledok:
STUN klient verzia 0.97
Primárne: Nezávislé zobrazenie, Nezávislý filter, náhodný port, bude hairpin
Hodnota návratu je 0x000002
Doslovný preklad:
Nezávislé zobrazenie — independent mapping
Nezávislý filter — independent filter
náhodný port — random port
bude hairpin — will hairpin
Vykonaním podobného príkazu na svojom počítači, som dostal:
STUN klient verzia 0.97
Primárne: Nezávislé zobrazenie, Filter závislý od portu, náhodný port, bude hairpin
Hodnota návratu je 0x000006
Filter závislý od portu — Port Dependent Filter
Rozdiel v výsledkoch výstupu príkazov hovoril o tom, že domáci router zasahoval do procesu prekladu paketov z Internetu, čo sa prejavovalo tým, že pri vykonaní príkazu na počítači:
stun stun.sipnet.ru -p 11111 -vsom dostal výsledok:
…
MappedAddress = XX.1XX.1X4.2XX:4398
…
v tomto momente sa na krátky čas otvorila UDP relácia, ak v tomto momente poslať UDP požiadavku (napríklad: netcat XX.1XX.1X4.2XX 4398 -u), tak požiadavka prišla na domácu router, čo potvrdil TCPDump, ktorý bol na ňom spustený, ale požiadavka nedošla k počítaču — IPtables ako NAT prekladač na routeri ju zahodila.

Ale samotný fakt prechodu UDP požiadavky cez provider NAT dával nádej na úspech. Keďže router je v mojej jurisdikcii, vyriešil som problém presmerovaním UDP/11111 portu na počítač:
iptables -t nat -A PREROUTING -i eth1 -p udp -d 10.1XX.2XX.XXX --dport 11111 -j DNAT --to-destination 192.168.X.XXXTýmto som získal možnosť iniciovať UDP reláciu a prijímať požiadavky z internetu z akéhokoľvek IP adresy. V tomto momente som spustil OpenVPN server (predtým nakonfigurovaný), pričom som počúval na port UDP/11111, uviedol externú IP adresu a port (XX.1XX.1X4.2XX:4398) na smartfóne a úspešne sa pripojil zo smartfónu k počítaču. Avšak v tejto implementácii vznikol problém, potreboval som nejakým spôsobom udržiavať UDP reláciu do momentu pripojenia OpenVPN klienta k serveru, varianta s periodickým spúšťaním STUN klienta sa mi nepáčila — nechcel som zbytočne zaťažovať STUN servery.
Takisto som si všimol záznam „bude hairpin — will hairpin„, tento režim
Hairpinning umožňuje jednému zariadeniu v lokálnej sieti za NAT prístup k inému zariadeniu v tej istej sieti cez externú adresu smerovača.

Nakoniec som problém udržania UDP relácie vyriešil jednoducho – spustil som klienta na tom istom počítači so serverom.
Fungovalo to takto:
- spustil som STUN klienta s lokálnym portom 11111
- dostal som odpoveď s externou IP adresou a portom XX.1XX.1X4.2XX:4398
- poslal som údaje s externou IP adresou a portom na e-mail (možný je akýkoľvek iný servis), nastavený na smartfóne
- spustil som OpenVPN server na počítači s počúvaním portu UDP/11111
- spustil som OpenVPN klienta na počítači s uvedením XX.1XX.1X4.2XX:4398 na pripojenie
- kedykoľvek som spustil OpenVPN klienta na smartfóne s uvedením IP adresy a portu (v mojom prípade sa IP adresa nemenila) na pripojenie

Tak som získal možnosť pripojiť sa k svojmu počítaču zo smartfónu. Táto implementácia umožňuje pripojiť akéhokoľvek OpenVPN klienta.
Praktika
Bude potrebné:
# apt install openvpn stun-client sendemailNapísaním niekoľkých skriptov, niekoľkých konfiguračných súborov a vygenerovaním potrebných certifikátov (pretože klient na smartfóne funguje len na základe certifikátov) som získal bežnú implementáciu OpenVPN servera.
Hlavný skript na počítači
# 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
doneSkript na posielanie údajov 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"Konfiguračný súbor servera:
# 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 20Konfiguračný súbor klienta:
# 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 30Generovanie certifikátov prebiehalo podľa tomto článku.
Spustenie skriptu:
# ./vpn11.shPredtým, než sa stal spustiteľným
# chmod +x vpn11.shNa strane smartfónu
Nainštalovaním aplikácie OpenVPN pre Android, skopírovaním konfiguračného súboru, certifikátov a nastavením sa podarilo dosiahnuť nasledovné:
Na smartfóne kontrolujem poštu
Opravil som číslo portu v nastaveniach
Spúšťam klienta a pripájam sa
Počas písania tohto článku som preniesol konfiguráciu z počítača na Raspberry Pi 3 a pokúsil sa spustiť všetko na LTE modeme, ale nepodarilo sa! Výsledok príkazu
# stun stun.ekiga.net -p 11111STUN klient verzia 0.97
Primárne: Nezávislé zobrazenie, Filter závislý od portu, náhodný port, bude hairpin
Hodnota návratu je 0x000006
hodnota Filter závislý na porte neumožnil systému spustiť.
Ale domáci poskytovateľ bez problémov umožnil systému spustiť na Raspberry Pi 3.
V spojení s webovou kamerou, s VLC pre
vytvorenie RTSP toku z webovej kamery
$ 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-keepa VLC na smartfóne na sledovanie (stream rtsp://10.2.0.1:8554/), vznikol slušný systém videodoborovania na diaľku, tiež je možné spustiť Samba, smerovať prenos cez VPN, diaľkovo ovládať počítač a mnoho ďalšieho...
Záver
Ako ukázala prax, na organizáciu VPN servera sa dá zaobísť aj bez vonkajšej IP adresy, za ktorú je potrebné platiť, rovnako ako za prenájom VPS/VDS. Ale všetko závisí od poskytovateľa. Samozrejme, chcel by som získať viac informácií o rôznych poskytovateľoch a typoch používaných NAT, ale toto je len začiatok...
Ďakujem za pozornosť!
Zdroj: habr.com
