Enostavno luknjanje UDP z uporabo tunela IPIP kot primera

Dobroe время sutok!

V tem članku vam želim povedati, kako sem implementiral (drugo) skript Bash za povezovanje dveh računalnikov, ki se nahajata za NAT, z uporabo tehnologije luknjanja UDP z uporabo operacijskega sistema Ubuntu/Debian kot primer.

Vzpostavitev povezave je sestavljena iz več korakov:

  1. Zagon vozlišča in čakanje, da je oddaljeno vozlišče pripravljeno;
  2. Določanje zunanjega naslova IP in vrat UDP;
  3. Prenos zunanjega naslova IP in vrat UDP na oddaljenega gostitelja;
  4. Pridobitev zunanjega naslova IP in vrat UDP od oddaljenega gostitelja;
  5. Organizacija predora IPIP;
  6. Nadzor povezave;
  7. Če je povezava prekinjena, izbrišite tunel IPIP.

Dolgo sem razmišljal in še vedno razmišljam, kaj je mogoče uporabiti za izmenjavo podatkov med vozlišči, najenostavnejše in najhitrejše zame trenutno deluje prek Yandex.disk.

  • Prvič, enostaven je za uporabo - potrebujete 3 dejanja: ustvarjanje, branje, brisanje. S curlom je to:
    Ustvari:

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

    Preberite:

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

    Izbriši:

    curl -s -X DELETE --user "$usename:$password" https://webdav.yandex.ru/$folder
  • Drugič, namestitev je enostavna:
    apt install curl

Če želite določiti zunanji naslov IP in vrata UDP, uporabite ukaz stun-client:

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

Namestitev z ukazom:

apt install stun-client

Za organizacijo tunela se uporabljajo standardna orodja OS iz paketa iproute2. obstaja veliko tunelov ki se lahko dvigne s standardnimi sredstvi (L2TPv3, GRE itd.), vendar sem izbral IPIP, ker ustvari minimalno dodatno obremenitev sistema. Probal sem L2TPv3 preko UDP in bil razočaran, hitrost je padla 10x, lahko pa so to razne omejitve vezane na ponudnike ali kaj drugega. Ker tunel IPIP deluje na ravni IP, se tunel FOU uporablja za delovanje na ravni vrat UDP. Za organizacijo tunela IPIP potrebujete:

— naložite modul FOU:

modprobe fou

— poslušajte lokalna vrata:

ip fou add port $localport ipproto 4

— ustvarite tunel:

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

— dvignite vmesnik tunela:

ip link set up dev fou$name

— dodelite notranje lokalne in notranje oddaljene naslove IP predora:

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

Brisanje tunela:

ip link del dev fou$name

ip fou del port $localport

Stanje tunela se spremlja z občasnim pinganjem notranjega naslova IP tunela oddaljenega vozlišča z ukazom:

ping -c 1 $peerip -s 0

Periodični ping je potreben predvsem za vzdrževanje kanala, sicer se lahko, ko je tunel nedejaven, počistijo tabele NAT na usmerjevalnikih in potem se povezava prekine.

Če ping izgine, se tunel IPIP izbriše in čaka na pripravljenost oddaljenega gostitelja.

Sam scenarij:

#!/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

Spremenljivke uporabniško ime, geslo и mapa mora biti obeh straneh enak, vendar intip - različni, na primer: 10.0.0.1 in 10.0.0.2. Čas na vozliščih mora biti sinhroniziran. Skript lahko zaženete takole:

nohup script.sh &

Želel bi vas opozoriti na dejstvo, da tunel IPIP ni varen z vidika dejstva, da promet ni šifriran, vendar je to mogoče enostavno rešiti z uporabo IPsec over ta članek, zdelo se mi je preprosto in razumljivo.

Ta skript uporabljam za povezavo s službenim računalnikom že nekaj tednov in nisem opazil nobenih težav. Priročno v smislu nastavitve in pozabe.

Morda boste imeli pripombe in predloge, z veseljem vam bom prisluhnil.

Спасибо за внимание!

Vir: www.habr.com

Dodaj komentar