Túnel VPN directo entre computadoras a través de NAT de proveedores (sin VPS, usando un servidor STUN y Yandex.Disk)

Continuación artículo sobre cómo logré organizar un túnel directo VPN-entre dos computadoras que se encuentran detrás de NATs de los proveedores. En el artículo anterior se describió el proceso de establecer una conexión mediante un tercero: un intermediario (un VPS alquilado VPS que cumplía el rol de algo así como un servidor STUN y transmisor de datos de nodos para la conexión). En este artículo, explicaré cómo me las arreglé sin VPS, pero los intermediarios permanecieron y fueron el servidor STUN y Yandex.Disk...
Túnel VPN directo entre computadoras a través de los NAT de los proveedores (sin VPS, utilizando un servidor STUN y Yandex.disk)

Introducción

Tras leer los comentarios de la publicación anterior, entendí que la principal desventaja de la implementación fue el uso de un intermediario: un tercero (VPS) que indicaba los parámetros actuales del nodo, a dónde y cómo conectar. Teniendo en cuenta las recomendaciones de utilizar un verdadero STUN (de los cuales hay muchos) para determinar los parámetros actuales de conexión. Primero decidí ver con TCPDump el contenido de los paquetes mientras trabajaba el servidor STUN con los clientes y obtuve un contenido completamente ilegible. Buscando en Google el protocolo, encontré un artículo con la descripción del protocolo. Entendí que no podía implementar la solicitud al servidor STUN por mi cuenta y guardé la idea en un "cajón lejano".

Teoría

Recientemente, tuve que instalar un servidor STUN en Debian desde el paquete

# apt install stun-server

y en las dependencias vi el paquete stun-client, pero no le presté mucha atención. Sin embargo, más tarde recordé el paquete stun-client y decidí investigar cómo funciona, buscando en Google y Yandex, obtuve:

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

Recibí en respuesta:

Versión del cliente STUN 0.97
Puerto 21234 abierto con fd 3
Puerto 21235 abierto con fd 4
Codificando mensaje STUN:
Codificando ChangeRequest: 0

A punto de enviar el msg de longitud 28 a 216.93.246.18:3478
Codificando mensaje STUN:
Codificando ChangeRequest: 4

A punto de enviar el msg de longitud 28 a 216.93.246.18:3478
Codificando mensaje STUN:
Codificando ChangeRequest: 2

A punto de enviar el msg de longitud 28 a 216.93.246.18:3478
Mensaje STUN recibido: 92 bytes
MappedAddress = :2885
SourceAddress = 216.93.246.18:3478
ChangedAddress = 216.93.246.17:3479
Atributo desconocido: 32800
ServerName = Vovida.org 0.98-CPC
Mensaje recibido de tipo 257 id=1
Codificando mensaje STUN:
Codificando ChangeRequest: 0

A punto de enviar el msg de longitud 28 a 216.93.246.17:3478
Codificando mensaje STUN:
Codificando ChangeRequest: 4

A punto de enviar el msg de longitud 28 a 216.93.246.18:3478
Codificando mensaje STUN:
Codificando ChangeRequest: 2

A punto de enviar el msg de longitud 28 a 216.93.246.18:3478
Codificando mensaje STUN:
Codificando ChangeRequest: 0

A punto de enviar el msg de longitud 28 a :2885
Mensaje STUN recibido: 28 bytes
ChangeRequest = 0
Mensaje recibido de tipo 1 id=11
Codificando mensaje STUN:
Codificando ChangeRequest: 0

A punto de enviar el msg de longitud 28 a 216.93.246.17:3478
Codificando mensaje STUN:
Codificando ChangeRequest: 4

A punto de enviar el msg de longitud 28 a 216.93.246.18:3478
Codificando mensaje STUN:
Codificando ChangeRequest: 2

A punto de enviar el msg de longitud 28 a 216.93.246.18:3478
Mensaje STUN recibido: 92 bytes
MappedAddress = :2885
SourceAddress = 216.93.246.17:3479
ChangedAddress = 216.93.246.18:3478
Atributo desconocido: 32800
ServerName = Vovida.org 0.98-CPC
Mensaje recibido de tipo 257 id=10
Codificando mensaje STUN:
Codificando ChangeRequest: 4

A punto de enviar el msg de longitud 28 a 216.93.246.18:3478
Codificando mensaje STUN:
Codificando ChangeRequest: 2

A punto de enviar el msg de longitud 28 a 216.93.246.18:3478
Codificando mensaje STUN:
Codificando ChangeRequest: 4

A punto de enviar el msg de longitud 28 a 216.93.246.18:3478
Codificando mensaje STUN:
Codificando ChangeRequest: 2

A punto de enviar el msg de longitud 28 a 216.93.246.18:3478
Codificando mensaje STUN:
Codificando ChangeRequest: 4

A punto de enviar el msg de longitud 28 a 216.93.246.18:3478
Codificando mensaje STUN:
Codificando ChangeRequest: 2

