ProHoster > Blog > Administration > Direct VPN tunnel between computers through NATs of providers (without VPS, using STUN server and Yandex.disk)
Direct VPN tunnel between computers through NATs of providers (without VPS, using STUN server and Yandex.disk)
Extension Articles about how I managed to organize a direct VPN tunnel between two computers located behind ISP NATs. The last article described the process of organizing a connection with the help of a third party - an intermediary (a rented VPS acting as something like a STUN server and a node data transmitter for connection). In this article I will tell you how I managed without VPS, but the intermediaries remained and they were the STUN server and Yandex.Disk ...
Introduction
After reading the comments of the last post, I realized that the main drawback of the implementation was the use of an intermediary - a third party (VPS) that indicated the current parameters of the node, where and how to connect. Given the recommendations to use a real STUN (of which there are a lot) to determine the current connection settings. First of all, I decided to use TCPDump to look at the contents of the packets when the STUN server was working with clients and received completely unreadable contents. Googling the protocol came across article describing the protocol. I realized that I canβt implement a request to the STUN server on my own and put the idea away.
Theory
I recently had to install a STUN server on Debian from the package
# apt install stun-server
and in the dependencies I saw the stun-client package, but somehow did not attach any importance to this. But later I remembered the stun-client package and decided to figure out how it works, by googling and using Yandex I got:
STUN client version 0.97
Opened port 21234 with fd 3
Opened port 21235 with fd 4
Encoding stun message:
Encoding ChangeRequest: 0
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 4
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2
About to send msg of len 28 to 216.93.246.18:3478
Received stun message: 92 bytes
MappedAddress = <My IP>:2885
SourceAddress = 216.93.246.18:3478
ChangedAddress = 216.93.246.17:3479
Unknown attribute: 32800
ServerName=Vovida.org 0.98-CPC
Received message of type 257 id=1
Encoding stun message:
Encoding ChangeRequest: 0
About to send msg of len 28 to 216.93.246.17:3478
Encoding stun message:
Encoding ChangeRequest: 4
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 0
About to send msg of len 28 to <My IP>:2885
Received stun message: 28 bytes
ChangeRequest = 0
Received message of type 1 id=11
Encoding stun message:
Encoding ChangeRequest: 0
About to send msg of len 28 to 216.93.246.17:3478
Encoding stun message:
Encoding ChangeRequest: 4
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2
About to send msg of len 28 to 216.93.246.18:3478
Received stun message: 92 bytes
MappedAddress = <My IP>:2885
SourceAddress = 216.93.246.17:3479
ChangedAddress = 216.93.246.18:3478
Unknown attribute: 32800
ServerName=Vovida.org 0.98-CPC
Received message of type 257 id=10
Encoding stun message:
Encoding ChangeRequest: 4
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 4
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 4
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 4
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 4
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2
About to send msg of len 28 to 216.93.246.18:3478
test I = 1
test II = 0
test III = 0
test I(2) = 1
is nat = 1
mapped IP same = 1
hair pin = 1
preserver port = 0
Primary: Independent Mapping, Port Dependent Filter, random port, will hairpin
return value is 0x000006
String with value
MappedAddress = <My IP>:2885
just what you need! It displayed the current state for the connection on the local UDP port 21234. But this is only half the battle, the question arose of how to transfer this data to a remote host and establish a VPN connection. Using the mail protocol, or maybe Telegram?! There are many options and I decided to use Yandex.disk, as I came across an article about working Curl via WebDav with Yandex.disk. After thinking about the implementation, I came up with this scheme:
Signal that nodes are ready to establish a connection by the presence of a specific file with a timestamp on Yandex.disk;
If the nodes are ready, then get the current parameters from the STUN server;
Upload current settings to Yandex.disk;
Check for the presence and read the parameters of a remote host from a file on Yandex.disk;
Establishing a connection to a remote host using OpenVPN.
Practice
After a little thought, taking into account the experience of the last article, I wrote a script in haste. We will need:
Copy to clipboard and paste into editor, for example:
# nano vpn10.sh
specify the login (2nd line) and password from Yandex.disk (3rd line).
specify the internal IP address of the tunnel (4th line).
make the script executable:
# chmod +x vpn10.sh
run script:
# ./vpn10.sh nZbVGBuX5dtturD
where nZbVGBuX5dtturD is the connection-id generated here
On the remote host, do the same, specify the appropriate internal tunnel IP address and connection ID.
To autorun the script on startup, I use the command "nohup /<path to the script>/vpn10.sh nZbVGBuX5dtturD > /var/log/vpn10.log 2>/dev/null &" contained in the file /etc/rc.local
Conclusion
The script works, tested on Ubuntu (18.04, 19.10, 20.04) and Debian 9. You can use any other service as a transmitter, but for the experience I used Yandex.disk.
During the experiments, it was found that some types of NAT providers do not allow you to establish a connection. Mostly from mobile operators, where torrents are blocked.
I plan to improve in terms of:
Automatic generation of secret.key every time you start, encrypting and copying to Yandex.disk for transmission to a remote host (Considered in the updated version)
Automatic assignment of interface IP addresses
Data encryption before uploading to Yandex.disk
Code optimization
Let there be IPv6 in every home!
Updated! Latest files and DEB package here β yandex.disk