Túnel VPN directo entre ordenadores a través de NAT dos provedores (sen VPS, usando o servidor STUN e Yandex.disk)

Extensión Artigo sobre como conseguín organizar un túnel VPN directo entre dous ordenadores situados detrás dos provedores de NAT. O artigo anterior describiu o proceso de organización dunha conexión coa axuda dun terceiro: un intermediario (un VPS alugado que actúa como un servidor STUN e un transmisor de datos de nodos para a conexión). Neste artigo vouvos contar como me fixen sen VPS, pero os intermediarios quedaron e foron o servidor STUN e Yandex.Disk...
Túnel VPN directo entre ordenadores a través de NAT do provedor (sen VPS, usando o servidor STUN e Yandex.disk)

Introdución

Despois de ler os comentarios da publicación anterior, decateime de que o principal inconveniente da implementación era o uso dun intermediario: un terceiro (VPS) que indicaba os parámetros actuais do nodo, onde e como conectarse. Considerando as recomendacións para usar este STUN (dos que hai moitos) para determinar os parámetros de conexión actuais. Primeiro de todo, decidín usar TCPDump para ver o contido dos paquetes cando o servidor STUN traballaba con clientes e recibía contido completamente ilexible. Buscando en Google o protocolo que atopei artigo que describe o protocolo. Decateime de que non podía implementar unha solicitude ao servidor STUN pola miña conta e coloque a idea nunha "caixa distante".

Teoría

Recentemente tiven que instalar o servidor STUN en Debian dende o paquete

# apt install stun-server

e nas dependencias vin o paquete stun-client, pero dalgún xeito non lle fixen caso. Pero máis tarde lembreime do paquete stun-client e decidín descubrir como funciona, despois de buscar en Google e buscar en Yandex conseguín:

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

Como resposta recibín:

Versión do cliente STUN 0.97
Porto aberto 21234 con fd 3
Porto aberto 21235 con fd 4
Codificación da mensaxe de aturdimento:
Solicitude de cambio de codificación: 0

A piques de enviar un mensaxe de len 28 ao 216.93.246.18:3478
Codificación da mensaxe de aturdimento:
Solicitude de cambio de codificación: 4

A piques de enviar un mensaxe de len 28 ao 216.93.246.18:3478
Codificación da mensaxe de aturdimento:
Solicitude de cambio de codificación: 2

A piques de enviar un mensaxe de len 28 ao 216.93.246.18:3478
Mensaxe de aturdimento recibida: 92 bytes
MappedAddress = <A miña IP>:2885
Enderezo fonte = 216.93.246.18:3478
Enderezo modificado = 216.93.246.17:3479
Atributo descoñecido: 32800
ServerName = Vovida.org 0.98-CPC
Mensaxe recibida do tipo 257 id=1
Codificación da mensaxe de aturdimento:
Solicitude de cambio de codificación: 0

A piques de enviar un mensaxe de len 28 ao 216.93.246.17:3478
Codificación da mensaxe de aturdimento:
Solicitude de cambio de codificación: 4

A piques de enviar un mensaxe de len 28 ao 216.93.246.18:3478
Codificación da mensaxe de aturdimento:
Solicitude de cambio de codificación: 2

A piques de enviar un mensaxe de len 28 ao 216.93.246.18:3478
Codificación da mensaxe de aturdimento:
Solicitude de cambio de codificación: 0

A piques de enviar un mensaxe de len 28 a <My IP>:2885
Mensaxe de aturdimento recibida: 28 bytes
Solicitude de cambio = 0
Mensaxe recibida do tipo 1 id=11
Codificación da mensaxe de aturdimento:
Solicitude de cambio de codificación: 0

A piques de enviar un mensaxe de len 28 ao 216.93.246.17:3478
Codificación da mensaxe de aturdimento:
Solicitude de cambio de codificación: 4

A piques de enviar un mensaxe de len 28 ao 216.93.246.18:3478
Codificación da mensaxe de aturdimento:
Solicitude de cambio de codificación: 2

A piques de enviar un mensaxe de len 28 ao 216.93.246.18:3478
Mensaxe de aturdimento recibida: 92 bytes
MappedAddress = <A miña IP>:2885
Enderezo fonte = 216.93.246.17:3479
Enderezo modificado = 216.93.246.18:3478
Atributo descoñecido: 32800
ServerName = Vovida.org 0.98-CPC
Mensaxe recibida do tipo 257 id=10
Codificación da mensaxe de aturdimento:
Solicitude de cambio de codificación: 4

A piques de enviar un mensaxe de len 28 ao 216.93.246.18:3478
Codificación da mensaxe de aturdimento:
Solicitude de cambio de codificación: 2

A piques de enviar un mensaxe de len 28 ao 216.93.246.18:3478
Codificación da mensaxe de aturdimento:
Solicitude de cambio de codificación: 4

A piques de enviar un mensaxe de len 28 ao 216.93.246.18:3478
Codificación da mensaxe de aturdimento:
Solicitude de cambio de codificación: 2

A piques de enviar un mensaxe de len 28 ao 216.93.246.18:3478
Codificación da mensaxe de aturdimento:
Solicitude de cambio de codificación: 4

