Enkel UDP-hullslagning ved å bruke en IPIP-tunnel som eksempel

God tid på dagen!

I denne artikkelen vil jeg fortelle deg hvordan jeg implementerte (en til) et Bash-skript for å koble sammen to datamaskiner bak NAT ved å bruke UDP-hullsteknologi ved å bruke Ubuntu/Debian OS som eksempel.

Etablering av en forbindelse består av flere trinn:

  1. Starte en node og vente på at den eksterne noden skal være klar;
  2. Bestemme den eksterne IP-adressen og UDP-porten;
  3. Overføre en ekstern IP-adresse og UDP-port til en ekstern vert;
  4. Innhenting av en ekstern IP-adresse og UDP-port fra en ekstern vert;
  5. Organisering av en IPIP-tunnel;
  6. Tilkobling overvåking;
  7. Hvis tilkoblingen blir brutt, slett IPIP-tunnelen.

Jeg tenkte lenge og tror fortsatt hva som kan brukes til å utveksle data mellom noder, det enkleste og raskeste for meg for øyeblikket fungerer gjennom Yandex.disk.

  • For det første er det enkelt å bruke - du trenger 3 handlinger: opprette, lese, slette. Med krøll er dette:
    Skape:

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

    Lese:

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

    Slett:

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

For å finne den eksterne IP-adressen og UDP-porten, bruk stun-client-kommandoen:

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

Installasjon med kommando:

apt install stun-client

For å organisere en tunnel brukes standard OS-verktøy fra iproute2-pakken. Finnes mange tunneler som kan heves ved bruk av standardmidler (L2TPv3, GRE, etc.), men jeg valgte IPIP fordi det skaper minimal ekstra belastning på systemet. Jeg prøvde L2TPv3 over UDP og ble skuffet, hastigheten falt 10 ganger, men dette kan være ulike restriksjoner knyttet til leverandører eller noe annet. Siden IPIP-tunnelen opererer på IP-nivå, brukes FOU-tunnelen til å operere på UDP-portnivå. For å organisere en IPIP-tunnel trenger du:

— last inn FOU-modulen:

modprobe fou

— lytt til lokal port:

ip fou add port $localport ipproto 4

— lag en tunnel:

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

— heve tunnelgrensesnittet:

ip link set up dev fou$name

- tilordne interne lokale og interne eksterne IP-adresser til tunnelen:

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

Slett en tunnel:

ip link del dev fou$name

ip fou del port $localport

Tunneltilstanden overvåkes ved å periodisk pinge den interne IP-adressen til den eksterne nodetunnelen med kommandoen:

ping -c 1 $peerip -s 0

Periodisk ping er nødvendig først og fremst for å opprettholde kanalen, ellers, når tunnelen er inaktiv, kan NAT-tabellene på ruterne bli slettet, og da vil forbindelsen bli brutt.

Hvis pinget forsvinner, slettes IPIP-tunnelen og venter på beredskap fra den eksterne verten.

Selve manuset:

#!/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 brukernavn, passord и mappe skal være lik på begge sider, men tips - forskjellige, for eksempel: 10.0.0.1 og 10.0.0.2. Tiden på nodene må synkroniseres. Du kan kjøre skriptet slik:

nohup script.sh &

Jeg vil gjøre deg oppmerksom på at IPIP-tunnelen er utrygg med tanke på at trafikken ikke er kryptert, men dette kan enkelt løses ved hjelp av IPsec over denne artikkelen, det virket enkelt og forståelig for meg.

Jeg har brukt dette skriptet for å koble til en arbeids-PC i flere uker nå og har ikke merket noen problemer. Praktisk med tanke på å sette den og glemme den.

Kanskje du vil ha kommentarer og forslag, jeg vil gjerne høre.

Takk for din oppmerksomhet!

Kilde: www.habr.com

Legg til en kommentar