Direktang VPN tunnel sa pagitan ng mga computer sa pamamagitan ng provider NATs (nang walang VPS, gamit ang STUN server at Yandex.disk)

Karugtong Artikulo tungkol sa kung paano ko nagawang ayusin ang isang direktang VPN tunnel sa pagitan ng dalawang computer na matatagpuan sa likod ng mga provider ng NAT. Inilarawan ng nakaraang artikulo ang proseso ng pag-aayos ng isang koneksyon sa tulong ng isang third party - isang tagapamagitan (isang inuupahang VPS na kumikilos bilang isang bagay tulad ng isang STUN server at isang node data transmitter para sa koneksyon). Sa artikulong ito sasabihin ko sa iyo kung paano ako nakayanan nang walang VPS, ngunit nanatili ang mga tagapamagitan at sila ang STUN server at Yandex.Disk...
Direktang VPN tunnel sa pagitan ng mga computer sa pamamagitan ng provider NATs (nang walang VPS, gamit ang STUN server at Yandex.disk)

Pagpapakilala

Matapos basahin ang mga komento ng nakaraang post, napagtanto ko na ang pangunahing disbentaha ng pagpapatupad ay ang paggamit ng isang tagapamagitan - isang third party (VPS) na nagpapahiwatig ng kasalukuyang mga parameter ng node, kung saan at kung paano kumonekta. Isinasaalang-alang ang mga rekomendasyon para gamitin itong STUN (na kung saan ay marami) upang matukoy ang kasalukuyang mga parameter ng koneksyon. Una sa lahat, nagpasya akong gumamit ng TCPDump upang tingnan ang mga nilalaman ng mga packet kapag ang STUN server ay nagtatrabaho sa mga kliyente at nakatanggap ng ganap na hindi nababasang nilalaman. Nag-googling sa protocol na nadatnan ko artikulong naglalarawan sa protocol. Napagtanto ko na hindi ko maaaring ipatupad ang isang kahilingan sa STUN server sa aking sarili at ilagay ang ideya sa isang "malayong kahon".

ВСория

Kamakailan ay kinailangan kong mag-install ng STUN server sa Debian mula sa package

# apt install stun-server

at sa mga dependency nakita ko ang stun-client package, ngunit kahit papaano ay hindi ko ito pinansin. Ngunit kalaunan ay naalala ko ang tungkol sa stun-client package at nagpasyang malaman kung paano ito gumagana, pagkatapos mag-googling at maghanap sa Yandex nakuha ko:

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

Bilang tugon natanggap ko:

bersyon ng STUN client 0.97
Binuksan ang port 21234 na may fd 3
Binuksan ang port 21235 na may fd 4
Encoding stun message:
Encoding ChangeRequest: 0

Magpapadala na ng msg ni len 28 sa 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 4

Magpapadala na ng msg ni len 28 sa 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2

Magpapadala na ng msg ni len 28 sa 216.93.246.18:3478
Nakatanggap ng stun message: 92 bytes
MappedAddress = <My IP>:2885
SourceAddress = 216.93.246.18:3478
ChangedAddress = 216.93.246.17:3479
Hindi kilalang katangian: 32800
ServerName = Vovida.org 0.98-CPC
Nakatanggap ng mensahe ng uri 257 id=1
Encoding stun message:
Encoding ChangeRequest: 0

Magpapadala na ng msg ni len 28 sa 216.93.246.17:3478
Encoding stun message:
Encoding ChangeRequest: 4

Magpapadala na ng msg ni len 28 sa 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2

Magpapadala na ng msg ni len 28 sa 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 0

Malapit nang magpadala ng msg ni len 28 sa <My IP>:2885
Nakatanggap ng stun message: 28 bytes
ChangeRequest = 0
Nakatanggap ng mensahe ng uri 1 id=11
Encoding stun message:
Encoding ChangeRequest: 0

Magpapadala na ng msg ni len 28 sa 216.93.246.17:3478
Encoding stun message:
Encoding ChangeRequest: 4

Magpapadala na ng msg ni len 28 sa 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2

Magpapadala na ng msg ni len 28 sa 216.93.246.18:3478
Nakatanggap ng stun message: 92 bytes
MappedAddress = <My IP>:2885
SourceAddress = 216.93.246.17:3479
ChangedAddress = 216.93.246.18:3478
Hindi kilalang katangian: 32800
ServerName = Vovida.org 0.98-CPC
Nakatanggap ng mensahe ng uri 257 id=10
Encoding stun message:
Encoding ChangeRequest: 4

Magpapadala na ng msg ni len 28 sa 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2

Magpapadala na ng msg ni len 28 sa 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 4

Magpapadala na ng msg ni len 28 sa 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2

Magpapadala na ng msg ni len 28 sa 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 4

Magpapadala na ng msg ni len 28 sa 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2

Magpapadala na ng msg ni len 28 sa 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 4

Magpapadala na ng msg ni len 28 sa 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2

Magpapadala na ng msg ni len 28 sa 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 4

Magpapadala na ng msg ni len 28 sa 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2

