如何解决“SocketException”访问被拒绝?

huangapple go评论120阅读模式
英文:

How to resolve "SocketException" access denied?

问题

I am trying to make my ASP.NET Core (.NET 6.0) application bind to a fixed port that is 49913. I have set this up using the launchSettings.json (for debugging) and appsettings.json (for release) as well:

launchSettings.json:

{
  "profiles": {
    "Controller": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": false,
      "applicationUrl": "https://[::1]:49913",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

appsettings.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http2"
    },
    "Endpoints": {
      "Https": {
        "Url": "https://[::1]:49913"
      }
    }
  }
}

But when I try to start the application, I'm getting a SocketException with error code 10013 (access denied). But I don't understand what's denying the access.

  • In CMD, netstat -aon does not list this port (or any of the 499XX range) as in-use
  • 49913 is well within the range of dynamic ports by any definition (most notably 49152-65535 as per RFC 6335)
  • A quick Google search turns up no result on other programs that might use that port apart from one page claiming it's used by "xsan", but a) this is a Mac program (and I'm on Windows), and b) I think this information was scraped from Apple's support site which merely claims xsan uses any dynamic port (and Wikipedia suggests it tends to use 63146 [citation needed]).
  • Even IANA's port number registry does not feature this port at all for anything

I tried a different port (namely 59913), just to see what would happen, and it works fine. Then I tried 49910, and it failed again with the same error (10013 access denied).

What's different about 49913 & Co. to make it fail? What can I do to find out what's up with that particular port range?

英文:

I am trying to make my ASP.NET Core (.NET 6.0) application bind to a fixed port that is 49913. I have set this up using the launchSettings.json (for debugging) and appsettings.json (for release) as well:

launchSettings.json:

{
  "profiles": {
    "Controller": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": false,
      "applicationUrl": "https://[::1]:49913",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

appsettings.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http2"
    },
    "Endpoints": {
      "Https": {
        "Url": "https://[::1]:49913"
      }
    }
  }
}

But when I try to start the application, I'm getting a SocketException with error code 10013 (access denied). But I don't understand what's denying the access.

  • In CMD, netstat -aon does not list this port (or any of the 499XX range) as in-use
  • 49913 is well within the range of dynamic ports by any definition (most notably 49152-65535 as per RFC 6335)
  • A quick Google search turns up no result on other programs that might use that port apart from one page claiming it's used by "xsan", but a) this is a Mac program (and I'm on Windows), and b) I think this information was scraped from Apple's support site which merely claims xsan uses any dynamic port (and Wikipedia suggests it tends to use 63146 [citation needed]).
  • Even IANA's port number registry does not feature this port at all for anything

I tried a different port (namely 59913), just to see what would happen, and it works fine. Then I tried 49910, and it failed again with the same error (10013 access denied).

What's different about 49913 & Co. to make it fail? What can I do to find out what's up with that particular port range?

答案1

得分: 1

通过评论中的一些链接的帮助,我能够弄清楚这个问题。

问题似乎与Windows的某些虚拟化功能有关,即HyperV(例如用于Windows沙箱)或WSL。

问题似乎是这些功能使用NAT(网络地址转换)时出现的,利用了"winnat"服务。该服务为NAT使用保留了一些端口范围,显然是连续100个端口为一块。

可以使用命令netsh int ipv4 show excludedportrange protocol=tcp在普通的cmd shell(不需要提权)中验证这一点。这是输出的样子(从德文翻译,数字为假的示例值):

协议“tcp”的排除端口范围

起始端口    结束端口
----------    --------
      1453        1453
      5357        5357
      6900        6900
      7564        7564
     50000       50059     *
     54267       54366
     54467       54566
     54869       54968
     55069       55168
     59013       59112
     59113       59212
     59230       59329
     59330       59429
     59696       59795
     59796       59895
     59896       59995
     59996       60095
     62249       62348
     62349       62448
     62449       62548

* - 管理的端口排除。

看起来,这个列表会随着时间增长;坦白说,我不确定这是否是我无法理解的技术必要性,或者是“资源泄漏”(其中“资源”是端口保留)。无论如何,一些答案建议重新启动"winnat"服务可以解决他们的问题,像这样(需要提权的shell):

net stop winnat
net start winnat

这样做会将大部分保留的端口释放回池中。如果有某个程序需要特定端口(例如Docker),那么你可以在这两个命令之间启动它,它应该可以工作。

然而,重新启动"winnat"会有一个“代价”:之后,像Windows沙箱这样的程序将无法再连接到互联网,即使你在"winnat"重新启动后重新启动了这些程序也是如此。为了解决这个问题,你需要重新启动计算机。但要注意,这意味着"winnat"将再次保留一些块,尽管可能与之前不同。

显然,这只是一个短期解决方案。如果不采取进一步措施,任何特定端口可能会在将来的某个时候再次结束在一系列保留端口中。

