UDP port forwarding required? - c++

Sorry because of this dumb question but I didn't quite find an answer. So for TCP only the server needs a port forwarding, but not the client. But since UDP doesn't technically differentiates between client and server, do I have to port forward for the client too? (AFAIK TCP does it itself as soon as it connects to the server)

If the client is behind a NAT firewall, then yes, you will need a client port forward. Many NAT routers support "automatic" UDP forwarding, that automatically sets up a temporary port forwarding whenever it sees an outgoing packet (the client is sending data to the server), so that the reply packets can make it back to the client. You may need to configure your router to enable this, and may need to set various timeout parameters to make it work properly (since UDP does not have any timeouts built into the protocol).
Note that this kind of reverse port forwarding is ALSO needed for TCP, but all NAT router/firewalls do that automatically, as they would be useless without it.

Related

NAT Hole Punching in boost::asio

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.

Is it possible to send TCP packet to UDP-only server?

I have a UDP server, but I have no UDP capability on client side. Is there a way to send packet via TCP so that UDP server can receive it normally? UDP server cannot be transformed into TCP server.
Reason for wanting to do this is that I'm using a SOCKS5 proxy that does not support UDP associate capability, but I have to use that proxy.
No. The UDP server cannot complete the 3-way handshake required for TCP. If you have IP-raw sockets, it is actually easier to implement UDP on top. However it seems extremely unlikely that you don't have a UDP-stack.
When you talk about "no UDP capability" do you mean the client has no UDP-stack, or is he just behind some firewall that blocks UDP? In the latter case use a proxy.
No, UDP server will not going to accept TCP packets at all (it's a different protocol, so network stack will never propagate those to the application).
If you have to use SOCKS5 proxy, the only way to connect to the said server is by using another proxy-like application, which will stand beyond SOCKS5, accept TCP connections (initiated by app behind SOCKS5 proxy) and retransmit data as UDP.

Redirect opened TCP connection

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.

TCP three way handshake fails

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.

UDP hole Punching

I've got some questions regarding hole punching with UDP. Based on the wiki http://en.wikipedia.org/wiki/UDP_hole_punching
1) To set up a UDP session between two parties (the client which is behind NAT, server which is non-NAT) does the client simply have to send a packet to the server and then the session is allowed both ways (send & receieve) through the firewall? Meaning the client can receive too from the server.
2) UDP Hole punching: Two clients first conenct to the server, then the server gives a client port / ip on to other clients, so the clients send packets to each other on those ports. Is this coorrect?
3) if #2 is true, Why would firewalls allow data to be received from another IP than the one used in making the connection on that very port? Sounds like a big security hole that should easly be filtered? I understand that source IP spoofing would trick it, but this?
Thanks in advance,
Johan
1) Yes, with most reasonable firewalls, unless you configure it in extremely paranoid mode.
2) Not exactly. This article explains it in more detail, but the idea is that one of the clients first sends a datagram to the other's public IP. Then this datagram is discarded, but the other client knows that it was sent because the first one told it through the server. Then the other client sends a datagram back to the first one to the same port from which the first datagram originated. Since NAT at the first client remembers that there was a packet from that port, it considers the incoming datagram to be a reply to the first one. The problem here is to figure out which public port NAT will choose to send the first datagram, but most NATs do it in a predictable way so it almost always works fine, sometimes just not from the first try.
1) Yes. However, you don't need hole punching if you're contacting a non-NATted server. Your client application just behaves normally.
2) Yes.
3) Some NATs do indeed restrict a public port to just one sender-receiver pair. If you need to hole-punch in such a scenario, your only chance is to guess the public port the NAT will choose for the direct connection.
However, NAT is not a security feature. Therefore, accepting any packets to the public port is not a security hole as there is no difference to the simple case of a client directly connected to the internet.