In diesem Artikel möchte ich Ihnen erklären, wie ich (ein anderes ) Skript in Bash implementiert habe, um zwei Computer hinter NAT mithilfe der UDP-Hole-Punching-Technologie am Beispiel des Ubuntu / Debian-Betriebssystems zu verbinden.
Das Herstellen einer Verbindung besteht aus mehreren Schritten:
- Starten eines Knotens und Warten auf die Bereitschaft des Remote-Knotens;
- Bestimmen der externen IP-Adresse und des UDP-Ports;
- Übertragung der externen IP-Adresse und des UDP-Ports an den Remote-Host;
- Abrufen einer externen IP-Adresse und eines UDP-Ports von einem Remote-Host;
- Organisation eines IPIP-Tunnels;
- Verbindungsüberwachung;
- Wenn die Verbindung unterbrochen wird, löschen Sie den IPIP-Tunnel.
Ich habe lange darüber nachgedacht und denke immer noch, dass es zum Austausch von Daten zwischen Knoten verwendet werden kann. Im Moment ist es für mich am einfachsten und schnellsten, über Yandex.Disk zu arbeiten.
- Erstens ist es einfach zu bedienen - Sie benötigen 3 Schritte: Erstellen, Lesen, Löschen. Mit Curl ist dies:
Erstellen:
curl -s -X MKCOL --user "$usename:$password" https://webdav.yandex.ru/$folder
Lesen:
curl -s --user "$usename:$password" -X PROPFIND -H "Depth: 1" https://webdav.yandex.ru/$folder
Löschen:
curl -s -X DELETE --user "$usename:$password" https://webdav.yandex.ru/$folder
- Zweitens ist es einfach zu installieren:
apt install curl
Verwenden Sie den Befehl stun-client, um die externe IP-Adresse und den UDP-Port zu ermitteln:
stun stun.sipnet.ru -v -p $1 2>&1 | grep "MappedAddress"
Installation mit dem Befehl:
apt install stun-client
Zum Organisieren des Tunnels werden die Standard-Betriebssystemtools aus dem iproute2-Paket verwendet. Es gibt viele Tunnel , die mit Standardmitteln eingerichtet werden können (L2TPv3, GRE usw.), aber ich habe IPIP gewählt, weil es das System nur minimal zusätzlich belastet. Ich habe L2TPv3 über UDP ausprobiert und war enttäuscht, die Geschwindigkeit ist um den Faktor 10 gesunken, aber es kann verschiedene Einschränkungen in Bezug auf Anbieter oder etwas anderes geben. Da der IPIP-Tunnel auf IP-Ebene betrieben wird, wird der FOU-Tunnel für den Betrieb auf UDP-Port-Ebene verwendet. Um einen IPIP-Tunnel zu organisieren, müssen Sie:
- das FOU-Modul laden:
modprobe fou
- lokalen Port abhören:
ip fou add port $localport ipproto 4
- einen Tunnel erstellen:
ip link add name fou$name type ipip remote $remoteip local $localip encap fou encap-sport $localport encap-dport $remoteport
- Rufen Sie die Tunnelschnittstelle auf:
ip link set up dev fou$name
- interne lokale und interne Remote-Tunnel-IP-Adresse zuweisen:
ip addr add $intIP peer $peerip dev fou$name
Tunnel löschen:
ip link del dev fou$name
ip fou del port $localport
Der Tunnelstatus wird überwacht, indem regelmäßig die interne IP-Adresse des Tunnels des Remote-Hosts mit dem folgenden Befehl gepingt wird:
ping -c 1 $peerip -s 0
Ein periodischer Ping ist in erster Linie erforderlich, um den Kanal aufrechtzuerhalten. Andernfalls können die NAT-Tabellen gelöscht werden, wenn der Tunnel auf den Routern inaktiv ist, und die Verbindung wird unterbrochen.
Wenn der Ping verloren geht, wird der IPIP-Tunnel gelöscht und wartet darauf, dass der Remote-Host bereit ist.
Das Skript selbst:
#!/bin/bash
username="username@yandex.ru"
password="password"
folder="vpnid"
intip="10.0.0.1"
localport=`shuf -i 10000-65000 -n 1`
cid=`shuf -i 10000-99999 -n 1`
tid=`shuf -i 10-99 -n 1`
function yaread {
curl -s --user "$1:$2" -X PROPFIND -H "Depth: 1" https://webdav.yandex.ru/$3 | sed 's/></>\n</g' | grep "displayname" | sed 's/<d:displayname>//g' | sed 's/<\/d:displayname>//g' | grep -v $3 | grep -v $4 | sort -r
}
function yacreate {
curl -s -X MKCOL --user "$1:$2" https://webdav.yandex.ru/$3
}
function yadelete {
curl -s -X DELETE --user "$1:$2" https://webdav.yandex.ru/$3
}
function myipport {
stun stun.sipnet.ru -v -p $1 2>&1 | grep "MappedAddress" | sort | uniq | awk '{print $3}' | head -n1
}
function tunnel-up {
modprobe fou
ip fou add port $4 ipproto 4
ip link add name fou$7 type ipip remote $1 local $3 encap fou encap-sport $4 encap-dport $2
ip link set up dev fou$7
ip addr add $6 peer $5 dev fou$7
}
function tunnel-check {
sleep 10
pings=0
until [[ $pings == 4 ]]; do
if ping -c 1 $1 -s 0 &>/dev/null;
then echo -n .; n=0
else echo -n !; ((pings++))
fi
sleep 15
done
}
function tunnel-down {
ip link del dev fou$1
ip fou del port $2
}
trap 'echo -e "\nDisconnecting..." && yadelete $username $password $folder; tunnel-down $tunnelid $localport; echo "IPIP tunnel disconnected!"; exit 1' 1 2 3 8 9 14 15
until [[ -n $end ]]; do
yacreate $username $password $folder
until [[ -n $ip ]]; do
mydate=`date +%s`
timeout="60"
list=`yaread $username $password $folder $cid | head -n1`
yacreate $username $password $folder/$mydate:$cid
for l in $list; do
if [ `echo $l | sed 's/:/ /g' | awk {'print $1'}` -ge $(($mydate-65)) ]; then
#echo $list
myipport=`myipport $localport`
yacreate $username $password $folder/$mydate:$cid:$myipport:$intip:$tid
timeout=$(( $timeout + `echo $l | sed 's/:/ /g' | awk {'print $1'}` - $mydate + 3 ))
ip=`echo $l | sed 's/:/ /g' | awk '{print $3}'`
port=`echo $l | sed 's/:/ /g' | awk '{print $4}'`
peerip=`echo $l | sed 's/:/ /g' | awk '{print $5}'`
peerid=`echo $l | sed 's/:/ /g' | awk '{print $6}'`
if [[ -n $peerid ]]; then tunnelid=$(($peerid*$tid)); fi
fi
done
if ( [[ -z "$ip" ]] && [ "$timeout" -gt 0 ] ) ; then
echo -n "!"
sleep $timeout
fi
done
localip=`ip route get $ip | head -n1 | sed 's|.*src ||' | cut -d' ' -f1`
tunnel-up $ip $port $localip $localport $peerip $intip $tunnelid
tunnel-check $peerip
tunnel-down $tunnelid $localport
yadelete $username $password $folder
unset ip port myipport
done
exit 0
Der Benutzername , Passwort und Ordner Variablen müssen auf beiden Seiten, aber die intip muss anders, zum Beispiel: 10.0.0.1 und 10.0.0.2. Die Zeit an den Knoten muss synchronisiert werden. Sie können das Skript folgendermaßen ausführen:
nohup script.sh &
Ich mache Sie darauf aufmerksam, dass der IPIP-Tunnel unter dem Gesichtspunkt der Tatsache, dass der Datenverkehr nicht verschlüsselt ist, unsicher ist. Dies lässt sich jedoch mit IPSec für diesen Artikel leicht lösen. Es schien mir einfach und unkompliziert.
Ich verwende dieses Skript seit mehreren Wochen, um eine Verbindung zu einem funktionierenden PC herzustellen, und habe keine Probleme festgestellt. Praktisch beim Einrichten und Vergessen.
Vielleicht haben Sie Kommentare und Vorschläge, ich werde mich freuen zu hören.
Vielen Dank für Ihre Aufmerksamkeit!