Perforation UDP simple en utilisant un tunnel IPIP comme exemple

Bon moment de la journée!

Dans cet article, je veux vous expliquer comment j'ai implémenté (une autre) un script Bash pour connecter deux ordinateurs situés derrière NAT à l'aide de la technologie de perforation UDP en utilisant le système d'exploitation Ubuntu/Debian comme exemple.

L'établissement d'une connexion comprend plusieurs étapes :

  1. Démarrer un nœud et attendre que le nœud distant soit prêt ;
  2. Détermination de l'adresse IP externe et du port UDP ;
  3. Transfert d'une adresse IP externe et d'un port UDP vers un 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 des connexions ;
  7. Si la connexion est perdue, supprimez le tunnel IPIP.

J'ai longtemps réfléchi et je pense toujours à ce qui 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 via Yandex.disk.

  • Premièrement, il est facile à utiliser - vous avez besoin de 3 actions : créer, lire, supprimer. Avec curl, c'est :
    Créer:

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

    Lire:

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

    Effacer:

    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 commande :

apt install stun-client

Pour organiser un tunnel, les outils standard du système d'exploitation du package iproute2 sont utilisés. Existe de nombreux tunnels qui peut être augmenté à l'aide de moyens standards (L2TPv3, GRE, etc.), mais j'ai choisi IPIP car cela 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é 10 fois, 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 il vous faut :

— 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

— relever l'interface du tunnel :

ip link set up dev fou$name

— attribuer des adresses IP locales internes et distantes internes du tunnel :

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

Supprimer un 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 du nœud distant avec la commande :

ping -c 1 $peerip -s 0

Un ping périodique est nécessaire principalement pour maintenir le canal, sinon, lorsque le tunnel est inactif, les tables NAT sur les routeurs peuvent être effacées et la connexion sera alors interrompue.

Si le ping disparaît, le tunnel IPIP est supprimé et attend la disponibilité de l'hôte distant.

Le scénario lui-même :

#!/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'utilisateur, Mot de passe и dossier devrait être le même des deux côtés, mais astuce - différents, par exemple : 10.0.0.1 et 10.0.0.2. L'heure sur les nœuds doit être synchronisée. Vous pouvez exécuter le script comme ceci :

nohup script.sh &

Je voudrais attirer votre attention sur le fait que le tunnel IPIP n'est pas sûr du point de vue du fait que le trafic n'est pas crypté, mais cela peut être facilement résolu en utilisant IPsec sur cet article, cela m'a semblé simple et compréhensible.

J'utilise ce script pour me connecter à un PC de travail depuis plusieurs semaines maintenant et je n'ai remarqué aucun problème. Pratique pour le régler et l'oublier.

Peut-être aurez-vous des commentaires et des suggestions, je serai heureux de vous écouter.

Je vous remercie!

Source: habr.com

Ajouter un commentaire