8

I'm building a P2P application that needs to be able to access nodes behind a NAT. This NAT does not allow inbound connections, therefore the nodes outside the network cannot reach out to the nodes behind the NAT.

My solution to this problem is that the node behind the NAT would reach out to the node outside, and the node outside, when the time is ready, connect to the node that is inside the NAT by using that pre-established TCP connection. Since this connection would be established by the node inside the NAT, this would not be blocked by the NAT.

Here's my question. I do not know which of the interpretations underlined are correct, or if both are wrong.

Interpretation #1

There is a concept of a TCP connection, effectively a tube, and when a node inside the NAT makes a request to anything on the outside world, that tube opens, the response is put into it, and the tube closes forever.

Result: The NAT will not allow any further TCP connections to the client from the node outside after that tube closes.

Interpretation #2

There is no such thing as a TCP connection, but, a TCP transmission. Since a TCP connection is defined as a local ip:port, and a remote ip:port, after a node behind the NAT calls a node outside, the node outside can call back using the same port the client made the request from, and that would "count" as the same TCP connection, not an unsolicited call in by the NAT.

Result: The NAT effectively guesses whether this connection was a response to what the node inside the NAT asked for by looking at the historic record. Since the node behind the NAT made the first call out, the node outside can call back in using the same client port and it would work.

My mental model was closer to #1, but when I inspected the connections with Wireshark, they did appear as separate TCP connections, or at least as separate entities.

Is it closer to #1, or #2, or am I hopelessly confused?

2
  • You might want to look up STUN and related work: en.wikipedia.org/wiki/STUN
    – pjc50
    Commented Mar 12, 2018 at 11:01
  • 6
    I strongly recommend that you first implement an IPv6 version of your application such that you don't have to deal with all the complexity of NAT in the first version. Once you have a working version on IPv6 start considering how to make it work on IPv4.
    – kasperd
    Commented Mar 12, 2018 at 23:27

3 Answers 3

9

TCP is a connection-oriented protocol, and it can only communicate through connections.

Before you start programming using TCP, it would be helpful to first understand how TCP works, and you should start with RFC 793, Transmission Control Protocol, which is the definition of TCP.

The RFC explains sockets and connections:

Multiplexing:

To allow for many processes within a single Host to use TCP communication facilities simultaneously, the TCP provides a set of addresses or ports within each host. Concatenated with the network and host addresses from the internet communication layer, this forms a socket. A pair of sockets uniquely identifies each connection. That is, a socket may be simultaneously used in multiple connections.

The binding of ports to processes is handled independently by each Host. However, it proves useful to attach frequently used processes (e.g., a "logger" or timesharing service) to fixed sockets which are made known to the public. These services can then be accessed through the known addresses. Establishing and learning the port addresses of other processes may involve more dynamic mechanisms.

Connections:

The reliability and flow control mechanisms described above require that TCPs initialize and maintain certain status information for each data stream. The combination of this information, including sockets, sequence numbers, and window sizes, is called a connection. Each connection is uniquely specified by a pair of sockets identifying its two sides.

When two processes wish to communicate, their TCP's must first establish a connection (initialize the status information on each side). When their communication is complete, the connection is terminated or closed to free the resources for other uses.

Since connections must be established between unreliable hosts and over the unreliable internet communication system, a handshake mechanism with clock-based sequence numbers is used to avoid erroneous initialization of connections.

As far as the outside TCP peer is concerned, it is connecting to the outside address of the NAT device, even though that device is forwarding to the other TCP peer on the inside, based on the connection initiated by the inside device.

You can also study RFC 5382, NAT Behavioral Requirements for TCP.

0
7

A TCP connection is considered to be "in force" as long as the software processes on either end keep the socket open.

When the process(es) on one or both ends close the socket (either gracefully or the connection gets aborted for some reason), this translates, on the wire, to a TCP packet with the FIN or RST flag set.

The NAT implementation on the NAT router looks for the FIN and RST flags, and when it sees a packet with these flags, it "closes the hole". After this point, the client has to initiate a new connection in order to "open a new hole".

To summarize, as long as your client and server keep their sockets open, the NAT association stays alive.

4

When I write of "usual" here, I am thinking of your average consumer WLAN-NAT router with a sane configuration, or some simple Linux networking with default settings. As usual, this can be made as complex or complicated as necessary. As the question is very basic, this seems to make most sense to me instead of going straight for any more complicated enterprise-level NAT solutions.

You have already accepted an answer, but let me try to directly address the question you asked:

How does NAT decide which connections are inbound, and which are outbound?

The basis for the decision (for any decision in a router) is a set of rules in some form or fashion. In this case, for each of the interfaces involved (i.e., the internal LAN interface vs. the external WAN/uplink interface), the administrator will have implemented rules. Those rules are quite different, i.e. the rules for a LAN interface look wildly different from those of a WAN interface.

Knowing where a packet comes from and where it goes to is the bread and butter of what a router does.

Let me start with an

Example

