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

Extensión Artículo sobre cómo logré organizar un túnel VPN directo entre dos computadoras ubicadas detrás de proveedores NAT. El artículo anterior describió el proceso de organización de una conexión con la ayuda de un tercero: un intermediario (un VPS alquilado que actúa como algo así como un servidor STUN y un nodo transmisor de datos para la conexión). En este artículo te contaré cómo me las arreglé sin VPS, pero los intermediarios quedaron y eran el servidor STUN y Yandex.Disk...
Túnel VPN directo entre computadoras a través de NAT del proveedor (sin VPS, usando el servidor STUN y Yandex.disk)

introducción

Después de leer los comentarios de la publicación anterior, me di cuenta de que el principal inconveniente de la implementación era el uso de un intermediario, un tercero (VPS), que indicaba los parámetros actuales del nodo, dónde y cómo conectarse. Teniendo en cuenta las recomendaciones para utilizar este STUN (de los cuales hay muchos) para determinar los parámetros de conexión actuales. En primer lugar, decidí usar TCPDump para ver el contenido de los paquetes cuando el servidor STUN estaba trabajando con clientes y recibía contenido completamente ilegible. Googleando el protocolo me encontré artículo que describe el protocolo. Me di cuenta de que no podía implementar una solicitud al servidor STUN por mi cuenta y puse la idea en un "cuadro distante".

Теория

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

# apt install stun-server

y en las dependencias vi el paquete stun-client, pero de alguna manera no le presté atención. Pero luego me acordé del paquete stun-client y decidí descubrir cómo funciona, después de buscar en Google y buscar en Yandex obtuve:

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

En respuesta recibí:

Cliente STUN versión 0.97
Puerto abierto 21234 con fd 3
Puerto abierto 21235 con fd 4
Codificación del mensaje de aturdimiento:
Solicitud de cambio de codificación: 0

A punto de enviar mensaje de len 28 al 216.93.246.18:3478
Codificación del mensaje de aturdimiento:
Solicitud de cambio de codificación: 4

A punto de enviar mensaje de len 28 al 216.93.246.18:3478
Codificación del mensaje de aturdimiento:
Solicitud de cambio de codificación: 2

A punto de enviar mensaje de len 28 al 216.93.246.18:3478
Mensaje de aturdimiento recibido: 92 bytes
Dirección asignada = <Mi IP>:2885
Dirección de origen = 216.93.246.18:3478
Dirección modificada = 216.93.246.17:3479
Atributo desconocido: 32800
Nombre del servidor = Vovida.org 0.98-CPC
Mensaje recibido de tipo 257 id=1
Codificación del mensaje de aturdimiento:
Solicitud de cambio de codificación: 0

A punto de enviar mensaje de len 28 al 216.93.246.17:3478
Codificación del mensaje de aturdimiento:
Solicitud de cambio de codificación: 4

A punto de enviar mensaje de len 28 al 216.93.246.18:3478
Codificación del mensaje de aturdimiento:
Solicitud de cambio de codificación: 2

A punto de enviar mensaje de len 28 al 216.93.246.18:3478
Codificación del mensaje de aturdimiento:
Solicitud de cambio de codificación: 0

A punto de enviar mensaje de len 28 a <Mi IP>:2885
Mensaje de aturdimiento recibido: 28 bytes
Solicitud de cambio = 0
Mensaje recibido de tipo 1 id=11
Codificación del mensaje de aturdimiento:
Solicitud de cambio de codificación: 0

A punto de enviar mensaje de len 28 al 216.93.246.17:3478
Codificación del mensaje de aturdimiento:
Solicitud de cambio de codificación: 4

A punto de enviar mensaje de len 28 al 216.93.246.18:3478
Codificación del mensaje de aturdimiento:
Solicitud de cambio de codificación: 2

A punto de enviar mensaje de len 28 al 216.93.246.18:3478
Mensaje de aturdimiento recibido: 92 bytes
Dirección asignada = <Mi IP>:2885
Dirección de origen = 216.93.246.17:3479
Dirección modificada = 216.93.246.18:3478
Atributo desconocido: 32800
Nombre del servidor = Vovida.org 0.98-CPC
Mensaje recibido de tipo 257 id=10
Codificación del mensaje de aturdimiento:
Solicitud de cambio de codificación: 4

A punto de enviar mensaje de len 28 al 216.93.246.18:3478
Codificación del mensaje de aturdimiento:
Solicitud de cambio de codificación: 2

A punto de enviar mensaje de len 28 al 216.93.246.18:3478
Codificación del mensaje de aturdimiento:
Solicitud de cambio de codificación: 4

A punto de enviar mensaje de len 28 al 216.93.246.18:3478
Codificación del mensaje de aturdimiento:
Solicitud de cambio de codificación: 2

