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.ruobtive 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 -veu 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.

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.XXXDessa 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.

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

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 sendemailEscrevendo 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
doneScript 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.confproto 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 20Arquivo de configuração do cliente:
# cat client.confcliente
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 30A geração de certificados foi realizada por este artigo.
Iniciando o script:
# ./vpn11.shPrimeiro, tornando-o executável
# chmod +x vpn11.shDo 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-mail
Ajusto o número da porta nas configurações
Iniciei o cliente e conectei-me
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 11111Versã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-keepe 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
