Guten Tag!
In diesem Artikel möchte ich beschreiben, wie ich () Bash-Skript entwickelt habe, um zwei Computer, die sich hinter NAT befinden, mithilfe der UDP-Hole-Punching-Technologie zu verbinden, am Beispiel von Ubuntu/Debian.
Die Verbindung erfolgt in mehreren Schritten:
- Start des Knotens und Warten auf die Bereitschaft des entfernten Knotens;
- Bestimmung der externen IP-Adresse und des UDP-Ports;
- Übertragung der externen IP-Adresse und des UDP-Ports an den entfernten Knoten;
- Empfang der externen IP-Adresse und des UDP-Ports vom entfernten Knoten;
- Etablierung eines IPIP-Tunnels;
- Überwachung der Verbindung;
- Bei Verbindungsabbrüchen den IPIP-Tunnel entfernen.
Ich habe lange nachgedacht und denke immer noch darüber nach, was ich zum Austausch von Daten zwischen den Knoten verwenden kann; für mich ist derzeit die einfachste und schnellste Lösung die Nutzung von Yandex.Disk.
- Erstens ist es einfach zu verwenden – es sind nur 3 Schritte erforderlich: erstellen, lesen, löschen. Mit curl sieht das so aus:
Erstellen:curl -s -X MKCOL --user "$usename:$password" https://webdav.yandex.ru/$folderLesen:
curl -s --user "$usename:$password" -X PROPFIND -H "Depth: 1" https://webdav.yandex.ru/$folderLöschen:
curl -s -X DELETE --user "$usename:$password" https://webdav.yandex.ru/$folder - Zweitens ist es einfach zu installieren:
apt install curl
Zur Bestimmung der externen IP-Adresse und des UDP-Ports verwenden Sie den stun-client mit dem Befehl:
stun stun.sipnet.ru -v -p $1 2>&1 | grep "MappedAddress"Installation mit dem Befehl:
apt install stun-clientFür die Organisation des Tunnels werden die integrierten Werkzeuge des Betriebssystems aus dem Paket iproute2 verwendet. Es gibt die man mit den integrierten Mitteln aufbauen kann (L2TPv3, GRE usw.), aber ich habe mich für IPIP entschieden, da es die geringste zusätzliche Belastung für das System verursacht. Ich habe L2TPv3 über UDP ausprobiert und war enttäuscht, die Geschwindigkeit fiel um das 10-Fache, aber dies könnten verschiedene Einschränkungen mit den Providern oder anderen Faktoren sein. Da der IPIP-Tunnel auf der IP-Ebene funktioniert, wird ein FOU-Tunnel verwendet, um auf der Ebene der UDP-Ports zu arbeiten. Für die Einrichtung eines IPIP-Tunnels sind folgende Schritte erforderlich:
— Laden Sie das FOU-Modul:
modprobe fou— Lokalen Port ab hören:
ip fou add port $localport ipproto 4— Tunnel erstellen:
ip link add name fou$name type ipip remote $remoteip local $localip encap fou encap-sport $localport encap-dport $remoteport— Schnittstelle des Tunnels aktivieren:
ip link set up dev fou$name— Interne lokale und entfernte IP-Adresse des Tunnels zuweisen:
ip addr add $intIP peer $peerip dev fou$nameTunnel entfernen:
ip link del dev fou$nameip fou del port $localportDer Zustand des Tunnels wird durch regelmäßiges Pingen der internen IP-Adresse des Remote-Knotens überwacht, mit dem Befehl:
ping -c 1 $peerip -s 0Das regelmäßige Pingen ist vor allem wichtig, um den Kanal aufrechtzuerhalten, da sonst bei Inaktivität des Tunnels auf Routern die NAT-Tabellen gelöscht werden können und die Verbindung dann unterbrochen wird.
Wenn das Pingen ausbleibt, wird der IPIP-Tunnel entfernt und wartet auf die Bereitschaft vom Remote-Knoten.
Das eigentliche Skript:
#!/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 0Variablen Benutzername, password und Ordner müssen auf beiden Seiten identisch sein, während intip unterschiedlich sein kann, zum Beispiel: 10.0.0.1 und 10.0.0.2. Die Zeit auf den Knoten sollte synchronisiert sein. Das Skript kann wie folgt gestartet werden:
nohup script.sh &Ich weise darauf hin, dass der IPIP-Tunnel aus Sicherheitsgründen unsicher ist, da der Verkehr nicht verschlüsselt ist, aber dies lässt sich leicht mit IPsec lösen. , erschien mir einfach und verständlich.
Ich benutze dieses Skript seit mehreren Wochen, um mich mit meinem Arbeits-PC zu verbinden, und habe keine Probleme festgestellt. Es ist praktisch, da ich es eingerichtet und vergessen habe.
Vielleicht haben Sie Anmerkungen oder Vorschläge, ich freue mich darauf, diese zu hören.
Vielen Dank für Ihre Aufmerksamkeit!
Quelle: habr.com