Wikipedia's NAT page has a lot of text on this issue, but a simple case (a simple company LAN vs. a single DSL uplink) this is what happens:

  1. The client PC tries to initiate a HTTP connection to an internet-based server, for example 198.51.100.20. The PC itself has a non-routed address like 192.0.2.2. The cheap DSL router has two interfaces, one internal (192.0.2.1) and an external (203.0.113.10, very likely changing often and provided through some local link protocol by the DLS provider). So the PC sends a SYN packet to 198.51.100.20:80 via its default gateway, which is 192.0.2.1.
  2. The router picks up the packet at its interface 192.0.2.1, like it also would do if there were no NAT involved at all. It has been configured to do NAT on this interface, so it proceeds to do these things:
    • Invent a new port number, which is unused so far. For example 12345.
    • Change the "sender" address in the IP header to 203.0.113.10.
    • Remember the original sender port number in the TCP header (provided by the PC), let's call it 4321.
    • Change the TCP header to contain the 12345 sender port number.
    • Add an entry (12345; 192.0.2.2; 4321) in its NAT translation table.
    • Send the packet along on its merry way to its own uplink/gateway.
  3. 198.51.100.20 eventually receives the packet, notices that it is a SYN ("establish new connection") and sends a SYN-ACK message back to the sender. From its point of view, this is the IP address 203.0.113.10, with the TCP destination port of 12345.
  4. The router receives this packet on its WAN interface. The WAN interface has been configured to resolve NATted addresses like this. The router then...
    • ...checks its NAT translation table, finds the entry...
    • ...modifies the packet to a destination of 192.0.2.2...
    • ...fixes the TCP destination port back to 4321...
    • ...and sends it alongs its merry way (on the LAN interface).
  5. The PC receives the packet and does not see anything about the NAT procedure. The packet looks just like if 198.51.100.20 had sent it, as if the NAT router was not there at all.

At no point at all does the topic of a "connection" appear. The NAT router (in its simplest form) does not need to care about the content of the messages. It cares about the IP addresses and the ports of the sender and receiver, but nothing else. (Granted: this is likely skipping over all kind of security- and performance-related issues; but this is about the very basic principle like the one at hand in this question.)

So how does the router know?

The router does not need to know about "connections" at all. In fact, similar procedures like described for TCP exist for the connectionless UDP protocol (UDP hole punching), or could, really, be implemented for any protocol that has something like port numbers in the transport layer.

The reason why the router needs to know the transport-level protocol (TCP, UDP, ...) in regards to NAT is mainly that the ports themselves are not part of IP; and ports are what makes the "hack" that (this kind of) NAT is, easily possible.

So, to your question:

How does NAT decide which connections are inbound, and which are outbound?

Outbound connections are per definitions those that start with a SYN packet (or an initial UDP punch in the case of UDP) appearing at the LAN interface. Calling them "connection" in the case of NAT is a bit much; they end up simply as a temporary entry in a NAT translation table (plus whatever security/performance additions the individual NAT router might employ as well).

Inbound connections do not exist in the scenario I used in the answer so far. There are of course variants of NAT that do this; for example you can statically identify a port on the WAN interface of the router with a specific IP:PORT on the LAN interface, which makes it possible to run a server inside your NATted LAN. This is also often supported by cheap consumer DSL/WLAN routers. And with "real" routers, you are obviously able to configure them in whichever form or fashion you like.

Further inbound/outbound IP packets are not different from the ones given in the example. Once the initial SYN handshake has been done and the router has the entry in its translation table, it will pass through (with the same translation as explained in the example) all further packets in both directions.

If, in the context of a thus established TCP connection, the server wants to send data to the client (which it is perfectly possible - TCP is bidirectional), these are just further IP packets, as far as the NAT router is concerned. It will not really care that much about the contents of those packets (i.e., whether they contain certain payloads, or are just "management" packets of TCP or whatever).

At no point does the router somehow "close the tube" as you put it. Obviously, the router will have some notion of when it can clear out the entry from the translation table (probably when it notices a FIN handshake which ends the connection, or by some timeout or some error state), but from start to finish it is one continuous affair.

7
  • 1
    Please use IP addresses from RFC5737, defined specifically for documentation purposes, instead of "hijacking" valid ones, especially from Google. Commented Mar 12, 2018 at 17:47
  • 1
    Connections are bidirectional, so they are both inbound and outbound. It is the initiation of the connection that would be inbound or outbound.
    – Ron Maupin
    Commented Mar 12, 2018 at 19:28
  • @RonMaupin, yes, I explain that in the last paragraphs, especially the second to last. Does that match what you meant, or did I write it in an obscure fashion?
    – AnoE
    Commented Mar 12, 2018 at 20:27
  • @PatrickMevzek, learn something new every day. Done + thanks!
    – AnoE
    Commented Mar 12, 2018 at 20:31
  • Thanks. I agree, my question would be perhaps more specifically phrased as initiation of the connection, not as a question regarding overall bidirectionality. I have already implemented port mapping, and the routers that act normally will work. I've asked this question to figure out what can be done for routers who do not collaborate, such as ones in coffee shops, public places and so on. This is a great response that goes over the overall situation though, very much appreciated.
    – Dean M.
    Commented Mar 12, 2018 at 20:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.