Kestrel 啟動失敗:SocketException (10013)「存取權限不足」完整排查指南(ASP.NET Core / Docker / Windows & Linux)

 

內容

摘要(TL;DR)

當你啟動 ASP.NET Core(Kestrel)看到 SocketException (10013): 嘗試存取通訊端被拒絕,因為存取權限不足,代表程式想在某個「位址/連接埠」上監聽,但系統不允許。最常見原因:

  • 連接埠被其他程式或服務(IIS、反向代理、防毒)占用或保留

  • 權限不足(Linux/macOS 綁定 <1024 特權埠需 root 或 CAP)

  • 防火牆/安全政策阻擋監聽

  • Docker 埠對映或主機位址設定不正確

快速解法

  1. 先改用 http://localhost:5000 測試能否啟動。

  2. 檢查該埠是否被佔用並關閉衝突程式。

  3. 若要用 80/443(Linux/macOS),請用 root 或設定 CAP_NET_BIND_SERVICE

  4. 在公司環境,確認防火牆/EDR/群組原則未阻擋。




1. 錯誤長什麼樣?

常見日誌片段(你的堆疊可能相似):

fail: Microsoft.Extensions.Hosting.Internal.Host[11]
Hosting failed to start
System.Net.Sockets.SocketException (10013): 嘗試存取通訊端被拒絕,因為存取權限不足。
   at System.Net.Sockets.Socket.Bind(EndPoint localEP)
   at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransportOptions.CreateDefaultBoundListenSocket(EndPoint endpoint)
   ...

關鍵點:Kestrel 想綁定(Bind)某個位址/埠,但被系統拒絕




2. 為什麼會被拒絕?(觀念釐清)

  • Kestrel 是直接用 Socket 綁定,不是 HTTP.sys(除非你改用 HttpSysServer)。

  • 連接埠被佔用時通常報 10048;但某些安全/權限限制也會讓你看到 10013

  • Linux / macOS:綁定 1024 以下的「特權埠」(如 80/443)需要 root 或額外能力(capabilities)。

  • Windows:一般使用者監聽 80/443 通常允許,但安全軟體、IIS、公司政策或其他系統服務可能攔截,導致權限被拒。




3. 最快的定位流程(5 分鐘搞定)

Step A. 先換高埠(5000/8080)

.NET 6~8 minimal hosting 模式下,於 Program.cs 暫時指定:

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseUrls("http://localhost:5000");
var app = builder.Build();
app.MapGet("/", () => "OK");
app.Run();

能啟動 → 多半是原本的位址/埠有權限或被占用問題。
仍失敗 → 往下看權限/安全工具/防火牆。

Step B. 找出誰占用該埠

Windows(PowerShell/命令提示字元)

netstat -ano | findstr :80
# 看到 PID 後
tasklist /FI "PID eq <上面看到的PID>"
# 或
Get-Process -Id 

Linux

sudo lsof -i :80
# 或
sudo ss -ltnp | grep :80

把衝突程式關掉(或改它的埠),再啟動 Kestrel。

Step C. 確認防火牆/安全工具

  • 暫停防毒/EDR 測試(內網環境請照流程申請)。

  • Windows Defender Firewall:新增入站規則允許你的埠(例如 5000)。

  • 公司電腦:可能有 GPO/EDR 政策阻擋「非授權程序監聽」,需要 IT 協助白名單。

Step D. 你的「位址」綁對了嗎?

  • localhost → 本機循環

  • 0.0.0.0 → 綁定所有介面(容器/伺服器常用)

  • 指定 192.168.x.x → 確保該 IP 真的存在於本機網卡
    綁到不存在的 IP 會報別種錯,但錯誤處理常混在一起,建議先用 localhost 測。




4. 常見情境 & 具體做法

