UDP hole punching i thjeshtë në shembullin e tunelit IPIP

Mirëmbrëma!

Në këtë artikull do të shpjegoj se si kam realizuar (një tjetër) skript në Bash për të lidhur dy kompjuterë që ndodhen pas NAT-it, duke përdorur teknologjinë UDP hole punching me shembuj nga sistemi operativ Ubuntu/Debian.

Organizimi i lidhjes përbëhet nga disa hapa:

  1. Nisja e nyjës dhe pritja për gatishmërinë e nyjës së largët;
  2. Përcaktimi i IP-së së jashtme dhe portit UDP;
  3. Transferimi i IP-së së jashtme dhe portit UDP te nyja e largët;
  4. Marrja e IP-së së jashtme dhe portit UDP nga nyja e largët;
  5. Organizimi i tunelit IPIP;
  6. Monitorimi i lidhjes;
  7. Në rast të ndërprerjes së lidhjes, fshij tunelin IPIP.

Kam menduar gjatë dhe ende mendoj, se çfarë mund të përdor për exchange të dhënash midis nyjave, gjëja më e thjeshtë dhe më e shpejtë për mua deri tani, është puna përmes Yandex.Disk.

  • SĂ« pari, Ă«shtĂ« thjeshtĂ«sia nĂ« pĂ«rdorim — nevojiten 3 veprime: krijo, lexoni, fshij. Me curl, kjo Ă«shtĂ«:
    Krijo:
    curl -s -X MKCOL --user "$usename:$password" https://webdav.yandex.ru/$folder

    Lexo:

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

    Fshi:

    curl -s -X DELETE --user "$usename:$password" https://webdav.yandex.ru/$folder
  • SĂ« dyti, Ă«shtĂ« thjeshtĂ«sia nĂ« instalim:
    apt install curl

Për të përcaktuar IP-në e jashtme dhe portin UDP përdoret komandën stun-client:

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

Instalimi me komandën:

apt install stun-client

Për organizimin e tunelit përdoren mjete standarde të sistemit nga paketa iproute2. Ekzistojnë të shumë tunelesh që mund të ngriten me mjete standarde (L2TPv3, GRE etj.), por unë zgjodha IPIP sepse ai krijon ngarkesën minimale shtesë në sistem. Kam provuar L2TPv3 mbi UDP dhe u zhgënjeva, shpejtësia ra 10 herë, por këto mund të jenë kufizime të ndryshme që lidhen me ofruesit e shërbimeve ose diçka tjetër. Duke qenë se tuneli IPIP funksionon në nivelin IP, përdoret tuneli FOU për të punuar në nivelin e porteve UDP. Për organizimin e tunelit IPIP duhen:

— ngarko modulin FOU:

modprobe fou

— dĂ«gjo portin lokal:

ip fou add port $localport ipproto 4

— krijo tunelin:

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

— aktivizo ndĂ«rfaqen e tunelit:

ip link set up dev fou$name

— cakto IP-nĂ« e brendshme lokale dhe IP-nĂ« e brendshme tĂ« largĂ«t tĂ« tunelit:

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

Fshi tunelin:

ip link del dev fou$name

ip fou del port $localport

Monitorimi i gjendjes së tunelit bëhet përmes një ping-u periodik ndaj adresës IP të brendshme të tunelit të nodit të largët, me komandën:

ping -c 1 $peerip -s 0

Ping-u periodik është i nevojshëm kryesisht për të mbajtur kanalin, nd otherwise, gjatë papunësisë së tunelit, tabelat NAT në router mund të pastrohen dhe atëherë lidhja do të ndërpritet.

Nëse ping-u humbet, atëherë tuneli IPIP fshihet dhe pret gatishmërinë nga nodi i largët.

Saktësisht skripti vetë:

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

Variablat username, password dhe folder duhet tĂ« jenĂ« identike nĂ« tĂ« dyja anĂ«t, ndĂ«rsa intip – janĂ« tĂ« ndryshme, pĂ«r shembull: 10.0.0.1 dhe 10.0.0.2. Koha nĂ« nodet duhet tĂ« jetĂ« e sinkronizuar. Skripti mund tĂ« fillohet kĂ«shtu:

nohup script.sh &

Vë re se tuneli IPIP nuk është i sigurt në aspektin që trafiku nuk është i koduar, por kjo zgjidhet lehtësisht me IPsec, këto artikuj, më është dukur i thjeshtë dhe i kuptueshëm.

Kam përdorur këtë skript për t'u lidhur me PC-në time të punës për disa javë dhe nuk kam hasur probleme. E lehtë për t'u konfiguruar dhe për ta lënë të punojë pas.

Ndoshta do të keni vërejtje dhe sugjerime, do të isha i lumtur t'i dëgjoja.

Faleminderit për vëmendjen!

Burimi: habr.com

Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster