Kestrel 啟動失敗:SocketException (10013)「存取權限不足」完整排查指南(ASP.NET Core / Docker / Windows & Linux)
內容
摘要(TL;DR)
當你啟動 ASP.NET Core(Kestrel)看到
SocketException (10013): 嘗試存取通訊端被拒絕,因為存取權限不足
,代表程式想在某個「位址/連接埠」上監聽,但系統不允許。最常見原因:
-
連接埠被其他程式或服務(IIS、反向代理、防毒)占用或保留
-
權限不足(Linux/macOS 綁定 <1024 特權埠需 root 或 CAP)
-
防火牆/安全政策阻擋監聽
-
Docker 埠對映或主機位址設定不正確
快速解法:
-
先改用
http://localhost:5000
測試能否啟動。 -
檢查該埠是否被佔用並關閉衝突程式。
-
若要用 80/443(Linux/macOS),請用 root 或設定
CAP_NET_BIND_SERVICE
。 -
在公司環境,確認防火牆/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. 範例:從錯誤到修好(實戰縮影)
-
啟動報
10013
。 -
改
UseUrls("http://localhost:5000")
→ 成功啟動。 -
用
netstat -ano | findstr :80
發現 80 被某程式占用。 -
停掉該程式或改它的埠,再把 Kestrel 改回 80。
-
若在 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 同步防火牆與政策設定。
留言
張貼留言