A punto de enviar mensaje de len 28 al 216.93.246.18:3478
Codificación del mensaje de aturdimiento:
Solicitud de cambio de codificación: 4

A punto de enviar mensaje de len 28 al 216.93.246.18:3478
Codificación del mensaje de aturdimiento:
Solicitud de cambio de codificación: 2

A punto de enviar mensaje de len 28 al 216.93.246.18:3478
Codificación del mensaje de aturdimiento:
Solicitud de cambio de codificación: 4

A punto de enviar mensaje de len 28 al 216.93.246.18:3478
Codificación del mensaje de aturdimiento:
Solicitud de cambio de codificación: 2

A punto de enviar mensaje de len 28 al 216.93.246.18:3478
Codificación del mensaje de aturdimiento:
Solicitud de cambio de codificación: 4

A punto de enviar mensaje de len 28 al 216.93.246.18:3478
Codificación del mensaje de aturdimiento:
Solicitud de cambio de codificación: 2

A punto de enviar mensaje de len 28 al 216.93.246.18:3478
prueba yo = 1
prueba II = 0
prueba III = 0
prueba I(2) = 1
es nat = 1
IP asignada igual = 1
horquilla = 1
puerto preservador = 0
Primario: mapeo independiente, filtro dependiente del puerto, puerto aleatorio, horquilla
El valor de retorno es 0x000006

Cadena con valor

Dirección asignada = <Mi IP>:2885

justo lo que necesitas! Mostraba el estado actual de la conexión en el puerto UDP local 21234. Pero esto es sólo la mitad de la batalla, surgió la pregunta de cómo transferir estos datos al host remoto y organizar una conexión VPN. ¿Usando el protocolo de correo, o quizás Telegram? Hay muchas opciones y decidí usar Yandex.disk, ya que encontré artículo sobre cómo trabajar Curl a través de WebDav con Yandex.disk. Después de pensar en la implementación, se me ocurrió el siguiente esquema:

  1. Señalar que los nodos están listos para establecer una conexión mediante la presencia de un archivo específico con una marca de tiempo en Yandex.disk;
  2. Si los nodos están listos, reciba los parámetros actuales del servidor STUN;
  3. Cargue la configuración actual en Yandex.disk;
  4. Verifique la presencia y lea los parámetros de un nodo remoto desde un archivo en Yandex.disk;
  5. Establecer una conexión con un host remoto mediante OpenVPN.

Práctica

Después de pensar un poco, teniendo en cuenta la experiencia del último artículo, rápidamente escribí un guión. Necesitaremos:

# apt install openvpn stun-client curl 

El guión en sí:

Versió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 necesitas:

  1. Copie al portapapeles y péguelo en el editor, por ejemplo:
    # nano vpn8.sh 
  2. especifique 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" especifique la dirección IP interna de la interfaz
  4. crear llave secreta dominio:
    # openvpn --genkey --secret secret.key 
  5. hacer que el script sea ejecutable:
    # chmod +x vpn8.sh
  6. ejecuta el script:
    # ./vpn8.sh nZbVGBuX5dtturD

    donde nZbVGBuX5dtturD es el ID de conexión generado aquí

En el nodo remoto, haga todo igual excepto generar la clave secreta y el ID de conexión, deben ser idénticos.

Versión actualizada (la hora debe estar sincronizada para su correcto funcionamiento):

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 necesitas:

  1. Copie al portapapeles y péguelo en el editor, por ejemplo:
    # nano vpn10.sh 
  2. indique el nombre de usuario (segunda línea) y la contraseña de Yandex.disk (tercera línea).
  3. especifique la dirección IP interna del túnel (cuarta línea).
  4. hacer que el script sea ejecutable:
    # chmod +x vpn10.sh
  5. ejecuta el script:
    # ./vpn10.sh nZbVGBuX5dtturD

    donde nZbVGBuX5dtturD es el ID de conexión generado aquí

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

Para ejecutar automáticamente el script cuando está encendido, uso el comando “nohup /<ruta al script>/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. Puede utilizar cualquier otro servicio como transmisor, pero por experiencia utilicé Yandex.disk.
Durante los experimentos, se descubrió que algunos tipos de proveedores NAT no permiten establecer una conexión. Principalmente de operadores móviles donde los torrents están bloqueados.

Planeo mejorar en términos de:

  • Generación automática de clave secreta cada vez que inicia, cifra y copia a Yandex.disk para transferirla a un nodo remoto (teniendo en cuenta en la versión actualizada)
  • Asignación automática de direcciones IP de interfaces
  • Cifrar datos antes de cargarlos en Yandex.disk
  • Optimización de código

¡Que haya IPv6 en todos los hogares!

¡Actualizado! Archivos más recientes y paquete DEB aquí - yandex.disco

Fuente: habr.com

Añadir un comentario