Perforation UDP simple en utilisant un tunnel IPIP comme exemple

Bon moment de la journée!



Dans cet article, je veux vous dire comment j'ai implémenté ( un autre ) script dans Bash pour connecter deux ordinateurs derriÚre NAT en utilisant la technologie de perforation UDP en utilisant l'exemple du systÚme d'exploitation Ubuntu / Debian.



L'Ă©tablissement d'une connexion se compose de plusieurs Ă©tapes:



  1. DĂ©marrer un nƓud et attendre que le nƓud distant soit prĂȘt;
  2. DĂ©terminer l'adresse IP externe et le port UDP;
  3. Transfert de l'adresse IP externe et du port UDP vers l'hĂŽte distant;
  4. Obtention d'une adresse IP externe et d'un port UDP Ă  partir d'un hĂŽte distant;
  5. Organisation d'un tunnel IPIP;
  6. Surveillance de la connexion;
  7. Si la connexion est perdue, supprimez le tunnel IPIP.


J'ai longtemps pensĂ© et je pense toujours qu'il peut ĂȘtre utilisĂ© pour Ă©changer des donnĂ©es entre nƓuds, le plus simple et le plus rapide pour moi en ce moment est de travailler avec Yandex.Disk.



  • Tout d'abord, c'est la facilitĂ© d'utilisation - vous avez besoin de 3 Ă©tapes: crĂ©er, lire, supprimer. Avec curl c'est:

    Créer:



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


    Lis:

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


    Supprimer:



    curl -s -X DELETE --user "$usename:$password" https://webdav.yandex.ru/$folder
  • DeuxiĂšmement, il est facile Ă  installer:



    apt install curl


Pour déterminer l'adresse IP externe et le port UDP, utilisez la commande stun-client:



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


Installation avec la commande:



apt install stun-client


Pour organiser le tunnel, les outils standard du systĂšme d'exploitation du package iproute2 sont utilisĂ©s. Il existe de nombreux tunnels qui peuvent ĂȘtre mis en place par des moyens standard (L2TPv3, GRE, etc.), mais j'ai choisi IPIP car il crĂ©e une charge supplĂ©mentaire minimale sur le systĂšme. J'ai essayĂ© L2TPv3 sur UDP et j'ai Ă©tĂ© déçu, la vitesse a chutĂ© d'un facteur 10, mais il peut s'agir de diverses restrictions liĂ©es aux fournisseurs ou Ă  autre chose. Puisque le tunnel IPIP fonctionne au niveau IP, le tunnel FOU est utilisĂ© pour fonctionner au niveau du port UDP. Pour organiser un tunnel IPIP, vous devez:



- charger le module FOU:



modprobe fou


- Ă©coutez le port local:



ip fou add port $localport ipproto 4


- créer un tunnel:



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


- afficher l'interface du tunnel:



ip link set up dev fou$name


- attribuer l'adresse IP du tunnel distant interne local et interne:



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


Supprimer le tunnel:



ip link del dev fou$name


ip fou del port $localport


L'Ă©tat du tunnel est surveillĂ© en envoyant pĂ©riodiquement une requĂȘte ping Ă  l'adresse IP interne du tunnel de l'hĂŽte distant Ă  l'aide de la commande:



ping -c 1 $peerip -s 0


Un ping pĂ©riodique est principalement nĂ©cessaire pour maintenir le canal, sinon, si le tunnel est inactif sur les routeurs, les tables NAT peuvent ĂȘtre effacĂ©es et la connexion sera interrompue.



Si le ping est perdu, le tunnel IPIP est abandonnĂ© et attend que l'hĂŽte distant soit prĂȘt.



Le script lui-mĂȘme:



#!/bin/bash
username="username@yandex.ru"
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


Les variables de nom d'utilisateur , de mot de passe et de dossier doivent ĂȘtre les mĂȘmes des deux cĂŽtĂ©s, mais l' intip doit ĂȘtre diffĂ©rent, par exemple: 10.0.0.1 et 10.0.0.2. L'heure aux nƓuds doit ĂȘtre synchronisĂ©e. Vous pouvez exĂ©cuter le script comme ceci:



nohup script.sh &


J'attire votre attention sur le fait que le tunnel IPIP n'est pas sécurisé du point de vue du fait que le trafic n'est pas crypté, mais cela est facilement résolu en utilisant IPsec pour cet article , cela m'a semblé simple et direct.



J'utilise ce script pour me connecter à un PC en état de marche depuis plusieurs semaines et je n'ai remarqué aucun problÚme. Pratique en termes de mise en place et d'oubli.



Vous aurez peut-ĂȘtre des commentaires et des suggestions, je serai heureux d’entendre.



Merci de votre attention!



All Articles