Goedenavond!
In dit artikel wil ik vertellen hoe ik () Bash-script heb geïmplementeerd om twee computers, die zich achter NAT bevinden, met behulp van de technologie UDP hole punching via het voorbeeld van Ubuntu/Debian met elkaar te verbinden.
Het opzetten van de verbinding bestaat uit verschillende stappen:
- Starten van de node en wachten op de gereedheid van de externe node;
- Bepalen van het externe IP-adres en UDP-poort;
- Doorgeven van het externe IP-adres en UDP-poort aan de externe node;
- Ontvangen van het externe IP-adres en UDP-poort van de externe node;
- Opzetten van een IPIP-tunnel;
- Monitoring van de verbinding;
- Bij verbroken verbinding de IPIP-tunnel verwijderen.
Ik heb lang nagedacht en denk nog steeds na over wat ik kan gebruiken voor gegevensuitwisseling tussen nodes. Op dit moment lijkt het me het eenvoudigste en snelste om via Yandex.Disk te werken.
- Ten eerste is het eenvoudig in gebruik — het zijn 3 stappen: maken, lezen, verwijderen. Met curl is dat:
Aanmaken:curl -s -X MKCOL --user "$usename:$password" https://webdav.yandex.ru/$folderLezen:
curl -s --user "$usename:$password" -X PROPFIND -H "Depth: 1" https://webdav.yandex.ru/$folderVerwijderen:
curl -s -X DELETE --user "$usename:$password" https://webdav.yandex.ru/$folder - Ten tweede is het eenvoudig te installeren:
apt install curl
Voor het bepalen van het externe IP-adres en UDP-poort worden de stun-client gebruikt met het commando:
stun stun.sipnet.ru -v -p $1 2>&1 | grep "MappedAddress"Installeren met het commando:
apt install stun-clientVoor het opzetten van de tunnel worden de standaardhulpmiddelen van het OS uit het iproute2-pakket gebruikt. Er zijn die met standaardhulpmiddelen kunnen worden opgezet (L2TPv3, GRE, enz.), maar ik heb voor IPIP gekozen omdat het minimale extra belasting voor het systeem creëert. Ik heb L2TPv3 boven UDP geprobeerd en was teleurgesteld; de snelheid viel met een factor 10, maar dat kan verschillende beperkingen hebben die verband houden met providers of andere zaken. Omdat de IPIP-tunnel op IP-niveau werkt, wordt een FOU-tunnel gebruikt om op UDP-poorten te kunnen werken. Voor het opzetten van een IPIP-tunnel is het nodig:
— laad de FOU-module:
modprobe fou— luister naar de lokale poort:
ip fou add port $localport ipproto 4— maak de tunnel aan:
ip link add name fou$name type ipip remote $remoteip local $localip encap fou encap-sport $localport encap-dport $remoteport— activeer de tunnelinterface:
ip link set up dev fou$name— wijs het interne lokale en interne externe IP-adres van de tunnel toe:
ip addr add $intIP peer $peerip dev fou$nameVerwijder de tunnel:
ip link del dev fou$nameip fou del port $localportDe statusmonitoring van de tunnel gebeurt door periodiek te pingen naar het interne IP-adres van de tunnel aan de andere kant met het commando:
ping -c 1 $peerip -s 0Periodiek pingen is vooral nodig om de verbinding te behouden; anders kunnen bij inactiviteit de NAT-tabellen op de routers worden gewist, waardoor de verbinding wordt verbroken.
Als de ping wegvalt, wordt de IPIP-tunnel verwijderd en wacht deze tot de andere kant weer beschikbaar is.
Eigenlijk is hier het script:
#!/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 0Variabelen username, password en map moeten gelijk zijn aan beide zijden, maar intip — verschillend, bijvoorbeeld: 10.0.0.1 en 10.0.0.2. De tijd op de knooppunten moet gesynchroniseerd zijn. Het script kan als volgt worden uitgevoerd:
nohup script.sh &Ik wil erop wijzen dat de IPIP-tunnel niet veilig is omdat het verkeer niet wordt versleuteld, maar dit kan eenvoudig worden opgelost met IPsec. , het leek me eenvoudig en duidelijk.
Ik gebruik dit script al een paar weken om verbinding te maken met mijn werk-PC en heb geen problemen ondervonden. Het is handig omdat ik het eenmaal heb ingesteld en het verder kan vergeten.
Misschien heeft u opmerkingen of suggesties, ik hoor het graag.
Bedankt voor uw aandacht!
Bron: habr.com
