Eenvoudig UDP-perforeren met als voorbeeld een IPIP-tunnel

Goede tijd van de dag!

In dit artikel wil ik je vertellen hoe ik het heb geïmplementeerd (Nog een) een Bash-script voor het verbinden van twee computers achter NAT met behulp van UDP-perforatietechnologie met het Ubuntu/Debian-besturingssysteem als voorbeeld.

Het tot stand brengen van een verbinding bestaat uit verschillende stappen:

  1. Een knooppunt starten en wachten tot het externe knooppunt gereed is;
  2. Bepalen van het externe IP-adres en UDP-poort;
  3. Een extern IP-adres en UDP-poort overbrengen naar een externe host;
  4. Een extern IP-adres en UDP-poort verkrijgen van een externe host;
  5. Organisatie van een IPIP-tunnel;
  6. Verbindingsbewaking;
  7. Als de verbinding verloren gaat, verwijdert u de IPIP-tunnel.

Ik heb lang nagedacht en denk nog steeds na over wat er kan worden gebruikt om gegevens tussen knooppunten uit te wisselen, het eenvoudigste en snelste voor mij op dit moment is werken via Yandex.disk.

  • Ten eerste is het gemakkelijk te gebruiken: je hebt 3 acties nodig: aanmaken, lezen, verwijderen. Met krul is dit:
    Creëren:

    curl -s -X MKCOL --user "$usename:$password" https://webdav.yandex.ru/$folder

    Lezen:

    curl -s --user "$usename:$password" -X PROPFIND -H "Depth: 1" https://webdav.yandex.ru/$folder

    Verwijderen:

    curl -s -X DELETE --user "$usename:$password" https://webdav.yandex.ru/$folder
  • Ten tweede is het eenvoudig te installeren:
    apt install curl

Gebruik de stun-client opdracht om het externe IP-adres en de UDP-poort te bepalen:

stun stun.sipnet.ru -v -p $1 2>&1 | grep "MappedAddress"

Installatie met commando:

apt install stun-client

Om een ​​tunnel te organiseren worden standaard OS-tools uit het iproute2-pakket gebruikt. Bestaat veel tunnels die kan worden verhoogd met behulp van standaardmiddelen (L2TPv3, GRE, enz.), maar ik heb voor IPIP gekozen omdat het een minimale extra belasting voor het systeem met zich meebrengt. Ik probeerde L2TPv3 via UDP en was teleurgesteld, de snelheid daalde 10 keer, maar dit kunnen verschillende beperkingen zijn die verband houden met providers of iets anders. Omdat de IPIP-tunnel op IP-niveau werkt, wordt de FOU-tunnel gebruikt om op UDP-poortniveau te werken. Om een ​​IPIP-tunnel te organiseren heeft u het volgende nodig:

— laad de FOU-module:

modprobe fou

- luister naar de lokale poort:

ip fou add port $localport ipproto 4

— maak een tunnel:

ip link add name fou$name type ipip remote $remoteip local $localip encap fou  encap-sport $localport encap-dport $remoteport

— verhoog de tunnelinterface:

ip link set up dev fou$name

— wijs interne lokale en interne externe IP-adressen van de tunnel toe:

ip addr add $intIP peer $peerip dev fou$name

Een tunnel verwijderen:

ip link del dev fou$name

ip fou del port $localport

De tunnelstatus wordt bewaakt door periodiek het interne IP-adres van de externe knooppunttunnel te pingen met de opdracht:

ping -c 1 $peerip -s 0

Periodieke ping is in de eerste plaats nodig om het kanaal in stand te houden, anders kunnen, wanneer de tunnel inactief is, de NAT-tabellen op de routers worden gewist en wordt de verbinding verbroken.

Als de ping verdwijnt, wordt de IPIP-tunnel verwijderd en wacht hij op gereedheid van de externe host.

Het script zelf:

#!/bin/bash
username="[email protected]"
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

variabelen gebruikersnaam, wachtwoord и map zou aan beide kanten hetzelfde moeten zijn, maar kijkje - verschillend, bijvoorbeeld: 10.0.0.1 en 10.0.0.2. De tijd op de knooppunten moet worden gesynchroniseerd. U kunt het script als volgt uitvoeren:

nohup script.sh &

Ik zou uw aandacht willen vestigen op het feit dat de IPIP-tunnel onveilig is vanuit het oogpunt van het feit dat het verkeer niet gecodeerd is, maar dit kan eenvoudig worden opgelost met behulp van IPsec via dit artikel, het leek mij eenvoudig en begrijpelijk.

Ik gebruik dit script nu al een aantal weken om verbinding te maken met een werk-pc en heb geen problemen opgemerkt. Handig qua instellen en vergeten.

Misschien heeft u opmerkingen en suggesties, ik luister graag.

Dank je wel!

Bron: www.habr.com

Voeg een reactie