Článek o tom, jak se mi podařilo spustit VPN server za NATem domácího poskytovatele (bez veřejné IP adresy). Hned na úvod podotýkám, že funkčnost tohoto řešení závisí přímo na typu NAT, který používá váš poskytovatel a také router.
Takže jsem potřeboval připojit svůj smartphone Android k domácímu počítači, oba zařízení jsou připojena k internetu přes poskytovatelské NAT, navíc je počítač připojen přes domácí router, který také NATil spojení.
Klasická schéma s použitím pronajatého VPS/VDS s veřejnou IP adresou, stejně jako pronájem veřejné IP adresy od poskytovatele, nebylo z důvodu několika příčin zvažováno.
S ohledem na zkušenosti z předchozích článků, po několika experimentech se STUN a NAT různých poskytovatelů. Rozhodl jsem se pro malý experiment a provedl jsem příkaz na domácím routeru běžící na firmware OpenWRT:
$ stun stun.sipnet.rudostal jsem výsledek:
STUN client verze 0.97
Primary: Independent Mapping, Independent Filter, random port, will hairpin
Návratová hodnota je 0x000002
Doslovný překlad:
Independent Mapping — nezávislé mapování
Independent Filter — nezávislý filtr
random port — náhodný port
will hairpin — dojde k zpětnému spojení
Prováděním podobného příkazu na svém PC jsem obdržel:
STUN client verze 0.97
Primární: Nezávislé mapování, filtrování podle portu, náhodný port, bude hairpin
Návratová hodnota je 0x000006
Port Dependent Filter — filtr závislý na portu
Rozdíl v výsledcích výstupu příkazů ukazoval na to, že domácí router přispíval „svou měrou“ do procesu překladu paketů z internetu, což se projevovalo tím, že při provádění příkazu na počítači:
stun stun.sipnet.ru -p 11111 -vjsem dostal výsledek:
…
MappedAddress = XX.1XX.1X4.2XX:4398
…
v tomto okamžiku se na chvilku otevřela UDP relace; pokud v tomto okamžiku pošlu UDP požadavek (například: netcat XX.1XX.1X4.2XX 4398 -u), požadavek dorazil na domácí router, což potvrdil TCPDump spuštěný na něm, ale požadavek nedorazil k počítači — IPtables na routeru jako NAT translator jej zablokoval.

Ale samotný fakt, že UDP požadavek prošel poskytovatelským NAT, dával naději na úspěch. Vzhledem k tomu, že router je v mé jurisdikci, vyřešil jsem problém přesměrování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ím jsem získal možnost iniciovat UDP relaci a přijímat dotazy z internetu z jakékoli IP adresy. V tu chvíli jsem spustil OpenVPN server (předem nakonfigurovaný), který naslouchal na portu UDP/11111, zadal jsem na smartphonu externí IP adresu a port (XX.1XX.1X4.2XX:4398) a úspěšně se připojil ze smartphonu k počítači. Ale v této implementaci vznikl problém, bylo třeba nějakým způsobem udržovat UDP relaci do doby připojení OpenVPN klienta k serveru, varianta s periodickým spuštěním STUN klienta se mi nelíbila – nechtěl jsem zbytečně zatěžovat STUN servery.
Také jsem si všiml záznamu „will hairpin — dojde k zpětnému spojení„, tento režim
Hairpinning umožňuje jednomu počítači v lokální síti za NAT přistupovat k jinému počítači ve stejné síti prostřednictvím externí adresy routeru.

Nakonec jsem problém s udržováním UDP relace vyřešil jednoduše – spustil jsem klienta na tomto stejném počítači se serverem.
Pracovalo to takto:
- spustil jsem STUN klienta s lokálním portem 11111
- dostal jsem odpověď s externí IP adresou a portem XX.1XX.1X4.2XX:4398
- odesílal jsem data s externí IP adresou a portem na email (možná jakoukoli jinou službu), nastavenou na smartphonu
- spustil jsem OpenVPN server na počítači s nasloucháním na portu UDP/11111
- spustil jsem OpenVPN klienta na počítači se zadáním XX.1XX.1X4.2XX:4398 pro připojení
- v jakoukoli dobu jsem spustil OpenVPN klienta na smartphonu se zadáním IP adresy a portu (v mém případě se IP adresa neměnila) pro připojení

Tím jsem získal možnost připojit se ke svému počítači ze smartphonu. Tato implementace umožňuje připojení jakéhokoli OpenVPN klienta.
Praxe
Bude potřeba:
# apt install openvpn stun-client sendemailNapsáním několika skriptů, pár konfiguračních souborů, generováním potřebných certifikátů (protože klient na smartphonu funguje pouze se certifikáty) jsem vytvořil běžnou implementaci OpenVPN serveru.
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 pro odesílání dat na email:
# 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í soubor serveru:
# 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í soubor klienta:
# cat client.confklient
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 30Generování certifikátů probíhalo podle tomto článku.
Spuštění skriptu:
# ./vpn11.shNejprve jsem ho učinil spustitelným
# chmod +x vpn11.shNa straně smartphonu
Nainstaloval jsem aplikaci OpenVPN pro Android, zkopírováním konfiguračního souboru, certifikátů a jeho nastavením, to dopadlo takto:
Na smartphonu kontroluji e-mail
Opravuji číslo portu v nastavení
Spouštím klienta a připojuji se
Během psaní článku jsem přenesl konfiguraci z počítače na Raspberry Pi 3 a zkusil spustit všechno na LTE modemu, ale nepodařilo se! Výsledek příkazu
# stun stun.ekiga.net -p 11111STUN client verze 0.97
Primární: Nezávislé mapování, filtrování podle portu, náhodný port, bude hairpin
Návratová hodnota je 0x000006
hodnotu Port Dependent Filter neumožnilo systému spustit se.
Ale domácí poskytovatel bez problémů umožnil systému spustit se na Raspberry Pi 3.
V kombinaci s webovou kamerou, s VLC pro
vytvoření RTSP streamu z webové 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 smartphonu pro sledování (stream rtsp:\/\/10.2.0.1:8554\/), vybudoval se slušný systém pro dozor na dálku, také je možné zvednout Samba, směrovat provoz přes VPN, vzdáleně ovládat počítač a mnoho dalšího…
Výstup
Jak ukázala praxe, pro organizaci VPN serveru se dá obejít i bez veřejné IP adresy, za kterou se musí platit, stejně jako za pronajímanou dedikované servery. Ale všechno závisí na poskytovateli. Samozřejmě jsem chtěl získat více informací o různých poskytovatelích a typech používaných NAT, ale to je zatím jen začátek...
Děkujeme za pozornost!
Zdroj: habr.com
