Articolo su come sono riuscito a avviare un server VPN dietro al NAT del provider domestico (senza indirizzo IP pubblico). Mi preme sottolineare che la funzionalità di questa implementazione dipende direttamente dal tipo di NAT utilizzato dal tuo provider, così come dal router.
Quindi, ho avuto la necessità di connettermi dal mio smartphone Android al computer di casa, entrambi i dispositivi sono collegati a Internet tramite NAT del provider, inoltre il computer è collegato tramite un router domestico che fa anch'esso NAT delle connessioni.
Non ho considerato lo schema classico con un VPS/VDS affittato con un indirizzo IP pubblico, così come l'affitto di un indirizzo IP pubblico dal provider, per vari motivi.
Tenendo conto dell'esperienza degli articoli precedenti, dopo aver effettuato alcuni esperimenti con STUN e NAT dei provider. Ho deciso di fare un piccolo esperimento, eseguendo il comando sul mio router di casa funzionante con il firmware OpenWRT:
$ stun stun.sipnet.ruho ottenuto il risultato:
STUN client version 0.97
Primary: Independent Mapping, Independent Filter, random port, will hairpin
Il valore di ritorno è 0x000002
Traduzione letterale:
Independent Mapping — mappatura indipendente
Independent Filter — filtro indipendente
random port — porta casuale
will hairpin — farà hairpin
Eseguendo un comando analogo sul mio PC, ho ottenuto:
STUN client version 0.97
Primary: Independent Mapping, Port Dependent Filter, random port, will hairpin
Il valore di ritorno è 0x000006
Port Dependent Filter — filtro dipendente dalla porta
La differenza nei risultati delle uscite dei comandi indicava che il router di casa stava apportando "un suo contributo" al processo di traslazione dei pacchetti da Internet, ciò si manifestava nel fatto che eseguendo il comando sul computer:
stun stun.sipnet.ru -p 11111 -vricevevo il risultato:
…
MappedAddress = XX.1XX.1X4.2XX:4398
…
in quel momento si apriva per un breve periodo una sessione UDP; se in quel frangente inviavo una richiesta UDP (ad esempio: netcat XX.1XX.1X4.2XX 4398 -u), la richiesta arrivava al router di casa, come confermato da TCPDump in esecuzione su di esso, ma la richiesta non raggiungeva il computer — IPtables come traslatore NAT nel router la scartava.

Ma il semplice fatto che la richiesta UDP passasse attraverso il NAT del provider dava speranza di successo. Poiché il router è sotto la mia giurisdizione, ho risolto il problema reindirizzando il port UDP/11111 al computer:
iptables -t nat -A PREROUTING -i eth1 -p udp -d 10.1XX.2XX.XXX --dport 11111 -j DNAT --to-destination 192.168.X.XXXIn questo modo ho ottenuto la possibilità di avviare una sessione UDP e ricevere richieste da Internet da qualsiasi indirizzo IP. In quel momento ho avviato OpenVPN-server (configurato in precedenza) in ascolto della porta UDP/11111, ho indicato sull'app smartphone l'indirizzo IP esterno e la porta (XX.1XX.1X4.2XX:4398) e mi sono connesso con successo dallo smartphone al computer. Ma in questa implementazione si è presentato un problema: dovevo in qualche modo mantenere la sessione UDP fino al momento in cui il client OpenVPN si collegava al server; non mi è piaciuta l'idea di avviare periodicamente un client STUN - non volevo sovraccaricare inutilmente i server STUN.
Ho notato anche la registrazione «will hairpin — farà hairpin«, questa modalità
Hairpinning consente a un computer nella rete locale dietro NAT di accedere a un altro computer nella stessa rete tramite l'indirizzo esterno del router.

Alla fine ho risolto il problema di mantenere la sessione UDP semplicemente avviando il client sullo stesso computer del server.
Funzionava così:
- avviavo il client STUN sulla porta locale 11111
- ricevevo una risposta con l'indirizzo IP esterno e la porta XX.1XX.1X4.2XX:4398
- inviavo i dati all'indirizzo IP esterno e alla porta tramite email (è possibile utilizzare qualsiasi altro servizio) configurato sullo smartphone
- avviavo il server OpenVPN sul computer in ascolto della porta UDP/11111
- avviavo il client OpenVPN sul computer specificando XX.1XX.1X4.2XX:4398 per la connessione
- in qualsiasi momento avviavo il client OpenVPN sullo smartphone specificando l'indirizzo IP e la porta (nel mio caso l'indirizzo IP non cambiava) per la connessione

In questo modo ho ottenuto la possibilità di connettermi al mio computer dallo smartphone. Questa implementazione consente di collegare qualsiasi client OpenVPN.
Pratica
Occorrerà:
# apt install openvpn stun-client sendemailScrivendo un paio di script, un paio di file di configurazione, generando i certificati necessari (poiché il client sullo smartphone funziona solo con certificati) è stata realizzata una normale implementazione di un server OpenVPN.
Lo script principale sul 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
doneScript per l'invio di dati via 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"File di configurazione del server:
# 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 20File di configurazione del client:
# 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 30La generazione dei certificati è stata effettuata secondo questo articolo.
Avvio dello script:
# ./vpn11.shFacendo prima in modo che sia eseguibile
# chmod +x vpn11.shDalla parte dello smartphone
Installando l'applicazione OpenVPN per Android, copiando il file di configurazione, i certificati e configurandolo, si è ottenuto quanto segue:
Controllo la posta sullo smartphone
Modifico il numero della porta nelle impostazioni
Avvio il client e mi connetto
Nel corso della stesura dell'articolo, ho trasferito la configurazione dal computer a Raspberry Pi 3 e ho provato a far partire tutto questo su un modem LTE, ma non sono riuscito! Risultato del comando
# stun stun.ekiga.net -p 11111STUN client version 0.97
Primary: Independent Mapping, Port Dependent Filter, random port, will hairpin
Il valore di ritorno è 0x000006
valore Filtro Dipendente dalla Porta non ha permesso al sistema di avviarsi.
Ma il provider domestico ha permesso senza problemi l'avvio del sistema su Raspberry Pi 3.
Insieme alla webcam, con VLC per
creare un flusso RTSP dalla webcam
$ 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-keepe VLC sullo smartphone per la visione (flusso rtsp://10.2.0.1:8554/), è stato realizzato un buon sistema di videosorveglianza a distanza, è anche possibile attivare Samba, instradare il traffico attraverso VPN, gestire il computer a distanza e molto altro...
Conclusione
Come ha dimostrato la pratica, per organizzare un server VPN si può fare a meno anche di un indirizzo IP pubblico per il quale è necessario pagare, così come per l'affitto VPS/VDS. Ma tutto dipende dal provider. Certamente avrei voluto ottenere più informazioni sui vari provider e sui tipi di NAT utilizzati, ma questo è solo l'inizio...
Grazie per l'attenzione!
Fonte: habr.com
