Advertisement

C# Simple Test with Client/Server LAN succeded but in WAN it fails

Started by November 06, 2018 07:08 PM
8 comments, last by hplus0603 6 years ago

I tried to program a simple networking test with a WAN server/client, but it failed. I know the problem is not the ports or the buffer to be sent, because I tried it using the localhost(127.0.0.1) and the string "hihi" was shown correctly by the server, but when I tried with my public IPv4(the ip you can get on any website googling for 'my ip'), that just don't works, and the server stays on the Waiting for connection... forever, and the client launchs an exception(not timeout) which says that the server didn't response. It's not a port forwarding problem, because then my localhost would not been worked neither. The code:

Server:


static void Main(string[] args)
        {
            TcpListener s = null;
            try
            {
                s = new TcpListener(IPAddress.Any, 8888);
                s.Start(1);
                byte[] dataBytes = new byte[4];
                string data;
                while(true)
                {
                    Console.WriteLine("Waiting for a connection...");
                    TcpClient c = s.AcceptTcpClient();
                    Console.WriteLine("Connected!");
                    c.ReceiveTimeout = 999999999;
                    NetworkStream ns = c.GetStream();
                    int i;
                    while((i = ns.Read(dataBytes, 0, dataBytes.Length)) != 0)
                    {
                        data = Encoding.ASCII.GetString(dataBytes, 0, i);
                        Console.WriteLine("Received: {0}", data);
                    }
                    c.Close();
                }
            }
            catch(SocketException e)
            {
                Console.WriteLine("An exception ocurred!");
            }
            finally
            {
                s.Stop();
            }
            Console.ReadLine();
        }

Client:


static void Main(string[] args)
        {
            string msg = "hihi";
            bool localhost = false;
            TcpClient c = null;
            try
            {
                if(!localhost)
                    c = new TcpClient("83.xx.xx.xx", 8888);
                else
                    c = new TcpClient("127.0.0.1", 8888);
                c.SendTimeout = 999999999;
                byte[] data = Encoding.ASCII.GetBytes(msg);
                NetworkStream ns = c.GetStream();
                ns.Write(data, 0, data.Length);
                Console.WriteLine("Sent: {0}", msg);
                ns.Close();
            }
            catch(SocketException e)
            {
                Console.WriteLine("An exception ocurred: {0}", e.ToString());
            }
            finally
            {
                c.Close();
            }
            Console.ReadLine();
        }

 

If you have a router, you need to set up port forwarding (or a similar alternative) in order for the router to know what to do with incoming traffic on that port.  By default, a router only knows what to do when something on the LAN side of the router tries to connect to something on the WAN side, and rejects anything else.

(This post assumes you're using typical network equipment found at home, not a cloud provider like Amazon)

Advertisement
21 minutes ago, Nypyren said:

If you have a router, you need to set up port forwarding (or a similar alternative) in order for the router to know what to do with incoming traffic on that port.  By default, a router only knows what to do when something on the LAN side of the router tries to connect to something on the WAN side, and rejects anything else.

(This post assumes you're using typical network equipment found at home, not a cloud provider like Amazon)

Yes, I'm using a normal router, i already opened that port for all the applications through the firewall inbound rules(I setted that as Tcp) and yet that did not work for me. What can be wrong? 

The firewall inbound rules are a separate thing from the router's port forwarding mapping table.  There are also firewalls in both the router and computer's operating system and it's not clear from your post which firewall you configured.

WAN -- cable/DSL modem -- router(mapping table, firewall, etc) -- switch(es) -- computer's network adapter -- driver/os/firewall/etc -- application software

Special cases:  Sometimes the modem and router are combined in one physical device.  If you only own a single computer you can plug it directly into a modem.

The router's main job that may affect you is to map IP addresses in packets arriving on the WAN side (83.x.x.x:wan_port) of the router to IP addresses in your LAN (192.168.x.x:lan_port) and lookup the MAC address to send the packet to on the LAN.  This is because typical home customers only have a single public-facing IPv4 address, but many internet connected devices.

When one of your computers connects to the outside world (LAN->router->WAN), the router automatically creates a temporary mapping so that returning traffic (WAN->LAN) gets back to the correct computer/port.

When the outside world sends traffic to the router (WAN->router), the router only allows the packet to continue (router->LAN) if it knows where on the LAN to send it, and if its security rules allow it.

If you just start up a listening socket on the LAN side, nothing automatically tells the router to make any mapping at all.  This is where you either use UPnP to tell the router to add a mapping, or use the router's web interface (opening http://192.168.0.1 or whatever its IP address is in a browser and manually configuring it), or using a WAN-side service to facilitate connections (STUN, etc).

If you are just trying to use your local IP like a loopback then the router shouldn't be involved.  If these are both running from the same machine then it's likely a system firewall rule preventing the server from listening on the port.  

*I misread, though, this could still be a part of the issue, assuming that the routing works from inside the network.

If your router isn't assigning that 83.xxx.xxx.xxx ip to your local machine then you are going to find an easier test to perform which simulates the same behavior as a normal server on the internet, is to just bind your server to your local IP 192.xxx or 10.xxx.  This will behave for basic testing the same way it would with a routable IP, you just can't access it from outside. But that's where port forwarding comes in.  To map that 83.xxx IP traffic to your internal IP, for accessing it from the internet, once it is tested.

Advertisement

Okay so, for future readers of that post, after reading about that, port forwarding means that the info that comes to the router public address through the port 8888 must be redirected to the local specific ip machine(192.168.x.x). Why? Because there can be different machines connected to one router, so the router needs to map all of them(i.e. pc1 -> 192.168.1.1, phone1 -> 192.168.1.2, pc2 -> 192.168.1.3, etc...). You need to tell the router which device will receive the incoming data, but it does not know about names, so you need to specify it with the specific local ip of your machine. How? Here is where upnp comes to the rescue. You need to use a dll called natupnp.dll and import some functions to your c# code (details here: http://pietschsoft.com/post/2009/02/NET-Framework-Communicate-through-NAT-Router-via-UPnP) and link the port to the local ip address of your machine(you can get it using ipconfig). Thanks to all for your help. 

Problem sounds very similar to a (CORS - cross origin resource sharing error). From a networking perspective, jumping to the terminal and running a ping IP_YOU_WANT would be a good start. If the traffic is getting received from the server, you might just be running into ingress rules blocking the traffic client side. If it's returning connection refused or timeout, thats a good sign that ports are not open to send outbound traffic to the server, or the client is not allowed to receive inbound traffic from the server. 

 

After reading your last post, I see that you were able to send the data to the proper requester through NAT gateways. Cheers.

Problem sounds very similar to a (CORS - cross origin resource sharing error). 

CORS is a layer 7 protocol concern. It sounds like the OP has a layer 3 or 4 networking issue. Other than "there are things that sometimes don't make data available where you think it should be," CORS has nothing to do with TCP/UDP/IP layer problems.

Here is where upnp comes to the rescue

UPnP is terrible. It requires users to trust that arbitrary devices on the inside should be able to arbitrarily configure rules for your firewall. This is not a good security model, which is why it's often off by default, or turned off by people who care about security. If your game depends on UPnP, then you're in trouble.

I think there are a few basic networking rules that need to be clarified here:

1) A typical home router implements NAT, and has one public IP address on the "outside," and has a DHCP server that hands on prive IP addresses to the inside.

2) When a machine on the inside wants to talk to the outside, it goes through the router, which re-writes the source packet IP:port from the inside values, to the outside IP address and some randomly chosen source port (which will hopefully stay persistent for the given inside IP:port tuple.)

3) When traffic comes back to the re-written IP:port, the router again re-writes going the other way, and forwards to the inside IP:port pair.

4) For IP protocols without ports, such as ICMP used for "ping," it only re-writes the IP address, but because there's no other identifying information, it can't tell the difference between answers intended for more than one internal machine. Thus, if you have two devices on the inside which both "ping" the same outside IP at the same time, only one of them will typically see the responses (unless the firewall has heuristics to try to make that case work.)

5) Port forwarding basically just lets you add another entry in the router NAT table, saying that "packets coming in to this port on the external IP, should be re-written to this other internal IP:port." The main difference is that this entry is persistent, rather than created when the internal host tries to communicate to the outside. Connecting to your router's admin interface and setting up a persistent port forward to your hosts' internal IP address is more robust than UPnP. However, make sure your host doesn't change its internal IP between sessions! (This can happen when DHCP leases expire -- you may want to look into assigning static IP addresses, or "locking" DHCP leases, if your router supports this.)

6) Because these forwarding rules are dynamically created based on observed connections, two clients, both behind different NAT firewalls, can actually talk directly to each other, if we can only arrange for the session IP:port table to have the right rewrite rules. This is what NAT punch-through (with an external introducer server) is for. Read up on the STUN and TURN protocols for one approach to make this work.

7) this may be one of the problems above Many routers don't like "hairpin" connections, where you try to connect to the external IP address of the router, from the internal side. It's called "hairpin" because it requires a 180-degree turn, where the packet arrives at the router from the inside, which should mean that it should be re-written and forwarded to the outside interface, but then it's targeting the actual address of the outside interface (your public IP) and thus the packet needs to both go out on, and come back in on, the same interface, requiring a "sharp 180 degree turn" in the software. (Obviously it shouldn't actually send the packet on the hardware.)

 

 

enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement