When I send a request to web-server from one of my computers connected to home wi-fi router - how the response packet finds its way back to my computer and not to the other?
All computers in my local network have only one public IP and different private Ips (starting with 192.168...) - but source address in outgoing IP packet will be that public IP, so the destination IP for response packet will be also that public IP.
Where is the information about private IP (like 192.168.2.101) stored?
Thanks to NAT, several private IP addresses can share single public IP.
In both TCP and UDP each packet contains a source IP and a source port (along with a destination IP and port). When a machine in private network sends request to public server, NAT device/router overwrites private source IP+source port in the request packet with the public IP of the router and some unique port, and stores original source IP+port pair and overwritten source port in Translation Table. Remote server responds to public IP of the router+overwritten port number, router does a search in Translation Table by overwritten port number, and put original private ip+port into response packet and sends it to private machine (to original IP+port). Image from Wikipedia:
(more detailed on Wikipedia)
So the answer is: Translation Table on router allows to distinguish computers in local network and deliver responses to correct local machines.
Let's say that I have a home network of 5 computers. They all share the same external IP address.
Suppose a machine that is outside the network sends a request (as a client) to one of the 5 computers (this computer will be the server) in this home network. It sends its message to the external IP address. Then, how does the router know to what computer in the home network the message has to be routed to?
Typically when you talk about NAT, there are two main “flavours” - Source NAT & Destination NAT. There is another function called “PAT” (or Port Address Translation).
Source NAT is utilised when all your 5 computers are trying to reach out to the public (Internet) network. At this point your 5 computers get MASQUARADED with your public IPv4 address.
Destination NAT is what you’re asking for. In this case, you must configure your router/firewall (device that holds your public address & maintains your public connection) to “REDIRECT” or “DNAT” all incoming packets destined to a specific application (or port). For instance, if you have an HTTP server running on your private network server with address 10.0.0.3, you simply instruct your router to send all (or selective) TCP packets that have been sent to the public IP on ports 80/443 & send those to 10.0.0.3.
In DNAT scenario you must explicitly instruct your router/firewall about every type of expected, incoming connection. Another example can be that same public address is been used for SMTP server and thus sending all TCP packets received on port 25 to be sent to local server 10.0.0.4 this time. And so on and so forth
That’s in short how it works.
Network Address Translation (NAT) allows a single device, such as a router, to act as an agent between the Internet (or public network) and a local network (or private network), which means that only a single unique IP address is required to represent an entire group of computers to anything outside their network.
ADDRESS TRANSLATION (NAT) OVERLOAD allows your 5 computers to communicate with your router. Each computer has unique private IP address.
When computer1 tries to communicate with website, it sends packet to router.
Router replace the private IP address (example: 192.168.1.1) with single public IP address (example: 205.65.45.100) but uses same source port number (for example Port 5000) which is used by computer. It won’t change the source port number. And Router maintains entry in NAT table.
The reply from the (web server) internet arrives at your public interface of your router.
The router accepts packet and check the destination port entry. With the help of the NAT table, your router understands that it belongs to computer1. Router changes single public IP address (example: 205.65.45.100) with your internal private address (example: 192.168.1.1) and your computer receives it.
This process is applicable for all 5 computers.
Above scenario is only applicable if your computers act as a client. If your computer acts as a server then the solution is “Port forwarding”.
Port forwarding is needed when a machine on the Internet needs to initiate a connection to a machine that's behind a firewall or NAT router.
Refer video for detail information.
https://www.youtube.com/watch?v=-K6jMYBfuIY
I am using UdpSocket to create a server, binding to 0.0.0.0:serverport. I can get the source IP when a datagram arrives by using recv_from.
However, I need to get my local server's IP (destination IP) which the remote client contacted. I can see it in Wireshark but cannot obtain it via the API.
Motivation: I have 2 IPs from same network, eth and wlan. When a client contacts me on my wlan IP, in Wireshark I see the response UDP packet will have the correct port (same as request), but the source IP is the IP of my eth interface, thus the client will not receive the answer. Listening on just my wlan IP does solve the issue, but I want to listen on all interfaces.
I have an application that sends data (server) to a UDP client. It runs perfectly on the same computer, and over the LAN as long as I know as the destination address of the client. However, the moment I do this over the internet, it no longer works because it does not have the address of the destination computer. Here is the server code:
public ServerSender(String address, Int32 port, int TTL)
{
m_Address = address;
m_Port = port;
m_TTL = TTL;
Init();
}
private Socket m_Socket;
private IPEndPoint m_EndPoint;
private String m_Address;
private Int32 m_Port;
private Int32 m_TTL;
private void Init()
{
IPAddress destAddr = IPAddress.Parse(m_Address);
m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
m_EndPoint = new IPEndPoint(destAddr, m_Port);
}
public void SendBytes(Byte[] bytes)
{
m_Socket.SendTo(bytes, 0, bytes.Length, SocketFlags.None, m_EndPoint);
}
Here is the client:
public void Connect(string strAddress, int port)
{
m_Address = IPAddress.Parse(strAddress);
m_Port = port;
m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); // Multicast Socket
m_Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
m_EndPoint = new IPEndPoint(m_Address, m_Port);
m_Socket.Bind(m_EndPoint);
m_Socket.Connect(m_EndPoint);
IsConnected = true;
this.DoRead();
}
private void DoRead()
{
try
{
m_Socket.BeginReceive(bytes, 0, bytes.Length, SocketFlags.None, new AsyncCallback(OnDataReceived), m_Socket);
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
Obviously the server will need to listen for the remote connection and the client will need to connect to the server. I would think that I could then get the remote address and then in the SendBytes method I would sent to a remote endpoint. I have tried many different examples of async servers and they all lead to various errors. Is there any simple way to change this code to allow it to connect to a remote host over the internet?
Thanks
To summarize / elaborate on the comments a bit:
You got an host with a public IP, i.e. directly connected to the inet (your 'server')
You got an host without a public IP, i.e. connected to the inet over some gateway/firewall ... (your 'client' )
Since I don't know how much you know about networking:
TCP / UDP packets are wrapped in IP packets. IP deals with IP addresses, TCP and UDP know about ports, but: TCP port 1 and UDP port 1 are different things!
Your network setup probably look like , with some sample IPs:
|--------| 47.46.43.42 |---------|192.168.0.1 |--------|
| Server |======== The INET =========| Gateway |==================| Client |
|--------| 81.82.83.84 |---------| 192.168.0.100|--------|
The gateway hererin is your 'router'.
Your client will be configured to send any traffic not belonging to the local LAN to the Gateway (if you are able to browse websites from your client, it is configured the right way).
Note again: The network devices will deliver IP packets to the proper recipients, if the destination IP belongs to 'their' network. They won't deliver to anyone if the destination IP is not known.
If your client tries to send an UDP packet to your server port 1 , it will send an IP packet that contains the destination IP 47.46.43.42 and the source IP 192.168.0.100 to the gateway, along with the destination port 1 and the port it uses to send the packet (lets assume port 2). The gateway receives the packet, sees the destination IP and sends the content of the IP packet as a new IP packet with (destination 47.46.43.42:1, source 81.82.83.84) further along. It has to use another UDP port for sending, lets say 15. The key thing here is: It also remembers that it sent a packet from 192.168.0.100 port 2 to 47.46.43.42 port 1 its own port 15. Whenever an UDP packet arrives on port 15 from 47.46.43.42, it can assume that it is some reply that should be forwarded to 192.168.0.100 port 2.
Then if the server receives the packet, all it sees is (dest IP 47.46.43.42:1, source IP 81.82.83.84:83:15). if it wants to send back an answer, it will send an IP packet with (dest 81.82.83.84:15, source 47.46.43.42:1). NOTE that the server only 'sees' the gateway, not your client behind it! The gateway receives the packet, recalls that it just sent an IP packet (dest 47.46.43.42:1, source 192.168.0.100:2), assumes that the IP packet is some kind of answer, and sends a new IP packet (dest 192.168.0.100:2, source 47.46.43.42:1) with the content received from the server to your client.
NOTE ESPECIALLY that this only works because the gateway received a packet from the client and learned from this that 192.168.0.100 and 81.82.83.84 'speak to each other'. Only because of that it knows what to do with packets arriving from your server!
Now lets try the other way round. There are two possible cases:
The server knows the IP of your client (192.168.0.100) . Recall that this IP is not known to any device in the internet, thus if it sends out an IP packet (dest 192.168.0.100, source 81.82.83.84), it will not reach the gateway because the only packets reaching the gateway are those with a destination IP of 47.46.43.42 . This option will never work.
The server knows the IP of the gateway and sends out an IP packet (destination 47.46.43.42, source 81.82.83.84). This packet will reach the gateway. But what should the gateway do with it? It never memorized that packets from IP 81.82.83.84 should probably be forwarded to your client.
The only way for the gateway to learn would be if the client sent out a packet to your server first. This option will not work either.
Thus, it does not suffice* for the server to know the IP of the client, but the gateway needs to learn about the 'conversation' between your server and client. And the way your gateway works requires that the client sends out a packet first, using precisely the port for sending that you want to use further on. If your server should send to your client UDP port 2, the client must have sent a packet to the server first from UDP port 2.
What your gateway does is NATTING, and you better read a bit about it.
I assume, however, some standard setup of your network. This is likely, but technically, it could be entirely different, perhaps your gateway acts as a firewall, partially blocking outgoing traffic as well, perhaps your server is configured to use your gateway as a gateway as well (weird, but technically possible).
Thus troubleshooting offline is hard, and I am sorry if I cannot give you the solution (TM) for your concrete problem here.
PS: You might wonder why your client can send packets to the gateway with a wrong destination IP, while your server can't. This relates to the fact, that on the ethernet layer, your LAN is a single network, while the internet is not...
Ignoring other possiblities such as Request.ServerVariables["HTTP_X_FORWARDED_FOR"], does Request.ServerVariables["REMOTE_ADDR"] gives me the "principal" IP of the client?
I'm talking about the IP that made the actual TCP connection.
Will ServerVariables["REMOTE_ADDR"] always be the "real" IP address of the remote endpoint?
Just to clarify: Even if it's a proxy who made the real TCP connection I'd like have its IP, and not a forwarded one.
Yes, except if its been through a NAT firewall. A NAT firewalled address would be masquerading many 192.168.x.x or any other private subnet behind a public IP address. So you'd be looking at the IP address of the NAT firewall (i.e. a Linksys Router or what have you).
Be warned that many cell phone carriers have HUGE NAT networks so they always look like they are coming from one or two public IP addresses.
The REMOTE_ADDR variable will be the IP of the system that directly connected to your web server to request the URL; so it would be the forward-most proxy server, if there is a proxy server.