Starting a VPN server behind a provider's NAT

An article about how I managed to run a VPN server behind the NAT of a home provider (without a white IP address). Let me tell you straight away: the performance of this implementation directly depends on the type of NAT used by your provider, as well as the router.
So, I had a need to connect from my Android smartphone to my home computer, both devices are connected to the Internet through provider NATs, plus the computer is connected through a home router, which also NATs connections.
The classic scheme using a leased VPS / VDS with a white IP address, as well as renting a white IP address from the provider, was not considered for several reasons.
Taking into account experience of past articles, having spent several experiments with STUNs and NATs of providers. I decided on a small experiment by executing the command on a home router running OpenWRT firmware:

$ stun stun.sipnet.ru

got the result:

STUN client version 0.97
Primary: Independent Mapping, Independent Filter, random port, will hairpin
return value is 0x000002

Literal translation:
Independent Mapping - independent display
Independent Filter - independent filter
random port - random port
will hairpin - there will be a hairpin
After running a similar command on my PC, I got:

STUN client version 0.97
Primary: Independent Mapping, Port Dependent Filter, random port, will hairpin
return value is 0x000006

Port Dependent Filter - port dependent filter
The difference in the results of the output of the commands indicated that the home router made "its contribution" to the process of broadcasting packets from the Internet, this was manifested in the fact that when the command was executed on the computer:

stun stun.sipnet.ru -p 11111 -v

i got the result:

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

at that moment, a UDP session was opened for a while, if at that moment a UDP request was sent (for example: netcat XX.1XX.1X4.2XX 4398 -u), then the request came to the home router, which was confirmed by TCPDump running on it, but the request did not reach the computer - IPtables as a NAT translator on the router dropped it.
Starting a VPN server behind a provider's NAT
But the very fact of passing a UDP request through the provider's NAT gave hope for success. Since the router is in my jurisdiction, I solved the problem by redirecting the UDP / 11111 port to the computer:

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

Thus, I got the opportunity to initiate a UDP session and receive requests from the Internet from any IP address. At this moment, I launched OpenVPN-server (after configuring it) listening to UDP/11111 port, indicated the external IP address and port (XX.1XX.1X4.2XX:4398) on the smartphone and successfully connected from the smartphone to the computer. But in this implementation, a problem arose, it was necessary to somehow maintain the UDP session until the OpenVPN client connected to the server, I didn’t like the option of periodically launching the STUN client - I didn’t want to load STUN servers in vain.
Also drew attention to the entry "will hairpin - there will be a hairpin", this mode

Hairpinning allows one machine on a local network behind NAT to access another machine on the same network at the router's external address.

Starting a VPN server behind a provider's NAT
As a result, I solved the problem of maintaining a UDP session simply - I launched the client on the same computer with the server.
It worked like this:

  • launched STUN client with local port 11111
  • received response with external IP address and port XX.1XX.1X4.2XX:4398
  • sent data with an external IP address and port to the mail (any other service is possible) configured on the smartphone
  • launched an OpenVPN server on a computer listening on UDP/11111 port
  • launched an OpenVPN client on a computer specifying XX.1XX.1X4.2XX:4398 to connect
  • at any time launched the OpenVPN client on the smartphone, specifying the IP address and port (in my case, the IP address did not change) to connect

Starting a VPN server behind a provider's NAT
Thus, I got the opportunity to connect to my computer from a smartphone. This implementation allows you to connect any OpenVPN client.

Practice

You will need:

# apt install openvpn stun-client sendemail

After writing a couple of scripts, a couple of configuration files, generating the necessary certificates (since the client on the smartphone works only with certificates), we got the usual implementation of the OpenVPN server.

Main script on computer

# 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

Email sending script:

# 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"

Server config file:

# 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

Client config file:

# cat client.conf

client
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

Certificates were generated according to this article.
Running the script:

# ./vpn11.sh

Making it executable first

# chmod +x vpn11.sh

On the smartphone side

By installing the application Open VPN for Android, copying the configuration file, certificates and configuring it, it turned out like this:
Checking email on my smartphoneStarting a VPN server behind a provider's NAT
I edit the port number in the settingsStarting a VPN server behind a provider's NAT
I start the client and connectStarting a VPN server behind a provider's NAT

In the process of writing the article, I transferred the configuration from the computer to the Raspberry Pi 3 and tried to run the whole thing on an LTE modem, but it didn’t work! command result

# stun stun.ekiga.net -p 11111

STUN client version 0.97
Primary: Independent Mapping, Port Dependent Filter, random port, will hairpin
return value is 0x000006

value Port Dependent Filter prevented the system from starting.
But the home provider let the system run on the Raspberry Pi 3 without any problems.
In conjunction with a webcam, with VLC for
creating an RTSP stream from a webcam

$ 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

and VLC on a smartphone for viewing (stream rtsp://10.2.0.1:8554/), it turned out not a bad video surveillance system at a distance, you can also set up Samba, route traffic through VPN, remotely control a computer and much more ...

Hack and predictor Aviator

As practice has shown, to organize a VPN server, you can do without an external IP address for which you need to pay, as well as for a rented VPS / VDS. But it all depends on the provider. Of course, I wanted to get more information about the various providers and types of NATs used, but this is only the beginning ...
Thank you for attention!

Source: habr.com

Add a comment