Paprastas UDP skylių pramušimas naudojant IPIP tunelį kaip pavyzdį

Geras dienos laikas!

Šiame straipsnyje noriu papasakoti, kaip įgyvendinau (dar viena) Bash scenarijus, skirtas sujungti du kompiuterius, esančius už NAT, naudojant UDP skylių perforavimo technologiją, kaip pavyzdį naudojant Ubuntu/Debian OS.

Ryšio užmezgimas susideda iš kelių žingsnių:

  1. Paleidžiamas mazgas ir laukiama, kol nuotolinis mazgas bus paruoštas;
  2. Išorinio IP adreso ir UDP prievado nustatymas;
  3. Išorinio IP adreso ir UDP prievado perkėlimas į nuotolinį pagrindinį kompiuterį;
  4. Išorinio IP adreso ir UDP prievado gavimas iš nuotolinio pagrindinio kompiuterio;
  5. IPIP tunelio organizavimas;
  6. Ryšio stebėjimas;
  7. Jei ryšys nutrūksta, ištrinkite IPIP tunelį.

Ilgai galvojau ir vis dar galvoju kuo galima keistis duomenimis tarp mazgų, man šiuo metu paprasčiausias ir greičiausias darbas per Yandex.disk.

  • Pirma, juo paprasta naudotis – reikia atlikti 3 veiksmus: kurti, skaityti, ištrinti. Su garbanomis tai yra:
    Sukurti:

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

    Skaityti:

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

    Ištrinti:

    curl -s -X DELETE --user "$usename:$password" https://webdav.yandex.ru/$folder
  • Antra, jį lengva įdiegti:
    apt install curl

Norėdami nustatyti išorinį IP adresą ir UDP prievadą, naudokite komandą stun-client:

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

Diegimas su komanda:

apt install stun-client

Norint organizuoti tunelį, naudojami standartiniai OS įrankiai iš paketo iproute2. Egzistuoja daug tunelių kurį galima pakelti naudojant standartines priemones (L2TPv3, GRE ir kt.), bet aš pasirinkau IPIP, nes sukuria minimalų papildomą sistemos apkrovą. Bandžiau L2TPv3 per UDP ir nusivyliau, greitis nukrito 10 kartų, bet tai gali būti įvairūs apribojimai susiję su tiekėjais ar dar kažkas. Kadangi IPIP tunelis veikia IP lygiu, FOU tunelis naudojamas veikti UDP prievado lygiu. Norėdami organizuoti IPIP tunelį, jums reikia:

— įkelti FOU modulį:

modprobe fou

— klausytis vietinio uosto:

ip fou add port $localport ipproto 4

— sukurti tunelį:

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

— pakelti tunelio sąsają:

ip link set up dev fou$name

— priskirti vidinius vietinius ir vidinius nuotolinius tunelio IP adresus:

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

Ištrinkite tunelį:

ip link del dev fou$name

ip fou del port $localport

Tunelio būsena stebima periodiškai pinguojant nuotolinio mazgo tunelio vidinį IP adresą su komanda:

ping -c 1 $peerip -s 0

Periodinis ping pirmiausia reikalingas kanalui palaikyti, nes priešingu atveju, kai tunelis neveikia, maršrutizatorių NAT lentelės gali būti išvalytos ir tada ryšys nutrūks.

Jei ping dingsta, IPIP tunelis ištrinamas ir laukiama nuotolinio kompiuterio paruošimo.

Pats scenarijus:

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

Kintamieji Nick, slaptažodis и folder turėtų būti vienodi iš abiejų pusių, bet žvilgtelėti - skiriasi, pavyzdžiui: 10.0.0.1 ir 10.0.0.2. Mazgų laikas turi būti sinchronizuotas. Galite paleisti scenarijų taip:

nohup script.sh &

Norėčiau atkreipti jūsų dėmesį į tai, kad IPIP tunelis yra nesaugus dėl to, kad srautas nėra užšifruotas, tačiau tai galima lengvai išspręsti naudojant IPsec per Šis straipsnis, man tai atrodė paprasta ir suprantama.

Jau keletą savaičių naudoju šį scenarijų prisijungimui prie darbo kompiuterio ir nepastebėjau jokių problemų. Patogu jį nustatyti ir pamiršti.

Galbūt turėsite pastabų ir pasiūlymų, mielai išklausysiu.

Dėkojame už dėmesį!

Šaltinis: www.habr.com

Добавить комментарий