Start eines VPN-Servers hinter einem Provider-NAT.

Artikel darüber, wie ich es geschafft habe, VPN-Server hinter dem NAT meines Internetanbieters (ohne öffentliche IP-Adresse) zu verbinden. Zunächst möchte ich klarstellen, dass die Funktionsfähigkeit dieser Implementierung direkt vom Typ des NAT abhängt, den Ihr Anbieter verwendet, sowie vom Router..
Ich hatte also die Notwendigkeit, mich von meinem Android-Smartphone mit meinem Heimcomputer zu verbinden, wobei beide Geräte über die NATs des Anbieters mit dem Internet verbunden sind; zusätzlich ist der Computer über den Heimrouter verbunden, der ebenfalls die Verbindungen NAT-ed.
Das klassische Schema mit einem gemieteten VPS/VDS mit öffentlicher IP-Adresse sowie das Mieten einer öffentlichen IP-Adresse beim Anbieter wurde aus mehreren Gründen nicht in Betracht gezogen.
Unter Berücksichtigung der Erfahrungen aus früheren Artikeln, nach mehreren Experimenten mit STUN und den NATs der Anbieter entschloss ich mich zu einem kleinen Experiment, indem ich den Befehl auf dem Heimrouter, der mit OpenWRT geflasht ist, ausführte:

$ stun stun.sipnet.ru

Ich erhielt folgendes Ergebnis:

STUN-Client-Version 0.97
Primary: Unabhängige Zuordnung, Unabhängiger Filter, zufälliger Port, wird Hairpin
Der Rückgabewert ist 0x000002

Wörtliche Übersetzung:
Unabhängige Zuordnung — unabhängige Zuordnung
Unabhängiger Filter — unabhängiger Filter
zufälliger Port — zufälliger Port
wird Hairpin — wird Hairpin
Nachdem ich einen ähnlichen Befehl auf meinem PC ausgeführt hatte, erhielt ich:

STUN-Client-Version 0.97
Primär: Unabhängige Zuordnung, Portabhängiger Filter, zufälliger Port, wird Hairpinning durchführen
Der Rückgabewert ist 0x000006

Portabhängiger Filter — portabhängiger Filter
Der Unterschied in den Ergebnissen der Befehlsausgaben deutete darauf hin, dass der Heimrouter 'seinen Teil' zum Paketweiterleitungsprozess aus dem Internet beitrug. Dies zeigte sich darin, dass bei der Ausführung des Befehls auf dem Computer:

stun stun.sipnet.ru -p 11111 -v

ich folgendes Ergebnis erhielt:


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

zu diesem Zeitpunkt wurde für kurze Zeit eine UDP-Sitzung geöffnet. Wenn zu diesem Zeitpunkt eine UDP-Anfrage gesendet wurde (zum Beispiel: netcat XX.1XX.1X4.2XX 4398 -u), kam die Anfrage beim Heimrouter an, was durch TCPDump, das darauf ausgeführt wurde, bestätigt wurde, aber die Anfrage erreichte nicht den Computer — IPtables auf dem Router verworf sie als NAT-Übersetzer.
Start eines VPN-Servers hinter dem NAT des Anbieters
Aber die Tatsache, dass die UDP-Anfrage durch das NAT des Anbieters ging, gab Hoffnung auf Erfolg. Da der Router in meiner Zuständigkeit ist, löste ich das Problem durch die Umleitung des UDP/11111 Ports auf den Computer:

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

Damit erhielt ich die Möglichkeit, eine UDP-Sitzung zu initiieren und Anfragen aus dem Internet von jeder IP-Adresse zu empfangen. In diesem Moment startete ich den OpenVPN-Server (nachdem ich ihn konfiguriert hatte), der den UDP/11111 Port überwachte, gab die externe IP-Adresse und den Port (XX.1XX.1X4.2XX:4398) auf dem Smartphone an und stellte erfolgreich eine Verbindung vom Smartphone zum Computer her. Doch in dieser Umsetzung gab es ein Problem; ich musste die UDP-Sitzung aufrechterhalten, bis der OpenVPN-Client mit dem Server verbunden war, und die Möglichkeit, den STUN-Client regelmäßig zu starten, gefiel mir nicht – ich wollte die STUN-Server nicht unnötig belasten.
Ich habe auch auf den Eintrag "wird Hairpin — wird Hairpin«, dieser Modus

