Iniciando um servidor VPN atrás de um NAT do provedor.

Artigo sobre como consegui iniciar um servidor VPN por trás do NAT do provedor de Internet (sem um endereço IP público). Para deixar claro: a funcionalidade desta implementação depende diretamente do tipo de NAT utilizado pelo seu provedor, assim como pelo roteador.
Então, surgiu a necessidade de me conectar do meu smartphone Android ao meu computador em casa, ambos os dispositivos conectados à Internet através de NATs do provedor, além disso, o computador está conectado através de um roteador doméstico, que também estava NATando as conexões.
A configuração clássica com o uso de um VPS/VDS alugado com um IP público, assim como o aluguel de um IP público do provedor, não foi considerada por várias razões.
Considerando a experiência de artigos anteriores, e realizando alguns testes com STUNs e NATs de provedores. Decidi fazer um pequeno experimento, executando o comando no roteador doméstico que estava executando o firmware OpenWRT:

$ stun stun.sipnet.ru

obtive o resultado:

Versão do cliente STUN 0.97
Primário: Mapeamento Independente, Filtro Independente, porta aleatória, irá hairpin
O valor retornado é 0x000002

Tradução literal:
Mapeamento Independente — mapeamento independente
Filtro Independente — filtro independente
porta aleatória — porta aleatória
irá hairpin — irá hairpin
Executando um comando semelhante no meu PC, obtive:

Versão do cliente STUN 0.97
Primário: Mapeamento Independente, Filtro Dependente de Porta, porta aleatória, irá hairpin
O valor retornado é 0x000006

Filtro Dependente de Porta — filtro dependente de porta
A diferença nos resultados das saídas de comandos indicava que o roteador doméstico estava contribuindo no processo de tradução de pacotes da Internet, manifestando-se no fato de que, ao executar o comando no computador:

stun stun.sipnet.ru -p 11111 -v

eu obtive o resultado:

…
MappedAddress = XX.1XX.1X4.2XX:4398
…

nesse momento, uma sessão UDP era temporariamente aberta; se nesse momento um pedido UDP fosse enviado (por exemplo: netcat XX.1XX.1X4.2XX 4398 -u), o pedido chegaria ao roteador doméstico, como confirmou o TCPDump executado nele, mas o pedido não chegava ao computador — o IPtables, atuando como tradutor NAT no roteador, o descartava.
Lançando um servidor VPN atrás do NAT do provedor
Mas o fato de o pedido UDP passar pelo NAT do provedor dava esperanças de sucesso. Como o roteador está sob minha jurisdição, resolvi o problema redirecionando a porta UDP/11111 para o computador:

iptables -t nat -A PREROUTING -i eth1 -p udp -d 10.1XX.2XX.XXX --dport 11111 -j DNAT --to-destination 192.168.X.XXX

Dessa forma, tive a oportunidade de iniciar uma sessão UDP e receber solicitações da Internet de qualquer endereço IP. Nesse momento, iniciei o servidor OpenVPN (após configurá-lo previamente) escutando a porta UDP/11111, especifiquei no smartphone o endereço IP externo e a porta (XX.1XX.1X4.2XX:4398) e conectei com sucesso o smartphone ao computador. No entanto, nesta implementação surgiu um problema, era necessário de alguma forma manter a sessão UDP até o momento em que o cliente OpenVPN se conectasse ao servidor, e a opção de executar periodicamente o cliente STUN não me agradou - não queria sobrecarregar os servidores STUN à toa.
Também notei a anotação "irá hairpin — irá hairpin"< , esse modo

Hairpinning permite que um dispositivo em uma rede local atrás de NAT acesse outro dispositivo na mesma rede pelo endereço externo do roteador.

Lançando um servidor VPN atrás do NAT do provedor
Assim, resolvi o problema de manter a sessão UDP de forma simples - executei o cliente no mesmo computador que o servidor.
Isso funcionou assim:

  • executava o cliente STUN na porta local 11111
  • recebia uma resposta com o endereço IP externo e a porta XX.1XX.1X4.2XX:4398
  • enviava os dados com o endereço IP externo e a porta para um e-mail (qualquer outro serviço é possível), configurado no smartphone
  • executava o servidor OpenVPN no computador escutando a porta UDP/11111
  • executava o cliente OpenVPN no computador especificando XX.1XX.1X4.2XX:4398 para conexão
  • a qualquer momento, executava o cliente OpenVPN no smartphone especificando o endereço IP e a porta (no meu caso, o endereço IP não mudava) para conexão

Lançando um servidor VPN atrás do NAT do provedor
Dessa forma, consegui me conectar ao meu computador usando o smartphone. Esta implementação permite conectar qualquer cliente OpenVPN.

Prática

Será necessário:

# apt install openvpn stun-client sendemail

Escrevendo alguns scripts, alguns arquivos de configuração, gerando os certificados necessários (já que o cliente no smartphone funciona apenas com certificados), obtive uma implementação comum do servidor OpenVPN.

O script principal no computador

