Perforare UDP simplă folosind un tunel IPIP ca exemplu

Moment bun al zilei!

În acest articol vreau să vă spun cum am implementat (încă unul) un script Bash pentru conectarea a două computere situate în spatele NAT folosind tehnologia de perforare UDP folosind sistemul de operare Ubuntu/Debian ca exemplu.

Stabilirea unei conexiuni constă în mai mulți pași:

  1. Pornirea unui nod și așteptarea ca nodul la distanță să fie gata;
  2. Determinarea adresei IP externe și a portului UDP;
  3. Transferarea unei adrese IP externe și a unui port UDP către o gazdă la distanță;
  4. Obținerea unei adrese IP externe și a unui port UDP de la o gazdă la distanță;
  5. Organizarea unui tunel IPIP;
  6. Monitorizarea conexiunii;
  7. Dacă conexiunea este pierdută, ștergeți tunelul IPIP.

M-am gândit mult timp și încă mă gândesc la ce poate fi folosit pentru a face schimb de date între noduri, cel mai simplu și mai rapid pentru mine în acest moment este să lucrez prin Yandex.disk.

  • În primul rând, este ușor de utilizat - aveți nevoie de 3 acțiuni: creați, citiți, ștergeți. Cu curl acesta este:
    Crea:

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

    Citit:

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

    Șterge:

    curl -s -X DELETE --user "$usename:$password" https://webdav.yandex.ru/$folder
  • În al doilea rând, este ușor de instalat:
    apt install curl

Pentru a determina adresa IP externă și portul UDP, utilizați comanda stun-client:

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

Instalare cu comanda:

apt install stun-client

Pentru a organiza un tunel, sunt folosite instrumente standard de SO din pachetul iproute2. Există multe tuneluri care poate fi ridicat folosind mijloace standard (L2TPv3, GRE, etc.), dar am ales IPIP deoarece creează încărcare suplimentară minimă asupra sistemului. Am încercat L2TPv3 peste UDP și am fost dezamăgit, viteza a scăzut de 10 ori, dar acestea ar putea fi diverse restricții legate de furnizori sau altceva. Deoarece tunelul IPIP operează la nivel IP, tunelul FOU este utilizat pentru a opera la nivel de port UDP. Pentru a organiza un tunel IPIP aveți nevoie de:

— încărcați modulul FOU:

modprobe fou

— ascultați portul local:

ip fou add port $localport ipproto 4

- creați un tunel:

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

— ridicați interfața tunelului:

ip link set up dev fou$name

— atribuiți adrese IP interne locale și interne la distanță ale tunelului:

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

Ștergeți un tunel:

ip link del dev fou$name

ip fou del port $localport

Starea tunelului este monitorizată prin ping periodic la adresa IP internă a tunelului nodului la distanță cu comanda:

ping -c 1 $peerip -s 0

Ping-ul periodic este necesar în primul rând pentru a menține canalul, în caz contrar, atunci când tunelul este inactiv, tabelele NAT de pe routere pot fi șterse și apoi conexiunea va fi întreruptă.

Dacă ping-ul dispare, atunci tunelul IPIP este șters și așteaptă pregătirea de la gazda la distanță.

Scenariul în sine:

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

variabile nume de utilizator, parola и dosar ar trebui să fie la fel pe ambele părți, dar intip - diferit, de exemplu: 10.0.0.1 și 10.0.0.2. Ora de pe noduri trebuie să fie sincronizată. Puteți rula scriptul astfel:

nohup script.sh &

Aș dori să vă atrag atenția asupra faptului că tunelul IPIP este nesigur din punctul de vedere al faptului că traficul nu este criptat, dar acest lucru poate fi rezolvat cu ușurință folosind IPsec peste acest articol, mi s-a părut simplu și de înțeles.

Folosesc acest script pentru a mă conecta la un computer de lucru de câteva săptămâni și nu am observat nicio problemă. Convenabil în ceea ce privește setarea și uitarea lui.

Poate veți avea comentarii și sugestii, voi fi bucuros să vă ascult.

Vă mulțumim pentru atenție!

Sursa: www.habr.com

Adauga un comentariu