A punto de enviar el msg de longitud 28 a 216.93.246.18:3478
Codificando mensaje STUN:
Codificando ChangeRequest: 4

A punto de enviar el msg de longitud 28 a 216.93.246.18:3478
Codificando mensaje STUN:
Codificando ChangeRequest: 2

A punto de enviar el msg de longitud 28 a 216.93.246.18:3478
Codificando mensaje STUN:
Codificando ChangeRequest: 4

A punto de enviar el msg de longitud 28 a 216.93.246.18:3478
Codificando mensaje STUN:
Codificando ChangeRequest: 2

A punto de enviar el msg de longitud 28 a 216.93.246.18:3478
test I = 1
test II = 0
test III = 0
test I(2) = 1
is nat = 1
mapped IP same = 1
hairpin = 1
preserver port = 0
Primario: Mapeo Independiente, Filtro Dependiente del Puerto, puerto aleatorio, se hará hairpin
El valor de retorno es 0x000006

La cadena con el valor

MappedAddress = :2885

es justo lo que necesitaba. Mostraba el estado actual para la conexión en el puerto UDP local 21234. Pero eso es solo la mitad del asunto, surgió la cuestión de cómo transmitir estos datos a un nodo remoto y organizar una conexión VPN. ¿Utilizar el protocolo postal, o tal vez Telegram? Hay muchas opciones y decidí usar Yandex.Disk, ya que me había aparecido. Artículo sobre el funcionamiento de Curl a través de WebDav con Yandex.Disk. Tras pensar en la implementación, llegué a este esquema:

  1. Notificar la disposición de los nodos para establecer conexión mediante la presencia de un archivo con una marca de tiempo en Yandex.Disk;
  2. Si los nodos están listos, obtener los parámetros actuales del servidor STUN;
  3. Cargar los parámetros actuales en Yandex.Disk;
  4. Verificar la existencia y leer los parámetros del nodo remoto desde un archivo en Yandex.Disk;
  5. Establecer la conexión con el nodo remoto a través de OpenVPN.

 

Práctica

Después de reflexionar un poco, y teniendo en cuenta la experiencia del artículo anterior, escribí un script de forma rápida. Necesitaremos:

# apt install openvpn stun-client curl 

El script en sí:

Opción inicial

# 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 que el script funcione, es necesario:

  1. Copiar al portapapeles y pegar en un editor, por ejemplo:
    # nano vpn8.sh 
  2. indicar el nombre de usuario y la contraseña de Yandex.Disk.
  3. en el campo «—ifconfig 10.45.54.(1 o 2) 255.255.255.252» indicar la dirección IP interna de la interfaz
  4. crear secret.key con el comando:
    # openvpn --genkey --secret secret.key 
  5. hacer que el script sea ejecutable:
    # chmod +x vpn8.sh
  6. ejecutar el script:
    # ./vpn8.sh nZbVGBuX5dtturD

    donde nZbVGBuX5dtturD — ID de la conexión generada aquí

En el nodo remoto, hacer lo mismo, excepto la generación de secret.key y el ID de la conexión, que deben ser idénticos.

Versión actualizada (para un funcionamiento correcto, el tiempo debe estar sincronizado):

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 que el script funcione, es necesario:

  1. Copiar al portapapeles y pegar en un editor, por ejemplo:
    # nano vpn10.sh 
  2. indicar el nombre de usuario (línea 2) y la contraseña de Yandex.Disk (línea 3).
  3. indicar la dirección IP interna del túnel (línea 4).
  4. hacer que el script sea ejecutable:
    # chmod +x vpn10.sh
  5. ejecutar el script:
    # ./vpn10.sh nZbVGBuX5dtturD

    donde nZbVGBuX5dtturD — ID de la conexión generada aquí

En el nodo remoto, hacer lo mismo, indicando la dirección interna correspondiente Dirección IP del túnel y el ID de la conexión.

Para el autoarranque del script al encender, uso el comando «nohup //vpn10.sh nZbVGBuX5dtturD > /var/log/vpn10.log 2>/dev/null &» contenido en el archivo /etc/rc.local

Conclusión

El script funciona, probado en Ubuntu (18.04, 19.10, 20.04) y Debian 9. Como transmisor, se puede usar cualquier otro servicio, pero para la experiencia usé Yandex.Disk.
Durante los experimentos, se descubrió que algunos tipos de NAT de los proveedores no permiten establecer una conexión. Esto ocurre principalmente con los operadores de telefonía móvil, donde se bloquean los torrents.

Planeo mejorar en los siguientes aspectos:

  • Generación automática de secret.key cada vez que se inicia, cifrado y carga en Yandex.Disk para su transmisión al nodo remoto (tenido en cuenta en la versión actualizada)
  • Asignación automática de direcciones IP a las interfaces
  • Cifrado de datos antes de cargar en Yandex.Disk
  • Optimización del código

¡Que haya IPv6 en cada hogar!

¡Actualizado! Últimos archivos y paquete DEB aquí — yandex.disk

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster