Απευθείας σήραγγα VPN μεταξύ υπολογιστών μέσω NAT των παρόχων (χωρίς VPS, χρησιμοποιώντας διακομιστή STUN και Yandex.disk)

Επέκταση Άρθρο για το πώς κατάφερα να οργανώσω μια απευθείας σήραγγα VPN μεταξύ δύο υπολογιστών που βρίσκονται πίσω από παρόχους NAT. Το προηγούμενο άρθρο περιέγραφε τη διαδικασία οργάνωσης μιας σύνδεσης με τη βοήθεια ενός τρίτου μέρους - ενός μεσάζοντα (ένα νοικιασμένο VPS που λειτουργεί ως διακομιστής STUN και ένας πομπός δεδομένων κόμβου για τη σύνδεση). Σε αυτό το άρθρο θα σας πω πώς τα κατάφερα χωρίς VPS, αλλά οι μεσάζοντες έμειναν και ήταν ο διακομιστής STUN και το Yandex.Disk...
Απευθείας σήραγγα VPN μεταξύ υπολογιστών μέσω NAT παρόχου (χωρίς VPS, χρησιμοποιώντας διακομιστή STUN και Yandex.disk)

Εισαγωγή

Αφού διάβασα τα σχόλια της προηγούμενης ανάρτησης, συνειδητοποίησα ότι το κύριο μειονέκτημα της υλοποίησης ήταν η χρήση ενός ενδιάμεσου - ενός τρίτου μέρους (VPS) που υπέδειξε τις τρέχουσες παραμέτρους του κόμβου, πού και πώς να συνδεθεί. Λαμβάνοντας υπόψη τις συστάσεις για τη χρήση αυτού του STUN (από τα οποία υπάρχουν πολλά) για να προσδιορίσετε τις τρέχουσες παραμέτρους σύνδεσης. Πρώτα απ 'όλα, αποφάσισα να χρησιμοποιήσω το TCPDump για να κοιτάξω τα περιεχόμενα των πακέτων όταν ο διακομιστής STUN δούλευε με πελάτες και λάμβανε εντελώς αδιάβαστο περιεχόμενο. Γκουγκλάροντας το πρωτόκολλο συνάντησα άρθρο που περιγράφει το πρωτόκολλο. Συνειδητοποίησα ότι δεν μπορούσα να υλοποιήσω μόνος μου ένα αίτημα στον διακομιστή STUN και έβαλα την ιδέα σε ένα "μακρινό πλαίσιο".

Θεωρία

Πρόσφατα έπρεπε να εγκαταστήσω τον διακομιστή STUN στο Debian από το πακέτο

# apt install stun-server

και στις εξαρτήσεις είδα το πακέτο stun-client, αλλά κατά κάποιο τρόπο δεν του έδωσα σημασία. Αλλά αργότερα θυμήθηκα το πακέτο stun-client και αποφάσισα να καταλάβω πώς λειτουργεί, αφού έψαξα και έψαξα στο Yandex, πήρα:

# apt install stun-client
# stun stun.ekiga.net -p 21234 -v

Σε απάντηση έλαβα:

STUN έκδοση πελάτη 0.97
Ανοιγμένη θύρα 21234 με fd 3
Ανοιγμένη θύρα 21235 με fd 4
Κωδικοποίηση μηνύματος αναισθητοποίησης:
Κωδικοποίηση αιτήματος αλλαγής: 0

Πρόκειται να στείλω μηνύματα του φακού 28 στο 216.93.246.18:3478
Κωδικοποίηση μηνύματος αναισθητοποίησης:
Κωδικοποίηση αιτήματος αλλαγής: 4

Πρόκειται να στείλω μηνύματα του φακού 28 στο 216.93.246.18:3478
Κωδικοποίηση μηνύματος αναισθητοποίησης:
Κωδικοποίηση αιτήματος αλλαγής: 2

Πρόκειται να στείλω μηνύματα του φακού 28 στο 216.93.246.18:3478
Λήφθηκε μήνυμα αναισθητοποίησης: 92 byte
MappedAddress = <Η IP μου>:2885
ΠηγήΔιεύθυνση = 216.93.246.18:3478
ChangedAddress = 216.93.246.17:3479
Άγνωστο χαρακτηριστικό: 32800
Όνομα διακομιστή = Vovida.org 0.98-CPC
Λήφθηκε μήνυμα τύπου 257 id=1
Κωδικοποίηση μηνύματος αναισθητοποίησης:
Κωδικοποίηση αιτήματος αλλαγής: 0

Πρόκειται να στείλω μηνύματα του φακού 28 στο 216.93.246.17:3478
Κωδικοποίηση μηνύματος αναισθητοποίησης:
Κωδικοποίηση αιτήματος αλλαγής: 4

Πρόκειται να στείλω μηνύματα του φακού 28 στο 216.93.246.18:3478
Κωδικοποίηση μηνύματος αναισθητοποίησης:
Κωδικοποίηση αιτήματος αλλαγής: 2

Πρόκειται να στείλω μηνύματα του φακού 28 στο 216.93.246.18:3478
Κωδικοποίηση μηνύματος αναισθητοποίησης:
Κωδικοποίηση αιτήματος αλλαγής: 0

Πρόκειται να στείλω μηνύματα len 28 στο <My IP>:2885
Λήφθηκε μήνυμα αναισθητοποίησης: 28 byte
ChangeRequest = 0
Λήφθηκε μήνυμα τύπου 1 id=11
Κωδικοποίηση μηνύματος αναισθητοποίησης:
Κωδικοποίηση αιτήματος αλλαγής: 0

Πρόκειται να στείλω μηνύματα του φακού 28 στο 216.93.246.17:3478
Κωδικοποίηση μηνύματος αναισθητοποίησης:
Κωδικοποίηση αιτήματος αλλαγής: 4

Πρόκειται να στείλω μηνύματα του φακού 28 στο 216.93.246.18:3478
Κωδικοποίηση μηνύματος αναισθητοποίησης:
Κωδικοποίηση αιτήματος αλλαγής: 2

Πρόκειται να στείλω μηνύματα του φακού 28 στο 216.93.246.18:3478
Λήφθηκε μήνυμα αναισθητοποίησης: 92 byte
MappedAddress = <Η IP μου>:2885
ΠηγήΔιεύθυνση = 216.93.246.17:3479
ChangedAddress = 216.93.246.18:3478
Άγνωστο χαρακτηριστικό: 32800
Όνομα διακομιστή = Vovida.org 0.98-CPC
Λήφθηκε μήνυμα τύπου 257 id=10
Κωδικοποίηση μηνύματος αναισθητοποίησης:
Κωδικοποίηση αιτήματος αλλαγής: 4

Πρόκειται να στείλω μηνύματα του φακού 28 στο 216.93.246.18:3478
Κωδικοποίηση μηνύματος αναισθητοποίησης:
Κωδικοποίηση αιτήματος αλλαγής: 2

Πρόκειται να στείλω μηνύματα του φακού 28 στο 216.93.246.18:3478
Κωδικοποίηση μηνύματος αναισθητοποίησης:
Κωδικοποίηση αιτήματος αλλαγής: 4

Πρόκειται να στείλω μηνύματα του φακού 28 στο 216.93.246.18:3478
Κωδικοποίηση μηνύματος αναισθητοποίησης:
Κωδικοποίηση αιτήματος αλλαγής: 2

Πρόκειται να στείλω μηνύματα του φακού 28 στο 216.93.246.18:3478
Κωδικοποίηση μηνύματος αναισθητοποίησης:
Κωδικοποίηση αιτήματος αλλαγής: 4

Πρόκειται να στείλω μηνύματα του φακού 28 στο 216.93.246.18:3478
Κωδικοποίηση μηνύματος αναισθητοποίησης:
Κωδικοποίηση αιτήματος αλλαγής: 2