Magpapadala na ng msg ni len 28 sa 216.93.246.18:3478
pagsubok I = 1
pagsubok II = 0
pagsubok III = 0
pagsubok I(2) = 1
ay nat = 1
nakamapang IP pareho = 1
hairpin = 1
preserve port = 0
Pangunahin: Independent Mapping, Port Dependent Filter, random port, will hairpin
Ang return value ay 0x000006

String na may halaga

MappedAddress = <My IP>:2885

basta ang kailangan mo! Ipinakita nito ang kasalukuyang katayuan para sa koneksyon sa lokal na UDP port 21234. Ngunit ito ay kalahati lamang ng labanan, ang tanong ay lumitaw kung paano ilipat ang data na ito sa malayong host at ayusin ang isang koneksyon sa VPN. Gamit ang mail protocol, o baka Telegram?! Maraming mga pagpipilian at nagpasya akong gamitin ang Yandex.disk, dahil napunta ako artikulo tungkol sa pagtatrabaho ng Curl sa pamamagitan ng WebDav gamit ang Yandex.disk. Matapos isipin ang tungkol sa pagpapatupad, naisip ko ang sumusunod na pamamaraan:

  1. Ipahiwatig na ang mga node ay handa nang magtatag ng isang koneksyon sa pamamagitan ng pagkakaroon ng isang partikular na file na may timestamp sa Yandex.disk;
  2. Kung handa na ang mga node, pagkatapos ay tumanggap ng kasalukuyang mga parameter mula sa server ng STUN;
  3. Mag-upload ng mga kasalukuyang setting sa Yandex.disk;
  4. Suriin ang presensya at basahin ang mga parameter ng isang malayong node mula sa isang file sa Yandex.disk;
  5. Pagtatatag ng koneksyon sa isang malayuang host gamit ang OpenVPN.

Pagsasanay

Matapos mag-isip ng kaunti, isinasaalang-alang ang karanasan ng huling artikulo, mabilis akong nagsulat ng isang script. Kakailanganin namin ang:

# apt install openvpn stun-client curl 

Ang script mismo:

orihinal na bersyon

# 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

Para gumana ang script kailangan mo:

  1. Kopyahin sa clipboard at i-paste sa editor, halimbawa:
    # nano vpn8.sh 
  2. tukuyin ang username at password para sa Yandex.disk.
  3. sa field na "β€”ifconfig 10.45.54.(1 o 2) 255.255.255.252" tukuyin ang panloob na IP address ng interface
  4. lumikha lihim.susi sa pamamagitan ng utos:
    # openvpn --genkey --secret secret.key 
  5. gawing executable ang script:
    # chmod +x vpn8.sh
  6. patakbuhin ang script:
    # ./vpn8.sh nZbVGBuX5dtturD

    kung saan ang nZbVGBuX5dtturD ay ang nabuong connection ID dito

Sa remote node, gawin ang lahat ng pareho maliban sa pagbuo ng secret.key at connection ID, dapat magkapareho ang mga ito.

Na-update na bersyon (dapat i-synchronize ang oras para sa tamang operasyon):

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

Para gumana ang script kailangan mo:

  1. Kopyahin sa clipboard at i-paste sa editor, halimbawa:
    # nano vpn10.sh 
  2. ipahiwatig ang login (2nd line) at password para sa Yandex.disk (3rd line).
  3. tukuyin ang panloob na IP address ng tunnel (ika-4 na linya).
  4. gawing executable ang script:
    # chmod +x vpn10.sh
  5. patakbuhin ang script:
    # ./vpn10.sh nZbVGBuX5dtturD

    kung saan ang nZbVGBuX5dtturD ay ang nabuong connection ID dito

Sa remote node, gawin ang parehong, tukuyin ang kaukulang panloob na IP address ng tunnel at connection ID.

Para i-autorun ang script kapag naka-on, ginagamit ko ang command na β€œnohup /<path to the script>/vpn10.sh nZbVGBuX5dtturD > /var/log/vpn10.log 2>/dev/null &” na nasa file /etc/ rc.lokal

Konklusyon

Gumagana ang script, nasubok sa Ubuntu (18.04, 19.10, 20.04) at Debian 9. Maaari mong gamitin ang anumang iba pang serbisyo bilang transmitter, ngunit para sa karanasan ginamit ko ang Yandex.disk.
Sa panahon ng mga eksperimento, natuklasan na ang ilang mga uri ng NAT provider ay hindi pinapayagan ang pagtatatag ng isang koneksyon. Pangunahin mula sa mga mobile operator kung saan naka-block ang mga torrents.

Plano kong pagbutihin sa mga tuntunin ng:

  • Awtomatikong pagbuo ng secret.key sa tuwing magsisimula ka, i-encrypt at kopyahin sa Yandex.disk para ilipat sa isang malayuang node (Isinasaalang-alang sa na-update na bersyon)
  • Awtomatikong pagtatalaga ng mga IP address ng mga interface
  • Pag-encrypt ng data bago i-upload sa Yandex.disk
  • Pag-optimize ng code

Hayaang magkaroon ng IPv6 sa bawat tahanan!

Nai-update! Pinakabagong mga file at DEB package dito - yandex.disk

Pinagmulan: www.habr.com

Magdagdag ng komento