Perforació UDP senzilla amb un túnel IPIP com a exemple

Bona hora del dia!

En aquest article vull explicar-vos com vaig implementar (un més) un script Bash per connectar dos ordinadors darrere de NAT mitjançant la tecnologia de perforació UDP utilitzant el sistema operatiu Ubuntu/Debian com a exemple.

L'establiment d'una connexió consta de diversos passos:

  1. Iniciar un node i esperar que el node remot estigui llest;
  2. Determinació de l'adreça IP externa i del port UDP;
  3. Transferir una adreça IP externa i un port UDP a un host remot;
  4. Obtenció d'una adreça IP externa i un port UDP d'un host remot;
  5. Organització d'un túnel IPIP;
  6. Supervisió de la connexió;
  7. Si es perd la connexió, suprimiu el túnel IPIP.

Vaig pensar durant molt de temps i encara penso què es pot utilitzar per intercanviar dades entre nodes, el més senzill i ràpid per a mi actualment és treballar a través de Yandex.disk.

  • En primer lloc, és fàcil d'utilitzar: necessiteu 3 accions: crear, llegir, suprimir. Amb rínxol això és:
    Crear:

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

    Llegeix:

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

    Suprimeix:

    curl -s -X DELETE --user "$usename:$password" https://webdav.yandex.ru/$folder
  • En segon lloc, és fàcil d'instal·lar:
    apt install curl

Per determinar l'adreça IP externa i el port UDP, utilitzeu l'ordre stun-client:

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

Instal·lació amb comandament:

apt install stun-client

Per organitzar un túnel, s'utilitzen les eines estàndard del sistema operatiu del paquet iproute2. Existeix molts túnels que es pot plantejar mitjançant mitjans estàndard (L2TPv3, GRE, etc.), però vaig triar IPIP perquè crea una càrrega addicional mínima al sistema. Vaig provar L2TPv3 a través d'UDP i em vaig decebre, la velocitat va baixar 10 vegades, però podrien ser diverses restriccions relacionades amb els proveïdors o una altra cosa. Com que el túnel IPIP funciona a nivell IP, el túnel FOU s'utilitza per operar a nivell de port UDP. Per organitzar un túnel IPIP necessiteu:

— Carregueu el mòdul FOU:

modprobe fou

— escoltar el port local:

ip fou add port $localport ipproto 4

- crear un túnel:

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

— augmentar la interfície del túnel:

ip link set up dev fou$name

— assigneu adreces IP internes locals i remotes internes del túnel:

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

Eliminar un túnel:

ip link del dev fou$name

ip fou del port $localport

L'estat del túnel es controla fent ping periòdicament a l'adreça IP interna del túnel del node remot amb l'ordre:

ping -c 1 $peerip -s 0

El ping periòdic és necessari principalment per mantenir el canal, en cas contrari, quan el túnel està inactiu, es poden esborrar les taules NAT dels encaminadors i, a continuació, es trencarà la connexió.

Si el ping desapareix, el túnel IPIP s'elimina i espera que l'amfitrió remot estigui preparat.

De fet, el guió en si:

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

Variables nom d'usuari, contrasenya и folder hauria de ser el mateix per ambdós costats, però ullada - diferents, per exemple: 10.0.0.1 i 10.0.0.2. L'hora dels nodes s'ha de sincronitzar. Podeu executar l'script així:

nohup script.sh &

M'agradaria cridar la vostra atenció sobre el fet que el túnel IPIP és insegur des del punt de vista del fet que el trànsit no està xifrat, però això es pot resoldre fàcilment mitjançant IPsec a través de aquest article, em va semblar senzill i entenedor.

He estat utilitzant aquest script per connectar-me a un ordinador de treball durant diverses setmanes i no he notat cap problema. Convenient pel que fa a configurar-lo i oblidar-lo.

Potser tindreu comentaris i suggeriments, estaré encantat d'escoltar-lo.

Gràcies!

Font: www.habr.com

Afegeix comentari