I would like to understand how udp hole punching works when two hosts each behind the port restricted cone NAT establish connection.
As I understood, it happens in several stages and involves three hosts.
Host A and host B are behind the port restricted cone NAT.
Host C is a server that can receive packets from the hosts A and B.
A sends a packet to C.
C receives packet from A and determines A's external address:port pair
B sends a packet to C.
C receives packet from B and determines B's external address:port pair
C sends the external address:port of B to A
C sends the external address:port of A to B
A sends packet_1 to B's external address
B sends packet_2 to A's external address
But I can't do it。it's the window,Who can tell me why?
in the golang
Only
net.ListenUDP() 's UDPConn can use the method WriteToUDP()
net.DialUDP 's UDPConn can't //
Sorry my English is very poor。
I think maybe nobody can read this。
囧TZ
Related
If server A receives a UDP packet, can it forward it to server B and have server B directly respond to the end client without going back through server A since UDP is connectionless?
My gut feeling is no, unless both server A and server B have the same IP address (anycast maybe?)
But if the client is built to also be a UDP server, it could work in theory since the (logical) response from server B would just look like a new request. But then this really doesn't work in practice because of firewalls and NAT, for the same reason it's hard to host a game server from behind your firewall, router, and ISP.
If server A receives a UDP packet, can it forward it to server B and have server B directly respond to the end client without going back through server A since UDP is connectionless?
Yes, it can. However, there are a few caveats:
NAT devices, which most client are behind of. There are several types of NAT devices. A full-cone NAT will accept the redirected packet just fine, but an address-restricted NAT would require the packet to return from the same address it was sent to (hence, your anycast idea would work, as well as simply having server B spoof the IP of server A). A port restricted or symmetric NAT would also require the same source port (i.e. server B has to send the response from the same port server A received it from).
Other types of network middleboxes, such as firewalls might block the returning packet
Application - will the client application accept a response from a different IP address and port?
I know about STUN, TURN and ICE. Suppose 2 users u1, u2, are behind two seperate NATs respectively. If the NAT mapping behavior is address independent and filtering behavior is port restricted NAT than How can I create a direct connection between two peers using client sockets. If any two peers who have not established connected prior to each other and if there is not mapping in NAT can two peers connect to each other if in case they know each others external ip address and port to be chose by NAT(generally same as local port)
Problem
I'm trying to develop a communication system where:
A, B are machines under NAT, A is the server B is the client
S is the STUN server
S is running on a machine reachable on the Internet
The flow is as follows:
A hits S with an opcode saying he's the server
S registers A as server
B hits S with an opcode saying he's the client
S sends to A B's external infos (IP, PORT)
S sends to B A's external infos (IP, PORT)
A starts sending B an opcode saying he's the server every 500ms
and meanwhile listens for packets saying he's got a client
B starts sending A an opcode saying he's the client every 500ms
and meanwhile listen for packets saying he's got the server
Trouble
Here's where the troubles start, the STUN server does its job, since both ends receive correct infos about the other.
But then I do never receive the other end's message, so both ends keep listening without receiving the handshake opcode nor anything else.
NAT's Behaviour
I did examine this NAT's behaviour and seems it does like this
A is at 192.168.X.X, on port 4444
connects to the outside exposing N.N.N.N:4444
so the port number is kept as long as it's free, gets a new (random ?) one if not available.
Tests
The tests I run have seen both ends (A, B) hosted on the same machine, both bound to the machine's internal IP, tried to bind to 127.0.0.1, 0.0.0.0, nothing changed.
If while they're listening for handshakes I echo something with nc to localhost, it is received and displayed (as an unrecognised message) without any problem. The connection routed via the NAT doesn't wotk tough, every packet is discarded.
Also tried with A hosted on the machine, B on an Android phone under mobile data, with a simple app written ad-hoc. Still locks waiting for something, like the nodejs tests.
Update:
Another thing I tried to do is to open an hole with nc
On two different machines under the same NAT I ran:
echo "GREET UNKOWN PEER" | nc -u <NAT IP> 4567 -p 4568
echo "GREET UNKOWN PEER" | nc -u <NAT IP> 4568 -p 4567
Different times for each machine. From my understanding this should punch an hole in the NAT with the first packets discarded and the subsequent forwarded. But nothing happened, no end got the message.
I've also tried:
from local machine
echo "GREET UNKOWN PEER" | nc -u <PUBLIC IP> 4567 -p 4568
from public machine
echo "GREET UNKOWN PEER" | nc -u <NAT IP> 4568 -p 4567
this one works, the local machine under NAT contacts the public one and after the first discarded packet is able to receive and send on the assigned port. I wonder why this doesn't work on two machines under the same NAT (???)
Code
I didn't show any code because I think there is some kind logic flaw in this, however here's the github project for that.
index.js contains the STUN server, the tests folder contains the test cases: test.js starts the stun server, PeerClientTest.js and PeerServerTest.js are mockups of the client and server.
Run node tests/test.js to start the server on a public machine (change IPs in config.js and tests/config.js)
then node tests/PeerServerTest.js to start the server ("A") and node tests/PeerClientTest.js to start the client ("B"). Both will recognize each other via STUN, then listen for the other end's handshake opcode while sending their own handshake opcode. This never happens so they just keep sending/listening forever.
Node is not required, so if there are better solutions in other languages just tell, will be appreciated.
B's NAT is filtering A's packets and is not letting them through. NAT filters unknown packets sent to it. Your server A is sending packet to client B. But client B previously never sent a packet through NAT to A. So to B's NAT A's packets are unknown and being discarded.
You need to punch a hole in B's NAT for the NAT to allow the incoming packets. Send a packet from B to A NAT's IP:Port. After that when you send a packet from A to B, B's NAT won't discard A's packet.
This won't work if A and B's NAT has a combination like Symmetric and Symmetric/PRC NAT. In this case you will have to use a TURN relay server.
Let's say host A want to send a package to 10.3.3.3, 10.3.3.3 is host B in the same subnet with A. But A thinks B is in the other net, will A try to use arp to get the mac address of B?
Will A set MAC to the route's MAC and send the package to the router directly? What will the router do if it received the package, it will send it to B directly?
Contrarily, if A think B is in the same net and actually, B is not, will A find B finally? A might send an arp but no one would response. Will A try to send the package to router?
The routing is entirely based on the destination address and the routing table (which will vary depending on the configuration of your subnet).
Lets suppose that,
Host A is 10.3.4.4 and is configured with netmask 255.255.255.0 and a router of 10.3.4.1
Host B is 10.3.3.3 and is configured with netmask 255.255.255.0.
In this case the routing table for host A will look something like,
Dest Gateway Mask
0.0.0.0 10.3.4.1 0.0.0.0
10.3.4.0 0.0.0.0 255.255.255.0
Starting at the bottom, host A will attempt to find which route to use. If host A tries to contact 10.3.4.x, it will match the first route, and instead of using a gateway it will send an ARP request "who has 10.3.4.x?" on the subnet broadcast address (10.3.4.255).
If host A tries to contact host B, it won't match the first routing rule, and will default to sending the packet to the gateway (10.3.4.1 in this example).
So no, A won't try to use ARP to get the MAC of host B if it isn't configured that host B is in the same subnet. If the router is configured with routing rules to route between subnets, it will deliver the packet, otherwise it will just get dropped.
Contrarily, if A think B is in the same net and actually, B is not,
will A find B finally? A might send an arp but no one would response.
Will A try to send the package to router?
No. The ARP request will get sent to the subnet broadcast address. If B isn't on that subnet and ignores the ARP request, A won't send the packet to the router, because where it sends the packet is just based on the destination IP address, there's no changing of where it's routed based on if the packet got delivered.
Just curious about a particular scenario of NAT. Let's suppose we have 4 computers sharing a global IP address under the NAT. I understand that the NAT box keeps an internal record to know which computer to forward requests to. But let's say on computer #2 I'm trying to download a file. And let's say on computer #1, #3, and #4, I'm just browsing the web normally. When the browser initiates a TCP connection to get that file, how does it know which computer to give it to? I mean like, each of the four computers is using port 80 to browse the web right? How does the NAT's record distinguish which "port 80" belongs to which computer?
Each unique TCP connection on the internet is made up of four numbers - {source IP, source port, destination IP, destination port}.
A NAT gateway (GW) translates this to {GW public IP, GW-mapped port, destination IP, destination port} so the outside routers know to return packets to this particular gateway. It also keeps a mapping of these mapped ports back to source IP and port number, along the lines of {GW-mapped port -> {source IP, source port}}, which allows it to figure out what internal machine to send the response packets to.
The concept of "port 80 for http" does not work like these. When a computer browse the web, only the server uses port 80, while the client will use a random port number. The server replies with a destination port, provided by the client, attached. Port 80 is just for knocking the web server's door.
What the NAT does do is translating all those 4 computers outward packets such that their source ports does not duplicate. When the NAT receives a packet, it will check if the attached destination port can be translated and translate it to the LAN if possible.