Hairpinning ermöglicht es einem Gerät im lokalen Netzwerk hinter NAT, auf ein anderes Gerät im selben Netzwerk über die externe Adresse des Routers zuzugreifen.

Start eines VPN-Servers hinter dem NAT des Anbieters
Letztendlich löste ich das Problem der Aufrechterhaltung der UDP-Sitzung einfach – ich startete den Client auf demselben Computer wie den Server.
So funktionierte es:

  • Ich startete den STUN-Client mit dem lokalen Port 11111
  • erhielt eine Antwort mit der externen IP-Adresse und dem Port XX.1XX.1X4.2XX:4398
  • sendete Daten mit der externen IP-Adresse und dem Port an die E-Mail (es kann jeder andere Dienst sein), der auf dem Smartphone eingerichtet ist
  • startete den OpenVPN-Server auf dem Computer, der den UDP/11111 Port überwacht
  • startete den OpenVPN-Client auf dem Computer mit Angabe von XX.1XX.1X4.2XX:4398 zur Verbindung
  • startete jederzeit den OpenVPN-Client auf dem Smartphone mit Angabe der IP-Adresse und des Ports (in meinem Fall änderte sich die IP-Adresse nicht) zur Verbindung

Start eines VPN-Servers hinter dem NAT des Anbieters
So erhielt ich die Möglichkeit, mich mit meinem Computer von meinem Smartphone aus zu verbinden. Diese Umsetzung ermöglicht es, jeden OpenVPN-Client zu verbinden.

Praxis

Benötigt wird:

# apt install openvpn stun-client sendemail

Nachdem ich ein paar Skripte und Konfigurationsdateien geschrieben und die erforderlichen Zertifikate generiert hatte (da der Client auf dem Smartphone nur mit Zertifikaten funktioniert), erhielt ich eine gewöhnliche Umsetzung eines OpenVPN-Servers.

Das Hauptskript auf dem 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
	done

Skript zum Versenden von Daten per 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"

Konfigurationsdatei des Servers:

# 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

Konfigurationsdatei des Clients:

# 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

Die Zertifikatserstellung erfolgte gemäß diesem Artikel.
Skript starten:

# ./vpn11.sh

Vorher ausführbar gemacht

# chmod +x vpn11.sh

Auf der Smartphone-Seite

Die App installiert OpenVPN für Android, die Konfigurationsdatei, Zertifikate kopiert und es eingerichtet, sah das Ergebnis so aus:
Auf dem Smartphone prüfe ich die E-MailsStart eines VPN-Servers hinter dem NAT des Anbieters
Ändere die Portnummer in den EinstellungenStart eines VPN-Servers hinter dem NAT des Anbieters
Starte den Client und verbinde michStart eines VPN-Servers hinter dem NAT des Anbieters

Während ich den Artikel schreibe, habe ich die Konfiguration vom Computer auf den Raspberry Pi 3 übertragen und versucht, das Ganze mit einem LTE-Modem zu starten, aber es hat nicht geklappt! Das Ergebnis des Befehls

# stun stun.ekiga.net -p 11111

STUN-Client-Version 0.97
Primär: Unabhängige Zuordnung, Portabhängiger Filter, zufälliger Port, wird Hairpinning durchführen
Der Rückgabewert ist 0x000006

system-id D Portabhängiger Filter verhinderte, dass das System startet.
Aber der heimische Anbieter ließ das System problemlos auf dem Raspberry Pi 3 laufen.
In Verbindung mit der Webcam, mit VLC für
die Erstellung eines RTSP-Streams von der 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-keep

und VLC auf dem Smartphone zur Anzeige (Stream rtsp://10.2.0.1:8554/), ergab ein gutes Überwachungssystem auf Entfernung, außerdem kann man Samba einrichten, den Verkehr über VPN routen, den Computer remote steuern und noch vieles mehr...

Ausgabe

Wie die Praxis zeigte, kann man für die Einrichtung eines VPN-Servers auch ohne eine externe IP-Adresse auskommen, für die man zahlen muss, ebenso wie für die gemietete VPS/VDS. Aber alles hängt vom Anbieter ab. Natürlich hätte ich gerne mehr Informationen über verschiedene Anbieter und die verwendeten NAT-Typen erhalten, aber das ist erst der Anfang...
Vielen Dank für Ihre Aufmerksamkeit!

Quelle: habr.com

60GB SSD 8Gb DDR4