Πρόκειται να στείλω μηνύματα του φακού 28 στο 216.93.246.18:3478
Κωδικοποίηση μηνύματος αναισθητοποίησης:
Κωδικοποίηση αιτήματος αλλαγής: 4

Πρόκειται να στείλω μηνύματα του φακού 28 στο 216.93.246.18:3478
Κωδικοποίηση μηνύματος αναισθητοποίησης:
Κωδικοποίηση αιτήματος αλλαγής: 2

Πρόκειται να στείλω μηνύματα του φακού 28 στο 216.93.246.18:3478
Κωδικοποίηση μηνύματος αναισθητοποίησης:
Κωδικοποίηση αιτήματος αλλαγής: 4

Πρόκειται να στείλω μηνύματα του φακού 28 στο 216.93.246.18:3478
Κωδικοποίηση μηνύματος αναισθητοποίησης:
Κωδικοποίηση αιτήματος αλλαγής: 2

Πρόκειται να στείλω μηνύματα του φακού 28 στο 216.93.246.18:3478
δοκιμή I = 1
δοκιμή II = 0
δοκιμή III = 0
δοκιμή I(2) = 1
είναι nat = 1
αντιστοιχισμένη IP ίδια = 1
φουρκέτα = 1
θύρα συντήρησης = 0
Κύρια: Ανεξάρτητη χαρτογράφηση, φίλτρο εξαρτώμενο από τη θύρα, τυχαία θύρα, φουρκέτα
Η τιμή επιστροφής είναι 0x000006

Συμβολοσειρά με τιμή

MappedAddress = <Η IP μου>:2885

ακριβώς αυτό που χρειάζεστε! Έδειχνε την τρέχουσα κατάσταση για τη σύνδεση στην τοπική θύρα UDP 21234. Αλλά αυτή είναι μόνο η μισή μάχη· προέκυψε το ερώτημα πώς να μεταφέρετε αυτά τα δεδομένα στον απομακρυσμένο κεντρικό υπολογιστή και να οργανώσετε μια σύνδεση VPN. Χρησιμοποιώντας το πρωτόκολλο αλληλογραφίας ή μήπως το Telegram;! Υπάρχουν πολλές επιλογές και αποφάσισα να χρησιμοποιήσω το Yandex.disk, από τότε που συνάντησα άρθρο σχετικά με την εργασία του Curl μέσω WebDav με το Yandex.disk. Αφού σκέφτηκα την υλοποίηση, κατέληξα στο ακόλουθο σχήμα:

  1. Σήμα ότι οι κόμβοι είναι έτοιμοι να δημιουργήσουν μια σύνδεση με την παρουσία ενός συγκεκριμένου αρχείου με χρονική σήμανση στο Yandex.disk.
  2. Εάν οι κόμβοι είναι έτοιμοι, τότε λάβετε τις τρέχουσες παραμέτρους από τον διακομιστή STUN.
  3. Μεταφορτώστε τις τρέχουσες ρυθμίσεις στο Yandex.disk.
  4. Ελέγξτε την παρουσία και την ανάγνωση των παραμέτρων ενός απομακρυσμένου κόμβου από ένα αρχείο στο Yandex.disk.
  5. Δημιουργία σύνδεσης με έναν απομακρυσμένο κεντρικό υπολογιστή χρησιμοποιώντας το OpenVPN.

Πρακτική

Αφού σκέφτηκα λίγο, λαμβάνοντας υπόψη την εμπειρία του τελευταίου άρθρου, έγραψα γρήγορα ένα σενάριο. Θα χρειαστούμε:

# apt install openvpn stun-client curl 

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

ΑΥΘΕΝΤΙΚΗ ΕΚΔΟΧΗ

# cat vpn8.sh

#!/bin/bash
######################## Задаем цветной текст ###
WARN='33[37;1;41m'				#
END='33[0m'					#
RED='33[0;31m'         #  ${RED}		#
GREEN='33[0;32m'      #  ${GREEN}		#
#################################################
####################### Проверяем наличие необходымих приложений #########################################################
al="echo readlink dirname grep awk md5sum shuf nc curl sleep openvpn cat stun"
ch=0
for i in $al; do which $i > /dev/null || echo -e "${WARN}Для работы необходим $i ${END}"; which $i > /dev/null || ch=1; done
if (( $ch > 0 )); then echo -e "${WARN}Ой, отсутствуют необходимые для корректной работы приложения${END}"; exit; fi
#######################################################################################################################

if [[ $1 == '' ]]; then echo -e "${WARN}Введите идентификатор соединения (любое уникальное слово, должно быть одинаковое с двух сторон!) ${END} t
${GREEN}Для запуска в автоматическом режиме при включении компьютера можно прописать в /etc/rc.local строку nohup /<путь к файлу>/vpn8.sh  > /var/log/vpn8.log 2>/dev/hull & ${END}"; exit; fi
ABSOLUTE_FILENAME=`readlink -f "$0"`                                                    # полный путь до скрипта
DIR=`dirname "$ABSOLUTE_FILENAME"`                                                      # каталог в котором лежит скрипт
############################### Проверка наличия секретного ключа ##################################
key="$DIR/secret.key"
if [ ! -f "$key" ]; then
				echo -e "${WARN}Секретный ключ VPN-соединения не найден, для генерации ключа выполните: 
openvpn --genkey --secret secret.key Внимание: ключ используется для авторизации и должен 
быть одинаковым с двух сторон!!!${END}
 # ls -l secret.key
 -rw------- 1 root root 637 ноя 27 11:12 secret.key
 # chmod 600 secret.key";
				exit;
				fi
########################################################################################################################

ABSOLUTE_FILENAME=`readlink -f "$0"`                                                    # полный путь до скрипта
DIR=`dirname "$ABSOLUTE_FILENAME"`                                                      # каталог в котором лежит скрипт
name=$(uname -n | md5sum | awk '{print $1}')
vpn=$(echo $1 | md5sum | awk '{print $1}')
stun="stun.ekiga.net" 	# STUN сервер
username="Yandex"	# Логин от Яндекс.диска	
password="Password"	# Пароль от Яндекс.диска
localport=`shuf -i 20000-65000 -n 1`	# генерация локального порта

echo "$(date) Создаю папку на Яндекс.диске"
curl -X MKCOL --user "${username}:${password}" https://webdav.yandex.ru/vpn-$vpn
echo "$(date) Очищаю папку от всякого мусора"
for i in `curl --silent --user "$username:$password" -X PROPFIND -H "Depth: 1" https://webdav.yandex.ru/vpn-$vpn/ | sed 's/></n/g' | grep "d:displayname" | sed 's/d:displayname//g' | sed 's/>//g' | sed 's/<//' | sed 's////g' | grep -v $(date +%Y-%m-%d-%H-%M)`; do
	echo "$(date) Delete: $i"
	curl -X DELETE --user "${username}:${password}" https://webdav.yandex.ru/vpn-$vpn/$i
	done

