Lihtne UDP hole punching IPIP-tunneli näitel

Tere päevast!

Selles artiklis tahan rääkida, kuidas ma rakendasin (veel ühe) Bash skripti kahe arvuti ühendamiseks, mis asuvad NAT-i taga, kasutades UDP hole punching tehnoloogiat Ubuntu/Debiani operatsioonisüsteemi näitel.

Ühenduse loomine koosneb mitmest etapist:

  1. Node käivitamine ja kaugkiibi valmiduse ootamine;
  2. Väline IP-aadress ja UDP-port määramine;
  3. Välist IP-aadressi ja UDP-porti edastamine kaugkiibile;
  4. Väline IP-aadress ja UDP-port kaugkiibilt vastuvõtmine;
  5. IPIP-tunneli loomine;
  6. Ühenduse jälgimine;
  7. Ühenduse katkestamise korral IPIP tunneli eemaldamine.

Mõtlesin kaua ja mõtlen endiselt, mida kasutada sõnumite vahetamiseks node'ide vahel, praegu tundub mulle kõige lihtsam ja kiirem variandina kasutada Yandex.Disc.

  • Esiteks, see on kasutamislihtsus — vajate kolme toimingut: loomine, lugemine, kustutamine. Curl'i abil on see:
    Loo:
    curl -s -X MKCOL --user "$usename:$password" https://webdav.yandex.ru/$folder

    Loe:

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

    Kusta:

    curl -s -X DELETE --user "$usename:$password" https://webdav.yandex.ru/$folder
  • Teiseks, see on lihtne seadistada:
    apt install curl

Välise IP-aadressi ja UDP-pordi määramiseks kasutage stun-client käsku:

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

Installimine käsuga:

apt install stun-client

Tunnelite korraldamiseks kasutatakse operatsioonisüsteemi standardilisi tööriistu paketist iproute2. On olemas palju tunnelit mida saab üles tõsta standardsete tööriistadega (L2TPv3, GRE jne), aga valisin IPIP, kuna see tekitab süsteemile minimaalselt lisakoormust. Olen proovinud L2TPv3 UDP peal ja pettunud, kiirus langes kümme korda, kuid see võib olla seotud pakkumise või millegi muuga. Kuna IPIP-tunnel töötab IP-tasandil, kasutatakse UDP-portide tasandil töötamiseks FOU-tunnelit. IPIP-tunneli loomiseks on vaja:

— laadida FOU moodul:

modprobe fou

— kuulata kohalikku porti:

ip fou add port $localport ipproto 4

— luua tunnel:

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

— tõsta tunnelite ühendus üles:

ip link set up dev fou$name

— määrata tunneli sisemine kohaliku ja kaug-IP-aadress:

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

Tunnel kustutatakse:

ip link del dev fou$name

ip fou del port $localport

Tunnel'i seisundi jälgimine toimub perioodilise pingiga kauguspunkti tunnel'i sisemise IP-aadressi abil, käsuga:

ping -c 1 $peerip -s 0

Perioodiline ping on vajalik eelkõige kanali säilitamiseks, vastasel juhul võivad marsruutijates NAT-tabelid tühjeneda, mis põhjustab ühenduse katkestamise.

Kui ping kaob, siis IPIP-tunnel eemaldatakse ja ootab kauguspunkti valmidust.

Tegelik 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 0

Muutujad username, password ja kaust peavad olema mõlemal pool samad, kuid intip on erinevad, näiteks: 10.0.0.1 ja 10.0.0.2. Kauguspunktide kellaaeg peab olema sünkroonitud. Skripti saab käivitada järgmiselt:

nohup script.sh &

Tahan tähelepanu juhtida, et IPIP-tunnel ei ole turvaline, sest liiklus ei ole krüpteeritud, kuid selle võib lihtsalt lahendada IPsec'i abil selles artiklis, ta näib mulle lihtne ja arusaadav.

Olen seda skripti kasutanud tööarvutile ühendamiseks juba mitu nädalat ja mingeid probleeme pole tähele pannud. Mugav on see, et seadistasin ja unustasin.

Võib-olla on teil mingeid märkusi ja ettepanekuid, olen avatud kuulama.

Aitäh tähelepanu eest!

Allikas: habr.com

Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster