Jednostavno UDP bušenje rupa korištenjem IPIP tunela kao primjera

Dobro vrijeme dana!

U ovom članku želim vam reći kako sam implementirao (još) Bash skripta za povezivanje dva računala koja se nalaze iza NAT-a korištenjem UDP tehnologije 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 vanjske IP adrese i UDP porta;
  3. Prijenos vanjske IP adrese i UDP porta na udaljeni host;
  4. Dobivanje vanjske IP adrese i UDP porta od udaljenog glavnog računala;
  5. Organizacija IPIP tunela;
  6. Praćenje veze;
  7. Ako se veza izgubi, izbrišite IPIP tunel.

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

  • Prvo, jednostavan je za korištenje - potrebne su vam 3 radnje: stvaranje, čitanje, brisanje. S curlom ovo je:
    Stvoriti:

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

    Čitati:

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

    Izbrisati:

    curl -s -X DELETE --user "$usename:$password" https://webdav.yandex.ru/$folder
  • Drugo, lako se postavlja:
    apt install curl

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

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

Instalacija s naredbom:

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 odabrao IPIP jer stvara minimalno dodatno opterećenje sustava. Probao sam L2TPv3 preko UDP-a i razočarao se, brzina je pala 10 puta, ali to mogu biti razna ograničenja vezana uz providere ili nešto drugo. Budući da IPIP tunel radi na IP razini, FOU tunel se koristi za rad na razini UDP porta. Za organizaciju IPIP tunela potrebno vam je:

— učitajte FOU modul:

modprobe fou

— slušati lokalni port:

ip fou add port $localport ipproto 4

— stvoriti tunel:

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

— podići sučelje tunela:

ip link set up dev fou$name

— dodijelite unutarnju lokalnu i unutarnju udaljenu IP adresu tunela:

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

Brisanje tunela:

ip link del dev fou$name

ip fou del port $localport

Stanje tunela nadzire se povremenim pinganjem interne IP adrese tunela udaljenog čvora naredbom:

ping -c 1 $peerip -s 0

Periodični ping je prvenstveno potreban za održavanje kanala, inače, kada je tunel u stanju mirovanja, NAT tablice na usmjerivačima mogu biti izbrisane i tada će veza biti prekinuta.

Ako ping nestane, tada se IPIP tunel briše i čeka spremnost od udaljenog glavnog računala.

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 и mapa treba biti isti s obje strane, ali zaviriti - različite, na primjer: 10.0.0.1 i 10.0.0.2. Vrijeme na čvorovima mora biti sinkronizirano. Skriptu možete pokrenuti ovako:

nohup script.sh &

Želio bih vam skrenuti pozornost na činjenicu da je IPIP tunel nesiguran s gledišta činjenice da promet nije šifriran, ali to se lako može riješiti pomoću IPsec-a preko ovaj članak, činilo mi se jednostavno i razumljivo.

Već nekoliko tjedana koristim ovu skriptu za povezivanje s radnim računalom i nisam primijetio nikakve probleme. Zgodno u smislu postavljanja i zaboravljanja.

Možda ćete imati primjedbe i prijedloge, bit će mi drago poslušati.

Hvala vam!

Izvor: www.habr.com

Dodajte komentar