I'm trying to implement NAT hole punching with boost::asio. By my understanding, NAT hole punch works like this (UDP/TCP):
Client A binds to a port and connects to Server S, and Client B does the same.
When S receives both request and matched, it sends the ip and port of A to B, and B to A.
A and B receives each other's ip and port, and now they send a message to each other from the same port and form a connection (because they are expecting a reply?)
So in boost::asio, I was able to achieve step 1-2, but however because both the client is not port-forwarded, if I attempt to connect from one client to the other, it just give me error like "client actively refuse connection" or "No response from client" (surprisingly the 2 clients have different error even tho they are using the same function).
And it seems like I can't run any asio::async_write without a successful async_connect or asio::tcp::socket::connect. And of course, both of these connect function gives me error when the destination port is not forwarded.
So how can I implement NAT hole punching in this situation, am I missing something in boost::asio? Any help is appreciated! Thank you.
Based on the "client actively refuse connection" error I assume you're trying a TCP connection. There is fundamental difference in how UDP and TCP hole punching works.
3. A and B receives each other's ip and port, and now they send a message to each other from the same port and form a connection (because they are expecting a reply?)
This is NOT how TCP hole punching works. Since TCP is point-to-point, in step 3 you have to predict the next incoming port of either A or B, and A or B need to try to establish a new connection using the predicted port of the other side. Obviously there are many different NAT implementations, and it is not always possible to reliably predict the port allocation, especially in case of carrier-grade NAT. Refer to TCP hole punching for further details. As an alternative to TCP hole punching, have a look into UPnP to add a port forwarding.
I'll start by saying that currently my server identifies based on sender IP, that is the IP of the client.
Now I am programming a game server (just for practice) and this got me thinking how do I uniquely identify a client if they are on the same IP. (Two players open a connection on the same machine / same network so the outward IP is the same).
I've searched for an answer both on google and here and gamedev.net but am unable to find what I am looking for, likely because I do not know the correct terms to query for.
Any guidance on this would be appreciated, especially in regards to efficiency and best practice.
Thanks.
There is no "connection" term in all stuff related to UDP, but it is common that an application that initiates a UDP socket maintains the same source port over the time, so you could identify it by source IP-port.
There is some stuff related to maintain communication between a client inside a NAT router (in NAT-UDP the client is the first host that send a UDP datagram to another host and trigger a new connection tracking entry) and a server.
This "connection tracking" is only for allow traffic from outside to inside, making a "temporal" relationship (with a timeout), that probably will not be used anymore (only once) sometimes.
If the server doesn't use the same destination port in outcoming datagram as source port in incoming one, the router won't send the datagram to the host inside NAT.
Best regards.
Is it possible to redirect an opened TCP connection to a third device?
For example I have two clients which are both connected to a central server. Both initiated the communication. They cannot accept any connections from outside the internet because the router's firewall is blocking them.
What if they want to connect to each other: is it possible to redirect the two connections with the server to become one peer-to-peer connection between the clients? (I have a feeling that this is not possible) My program allows that both devices can work as a TCP server, just firewalls are blocking them.
Currently I am using two solutions to communicate between the two clients. One is using UPnP port mappings, the other that messages sent to server are repeated and transmitted to the clients.
Is there any other solution? I am especially interested in methods which are using C++, Qt and Linux.
You cannot redirect already opened TCP connections to another device, because in this case the endpoints of the connection would need to change - but the endpoint (ip+port) is an essential part of the connection. So you could only transfer the data you received at the server from one connection to the other and back, or you could try to make the two parties connect directly to each other from start with TCP hole punching like mentioned in a comment already. But this will only work for simple NAT setups.
Simple port forwarding at the server will not work for already established connections, because you would have to rewrite not only sender and receiver of all packets (e.g. NAT) but also rewrite the sequence numbers etc so they match the other established connection. So you would need to do the forwarding in user space or inside the kernel at the connection level and not the packet level with techniques like socket splicing.
I have a C++ application which accepts TCP connections and then reads the traffic sent to it. It has worked very well until I moved it to a new machine. It seems like winsock never accepts the inbound tcp connection. In my code it never returns from the select statement. I can see using netstat/tcpview that the application is listening on port 14005.
I can connect to this port if I just telnet in locally. However, when someone tries to connect in via an outside IP address the TCP 3 way handshake never finishes. I can see the inbound SYN packet in wireshark. It is going to the correct port, 14005. However my system never sends the SYN-ACK back. This is just something that winsock is suppose to handle right? The machine does have multiple NIC cards, but I'm binding with INADDR_ANY so this shouldn't matter. Is there some way I can dig deeper to see why this handshake never takes place?
per ways to dig deeper: nothing more than wireshark / tshark (which you already use, however if you want to play with packets, look at scapy)
what happens if you reduce headache - only use one nic and network, put the client on the same network (ie, no router or smart switch between), (last resort) disable unneeded network services.
TCP standard has "simultaneous open" feature.
The implication of the feature, client trying to connect to local port, when the port is from ephemeral range, can occasionally connect to itself (see here).
So client think it's connected to server, while it actually connected to itself. From other side, server can not open its server port, since it's occupied/stolen by client.
I'm using RHEL 5.3 and my clients constantly tries to connect to local server.
Eventually client connects to itself.
I want to prevent the situation. I see two possible solutions to the problem:
Don't use ephemeral ports for server ports.
Agree ephemeral port range and configure it on your machines (see ephemeral range)
Check connect() as somebody propose here.
What do you thinks?
How do you handle the issue?
P.S. 1
Except of the solution, which I obviously looking for,
I'd like you to share your real life experience with the problem.
When I found the cause of the problem, I was "astonished" on my work place people are not familiar with it. Polling server by connecting it periodically is IMHO common practice,
so how it's that the problem is not commonly known.
When I stumbled into this I was flabbergasted. I could figure out that the outgoing
port number accidentally matches the incoming port number, but not why the TCP
handshake (SYN SYN-ACK ACK) would succeed (ask yourself: who is sending the ACK if
there is nobody doing a listen() and accept()???)
Both Linux and FreeBSD show this behavior.
Anyway, one solution is to stay out of the high range of port numbers for servers.
I noticed that Darwin side-steps this issue by not allowing the outgoing port
to be the same as the destination port. They must have been bitten by this as well...
An easy way to show this effect is as follows:
while true
do
telnet 127.0.0.1 50000
done
And wait for a minute or so and you will be chatting with yourself...
Trying 127.0.0.1...
telnet: Unable to connect to remote host: Connection refused
Trying 127.0.0.1...
telnet: Unable to connect to remote host: Connection refused
Trying 127.0.0.1...
telnet: Unable to connect to remote host: Connection refused
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
hello?
hello?
Anyway, it makes good job interview material.
Bind the client socket to port 0 (system assigns), check the system assigned port, if it matches the local server port you already know the server is down and and can skip connect().
For server you need to bind() socket to port. Once addr:port pair had socket bound, it will no longer be used for implicit binding in connect().
No problem, no trouble.
Note that this solution is theoretical and I have not tested it on my own. I've not experienced it before (or did not realize) and hopefully I won't experience it anymore.
I'm assuming that you cannot edit neither the client source code nor the server source. Additionally I'm assuming the real problem is the server which cannot start.
Launch the server with a starter application. If the target port that the server will bind is being used by any process, create an RST (reset packet) by using raw sockets.
The post below briefly describes what an RST packet is (taken from http://forum.soft32.com/linux/killing-socket-connection-cmdline-ftopict473059.html)
You have to look at a "raw socket" packet generator.
And you have to be superuser.
You probably need a network sniffer as well.
http://en.wikipedia.org/wiki/Raw_socket
http://kerneltrap.org/node/3072 - TCP RST attacks
http://search.cpan.org/dist/Net-RawIP/lib/Net/RawIP.pm - a Perl module
http://mixter.void.ru/rawip.html - raw IP in C
In the C version, you want a TH_RST packet.
RST is designed to handle the following case.
A and B establish a connection.
B reboots, and forgets about this.
A sends a packet to B to port X from port Y.
B sends a RST packet back, saying "what are you talking about? I don't
have a connection with you. Please close this connection down."
So you have to know/fake the IP address of B, and know both ports X
and Y. One of the ports will be the well known port number. The other
you have to find out. I thnk you also need to know the sequence
number.
Typically people do this with a sniffer. You could use a switch with a
packet mirroring function, or run a sniffer on either host A or B.
As a note, Comcast did this to disable P2P traffic.
http://www.eff.org/wp/packet-forgery-isps-report-comcast-affair
In our case we don't need to use a sniffer since we know the information below:
So you have to know/fake the IP address of B, and know both ports X
and Y
X = Y and B's IP address is localhost
Tutorial on http://mixter.void.ru/rawip.html describes how to use Raw Sockets.
NOTE that any other process on the system might also steal our target port from ephemeral pool. (e.g. Mozilla Firefox) This solution will not work on this type of connections since X != Y B's IP address is not localhost but something like 192.168.1.43 on eth0. In this case you might use netstat to retrieve X, Y and B's IP address and then create a RST packet accordingly.
Hmm, that is an odd problem. If you have a client / server on the same machine and it will always be on the same machine perhaps shared memory or a Unix domain socket or some other form of IPC is a better choice.
Other options would be to run the server on a fixed port and the client on a fixed source port. Say, the server runs on 5000 and the client runs on 5001. You do have the issue of binding to either of these if something else is bound to them.
You could run the server on an even port number and force the client to an odd port number. Pick a random number in the ephemeral range, OR it with 1, and then call bind() with that. If bind() fails with EADDRINUSE then pick a different odd port number and try again.
This option isn't actually implemented in most TCPs. Do you have an actual problem?
That's an interesting issue! If you're mostly concerned that your server is running, you could always implement a heartbeat mechanism in the server itself to report status to another process. Or you could write a script to check and see if your server process is running.
If you're concerned more about the actual connection to the server being available, I'd suggest moving your client to a different machine. This way you can verify that your server at least has some network connectivity.
In my opinion, this is a bug in the TCP spec; listening sockets shouldn't be able to send unsolicited SYNs, and receiving a SYN (rather than a SYN+ACK) after you've sent one should be illegal and result in a reset, which would quickly let the client close the unluckily-chosen local port. But nobody asked for my opinion ;)
As you say, the obvious answer is not to listen in the ephemeral port range. Another solution, if you know you'll be connecting to a local machine, is to design your protocol so that the server sends the first message, and have a short timeout on the client side for receiving that message.
The actual problem you are having seems to be that while the server is down, something else can use the ephemeral port you expect for your server as the source port for an outgoing connection. The detail of how that happens is separate to the actual problem, and it can happen in ways other than the way you describe.
The solution to that problem is to set SO_REUSEADDR on the socket. That will let you create a server on a port that has a current outgoing connection.
If you really care about that port number, you can use operating specific methods to stop it being allocated as an ephemeral port.