# cat vpn11.sh
#!/bin/bash
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
ABSOLUTE_FILENAME=`readlink -f "$0"`
DIR=`dirname "$ABSOLUTE_FILENAME"`
localport=11111
until [[ $a ]]; do
	address=`stun stun.sipnet.ru -v -p $localport 2>&1 | grep "MappedAddress" | sort | uniq | head -n 1 | sed 's/:/ /g' | awk '{print $3" "$4}'`
        ip=`echo "$address" | awk {'print $1'}`
        port=`echo "$address" | awk {'print $2'}`
	srv="openvpn --config $DIR/server.conf --port $localport --daemon"
	$srv
	echo "$(date) Сервер запущен с внешним адресом $ip:$port"
	$DIR/sendemail.sh "OpenVPN-Server" "$ip:$port"
	sleep 1
	openvpn --config $DIR/client.conf --remote $ip --port $port
	echo "$(date) Cоединение клиента с сервером разорвано"
	for i in `ps xa | grep "$srv" | grep -v grep | awk '{print $1}'`; do
		kill $i && echo "$(date) Завершен процесс сервера $i ($srv)"
		done
	echo "Жду 15 сек"
	sleep 15
	done

Script para enviar dados por e-mail:

# cat sendemail.sh 
#!/bin/bash
from="От кого"
pass="Пароль"
to="Кому"
theme="$1"
message="$2"
server="smtp.yandex.ru:587"
sendEmail -o tls=yes -f "$from" -t "$to" -s "$server" -xu "$from" -xp "$pass" -u "$theme" -m "$message"

Arquivo de configuração do servidor:

# cat server.conf
proto udp
dev tun
ca      /home/vpn11-srv/ca.crt
cert    /home/vpn11-srv/server.crt
key     /home/vpn11-srv/server.key
dh      /home/vpn11-srv/dh2048.pem
server 10.2.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
tls-server
tls-auth /home/vpn11-srv/ta.key 0
tls-timeout 60
auth    SHA256
cipher  AES-256-CBC
client-to-client
keepalive 10 30
comp-lzo
max-clients 10
user nobody
group nogroup
persist-key
persist-tun
log /var/log/vpn11-server.log
verb 3
mute 20

Arquivo de configuração do cliente:

# cat client.conf
cliente
dev tun
proto udp
ca      "/home/vpn11-srv/ca.crt"
cert    "/home/vpn11-srv/client1.crt"
key     "/home/vpn11-srv/client1.key"
tls-client
tls-auth "/home/vpn11-srv/ta.key" 1
auth SHA256
cipher AES-256-CBC
auth-nocache
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
log /var/log/vpn11-clent.log
verb 3
mute 20
ping 10
ping-exit 30

A geração de certificados foi realizada por este artigo.
Iniciando o script:

# ./vpn11.sh

Primeiro, tornando-o executável

# chmod +x vpn11.sh

Do lado do smartphone

Instalando o aplicativo OpenVPN para Android, copiando o arquivo de configuração, certificados e configurando-o, ficou assim:
No smartphone, verifico o e-mailLançando um servidor VPN atrás do NAT do provedor
Ajusto o número da porta nas configuraçõesLançando um servidor VPN atrás do NAT do provedor
Iniciei o cliente e conectei-meLançando um servidor VPN atrás do NAT do provedor

Durante a redação deste artigo, transferi a configuração do computador para o Raspberry Pi 3 e tentei executar tudo isso em um modem LTE, mas não funcionou! O resultado do comando

# stun stun.ekiga.net -p 11111

Versão do cliente STUN 0.97
Primário: Mapeamento Independente, Filtro Dependente de Porta, porta aleatória, irá hairpin
O valor retornado é 0x000006

valor Filtro Dependente da Porta não permitiu que o sistema iniciasse.
Mas o provedor doméstico não teve problemas para iniciar o sistema no Raspberry Pi 3.
Em conjunto com a câmera web, com o VLC para
criar um fluxo RTSP a partir da câmera web

$ cvlc v4l2:///dev/video0:chroma=h264 :input-slave=alsa://hw:1,0 --sout '#transcode{vcodec=x264,venc=x264{preset=ultrafast,profile=baseline,level=31},vb=2048,fps=12,scale=1,acodec=mpga,ab=128,channels=2,samplerate=44100,scodec=none}:rtp{sdp=rtsp://10.2.0.1:8554/}' --no-sout-all --sout-keep

e VLC no smartphone para visualização (fluxo rtsp://10.2.0.1:8554/), resultou em um bom sistema de vigilância remota; também é possível levantar Samba, roteamento de tráfego via VPN, controle remoto de computadores e muito mais...

Saída

Como demonstrou a prática, para organizar um servidor VPN, é possível fazê-lo sem um endereço IP externo pelo qual é necessário pagar, assim como por um VPS/VDS. Mas tudo depende do provedor. Claro, gostaria de obter mais informações sobre diferentes provedores e tipos de NAT utilizados, mas isso é apenas o começo...
Obrigado pela atenção!

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster