Enkel UDP-hulsning ved hjælp af en IPIP-tunnel som eksempel

God dag!

I denne artikel vil jeg fortælle dig, hvordan jeg implementerede (en til) et Bash-script til at forbinde to computere, der er placeret bag NAT, ved hjælp af UDP-hulleteknologi ved hjælp af Ubuntu/Debian OS som eksempel.

Etablering af en forbindelse består af flere trin:

  1. Starte en node og vente på, at den eksterne node er klar;
  2. Bestemmelse af den eksterne IP-adresse og UDP-port;
  3. Overførsel af en ekstern IP-adresse og UDP-port til en fjernvært;
  4. Indhentning af en ekstern IP-adresse og UDP-port fra en ekstern vært;
  5. Organisering af en IPIP-tunnel;
  6. Forbindelsesovervågning;
  7. Hvis forbindelsen afbrydes, skal du slette IPIP-tunnelen.

Jeg tænkte længe og tror stadig, hvad der kan bruges til at udveksle data mellem noder, det enkleste og hurtigste for mig i øjeblikket arbejder gennem Yandex.disk.

  • For det første er det nemt at bruge - du har brug for 3 handlinger: oprette, læse, slette. Med krølle er dette:
    Skab:

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

    Læs:

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

    Slet:

    curl -s -X DELETE --user "$usename:$password" https://webdav.yandex.ru/$folder
  • For det andet er det nemt at installere:
    apt install curl

For at bestemme den eksterne IP-adresse og UDP-port skal du bruge kommandoen stun-client:

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

Installation med kommando:

apt install stun-client

For at organisere en tunnel bruges standard OS-værktøjer fra iproute2-pakken. Eksisterer mange tunneler som kan hæves ved hjælp af standardmidler (L2TPv3, GRE osv.), men jeg valgte IPIP fordi det skaber minimal ekstra belastning på systemet. Jeg prøvede L2TPv3 over UDP og var skuffet, hastigheden faldt 10 gange, men disse kunne være forskellige restriktioner relateret til udbydere eller noget andet. Da IPIP-tunnelen fungerer på IP-niveau, bruges FOU-tunnelen til at operere på UDP-portniveau. For at organisere en IPIP-tunnel har du brug for:

— indlæs FOU-modulet:

modprobe fou

— lyt til lokal havn:

ip fou add port $localport ipproto 4

— opret en tunnel:

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

— hæv tunnelgrænsefladen:

ip link set up dev fou$name

— tildel interne lokale og interne eksterne IP-adresser for tunnelen:

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

Slet en tunnel:

ip link del dev fou$name

ip fou del port $localport

Tunneltilstanden overvåges ved periodisk at pinge den interne IP-adresse på den eksterne nodetunnel med kommandoen:

ping -c 1 $peerip -s 0

Periodisk ping er primært nødvendig for at vedligeholde kanalen, ellers, når tunnelen er inaktiv, kan NAT-tabellerne på routerne blive ryddet, og derefter vil forbindelsen blive afbrudt.

Hvis ping forsvinder, slettes IPIP-tunnelen og venter på klargøring fra den eksterne vært.

Selve scriptet:

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

Variabler brugernavn, adgangskode и mappe skal være ens på begge sider, men kig - forskellige, for eksempel: 10.0.0.1 og 10.0.0.2. Tiden på noderne skal synkroniseres. Du kan køre scriptet sådan her:

nohup script.sh &

Jeg vil gerne henlede opmærksomheden på, at IPIP-tunnelen er usikker ud fra det synspunkt, at trafikken ikke er krypteret, men det kan nemt løses ved hjælp af IPsec over denne artikel, det virkede simpelt og forståeligt for mig.

Jeg har brugt dette script til at oprette forbindelse til en arbejds-pc i flere uger nu og har ikke bemærket nogen problemer. Praktisk i forhold til at indstille det og glemme det.

Måske vil du have kommentarer og forslag, jeg vil med glæde lytte.

Tak for din opmærksomhed!

Kilde: www.habr.com

Tilføj en kommentar