Απλή διάτρηση οπών UDP χρησιμοποιώντας ως παράδειγμα τη σήραγγα IPIP

Καλημέρα!

Σε αυτό το άρθρο θέλω να σας πω πώς υλοποίησα (ένα ακόμα) Σκριπτ Bash για τη σύνδεση δύο υπολογιστών πίσω από NAT χρησιμοποιώντας τεχνολογία διάτρησης οπών UDP χρησιμοποιώντας το λειτουργικό σύστημα ως παράδειγμα Ubuntu/Debian.

Η δημιουργία μιας σύνδεσης αποτελείται από διάφορα βήματα:

  1. Έναρξη ενός κόμβου και αναμονή για την ετοιμότητα του απομακρυσμένου κόμβου.
  2. Προσδιορισμός της εξωτερικής διεύθυνσης IP και της θύρας UDP.
  3. Μεταβίβαση εξωτερικής διεύθυνσης IP και θύρας UDP σε απομακρυσμένο κόμβο.
  4. Λήψη εξωτερικής διεύθυνσης IP και θύρας UDP από έναν απομακρυσμένο κόμβο.
  5. Οργάνωση σήραγγας IPIP;
  6. Παρακολούθηση σύνδεσης;
  7. Εάν η σύνδεση έχει διακοπεί, διαγράψτε τη σήραγγα IPIP.

Σκέφτηκα για πολύ καιρό και εξακολουθώ να πιστεύω ότι τι μπορεί να χρησιμοποιηθεί για την ανταλλαγή δεδομένων μεταξύ κόμβων, το πιο απλό και γρήγορο για μένα αυτή τη στιγμή είναι η εργασία μέσω του Yandex.disk.

  • Πρώτον, είναι εύκολο στη χρήση - χρειάζεστε 3 ενέργειες: δημιουργία, ανάγνωση, διαγραφή. Με το curl είναι:
    Δημιουργώ:
    curl -s -X MKCOL --user "$usename:$password" https://webdav.yandex.ru/$folder

    Ανάγνωση:

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

    Διαγράφω:

    curl -s -X DELETE --user "$usename:$password" https://webdav.yandex.ru/$folder
  • Δεύτερον, είναι εύκολο στην εγκατάσταση:
    apt install curl

Για να προσδιορίσετε την εξωτερική διεύθυνση IP και τη θύρα UDP, χρησιμοποιήστε την εντολή stun-client:

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

Εγκατάσταση με εντολή:

apt install stun-client

Για την οργάνωση της σήραγγας, χρησιμοποιούνται τυπικά εργαλεία λειτουργικού συστήματος από το πακέτο iproute2. Υπάρχει πολλές σήραγγες το οποίο μπορεί να αυξηθεί με τυπικά μέσα (L2TPv3, GRE, κ.λπ.), αλλά επέλεξα το IPIP επειδή δημιουργεί ελάχιστο πρόσθετο φορτίο στο σύστημα. Δοκίμασα το L2TPv3 μέσω UDP και απογοητεύτηκα, η ταχύτητα έπεσε 10 φορές, αλλά αυτό θα μπορούσε να οφείλεται σε διάφορους περιορισμούς που σχετίζονται με τους παρόχους ή σε κάτι άλλο. Δεδομένου ότι η σήραγγα IPIP λειτουργεί σε επίπεδο IP, η σήραγγα FOU χρησιμοποιείται για να λειτουργεί σε επίπεδο θύρας UDP. Για να οργανώσετε μια σήραγγα IPIP χρειάζεστε:

— μονάδα φόρτωσης FOU:

modprobe fou

— ακούστε την τοπική θύρα:

ip fou add port $localport ipproto 4

— δημιουργία σήραγγας:

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

— ανύψωση της διεπαφής της σήραγγας:

ip link set up dev fou$name

— εκχώρηση εσωτερικής τοπικής και εσωτερικής απομακρυσμένης διεύθυνσης IP της σήραγγας:

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

Διαγραφή σήραγγας:

ip link del dev fou$name

ip fou del port $localport

Η παρακολούθηση της κατάστασης της σήραγγας γίνεται με περιοδικό pinging της εσωτερικής διεύθυνσης IP της σήραγγας του απομακρυσμένου κόμβου χρησιμοποιώντας την εντολή:

ping -c 1 $peerip -s 0

Το περιοδικό ping είναι απαραίτητο κυρίως για τη διατήρηση του καναλιού, διαφορετικά, όταν η σήραγγα είναι αδρανής, οι πίνακες NAT στους δρομολογητές ενδέχεται να διαγραφούν και στη συνέχεια η σύνδεση να διακοπεί.

Εάν χαθεί το ping, η σήραγγα IPIP διαγράφεται και περιμένει την ετοιμότητα από τον απομακρυσμένο κόμβο.

Το ίδιο το σενάριο:

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

Μεταβλητές όνομα χρήστη, κωδικό πρόσβασης и φάκελο θα έπρεπε να είναι το ίδιο και στις δύο πλευρές, αλλά κρυφοκοίταγμα — διαφορετικά, για παράδειγμα: 10.0.0.1 και 10.0.0.2. Η ώρα στους κόμβους πρέπει να είναι συγχρονισμένη. Μπορείτε να εκτελέσετε το σενάριο ως εξής:

nohup script.sh &

Λάβετε υπόψη ότι η σήραγγα IPIP δεν είναι ασφαλής όσον αφορά το γεγονός ότι η κίνηση δεν είναι κρυπτογραφημένη, αλλά αυτό μπορεί εύκολα να λυθεί χρησιμοποιώντας το IPsec. Αυτό το άρθρο, μου φάνηκε απλό και ξεκάθαρο.

Χρησιμοποιώ αυτό το σενάριο για να συνδεθώ στον υπολογιστή της εργασίας μου εδώ και αρκετές εβδομάδες και δεν έχω παρατηρήσει κανένα πρόβλημα. Είναι βολικό με την έννοια ότι το ρυθμίζεις και το ξεχνάς.

Ίσως έχετε σχόλια και προτάσεις, θα χαρώ να τις ακούσω.

Спасибо за внимание!

Πηγή: www.habr.com

Αγοράστε αξιόπιστη φιλοξενία για ιστότοπους με προστασία DDoS, διακομιστές VPS VDS 🔥 Αγοράστε αξιόπιστη φιλοξενία ιστοσελίδων με προστασία DDoS, διακομιστές VPS VDS | ProHoster