4.1 你想用 80/443(正式環境)

  • Linux/macOS

    • 以 root 執行,或給 dotnet/程式檔 CAP_NET_BIND_SERVICE

      # 對 dotnet 全域賦予(或改成你的可執行檔路徑)
      sudo setcap 'cap_net_bind_service=+ep' /usr/share/dotnet/dotnet
      # 或針對你的可執行檔
      sudo setcap 'cap_net_bind_service=+ep' /path/to/yourapp
      
  • Windows

    • 先檢查是否有 IIS、反向代理、VM/代理工具占用。

    • 多半不需 URLACL(那是 HttpSysServer/netsh http 的世界),但若你改用 HttpSys,才會需要:

      netsh http add urlacl url=http://+:80/ user=Everyone
      
    • 在企業環境,80/443 可能被政策鎖定,請找 IT 開通。

4.2 Docker(本機或伺服器)

  • 映射高位主機埠最省事:

    docker run -d -p 5000:80 yourimage
    # 容器內 Kestrel 監聽 http://0.0.0.0:80
    # 主機以 http://localhost:5000 存取
    

    容器內 Kestrel 監聽 http://0.0.0.0:80,主機用 http://localhost:5000 存取。

  • 已有服務綁住主機的 80/443?改映射或停掉衝突服務。

  • Kubernetes 同理,檢查 Service/Ingress 對映與 NodePort/LoadBalancer 設定。

4.3 正式設定(appsettings.json / Kestrel)

appsettings.json:
{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://0.0.0.0:5000"
      },
      "Https": {
        "Url": "https://0.0.0.0:5001"
      }
    }
  }
}

Program.cs

builder.WebHost.ConfigureKestrel(options =>
{
    options.ListenAnyIP(5000);        // HTTP
    // options.ListenAnyIP(5001, lo => lo.UseHttps()); // 若要 HTTPS
});



5. 加碼:排查小抄(Checklist)

  • 換成 localhost:5000 能否啟動?

  • 該埠是否被佔用(netstat/lsof/ss)?

  • 在 Linux/macOS 綁 80/443:是否 root 或設了 CAP_NET_BIND_SERVICE

  • 防火牆/EDR 是否允許監聽?

  • 綁定的主機位址是否正確?(localhost/0.0.0.0/實際網卡 IP)

  • Docker 埠映射是否衝突(-p 主機:容器)?

  • 公司政策/IIS/代理是否保留了 80/443?




6. 範例:從錯誤到修好(實戰縮影)

  1. 啟動報 10013

  2. UseUrls("http://localhost:5000") → 成功啟動。

  3. netstat -ano | findstr :80 發現 80 被某程式占用。

  4. 停掉該程式或改它的埠,再把 Kestrel 改回 80。

  5. 若在 Linux 要用 80,補上 setcap 權限或用 root 服務啟動。




7. 常見問答(FAQ)

Q1:為什麼我用 5000 還是失敗?
A:檢查是否被 EDR/防火牆阻擋,或是你綁定了不存在的 IP。也可能是同一埠已被你的另一個測試程式佔用。

Q2:Windows 下一定要當管理員才能用 80 嗎?
A:通常不必;但企業安全設定、IIS 或其他服務可能讓你實際上「沒權限」或已被占用。

Q3:netsh http add urlacl 一定要嗎?
A:只有在你使用 HttpSysServer(非 Kestrel)時才需要 URLACL。Kestrel 用的是原生 Socket 綁定。




8. 結語

SocketException (10013) 的本質是「系統不讓你在該位址/埠監聽」。先用高埠驗證、再查佔用者、最後處理權限與安全政策,多半 5~10 分鐘就能定位並修好。若你在公司受控環境,記得與 IT 同步防火牆與政策設定。

留言

這個網誌中的熱門文章

🛠【ASP.NET Core + Oracle】解決 ORA-00904 "FALSE": 無效的 ID 錯誤與資料欄位動態插入顯示問題

🛠【實戰排除教學】從 VS Code 的 _logger 錯誤,到 PowerShell 找不到 npm/serve,再到 Oracle ORA-03135 連線中斷——一次搞懂!

🔎如何在 Oracle PL/SQL 儲存過程中為文字欄位加入換行符號(CHR(10))——以 Updlcmremark 為例