9

What I have discovered is that there are a number of ports on my Windows 10 box which (1) are not in use by any process and (2) I cannot listen on.

I discovered this problem trying to run a node server which used port 3000. I found a number of questions on this topic. This one is typical: Node.js Port 3000 already in use but it actually isn't?

All the respondents of this question and similar questions all suggest using "netstat -ano" to find the process which is using the port and killing it.

What I have found is that there are large number of ports blocked which are not tied to processes. This is not related to AV or firewall. I turned off the firewall and I have only Windows Defender AV.

I wrote a program to listen on the ports between 3000 and 5000 inclusive on 127.0.0.1.

        int port = 3000;
        while(port <= 5001)
        {
            try
            {
                ListenOnPort(port);
                ++port;

            }
            catch (Exception ex)
            {
                Console.WriteLine($"Listen on {port} failed: {ex.Message}");
                ++port;
            }
        }

Where ListenOnPort is...

    private static void ListenOnPort(int v)
    {
        var uri = new UriBuilder("http", "127.0.0.1", v);
        HttpListener listener = new HttpListener();
        listener.Prefixes.Add(uri.Uri.ToString());
        Console.WriteLine($"Listening on {v}");
        listener.TimeoutManager.IdleConnection = new TimeSpan(0, 0, 1);
        listener.Start();
        var task = listener.GetContextAsync();
        if(task.Wait(new TimeSpan(0,0,1)))
        {
            HttpListenerResponse response = task.Result.Response;
            // Construct a response.
            string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
            // Get a response stream and write the response to it.
            response.ContentLength64 = buffer.Length;
            System.IO.Stream output = response.OutputStream;
            output.Write(buffer, 0, buffer.Length);
            // You must close the output stream.
            output.Close();
        }
        listener.Stop();
    }

The program produced output similar to this...

Listening on 3000
Listen on 3000 failed: The process cannot access the file because it is being used by another process
Listening on 3001
Listen on 3001 failed: The process cannot access the file because it is being used by another process
Listening on 3002
Listen on 3002 failed: The process cannot access the file because it is being used by another process
Listening on 3003
Listen on 3003 failed: The process cannot access the file because it is being used by another     process
Listening on 3004
Listen on 3004 failed: The process cannot access the file because it is being used by another process
Listening on 3005
Listen on 3005 failed: The process cannot access the file because it is being used by another process
Listening on 3006
Listening on 3007
Listening on 3008
Listening on 3009
Listening on 3010

What I discovered is that between the ranges of 3000 and 5000, there are 624 ports which are blocked. Meanwhile "netstat -ano" shows that there are exactly 5 ports in use in that range. So what is blocking the 619 other ports?

AQuirky
  • 4,691
  • 2
  • 32
  • 51

2 Answers2

13

Right...

While looking for something else I found the answer (at least the source of the problem). The reason I cannot connect to these ports is because they are all part of excluded port ranges on windows. To see the excluded ports use...

$ netsh int ipv4 show excludedportrange tcp

And there, magically, is a list of all the ports I cannot connect to. These excluded port ranges apparently originate from HyperV and Docker, both of which I have installed. There is apparently a way to get the ports back...not easy since it involves uninstalling Docker and HyperV, then reserving the port ranges for yourself and then reinstalling HyperV and Docker. Not worth it. Now that I simply know how to find the ports I cannot use, I will simply not use them!

AQuirky
  • 4,691
  • 2
  • 32
  • 51
  • Thank you! I was wondering all the time why some of my kubernetes port forwardings didn't work in the browser on Windows 10 but worked inside WSL2. E.g. ` Elasticsearch = 9200 Prometheus = 9090 Alertmanager = 9093 PushGateway = 9091 ` I could succesfully create a port forwarding, but outside of WSL2 the Windows system just wasn't listening to those ports. Now I know why. – Michael Dec 18 '20 at 14:39
  • Thanks~!. I got the same problem with a mariadb on which the listening port is 3306. – tommybee Feb 23 '21 at 06:02
2

Set the Windows "Dynamic Port Range" in a non conflicting place

We managed to contain this problem for the case where you can not change your port numbers (like a non configurable application).

When you issue the command:

netsh int ip show excludedportrange protocol=tcp

You get an output with a list of port ranges reserved:

Protocol tcp Port Exclusion Ranges

Start Port    End Port
----------    --------
     33474       33573
     50000       50059     *
     58159       58258
     58259       58358
     58359       58458
     58459       58558
     58559       58658
     58659       58758
     58759       58858

* - Administered port exclusions.

The most likely reason for this is Windows Hyper-V (Microsoft's hardware virtualization product) that reserves random port ranges (usually blocks of 100 ports). This becomes a pain, because if you are developing an application or larger solution that uses multiple ports, some times you get a conflict and some times not after rebooting your system.

To find the "Dynamic Port Range" you can issue the command:

netsh int ipv4 show dynamicport tcp

The answer:

Protocol tcp Dynamic Port Range
---------------------------------
Start Port      : 1024
Number of Ports : 64511

You can instruct Windows to modify this range out of the conflicting area. Let's say your development is under and up to port 60000, you can issue the following command to restrict the dynamic port range out of it (you must have administrator privilegs):

netsh int ipv4 set dynamic tcp start=60001 num=5534

To make Hyper-V (and Windows in general) use this new dynamic range you have to reboot your system.

Now if we request the excluded port range:

netsh int ip show excludedportrange protocol=tcp

The response has changed:

Protocol tcp Port Exclusion Ranges

Start Port    End Port
----------    --------
     50000       50059     *
     63904       64003
     64004       64103
     64105       64204
     64205       64304
     64305       64404
     64405       64504
     64505       64604
     64605       64704

* - Administered port exclusions.

Only the "Administered port exclusions" remains below port 60001