Start eines VPN-Servers hinter einem Provider-NAT

Ein Artikel darüber, wie ich es geschafft habe, VPN-Server hinter dem NAT meines Internetanbieters (ohne öffentliche IP-Adresse) Zugriff zu erhalten. Zunächst sei gesagt, dass die Funktionalität dieser Implementierung direkt von der Art des NAT abhängt, das Ihr Anbieter sowie der Router verwendet..
Also hatte ich die Notwendigkeit, mich mit 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 einen Heimrouter verbunden, der ebenfalls die Verbindungen NATed.
Das klassische Schema mit einem gemieteten VPS/VDS mit öffentlicher IP-Adresse sowie die Anmietung einer öffentlichen IP-Adresse beim Anbieter wurde aus mehreren Gründen nicht in Betracht gezogen.
Unter Berücksichtigung der Erfahrungen aus früheren Artikeln,habe ich einige Experimente mit STUNs und den NATs der Anbieter durchgeführt. Ich habe mich entschlossen, ein kleines Experiment durchzuführen, indem ich den Befehl auf meinem Heimrouter, der mit OpenWRT geflasht ist, ausführt:

$ stun stun.sipnet.ru

ich erhielt folgendes Ergebnis:

STUN-Client-Version 0.97
Primary: Independent Mapping, Independent Filter, zufälliger Port, wird Hairpin
Der Rückgabewert ist 0x000002

Wörtliche Übersetzung:
Independent Mapping — unabhängige Zuordnung
Independent Filter — unabhängiger Filter
random port — zufälliger Port
will hairpin — wird Hairpin
Nachdem ich einen ähnlichen Befehl auf meinem PC ausgeführt habe, erhielt ich:

STUN-Client-Version 0.97
Primär: Unabhängige Zuordnung, portspezifischer Filter, zufälliger Port, wird hairpin
Der Rückgabewert ist 0x000006

Portabhängiger Filter — portabhängiger Filter
Die Unterschiede in den Ergebnissen der Befehle deuteten darauf hin, dass der Heimrouter seinen Teil zum Prozess der Paketübertragung aus dem Internet beitrug. Dies zeigte sich darin, dass beim Ausführen des Befehls auf dem Computer:

stun stun.sipnet.ru -p 11111 -v

Ich erhielt das Ergebnis:


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

In diesem Moment öffnete sich für kurze Zeit eine UDP-Sitzung. Wenn man zu diesem Zeitpunkt eine UDP-Anfrage sendete (z. B.: netcat XX.1XX.1X4.2XX 4398 -u), kam die Anfrage beim Heimrouter an, wie durch TCPDump bestätigt, das auf ihm ausgeführt wurde, jedoch erreichte die Anfrage nicht den Computer — IPtables als NAT-Übersetzer auf dem Router verworf sie.
Start eines VPN-Servers hinter dem NAT des Providers
Doch der Umstand, dass die UDP-Anfrage durch das providerseitige NAT ging, gab Hoffnung auf Erfolg. Da der Router in meinem Zuständigkeitsbereich liegt, entschied ich mich, das Problem durch das Weiterleiten von UDP/11111 auf den Computer zu lösen:

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

Dadurch 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 auf den UDP/11111-Port hörte. Ich gab auf dem Smartphone die externe IP-Adresse und den Port (XX.1XX.1X4.2XX:4398) an und konnte erfolgreich von meinem Smartphone mit dem Computer eine Verbindung herstellen. In dieser Implementierung trat jedoch ein Problem auf; ich musste irgendwie die UDP-Sitzung aufrechterhalten, bis der OpenVPN-Client mit dem Server verbunden war. Die Option, den STUN-Client sporadisch zu starten, gefiel mir nicht - ich wollte die STUN-Server nicht unnötig belasten.
Ich habe auch die Aufzeichnung „will 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 Providers
Letztendlich habe ich das Problem der Aufrechterhaltung der UDP-Sitzung einfach gelöst - ich startete den Client auf demselben Computer wie den Server.
Das funktionierte so:

  • Ich startete den STUN-Client mit dem lokalen Port 11111
  • erhielt die Antwort mit der externen IP-Adresse und dem Port XX.1XX.1X4.2XX:4398
  • sandte Daten mit der externen IP-Adresse und dem Port per E-Mail (jeder andere Dienst ist möglich), die auf dem Smartphone eingerichtet war.
  • Habe einen OpenVPN-Server auf einem Computer mit der Überwachung des UDP/11111 Ports gestartet
  • Habe einen OpenVPN-Client auf einem Computer mit der IP-Adresse XX.1XX.1X4.2XX:4398 für die Verbindung gestartet
  • Jederzeit habe ich den OpenVPN-Client auf meinem Smartphone mit Angabe der IP-Adresse und des Ports (in meinem Fall ändert sich die IP-Adresse nicht) für die Verbindung gestartet

Start eines VPN-Servers hinter dem NAT des Providers
So konnte ich mich von meinem Smartphone mit meinem Computer verbinden. Diese Implementierung ermöglicht es, jeden OpenVPN-Client zu verbinden.

Praxis

Benötigt wird:

# apt install openvpn stun-client sendemail

Durch das Schreiben mehrerer Skripte, einiger Konfigurationsdateien und das Erzeugen der notwendigen Zertifikate (da der Client auf dem Smartphone nur mit Zertifikaten funktioniert) entstand eine normale Implementierung 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 Generierung der Zertifikate erfolgte über in diesem Artikel.
Das Skript wird gestartet:

# ./vpn11.sh

Zuvor haben wir es ausführbar gemacht

# chmod +x vpn11.sh

Auf der Smartphone-Seite

Die App OpenVPN für Android, indem ich die Konfigurationsdatei, Zertifikate kopiert und alles eingerichtet habe, kam es zu folgendem Ergebnis:
Ich überprüfe die E-Mails auf dem SmartphoneStart eines VPN-Servers hinter dem NAT des Providers
Ich ändere die Portnummer in den EinstellungenStart eines VPN-Servers hinter dem NAT des Providers
Ich starte den Client und verbinde michStart eines VPN-Servers hinter dem NAT des Providers

Während ich den Artikel schreibe, habe ich die Konfiguration vom Computer auf den Raspberry Pi 3 übertragen und versucht, das Ganze über ein 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, portspezifischer Filter, zufälliger Port, wird hairpin
Der Rückgabewert ist 0x000006

den Wert Portabhängiger Filter verhindert, dass das System startet.
Aber der heimische Anbieter ließ das System ohne Probleme auf dem Raspberry Pi 3 starten.
In Verbindung mit der Webcam, mit VLC zur
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 Ansicht (Stream rtsp://10.2.0.1:8554/), ein ziemlich gutes Überwachungssystem aus der Ferne, außerdem kann Samba aktiviert, der Datenverkehr über VPN geroutet, der Computer remote gesteuert und vieles mehr…

Fazit

Wie die Praxis zeigt, kann man zur Organisation eines VPN-Servers auch ohne externe IP-Adresse auskommen, für die man bezahlen muss, ebenso wie für gemietete VPS/VDS. Aber alles hängt vom Provider ab. Natürlich wäre es schön gewesen, mehr Informationen über verschiedene Anbieter und die verwendeten Arten von NATs zu bekommen, aber das ist erst der Anfang…
Vielen Dank für Ihre Aufmerksamkeit!

Quelle: habr.com

Zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen 🔥 Zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen | ProHoster