Jednostavno UDP bušenje rupa koristeći IPIP tunel kao primjer

Dobar dan dana!

U ovom članku želim vam reći kako sam implementirao (drugi) Bash skripta za povezivanje dva računala smještena iza NAT-a koristeći UDP tehnologiju bušenja rupa koristeći Ubuntu/Debian OS kao primjer.

Uspostavljanje veze sastoji se od nekoliko koraka:

  1. Pokretanje čvora i čekanje da udaljeni čvor bude spreman;
  2. Određivanje eksterne IP adrese i UDP porta;
  3. Prijenos vanjske IP adrese i UDP porta na udaljeni host;
  4. Dobijanje eksterne IP adrese i UDP porta od udaljenog hosta;
  5. Organizacija IPIP tunela;
  6. Monitoring veze;
  7. Ako se veza izgubi, izbrišite IPIP tunel.

Dugo sam razmišljao i još uvijek razmišljam šta se može koristiti za razmjenu podataka između čvorova, najjednostavniji i najbrži za mene trenutno je rad preko Yandex.disk.

  • Prvo, jednostavan je za korištenje - potrebne su vam 3 radnje: kreiranje, čitanje, brisanje. Sa curl ovo je:
    Stvoriti:

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

    Pročitajte:

    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
  • Drugo, lako se instalira:
    apt install curl

Da biste odredili eksternu IP adresu i UDP port, koristite naredbu stun-client:

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

Instalacija sa komandom:

apt install stun-client

Za organizaciju tunela koriste se standardni OS alati iz paketa iproute2. Postoji mnogo tunela koji se može podići standardnim sredstvima (L2TPv3, GRE, itd.), ali sam izabrao IPIP jer stvara minimalno dodatno opterećenje na sistemu. Probao sam L2TPv3 preko UDP-a i bio sam razočaran, brzina je pala 10 puta, ali to mogu biti razna ograničenja vezana za provajdere ili nešto drugo. Pošto IPIP tunel radi na IP nivou, FOU tunel se koristi za rad na nivou UDP porta. Za organizaciju IPIP tunela potrebno vam je:

— učitajte FOU modul:

modprobe fou

— slušajte lokalni port:

ip fou add port $localport ipproto 4

— kreirajte tunel:

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

— podignite tunelski interfejs:

ip link set up dev fou$name

— dodijeliti interne lokalne i interne udaljene IP adrese tunela:

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

Izbrišite tunel:

ip link del dev fou$name

ip fou del port $localport

Stanje tunela se prati periodičnim pingovanjem interne IP adrese tunela udaljenog čvora naredbom:

ping -c 1 $peerip -s 0

Periodični ping je potreban prvenstveno za održavanje kanala, inače, kada je tunel neaktivan, NAT tabele na ruterima mogu biti obrisane i tada će veza biti prekinuta.

Ako ping nestane, tada se IPIP tunel briše i čeka spremnost udaljenog hosta.

Sama skripta:

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

Varijable korisničko ime, lozinka и folder trebao bi biti isti na obje strane, ali peek - različite, na primjer: 10.0.0.1 i 10.0.0.2. Vrijeme na čvorovima mora biti sinhronizirano. Skriptu možete pokrenuti ovako:

nohup script.sh &

Skrećem vam pažnju da IPIP tunel nije bezbedan sa stanovišta činjenice da saobraćaj nije šifrovan, ali to se lako može rešiti korišćenjem IPsec-a preko ovaj članak, činilo mi se jednostavno i razumljivo.

Koristim ovu skriptu za povezivanje na radni PC već nekoliko sedmica i nisam primijetio nikakve probleme. Pogodno u smislu postavljanja i zaboravljanja.

Možda ćete imati primjedbe i prijedloge, rado ću ih saslušati.

Spasibo za vnimanie!

izvor: www.habr.com

Dodajte komentar