A piques de enviar un mensaxe de len 28 ao 216.93.246.18:3478
Codificación da mensaxe de aturdimento:
Solicitude de cambio de codificación: 2

A piques de enviar un mensaxe de len 28 ao 216.93.246.18:3478
Codificación da mensaxe de aturdimento:
Solicitude de cambio de codificación: 4

A piques de enviar un mensaxe de len 28 ao 216.93.246.18:3478
Codificación da mensaxe de aturdimento:
Solicitude de cambio de codificación: 2

A piques de enviar un mensaxe de len 28 ao 216.93.246.18:3478
Codificación da mensaxe de aturdimento:
Solicitude de cambio de codificación: 4

A piques de enviar un mensaxe de len 28 ao 216.93.246.18:3478
Codificación da mensaxe de aturdimento:
Solicitude de cambio de codificación: 2

A piques de enviar un mensaxe de len 28 ao 216.93.246.18:3478
proba I = 1
proba II = 0
proba III = 0
proba I(2) = 1
é nat = 1
IP asignada igual = 1
horquilla = 1
porto do preservador = 0
Principal: Mapeo independente, filtro dependente do porto, porto aleatorio, forquilla
O valor de retorno é 0x000006

Cadea con valor

MappedAddress = <A miña IP>:2885

xusto o que necesitas! Mostrou o estado actual da conexión no porto UDP local 21234. Pero esta é só a metade da batalla, xurdiu a pregunta de como transferir estes datos ao host remoto e organizar unha conexión VPN. Usando o protocolo de correo, ou quizais Telegram?! Hai moitas opcións e decidín usar Yandex.disk, xa que me atopei artigo sobre o traballo de Curl a través de WebDav con Yandex.disk. Despois de pensar na implementación, pensei co seguinte esquema:

  1. Sinalar que os nós están preparados para establecer unha conexión coa presenza dun ficheiro específico cunha marca de tempo en Yandex.disk;
  2. Se os nodos están listos, recibe os parámetros actuais do servidor STUN;
  3. Cargue a configuración actual a Yandex.disk;
  4. Comprobe a presenza e lectura dos parámetros dun nodo remoto desde un ficheiro en Yandex.disk;
  5. Establecendo unha conexión cun host remoto usando OpenVPN.

Práctica

Despois de pensalo un pouco, tendo en conta a experiencia do último artigo, axiña escribín un guión. Necesitaremos:

# apt install openvpn stun-client curl 

O guión en si:

versión orixinal

# 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 o script funcione necesitas:

  1. Copia no portapapeis e pega no editor, por exemplo:
    # nano vpn8.sh 
  2. especifique o nome de usuario e o contrasinal para Yandex.disk.
  3. no campo "—ifconfig 10.45.54.(1 ou 2) 255.255.255.252" especifique o enderezo IP interno da interface
  4. crear segredo.chave comando:
    # openvpn --genkey --secret secret.key 
  5. facer o script executable:
    # chmod +x vpn8.sh
  6. executa o script:
    # ./vpn8.sh nZbVGBuX5dtturD

    onde nZbVGBuX5dtturD é o ID de conexión xerado aquí

No nodo remoto, fai todo o mesmo, excepto para xerar secret.key e ID de conexión, deben ser idénticos.

Versión actualizada (o tempo debe estar sincronizado para que funcione correctamente):

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 o script funcione necesitas:

  1. Copia no portapapeis e pega no editor, por exemplo:
    # nano vpn10.sh 
  2. indica o inicio de sesión (2ª liña) e o contrasinal para Yandex.disk (3ª liña).
  3. especifique o enderezo IP interno do túnel (4ª liña).
  4. facer o script executable:
    # chmod +x vpn10.sh
  5. executa o script:
    # ./vpn10.sh nZbVGBuX5dtturD

    onde nZbVGBuX5dtturD é o ID de conexión xerado aquí

No nodo remoto, faga o mesmo, especifique o enderezo IP interno correspondente do túnel e o ID de conexión.

Para executar automaticamente o script cando esteo activado, uso o comando "nohup /<ruta ao script>/vpn10.sh nZbVGBuX5dtturD > /var/log/vpn10.log 2>/dev/null &" contido no ficheiro /etc/ rc.local

Conclusión

O script funciona, probado en Ubuntu (18.04, 19.10, 20.04) e Debian 9. Podes usar calquera outro servizo como transmisor, pero por experiencia usei Yandex.disk.
Durante os experimentos, descubriuse que algúns tipos de provedores de NAT non permiten establecer unha conexión. Principalmente de operadores móbiles onde os torrents están bloqueados.

Penso mellorar en canto a:

  • Xeración automática de secret.key cada vez que inicia, cifra e copia a Yandex.disk para transferir a un nodo remoto (tendo en conta na versión actualizada)
  • Asignación automática de enderezos IP das interfaces
  • Cifrando datos antes de cargalos en Yandex.disk
  • Optimización de código

Que haxa IPv6 en cada casa!

Actualizado Últimos ficheiros e paquete DEB aquí - yandex.disco

Fonte: www.habr.com

Engadir un comentario