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

Mirëmengjes!

Në këtë artikull dua të flas se si realizova (një tjetër) skript në Bash për lidhjen e dy kompjuterëve, të cilët ndodhen pas NAT, duke përdorur teknologjinë UDP hole punching në shembullin e OS Ubuntu/Debian.

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

  1. Nisja e nodit dhe pritja për gatishmërinë e nodit të largët;
  2. Përcaktimi i adresës IP të jashtme dhe portit UDP;
  3. Shkolla e adresës IP të jashtme dhe portit UDP në nodin e largët;
  4. Marrja e adresës IP të jashtme dhe portit UDP nga nodi i largët;
  5. Organizimi i tunelit IPIP;
  6. Monitorimi i lidhjes;
  7. Në rast ndërprerjeje të lidhjes, fshij tunelin IPIP.

Kam menduar për një kohë të gjatë dhe ende po mendoj se çfarë mund të përdor për shkëmbimin e të dhënave midis nodëve; më e thjeshta dhe më e shpejtë për mua deri tani është funksionimi përmes Yandex.disk.

  • SĂ« pari, Ă«shtĂ« thjeshtĂ«sia nĂ« pĂ«rdorim — kĂ«rkohen 3 veprime: krijo, lexoni, fshini. 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 adresën IP të jashtme dhe portin UDP përdoret stun-client me komandën:

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 mjetet standarde të OS nga paketa iproute2. Ekzistojnë llojra tunelesh që mund të ngrihen me mjete standarde (L2TPv3, GRE etj.), por unë zgjodha IPIP sepse krijon ngarkesë minimale shtesë në sistem. Kam provuar L2TPv3 mbi UDP dhe u zhgënjeva, shpejtësia ra 10 herë, por mund të jenë kufizime të ndryshme që lidhen me ofruesit ose ndonjë gjë 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 nevojiten:

— 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

— ngri interfacin e tunelit:

ip link set up dev fou$name

— cakto adresĂ«n e brendshme lokale dhe adresĂ«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 ping-eve periodike të 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 për të mbajtur kanalin, përndryshe gjatë pushimit të tunelit, mund të pastrohen tabelat NAT në routera dhe atëherë lidhja do të pritet.

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

Vërtet skenari 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Ă« tĂ« njĂ«jta nĂ« tĂ« dy anĂ«t, ndĂ«rsa intip — tĂ« ndryshme, pĂ«r shembull: 10.0.0.1 dhe 10.0.0.2. Koha nĂ« nodĂ« duhet tĂ« jetĂ« e sinkronizuar. Skriptin mund ta nisin kĂ«shtu:

nohup script.sh &

Vërej se tuneli IPIP nuk është i sigurt në aspektin se trafikuesi nuk është i enkriptuar, por kjo zgjidhet lehtë duke përdorur IPsec për këtë artikull, më duket e thjeshtë dhe e kuptueshme.

PĂ«rdor kĂ«tĂ« skript pĂ«r tĂ« lidhur me PC-nĂ« time tĂ« punĂ«s pĂ«r disa javĂ« dhe nuk kam vĂ«nĂ« re probleme. ËshtĂ« e lehtĂ« nĂ« kuptimin se e kam konfiguruar dhe e kam harruar.

Ndoshta keni ndonjë koment ose propozim, do të jem i lumtur të dëgjoj.

Faleminderit për vëmendjen!

Burimi: habr.com

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