为了确保这不会发生,并且所需端口在将来仍然可以自由使用,你可以使用这些命令(需要提权的shell)来保留该端口(或一个端口范围):

netsh int ipv4 add excludedportrange protocol=tcp startport=49913 numberofports=1(仅保留49913

netsh int ipv4 add excludedportrange protocol=tcp startport=49900 numberofports=100(保留整个范围49900-49999

这意味着这些端口被保留,但没有使用。尽管它们被保留,你的程序仍然可以绑定到它们。

如果需要,使用delete代替add会将排除的端口范围从列表中删除。新添加的范围将显示为“Managed port exclusion”(后面带有*)。


替代方法

如果你查看了排除的端口范围,并且它没有列出包含你期望但被阻止的端口的范围,那么可能是端口可绑定设置出了问题。

动态端口范围并不总是今天的范围,为了适应最新变化,Windows在一段时间前调整/更新了其动态端口范围的规则。然而,一些用户声称这个自动更新对他们没有起作用,因此他们需要手动调整它。你可以使用这个命令检查你系统上配置的动态端口范围是什么:

netsh int ipv4 show dynamic protocol=tcp(不需要提权)

正确的示例输出如下:

协议 tcp 动态端口范围
---------------------------------
起始端口      : 49152
端口数量       : 16384

如果这不符合你的输出,它可能仍然看起来像这样:

协议 tcp 动态端口范围
---------------------------------
起始端口      : 1024
端口数量       : 64511

你可以使用这个命令来修复它(需要提权的shell):

netsh int ipv4 set dynamic tcp start=49152 num=16384

英文:

With the help of some links in the comments I was able to figure it out.

Various different bits of the question and answers here suggest the problem is related to some virtualization feature of Windows, namely HyperV (which is used for the Windows Sandbox for example) or WSL.

The problem appears to be that these features use NAT, utilizing the winnat service. This service reserves some port ranges for the NAT usage, apparently in blocks of 100 consecutive ports.

One can verify that using the command netsh int ipv4 show excludedportrange protocol=tcp in a regular cmd shell (no elevation needed). This is what the output might look like (translated from German, numbers are faked example values):

Excluded port ranges for the protocol "tcp"

Start port    End port
----------    --------
      1453        1453
      5357        5357
      6900        6900
      7564        7564
     50000       50059     *
     54267       54366
     54467       54566
     54869       54968
     55069       55168
     59013       59112
     59113       59212
     59230       59329
     59330       59429
     59696       59795
     59796       59895
     59896       59995
     59996       60095
     62249       62348
     62349       62448
     62449       62548

* - Managed port exclusions.

By the looks of it, this list grows over time; frankly, I'm not sure if that's a technical necessity I am failing to understand, or a "resource leak" (where the "resource" are port reservations). Anyway, some answers suggest that restarting the winnat service fixed their problem, like so (elevated shell required):

net stop winnat
net start winnat

Doing so will release most of the reserved ports back to the pool. If there is some program that needs a specific port (Docker for example), then you can start that in between those two commands, and it should work.

However, restarting winnat comes at a "cost": afterwards, programs like Windows Sandbox cannot connect to the Internet any longer, even if you [re]started those programs after the restart of winnat. To fix this, you need to reboot your computer. Beware however that this will mean winnat will reserve some blocks again, albeit probably different ones than before.

Obviously, this is just a short term solution. Without further actions taken, any particular port may by chance end up in a range of reserved ports again at some point in the future.

To make sure this doesn't happen and the desired port remains free to use in the future, you can reserve that port (or a port range) yourself using these commands (elevated shell required):

netsh int ipv4 add excludedportrange protocol=tcp startport=49913 numberofports=1 (only reserve 49913)

netsh int ipv4 add excludedportrange protocol=tcp startport=49900 numberofports=100 (reserves the whole range 49900-49999)

This will mean these ports are reserved, but not used. Despite them being reserved, your program can still bind to them.

In case it's needed, using delete instead of add removes an excluded port range again from that list. The newly added range will appear as "Managed port exclusion" (with a * behind it).


The alternative

If you looked up the excluded port ranges and it did not list a range that included your desired but blocked port, then there might be a problem with the setting which ports can be bound to.

The dynamic port range wasn't always the range it is today, and to adapt to the latest change, Windows adjusted/updated the rules for its dynamic port range some time back. Some users however claimed that this automatic update hadn't worked for them, so they needed to manually adjust it. You can check what the configured dynamic port range is on your system using this command:

netsh int ipv4 show dynamic protocol=tcp (no elevation needed)

A correct example output looks like this:

Protocol tcp Dynamic Port Range
---------------------------------
Start Port      : 49152
Number of Ports : 16384

If that doesn't match your output, it may still look like this:

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

You can use this command to fix it (elevated shell required):

netsh int ipv4 set dynamic tcp start=49152 num=16384

huangapple
  • 本文由 发表于 2023年6月26日 16:58:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/76555128.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定