until [ $c ];do

	until [[ $b ]]; do
		echo "$(date) Проверяю папку"
		date=`date +%Y-%m-%d-%H-%M`
		mydata=`curl --silent --user "${username}:${password}" -X PROPFIND -H "Depth: 1" https://webdav.yandex.ru/vpn-$vpn/ | sed 's/></>n</g' | grep $name | grep $date | grep "d:displayname"`
		if [[ -z $mydata ]]; 	then
						echo "$(date) Файл готовности создан"
					        echo "$date" > "/tmp/$date-$name-ready.txt"
					        curl -T "/tmp/$date-$name-ready.txt" --user "$username:$password" https://webdav.yandex.ru/vpn-$vpn/$date-$name-ready.txt
					else
						echo "$(date) Файл готовности уже существует - $date"
					fi
		remote=`curl --silent --user "${username}:${password}" -X PROPFIND -H "Depth: 1" https://webdav.yandex.ru/vpn-$vpn/ | sed 's/></>n</g' | grep -v $name | grep $date | grep "d:displayname"`
		if [[ -z $remote ]];	then
						echo -e "$(date) ${RED} Удаленный узел не готов ${END}"
						echo "$(date) Жду"
						sleep 20
					else
						echo -e "$(date) ${GREEN} Удаленный узел готов ${END}"
						b=1
						a=''
					fi
	done

	until [ $a ]; do
		echo "$(date) Подключение и получение данных от STUN сервера: $stun"
                mydata=`stun $stun -p $localport -v 2>&1 | grep MappedAddress | sort | uniq`
                echo -e "$(date) ${GREEN}Мои данные соединения: $mydata${END}"
                echo "$mydata" > "$DIR/mydata"
                echo "$(date) Загрузка данных на Яндекс.диск"
                curl -T "$DIR/mydata" --user "$username:$password" https://webdav.yandex.ru/vpn-$vpn/$name.txt
		echo "$(date) Получение файла данных удаленного узла"
		filename=$(curl --silent --user "${username}:${password}" -X PROPFIND -H "Depth: 1" https://webdav.yandex.ru/vpn-$vpn/ | sed 's/></n/g' | grep "d:displayname>" | grep "txt" | grep -v "$name" | grep -v "ready" | sed 's|.*d:displayname>||' | sed 's/</ /g' | awk '{print $1}')
		echo "$(date) Чтение файла данных удаленного узла: $filename"
		address=$(curl --silent --user "$username:$password" https://webdav.yandex.ru/vpn-$vpn/$filename | sort | uniq | head -n1 | sed 's/:/ /g')
		echo "$(date) Определение IP-адреса и порта"
		ip=$(echo "$address" | awk '{print $3}')
		port=$(echo "$address" | awk '{print $4}')
		if [[ -n "$ip" && -n "$port" ]]; then
			echo -e "$(date) ${GREEN} Соединение $ip $port ${END}"
       		 	openvpn --remote $ip --rport $port --lport $localport 
	       	 	    --proto udp --dev tap --float --auth-nocache --verb 3 --mute 20 
	       	 	    --ifconfig 10.45.54.2 255.255.255.252 
	       		    --secret "$DIR/secret.key" 
	       		    --auth SHA256 --cipher AES-256-CBC 
	        	    --ncp-disable --ping 10  --ping-exit 30 
	        	    --comp-lzo yes
			echo -e "$(date) ${WARN} Соединение разорвано${END}"
			a=1
			b=''
			else
			a=1
			b=''
			fi
	done
done

Για να λειτουργήσει το σενάριο χρειάζεστε:

  1. Αντιγράψτε στο πρόχειρο και επικολλήστε στο πρόγραμμα επεξεργασίας, για παράδειγμα:
    # nano vpn8.sh 
  2. καθορίστε το όνομα χρήστη και τον κωδικό πρόσβασης για το Yandex.disk.
  3. στο πεδίο "—ifconfig 10.45.54.(1 or 2) 255.255.255.252" καθορίστε την εσωτερική διεύθυνση IP της διεπαφής
  4. δημιουργώ μυστικό κλειδί με εντολή:
    # openvpn --genkey --secret secret.key 
  5. κάντε το σενάριο εκτελέσιμο:
    # chmod +x vpn8.sh
  6. τρέξτε το σενάριο:
    # ./vpn8.sh nZbVGBuX5dtturD

    όπου nZbVGBuX5dtturD είναι το αναγνωριστικό σύνδεσης που δημιουργήθηκε εδώ

Στον απομακρυσμένο κόμβο, κάντε τα πάντα το ίδιο εκτός από τη δημιουργία μυστικού κλειδιού και αναγνωριστικού σύνδεσης, πρέπει να είναι πανομοιότυπα.

Ενημερωμένη έκδοση (η ώρα πρέπει να συγχρονιστεί για σωστή λειτουργία):

cat vpn10.sh

#!/bin/bash
stuns="stun.sipnet.ru stun.ekiga.net"   		# Список STUN серверов через пробел
username=" Login "		# Логин от Яндекс.диска
password=" Password "   	# Пароль от Яндекс.диска
intip="10.23.22.1"		# IP-адрес внутреннего интерфейса
WARN='33[37;1;41m'
END='33[0m'
RED='33[0;31m'
GREEN='33[0;32m'
al="ip echo readlink dirname grep awk md5sum openssl sha256sum shuf curl sleep openvpn cat stun"
ch=0
for i in $al; do which $i > /dev/null || echo -e "${WARN}Для работы необходим $i ${END}"; which $i > /dev/null || ch=1; done
if (( $ch > 0 )); then echo -e "${WARN}Ой, отсутствуют необходимые для корректной работы приложения${END}"; exit; fi
if [[ $1 == '' ]];
then
echo -e "${WARN}Введите идентификатор соединения (любое уникальное слово, должно быть одинаковое с двух сторон!) ${END} t
${GREEN}Для запуска в автоматическом режиме при включении компьютера можно прописать в /etc/rc.local строку nohup /<путь к файлу>/vpn10.sh  > /var/log/vpn10.log 2>/dev/hull & ${END}"
exit
fi
ABSOLUTE_FILENAME=`readlink -f "$0"`                                                    # полный путь до скрипта
DIR=`dirname "$ABSOLUTE_FILENAME"`                                                      # каталог в котором лежит скрипт
key="$DIR/secret.key"
until [[ -n "$iftosrv" ]]
do
echo "$(date) Определяю сетевой интерфейс"; iftosrv=`ip route get 8.8.8.8 | head -n 1 | sed 's|.*dev ||' | awk '{print $1}'`
sleep 5
done
timedatectl
name=$(uname -n | md5sum | awk '{print $1}')
vpn=$(echo $1 | md5sum | awk '{print $1}')
echo "$(date) Создаю папку на Яндекс.диске"
curl -X MKCOL --user "${username}:${password}" https://webdav.yandex.ru/vpn-$vpn
echo "$(date) ID на диске: $vpn"
until [ $c ];do
echo "$(date) Очищаю папку от всякого мусора"
for i in `curl --silent --user "$username:$password" -X PROPFIND -H "Depth: 1" https://webdav.yandex.ru/vpn-$vpn/ | sed 's/></n/g' | grep "d:displayname" | sed 's/d:displayname//g' | sed 's/>//g' | sed 's/<//' | sed 's////g' | grep -v $(date +%Y-%m-%d-%H-%M)`
do
echo -e "$(date)${RED} Удаляю старый файл: $i${END}"
curl -X DELETE --user "${username}:${password}" https://webdav.yandex.ru/vpn-$vpn/$i
done
echo "$(date) ID на диске: $vpn"
openvpn --genkey --secret "$key"
passwd=`echo "$vpn-tt" | sha256sum | awk '{print $1}'`
openssl AES-256-CBC -e -in "$key" -out "$DIR/file.enc" -k "$passwd" -base64
curl -T "$DIR/file.enc" --user "$username:$password" https://webdav.yandex.ru/vpn-$vpn/key.enc
rm "$DIR"/file.enc
echo -e "$(date) ${GREEN}Фаза 1 - Получение готовности удаленного узла${END}"
go=3
localport=`shuf -i 20000-65000 -n 1`    # генерация локального порта
start=''
remote=''
timeout1=''
nextcheck=''
timestart=''
until [[ $b ]]
do
echo "$(date) Проверяю папку"
date=`date +%s`
timeout1=60
echo "$(date) Создание файла готовности $date"
echo "$date" > "/tmp/ready-$date-$name.txt"
curl -T "/tmp/ready-$date-$name.txt" --user "$username:$password" https://webdav.yandex.ru/vpn-$vpn/ready-$name.txt
readyfile=`curl --silent --user "${username}:${password}" -X PROPFIND -H "Depth: 1" https://webdav.yandex.ru/vpn-$vpn/ | sed 's/></>n</g' | grep -v $name | grep "ready" | grep "d:displayname" | sed 's/<d:displayname>//g' | sed 's/</d:displayname>//g'`
if [[ -z $readyfile ]]
then
echo -e "$(date) ${RED} Удаленный узел не готов ${END}"
echo "$(date) Жду 60 секунд"
sleep $timeout1
else
remote=$(curl --silent --user "$username:$password" https://webdav.yandex.ru/vpn-$vpn/$readyfile)
echo -e "$(date) ${GREEN} Удаленный узел готов ${END}"
start=`curl --silent --user "${username}:${password}" -X PROPFIND -H "Depth: 1" https://webdav.yandex.ru/vpn-$vpn/ | sed 's/></>n</g' | grep "start" | grep "d:displayname" | sed 's/-/ /g' | awk '{print $2}'`
if [[ -z $start ]]
then
let nextcheck=$timeout1-$date+$remote
let timestart=$date+$timeout1-$nextcheck
go=$nextcheck
echo "$timestart" > "/tmp/start-$date-$name.txt"
curl -T "/tmp/start-$date-$name.txt" --user "$username:$password" https://webdav.yandex.ru/vpn-$vpn/start-$date-$name.txt
else
echo "$(date) жду $go секунд"
sleep $go
b=1
a=''
fi
fi
done
echo -e "$(date) ${GREEN}Фаза 2 - Обмен данными и установка соединения${END}"
mydata=''
filename=''
address=''
myip=''
ip=''
port=''
ex=0
until [ $a ]; do
until [[ -n "$mydata" ]]; do
k=`echo "$stuns" | wc -w`
x=1
z=`shuf -i 1-$k -n 1`
for st in $stuns; do
if [[ $x == $z ]]; then
stun=$st;
fi;
(( x++ ));
done
echo "$(date) Подключение и получение данных от STUN сервера: $stun"
sleep 5 && for pid in $(ps xa | grep "stun "$stun" 1 -p "$localport" -v" | grep -v grep | awk '{print $1}'); do kill $pid; done &
mydata=`stun "$stun" 1 -p "$localport" -v 2>&1 | grep "MappedAddress" | sort | uniq`
done
echo -e "$(date) ${GREEN}Мои данные соединения: $mydata${END}"
echo "$(date) Загрузка данных на Яндекс.диск"
echo "$mydata" > "$DIR/mydata"
echo "IntIP $intip" >> "$DIR/mydata"
curl -T "$DIR/mydata" --user "$username:$password" https://webdav.yandex.ru/vpn-$vpn/$name-ipport.txt
rm "$DIR/mydata"
sleep 5
echo "$(date) Получение файла данных удаленного узла"
filename=$(curl --silent --user "${username}:${password}" -X PROPFIND -H "Depth: 1" https://webdav.yandex.ru/vpn-$vpn/ | sed 's/></n/g' | grep "d:displayname>" | grep "ipport" | grep -v "$name" |  sed 's|.*d:displayname>||' | sed 's/</ /g' | awk '{print $1}')
if [[ -n "$filename" ]]
then
echo "$(date) Чтение файла данных удаленного узла: $filename"
address=$(curl --silent --user "$username:$password" https://webdav.yandex.ru/vpn-$vpn/$filename | grep "MappedAddress" | head -n1 | sed 's/:/ /g')
intip2=$(curl --silent --user "$username:$password" https://webdav.yandex.ru/vpn-$vpn/$filename | grep "IntIP" | head -n1 | awk '{print $2}')
echo "$(date) Определение IP-адреса и порта: $address $sesid2 $tunid2"
ip=$(echo "$address" | awk '{print $3}')
port=$(echo "$address" | awk '{print $4}')
myip=`ip route get "$ip" | head -n 1 | sed 's|.*src ||' | awk '{print $1}'`
if [[ -n "$ip" && -n "$port" && -n "$myip" && -n "$localport" ]];
then
echo -e "$(date) ${GREEN} Соединение $ip $port ${END}"
echo -e  "`date` ${GREEN} $myip:$localport -> $ip:$port ${END}"
curl --silent --user "$username:$password" https://webdav.yandex.ru/vpn-$vpn/key.enc > "$DIR/secret.enc"
openssl AES-256-CBC -d -in "$DIR/secret.enc" -out "$key" -k "$passwd" -base64
chmod 600 "$key"
rm "$DIR/secret.enc"
openvpn --remote $ip --rport $port --lport $localport 
--proto udp --dev tun --float --auth-nocache --verb 3 --mute 20 
--ifconfig "$intip" "$intip2" 
--secret "$key" 
--auth SHA256 --cipher AES-256-CBC 
--ncp-disable --ping 10 --ping-exit 20 
--comp-lzo yes
a=1
b=''
fi
else
if (( $ex >= 5 ))
then
echo "$(date) Сброс"
a=1
b=''
fi
(( ex++ ))
sleep 5
fi
done
done

Για να λειτουργήσει το σενάριο χρειάζεστε:

  1. Αντιγράψτε στο πρόχειρο και επικολλήστε στο πρόγραμμα επεξεργασίας, για παράδειγμα:
    # nano vpn10.sh 
  2. υποδείξτε τη σύνδεση (2η γραμμή) και τον κωδικό πρόσβασης για το Yandex.disk (3η γραμμή).
  3. καθορίστε την εσωτερική διεύθυνση IP του τούνελ (4η γραμμή).
  4. κάντε το σενάριο εκτελέσιμο:
    # chmod +x vpn10.sh
  5. τρέξτε το σενάριο:
    # ./vpn10.sh nZbVGBuX5dtturD

    όπου nZbVGBuX5dtturD είναι το αναγνωριστικό σύνδεσης που δημιουργήθηκε εδώ

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

Για να εκτελέσω αυτόματα το σενάριο όταν είναι ενεργοποιημένο, χρησιμοποιώ την εντολή "nohup /<path to the script>/vpn10.sh nZbVGBuX5dtturD > /var/log/vpn10.log 2>/dev/null &" που περιέχεται στο αρχείο /etc/ rc.τοπικό

Συμπέρασμα

Το σενάριο λειτουργεί, δοκιμάστηκε στο Ubuntu (18.04, 19.10, 20.04) και στο Debian 9. Μπορείτε να χρησιμοποιήσετε οποιαδήποτε άλλη υπηρεσία ως πομπό, αλλά για εμπειρία χρησιμοποίησα το Yandex.disk.
Κατά τη διάρκεια των πειραμάτων, ανακαλύφθηκε ότι ορισμένοι τύποι παρόχων NAT δεν επιτρέπουν τη δημιουργία σύνδεσης. Κυρίως από παρόχους κινητής τηλεφωνίας όπου τα torrent είναι μπλοκαρισμένα.

Σκοπεύω να βελτιωθώ ως προς:

  • Αυτόματη δημιουργία του secret.key κάθε φορά που ξεκινάτε, κρυπτογραφείτε και αντιγράφετε στο Yandex.disk για μεταφορά σε απομακρυσμένο κόμβο (Λαμβάνοντας υπόψη την ενημερωμένη έκδοση)
  • Αυτόματη εκχώρηση διευθύνσεων IP διεπαφών
  • Κρυπτογράφηση δεδομένων πριν από τη μεταφόρτωση στο Yandex.disk
  • Βελτιστοποίηση κώδικα

Ας υπάρχει IPv6 σε κάθε σπίτι!

ΕΠΙΚΑΙΡΟΠΟΙΗΜΕΝΟ! Τα τελευταία αρχεία και το πακέτο DEB εδώ - yandex.disk

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο