aarant / pynat Goto Github PK
View Code? Open in Web Editor NEWDiscover external IP addresses and NAT topologies using STUN.
License: MIT License
Discover external IP addresses and NAT topologies using STUN.
License: MIT License
When I use pip install pynat
, I get an error because I don't have six
installed. It's not good for me to add pynat
in requirements.txt
. Can the developer please fix this issue?
pynat --source_ip <public IP>
I get the following error,
sock.bind((source_ip, source_port))
OSError: [Errno 49] Can't assign requested address
If i try with 0.0.0.0 which is the default then it works fine. I want to test this against another public ip.
I have fork your pynat project to github.com/nomnom-btc/pynat
pynat current supports both python 3.x and python 2.7 now. all changes exist in one file (pynat.py), please refer to https://github.com/nomnom-btc/pynat/blob/master/pynat.py for details.
Hi, thanks for reviving the old PySTUN! However I've found that the NAT detection is strange and gives results that are later not verifiable. So I would like to share my findings with you, to see if it's possible to improve PyNAT.
PyNAT detects my (consumer-grade, typical home router) NAT as Symmetric, but I don't think this is actually true. From my manual tests, the NAT seems to be Port-Restricted Cone NAT, i.e. ports allow inbound packets if they come from same IP:port than a previously outbound packet was sent, and local outbound ports are kept the same on the external side.
I feel the issue comes from using the STUN response's CHANGED-ADDRESS
field, which I didn't know about until I saw it in PyNAT code. Went ahead to have a look at STUN spec: RFC 8489 but it only says that attribute 0x0005 is "Reserved; was CHANGED-ADDRESS prior to [RFC5389]"...
In RFC 5389 they still refer to an even older version of the spec, mentioning that this attribute got removed:
Removed the usage of STUN for NAT type detection and binding
lifetime discovery. These techniques have proven overly brittle
due to wider variations in the types of NAT devices than described
in this document. Removed the RESPONSE-ADDRESS, CHANGED-ADDRESS,
CHANGE-REQUEST, SOURCE-ADDRESS, and REFLECTED-FROM attributes.
I added some logs in the PyNAT code and saw this:
$ pynat
stun_addr: ('stun.voipbuster.com', 3478)
ext_ip, ext_port: 1.2.3.4 54320 <--- External port = 54320
change_addr: ('77.72.169.213', 3479)
recv_ext_ip, recv_ext_port: 1.2.3.4 1053 <--- Mismatch, 54320 != 1053
Network type: Symmetric NAT
Internal address: 192.168.1.2:54320
External address: 1.2.3.4:54320
Where 1.2.3.4
is my public IP address. PySTUN performs a STUN request from internal port 54320, and that's the external port that comes in the response from voipbuster. However, the next request that is done with the change_addr claims a different external port 1053, which is why PyNAT classifies my NAT as Symmetric.
What seems strange to me is that this second port, 1053, is repeated in all tests, even though PyNAT varies the STUN server that is used for each test. If this actually was a Symmetric NAT, the external port should be changing for each different destination, shouldn't it?
Then I went ahead and did this same test on my own. For this I use 2 different cloud servers, I access them with SSH and use Netcat to perform hole-punching on my NAT and later check connectivity. This is the result:
On SERVER 1 (IP: 1.0.0.1): listen for incoming UDP on port 51000.
$ nc -vnul 51000
Listening on 0.0.0.0 51000
On SERVER 2 (IP: 2.0.0.2): listen for incoming UDP on port 52000.
$ nc -vnul 52000
Listening on 0.0.0.0 52000
On CLIENT (IP: 1.2.3.4): Send data from port 55000 to Server 1 and Server 2, i.e. hole-punch the NAT's port 55000.
$ echo "TO SERVER 1" | nc -vnu -p 55000 1.0.0.1 51000
Connected to 1.0.0.1:51000
$ echo "TO SERVER 2" | nc -vnu -p 55000 2.0.0.2 52000
Connected to 2.0.0.2:52000
Data appears on Server 1 and 2 output, confirming that it has arrived correctly:
Connection received from 1.2.3.4 55000
TO SERVER 1
Connection received from 1.2.3.4 55000
TO SERVER 2
On CLIENT: listen for incoming UDP on port 55000 which has been hole-punched in previous commands.
$ nc -vnul 55000
Listening on 0.0.0.0 55000
On SERVER 1: stop listening, and send data to Client.
(Ctrl+C)
$ echo "FROM SERVER 1" | nc -vnu -p 51000 1.2.3.4 55000
Connected to 1.2.3.4:55000
Data appears on Client output:
Connection received from 1.0.0.1 51000
FROM SERVER 1
... confirming that Server 1 can send data. This means there is connectivity to the Client through the port 55000 that was punched before.
On CLIENT: restart the listener (this is needed by Netcat).
(Ctrl+C)
$ nc -vnul 55000
Listening on 0.0.0.0 55000
On SERVER 2: stop listening, and send data to Client.
(Ctrl+C)
$ echo "FROM SERVER 2" | nc -vnu -p 52000 1.2.3.4 55000
Connected to 1.2.3.4:55000
Here is the interesting thing: data appears on Client output:
Connection received from 2.0.0.2 52000
FROM SERVER 2
... confirming that Server 2 can also send data to the same port, and also that when multiple, consecutive outbound connections are made to different servers, the external port is not randomly changed by the NAT.
In principle that reminds of the behavior of Full-Cone NAT, but in reality it is an (Address- and) Port-Restricted NAT. I know because the ports that get opened in the NAT, will only allow inbound packets from the same exact source IP and port. I tested changing the listening ports, or opening a port only for Server 1 and then trying to send data from Server 2, and it didn't work, which means it's not a Full-Cone NAT.
I believe the external port 1053 is maybe an unintended consequence of using an old and now deprecated STUN method to try and force different Address and Port on the STUN responses from the servers, but it could be causing bad detection of NAT types.
I wish I had more time to work on this and provide some code, but right now I only could get time to do this study and write this issue... but what do you think? Maybe it would be possible to use two different STUN servers for testing, like I did by hand in my tests? This would mean that CHANGED-ADDRESS is not needed any more.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.