Egyszerű UDP hole punching IPIP alaguton keresztül bemutatva.

Jó napot!

Ebben a cikkben szeretném elmondani, hogyan valósítottam meg (még egy) Bash szkriptet két, NAT mögött lévő számítógép összekapcsolására, UDP hole punching technológia felhasználásával, az Ubuntu/Debian operációs rendszer példáján.

A kapcsolat létrehozása több lépésből áll:

  1. A csomópont indítása és a távoli csomópont készenlétének várakozása;
  2. A külső IP-cím és UDP-port meghatározása;
  3. A külső IP-cím és UDP-port átadása a távoli csomópontnak;
  4. A külső IP-cím és UDP-port megkapása a távoli csomóponttól;
  5. IPIP-alagút létrehozása;
  6. A kapcsolat figyelése;
  7. Kapcsolat megszakadása esetén az IPIP alagút törlése.

Hosszú ideig gondolkodtam, és még mindig azon gondolkodom, hogy mit lehetne használni az adatok cseréjére a csomópontok között, a legegyszerűbb és leggyorsabb, amit jelenleg ismerek, az a Yandex.Disk-en keresztüli munka.

  • Először is, ez egyszerű a használatában – három lépés szükséges: létrehozás, olvasás, törlés. Curl segítségével ez:
    Létrehozás:
    curl -s -X MKCOL --user "$usename:$password" https://webdav.yandex.ru/$folder

    Olvasás:

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

    Törlés:

    curl -s -X DELETE --user "$usename:$password" https://webdav.yandex.ru/$folder
  • Másodszor, ez egyszerű a telepítésben:
    apt install curl

A külső IP-cím és UDP-port meghatározásához stun-client parancsot használunk:

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

Telepítés parancs:

apt install stun-client

Az alagút létrehozásához az iproute2 csomagból származó beépített eszközöket használunk. Számos alagút hozható létre beépített eszközökkel (L2TPv3, GRE stb.), de én az IPIP-et választottam, mert ez minimális extra terhelést jelent a rendszerre. Próbáltam az L2TPv3-at UDP felett, és csalódtam, a sebesség tízszeresére csökkent, de ez lehet különböző korlátozások következménye a szolgáltatóktól vagy más okok miatt. Mivel az IPIP-alagút az IP szinten működik, FOU-alagutat használunk, hogy a UDP-port szinten működhessünk. Az IPIP-alagút létrehozásához szükséges:

— a FOU modul betöltése:

modprobe fou

— helyi port figyelése:

ip fou add port $localport ipproto 4

— alagút létrehozása:

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

— alagút interfész aktiválása:

ip link set up dev fou$name

— belső helyi és távoli IP-cím hozzárendelése az alagúthoz:

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

Alagút törlése:

ip link del dev fou$name

ip fou del port $localport

A tunnel's status is monitored by periodically pinging the internal IP address of the remote node's tunnel with the command:

ping -c 1 $peerip -s 0

Periodic pinging is primarily needed to maintain the channel; otherwise, if the tunnel is idle, NAT tables may be cleared on the routers, causing the connection to break.

If the ping stops, the IPIP tunnel gets removed and waits for readiness from the remote node.

Here is the actual script:

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

Változók username, password és folder must be the same on both sides, while intip — can be different, for example: 10.0.0.1 and 10.0.0.2. The time on the nodes must be synchronized. You can run the script like this:

nohup script.sh &

Please note that the IPIP tunnel is not secure in terms of unencrypted traffic, but this can be easily resolved by using IPsec. cikkbenI found it simple and comprehensible.

I have been using this script to connect to my work PC for several weeks, and I haven't noticed any problems. It's convenient in that I set it up and forgot about it.

You may have comments and suggestions; I would be happy to hear them.

Köszönöm a figyelmet!

Forrás: habr.com

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster