Jednoduché dierovanie UDP pomocou tunela IPIP ako príklad

Dobrý čas dňa!

V tomto článku vám chcem povedať, ako som implementoval (ešte jeden) Bash skript na prepojenie dvoch počítačov za NAT pomocou technológie dierovania UDP s použitím OS Ubuntu/Debian ako príklad.

Vytvorenie spojenia pozostáva z niekoľkých krokov:

  1. Spustenie uzla a čakanie, kým bude vzdialený uzol pripravený;
  2. Určenie externej adresy IP a portu UDP;
  3. Prenos externej IP adresy a UDP portu na vzdialený hostiteľ;
  4. Získanie externej IP adresy a UDP portu zo vzdialeného hostiteľa;
  5. Organizácia tunela IPIP;
  6. Monitorovanie pripojenia;
  7. Ak sa spojenie stratí, odstráňte tunel IPIP.

Dlho som premýšľal a stále premýšľam, čo sa dá použiť na výmenu údajov medzi uzlami, najjednoduchšie a najrýchlejšie je pre mňa momentálne práca cez Yandex.disk.

  • Po prvé, je to jednoduché - potrebujete 3 akcie: vytvoriť, prečítať, odstrániť. S curl je to:
    Vytvoriť:

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

    Čítať:

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

    Odstrániť:

    curl -s -X DELETE --user "$usename:$password" https://webdav.yandex.ru/$folder
  • Po druhé, inštalácia je jednoduchá:
    apt install curl

Na určenie externej adresy IP a portu UDP použite príkaz stun-client:

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

Inštalácia pomocou príkazu:

apt install stun-client

Na organizáciu tunela sa používajú štandardné nástroje OS z balíka iproute2. Existuje veľa tunelov ktoré je možné zvýšiť pomocou štandardných prostriedkov (L2TPv3, GRE atď.), ale zvolil som IPIP, pretože vytvára minimálne dodatočné zaťaženie systému. Skúšal som L2TPv3 cez UDP a bol som sklamaný, rýchlosť klesla 10x, ale môžu to byť rôzne obmedzenia týkajúce sa poskytovateľov alebo niečo iné. Keďže tunel IPIP funguje na úrovni IP, tunel FOU sa používa na prevádzku na úrovni portu UDP. Na usporiadanie tunela IPIP potrebujete:

— načítať modul FOU:

modprobe fou

- počúvať miestny prístav:

ip fou add port $localport ipproto 4

- vytvorte tunel:

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

— zvýšiť rozhranie tunela:

ip link set up dev fou$name

— priradiť interné lokálne a interné vzdialené IP adresy tunela:

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

Odstránenie tunela:

ip link del dev fou$name

ip fou del port $localport

Stav tunela sa monitoruje pravidelným pingom na internú adresu IP tunela vzdialeného uzla pomocou príkazu:

ping -c 1 $peerip -s 0

Pravidelný ping je potrebný predovšetkým na udržiavanie kanála, inak, keď je tunel nečinný, môžu sa tabuľky NAT na smerovačoch vymazať a potom sa spojenie preruší.

Ak ping zmizne, tunel IPIP sa vymaže a čaká na pripravenosť od vzdialeného hostiteľa.

Samotný skript:

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

Premenné meno, heslo и zložka by mala byť rovnaká na oboch stranách, ale intip - rôzne, napríklad: 10.0.0.1 a 10.0.0.2. Čas na uzloch musí byť synchronizovaný. Skript môžete spustiť takto:

nohup script.sh &

Chcel by som upozorniť na skutočnosť, že IPIP tunel je nebezpečný z pohľadu nešifrovania prevádzky, ale dá sa to jednoducho vyriešiť pomocou IPsec over v tomto článku, zdalo sa mi to jednoduché a zrozumiteľné.

Tento skript používam na pripojenie k pracovnému počítaču už niekoľko týždňov a nezaznamenal som žiadne problémy. Pohodlné z hľadiska nastavenia a zabudnutia.

Možno budete mať pripomienky a návrhy, rád si vypočujem.

Ďakujem vám za pozornosť!

Zdroj: hab.com

Pridať komentár