A needs to contact B, A is not behind NAT, B is.
We have to assume that B is behind a hide NAT (overload, NAPT per RFC 2663) and doesn’t have the option of creating a static NAT, otherwise A could open a connection to B using the static NAT and in that case there would be no need for C.
The issue is that B cannot accept inbound connections due to the NAT type. With NAPT there are no open inbound ports. Connections are initiated from B through the NAT and B's IP is translated to the IP configured for the NAT. B's port number may also be translated if it is not free on the NAT.
B could of course initiate the connection to A, but if B is the server it would not know that A was trying to contact it, or what address to use to reach A.
It would help if you understood the methods of NAT traversal that are used to allow A to connect to B and then you can see at no point does anything connect inbound to B, in fitting with the restriction NAT places on inbound connections to B:
One simple method to achieve the connection is Relaying:
- B could contact A, but it doesn’t know A’s IP address
- A and B both know the IP address of an intermediary device – C (which is not behind NAT)
- A and B both make outbound connections to C
- C stitches the two connections together and relays the messages from A to B and vice versa.
Another method is Connection Reversal:
- B could contact A, but it doesn’t know A’s IP address
- A and B both know the IP address of an intermediary device – C
- A and B both make outbound connections to C
- B can now learn of A's IP address and port
- B can now make a direct outbound connection to A
With relaying there is a big overhead on C as it is in the data path for all traffic between A and B. With connection reversal, C is only used to learn A's IP address. Once the connection is set up, traffic between A and B is routed direct, bypassing C.
I think the main point of your confusion is due to the first step in each of these methods. Yes, in your specific example, B could contact A directly if it knew which IP:port to connect to, but it doesn't, so either needs to broker the whole connection through a relay server or use an intermediary server to learn the IP:port and then make that connection outbound itself.
There is a lot more detail in RFC 5128 - State of Peer-to-Peer(P2P) Communication Across Network Address Translators(NATs)
https://www.rfc-editor.org/rfc/rfc5128#page-8
There are many methods explained, this could be a variation on 3.1 Relaying
3.1. Relaying
The most reliable, but least efficient, method of implementing
peer- to-peer communication in the presence of a NAT device is to
make the peer-to-peer communication look to the network like
client/server communication through relaying. Consider the
scenario in figure 1. Two client hosts, A and B, have each
initiated TCP or UDP connections to a well-known rendezvous server
S. The Rendezvous Server S has a publicly addressable IP address
and is used for the purposes of registration, discovery, and relay.
Hosts behind NAT register with the server. Peer hosts can discover
hosts behind NATs and relay all end-to-end messages using the
server. The clients reside on separate private networks, and their
respective NAT devices prevent either client from directly
initiating a connection to the other.
Registry, Discovery
Combined with Relay
Server S
192.0.2.128:20001
|
+----------------------------+----------------------------+
| ^ Registry/ ^ ^ Registry/ ^ |
| | Relay-Req Session(A-S) | | Relay-Req Session(B-S) | |
| | 192.0.2.128:20001 | | 192.0.2.128:20001 | |
| | 192.0.2.1:62000 | | 192.0.2.254:31000 | |
| |
+--------------+ +--------------+
| 192.0.2.1 | | 192.0.2.254 |
| | | |
| NAT A | | NAT B |
+--------------+ +--------------+
| |
| ^ Registry/ ^ ^ Registry/ ^ |
| | Relay-Req Session(A-S) | | Relay-Req Session(B-S) | |
| | 192.0.2.128:20001 | | 192.0.2.128:20001 | |
| | 10.0.0.1:1234 | | 10.1.1.3:1234 | |
| |
Client A Client B
10.0.0.1:1234 10.1.1.3:1234
Figure 1: Use of a Relay Server to communicate with peers
Instead of attempting a direct connection, the two clients can
simply use the server S to relay messages between them. For
example, to send a message to client B, client A simply sends the
message to server S along its already established client/server
connection, and server S then sends the message on to client B
using its existing client/server connection with B.
This method has the advantage that it will always work as long as
both clients have connectivity to the server. The enroute NAT device
is not required to be EIM-NAT. The obvious disadvantages of relaying
are that it consumes the server's processing power and network
bandwidth, and communication latency between the peering clients is
likely to be increased even if the server has sufficient I/O
bandwidth and is located correctly topology-wise. The TURN protocol
[TURN] defines a method of implementing application agnostic,
session-oriented, packet relay in a relatively secure fashion.
You could also use 3.2 - Connection Reversal which applies more specifically to your case:
3.2. Connection Reversal
The following connection reversal technique for a direct
communication works only when one of the peers is behind a NAT device
and the other is not. For example, consider the scenario in figure
2. Client A is behind a NAT, but client B has a publicly addressable IP address. Rendezvous Server S has a publicly
addressable IP address and is used for the purposes of registration
and discovery. Hosts behind a NAT register their endpoints with the
server. Peer hosts discover endpoints of hosts behind a NAT using
the server.
Registry and Discovery
Server S
192.0.2.128:20001
|
+----------------------------+----------------------------+
| ^ Registry Session(A-S) ^ ^ Registry Session(B-S) ^ |
| | 192.0.2.128:20001 | | 192.0.2.128:20001 | |
| | 192.0.2.1:62000 | | 192.0.2.254:1234 | |
| |
| ^ P2P Session (A-B) ^ | P2P Session (B-A) | |
| | 192.0.2.254:1234 | | 192.0.2.1:62000 | |
| | 192.0.2.1:62000 | v 192.0.2.254:1234 v |
| |
+--------------+ |
| 192.0.2.1 | |
| | |
| NAT A | |
+--------------+ |
| |
| ^ Registry Session(A-S) ^ |
| | 192.0.2.128:20001 | |
| | 10.0.0.1:1234 | |
| |
| ^ P2P Session (A-B) ^ |
| | 192.0.2.254:1234 | |
| | 10.0.0.1:1234 | |
| |
Private Client A Public Client B
10.0.0.1:1234 192.0.2.254:1234
Figure 2: Connection reversal using Rendezvous server
Client A has private IP address 10.0.0.1, and the application is
using TCP port 1234. This client has established a connection with
server S at public IP address 192.0.2.128 and port 20001. NAT A has
assigned TCP port 62000, at its own public IP address 192.0.2.1, to
serve as the temporary public endpoint address for A's session with
S; therefore, server S believes that client A is at IP address
192.0.2.1 using port 62000. Client B, however, has its own permanent IP address, 192.0.2.254, and the application on B is
accepting TCP connections at port 1234.
Now suppose client B wishes to establish a direct communication
session with client A. B might first attempt to contact client A
either at the address client A believes itself to have, namely,
10.0.0.1:1234, or at the address of A as observed by server S, namely, 192.0.2.1:62000. In either case, the connection will fail.
In the first case, traffic directed to IP address 10.0.0.1 will
simply be dropped by the network because 10.0.0.1 is not a publicly
routable IP address. In the second case, the TCP SYN request from B
will arrive at NAT A directed to port 62000, but NAT A will reject
the connection request because only outgoing connections are allowed.
After attempting and failing to establish a direct connection to A,
client B can use server S to relay a request to client A to initiate
a "reversed" connection to client B. Client A, upon receiving this
relayed request through S, opens a TCP connection to client B at B's
public IP address and port number. NAT A allows the connection to
proceed because it is originating inside the firewall, and client B
can receive the connection because it is not behind a NAT device.
A variety of current peer-to-peer applications implement this
technique. Its main limitation, of course, is that it only works so
long as only one of the communicating peers is behind a NAT device.
If the NAT device is EIM-NAT, the public client can contact external
server S to determine the specific public endpoint from which to
expect Client-A-originated connection and allow connections from just
those endpoints. If the NAT device is EIM-NAT, the public client can
contact the external server S to determine the specific public
endpoint from which to expect connections originated by client A, and
allow connections from just that endpoint. If the NAT device is not
EIM-NAT, the public client cannot know the specific public endpoint
from which to expect connections originated by client A. In the
increasingly common case where both peers can be behind NATs, the
Connection Reversal method fails. Connection Reversal is not a
general solution to the peer-to-peer connection problem. If neither
a "forward" nor a "reverse" connection can be established,
applications often fall back to another mechanism such as relaying.