Perforación simple de buratos UDP usando un túnel IPIP como exemplo

Bo día!

Neste artigo quero contarche como implementei (Outro) un script Bash para conectar dous ordenadores situados detrás de NAT usando a tecnoloxía de perforación UDP usando o sistema operativo Ubuntu/Debian como exemplo.

Establecer unha conexión consta de varios pasos:

  1. Iniciando un nodo e esperando a que o nodo remoto estea listo;
  2. Determinar o enderezo IP externo e o porto UDP;
  3. Transferir un enderezo IP externo e un porto UDP a un host remoto;
  4. Obtención dun enderezo IP externo e un porto UDP dun host remoto;
  5. Organización dun túnel IPIP;
  6. Monitorización da conexión;
  7. Se se perde a conexión, elimine o túnel IPIP.

Pensei durante moito tempo e aínda penso o que se pode usar para intercambiar datos entre nós, o máis sinxelo e rápido para min neste momento é traballar a través de Yandex.disk.

  • En primeiro lugar, é fácil de usar: precisas 3 accións: crear, ler, eliminar. Con rizo isto é:
    Crear:

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

    Ler:

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

    Eliminar:

    curl -s -X DELETE --user "$usename:$password" https://webdav.yandex.ru/$folder
  • En segundo lugar, é fácil de instalar:
    apt install curl

Para determinar o enderezo IP externo e o porto UDP, use o comando stun-client:

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

Instalación con comando:

apt install stun-client

Para organizar un túnel, utilízanse ferramentas do sistema operativo estándar do paquete iproute2. Existe moitos túneles que se pode levantar mediante medios estándar (L2TPv3, GRE, etc.), pero escollín IPIP porque crea unha carga adicional mínima no sistema. Probei L2TPv3 a través de UDP e quedei decepcionado, a velocidade baixou 10 veces, pero estas poden ser varias restricións relacionadas con provedores ou outra cousa. Dado que o túnel IPIP funciona a nivel IP, o túnel FOU úsase para operar a nivel de porto UDP. Para organizar un túnel IPIP necesitas:

- cargar o módulo FOU:

modprobe fou

- escoitar o porto 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

- elevar a interface do túnel:

ip link set up dev fou$name

— asignar enderezos IP internos locais e remotos internos do 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

O estado do túnel monitorízase facendo ping periodicamente ao enderezo IP interno do túnel do nodo remoto co comando:

ping -c 1 $peerip -s 0

O ping periódico é necesario principalmente para manter a canle, se non, cando o túnel está inactivo, as táboas NAT dos enrutadores poden ser borradas e entón a conexión romperase.

Se o ping desaparece, o túnel IPIP elimínase e agarda a que o servidor remoto estea listo.

O guión 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 nome de usuario, contrasinal и dobrador debe ser o mesmo nos dous lados, pero tip - diferente, por exemplo: 10.0.0.1 e 10.0.0.2. O tempo nos nodos debe estar sincronizado. Pode executar o script deste xeito:

nohup script.sh &

Gustaríame chamar a súa atención sobre o feito de que o túnel IPIP non é seguro dende o punto de vista de que o tráfico non está cifrado, pero isto pódese resolver facilmente usando IPsec sobre Este artigo, pareceume sinxelo e comprensible.

Levo varias semanas usando este script para conectarme a un PC de traballo e non notei ningún problema. Conveniente en canto a configuralo e esquecelo.

Quizais teñas comentarios e suxestións, estarei encantado de escoitar.

Спасибо за внимание!

Fonte: www.habr.com

Engadir un comentario