Guten Tag!
In diesem Artikel möchte ich erzÀhlen, wie ich () Bash-Skript zur Verbindung zweier Computer hinter NAT mit der Technologie UDP Hole Punching am Beispiel von Ubuntu/Debian umgesetzt habe.
Die Einrichtung der Verbindung besteht aus mehreren Schritten:
- Starten des Knotens und Warten auf die Bereitschaft des entfernten Knotens;
- Bestimmen der externen IP-Adresse und des UDP-Ports;
- Ăbertragung der externen IP-Adresse und des UDP-Ports an den entfernten Knoten;
- Erhalt der externen IP-Adresse und des UDP-Ports vom entfernten Knoten;
- Einrichten eines IPIP-Tunnels;
- Ăberwachung der Verbindung;
- Bei Verbindungsabbruch den IPIP-Tunnel löschen.
Ich habe lange nachgedacht und ĂŒberlege weiterhin, was ich fĂŒr den Datenaustausch zwischen den Knoten verwenden kann. Am einfachsten und schnellsten fĂŒr mich ist derzeit die Arbeit ĂŒber Yandex.Disk.
- Erstens ist es einfach in der Benutzung â es sind 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, es ist einfach zu installieren:
apt install curl
Zur Bestimmung der externen IP-Adresse und des UDP-Ports wird der Befehl stun-client verwendet:
stun stun.sipnet.ru -v -p $1 2>&1 | grep "MappedAddress"Installation mit dem Befehl:
apt install stun-clientZur Einrichtung des Tunnels werden die Standardtools des Betriebssystems aus dem Paket iproute2 verwendet. Es gibt die mit den vorhandenen Mitteln (L2TPv3, GRE usw.) erstellt werden können, aber ich habe IPIP gewĂ€hlt, weil 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 Zehnfache, aber das könnten verschiedene EinschrĂ€nkungen von Anbietern oder Ăhnlichem sein. Da der IPIP-Tunnel auf der IP-Ebene arbeitet, wird ein FOU-Tunnel verwendet, um auf der Ebene der UDP-Ports zu arbeiten. FĂŒr die Einrichtung eines IPIP-Tunnels benötigt man:
â die FOU-Modul laden:
modprobe fouâ auf dem lokalen Port lauschen:
ip fou add port $localport ipproto 4â den Tunnel erstellen:
ip link add name fou$name type ipip remote $remoteip local $localip encap fou encap-sport $localport encap-dport $remoteportâ das Schnittstellen des Tunnels aktivieren:
ip link set up dev fou$nameâ die interne lokale und die interne 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 $localportDie Ăberwachung des Tunnelzustands erfolgt durch periodisches Pingen der internen IP-Adresse des Tunnel-Remote-Knotens mit dem Befehl:
ping -c 1 $peerip -s 0Das periodische Pingen dient in erster Linie der Aufrechterhaltung des Kanals, da sonst bei InaktivitÀt des Tunnels auf den Routern die NAT-Tabellen gelöscht werden könnten, und die Verbindung dann abbricht.
Wenn der Ping ausfÀllt, wird das IPIP-Tunnel entfernt und wartet auf die Bereitschaft des Remote-Knotens.
Hier ist 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 username, passwort und folder mĂŒssen auf beiden Seiten identisch sein, wĂ€hrend intip â unterschiedlich sein können, zum Beispiel: 10.0.0.1 und 10.0.0.2. Die Zeit auf den Knoten sollte synchronisiert sein. Das Skript kann folgendermaĂen gestartet werden:
nohup script.sh &Ich möchte darauf hinweisen, dass das IPIP-Tunnel aus Sicht der Sicherheit nicht sicher ist, da der Datenverkehr nicht verschlĂŒsselt wird, aber dies lĂ€sst sich leicht mit IPsec lösen, es schien mir einfach und verstĂ€ndlich.
Ich verwende dieses Skript bereits seit einigen Wochen fĂŒr die Verbindung zu meinem Arbeits-PC und habe keine Probleme festgestellt. Es ist praktisch, da ich es eingerichtet habe und es einfach funktioniert.
Vielleicht haben Sie Anmerkungen oder VorschlÀge, ich wÀre froh, sie zu hören.
Vielen Dank fĂŒr Ihre Aufmerksamkeit!
Quelle: habr.com
