【Windows 11】llama-serverがWinError 10013で起動できない原因はHyper-V/HNSの除外ポートだった
ローカルLLMを llama.cpp の llama-server.exe で起動しようとしたところ、以前まで普通に使えていた 8080 ポートで突然起動できなくなった。
表示されたエラーはこれ。
couldn't bind HTTP server socket, hostname: 127.0.0.1, port: 8080
最初は「8080を別プロセスが使っているのだろう」と考えたが、netstat では何も出ない。
さらにPythonのHTTPサーバーでも同じポートが使えず、
PermissionError: [WinError 10013]
アクセス許可で禁じられた方法でソケットにアクセスしようとしました。
となった。
調べた結果、原因は llama.cpp ではなく、
WindowsのHyper-V / HNS / WinNATが自動生成した除外ポート範囲に8080が入っていたこと
だった。
しかも、この除外ポート範囲は固定ではなく、サービス再起動によって別のポート帯へ移動した。
同じ現象に遭遇したときのために、切り分け手順を残しておく。
環境
今回の環境は以下。
- Windows 11
- llama.cpp
- llama-server.exe
- WSL2
- Hyper-V
- Aider
- Qwen系GGUFモデル
- RTX 3060 12GB
ローカルLLMは、
Aider
↓
llama.cpp
↓
Qwen
という構成で、Codex代わりのローカルコーディング環境として利用している。
llama-serverが突然起動しなくなった
普段使っている起動コマンドは以下。
X:\LLM\llama-cuda\llama-server.exe `
-m "X:\LLM\models\Qwen3.8-27B-UD-IQ3_XXS.gguf" `
-md "X:\LLM\models\MTP\mtp-Qwen3.8-27B-Q4_0.gguf" `
-ngl 50 `
-c 32768 `
--host 127.0.0.1 `
--port 8080
ところが、この日は起動直後に以下のエラー。
couldn't bind HTTP server socket, hostname: 127.0.0.1, port: 8080
まず8080のポート競合を疑う
最初に確認したのは定番のこれ。
netstat -ano | findstr :8080
結果は何も表示されない。
つまり、8080で待ち受けている通常のプロセスは存在しない。
それでも念のため、8081へ変更。
--port 8081
しかし同じエラー。
さらに、
--host 0.0.0.0
に変更しても失敗した。
ここで、単純なポート競合ではないと判断した。
Pythonでも8080を使えない
llama.cpp 固有の問題か確認するため、Pythonの簡易HTTPサーバーを起動した。
python -m http.server 8080 --bind 127.0.0.1
するとこちらも失敗。
PermissionError: [WinError 10013]
アクセス許可で禁じられた方法でソケットにアクセスしようとしました。
これで、問題は llama-server.exe ではなく、
Windows側が8080へのbindを拒否している
ことが分かった。
Windowsの除外ポートを確認する
Windowsには、プロセスがLISTENしていなくても、OS側が予約してアプリから使えないポートが存在する。
確認コマンドはこちら。
netsh interface ipv4 show excludedportrange protocol=tcp
実際の結果。
プロトコル tcp ポート除外範囲
開始ポート 終了ポート
---------- --------
80 80
5357 5357
7213 7312
7313 7412
7413 7512
7513 7612
7680 7779
7866 7965
8064 8064
8065 8065
8066 8165
8166 8265
8266 8365
8366 8465
8466 8565
50000 50059
8080を見ると、
8066 ~ 8165
の中に完全に含まれている。
つまり8080は、
未使用だが使用禁止
の状態だった。
これが、
netstat -ano | findstr :8080
で何も表示されないにもかかわらず、
WinError 10013
になる原因だった。
何が除外ポートを作っているのか調べる
次に仮想ネットワーク関係を確認した。
Get-NetNat
こちらは何も表示されなかった。
続いて管理者PowerShellで、
Get-HnsNetwork
を実行。
以下のネットワークが存在していた。
Name : WSL (Hyper-V firewall)
Type : ICS
NatName : ICSA...
State : 1
さらにネットワークアダプターを確認。
Get-NetAdapter |
Sort-Object Name |
Format-Table Name, InterfaceDescription, Status
以下が存在。
vEthernet (WSL (Hyper-V firewall))
Hyper-V Virtual Ethernet Adapter
サービスも確認した。
Get-Service hns,vmcompute,winnat -ErrorAction SilentlyContinue
結果。
Running hns
Running vmcompute
Running winnat
つまり、
- HNS
- Hyper-V
- WinNAT
の仮想ネットワーク基盤が稼働している。
WSLを停止しても除外ポートは消えなかった
まずWSLそのものを停止。
wsl --shutdown
その後、再度確認。
netsh interface ipv4 show excludedportrange protocol=tcp
しかし、大量の除外範囲はそのまま残った。
このことから、
Linux VMそのものが8080を直接予約しているわけではない
ことが分かった。
HNS / Hyper-V / WinNATを停止すると予約が消えた
さらに切り分けるため、管理者PowerShellで以下を停止。
Stop-Service hns -Force
Stop-Service vmcompute -Force
Stop-Service winnat -Force
その直後に再確認。
netsh interface ipv4 show excludedportrange protocol=tcp
結果。
開始ポート 終了ポート
---------- --------
80 80
5357 5357
8064 8064
8065 8065
50000 50059
先ほど存在していた、
7213 ~ 8565
付近の大量予約が消えた。
これで、
大量の除外ポートを作っていたのはHNS / Hyper-V / WinNAT系
と判断できる。
サービスを再起動すると予約ポートが別の場所へ移動した
サービスを戻す。
Start-Service winnat
Start-Service vmcompute
Start-Service hns
再度確認。
netsh interface ipv4 show excludedportrange protocol=tcp
すると今度は以下のようになった。
35059 ~ 36158
付近に大量の除外ポートが移動していた。
つまり、
除外ポート範囲は固定ではない。
再起動や仮想ネットワークの再構成によって変化する場合がある。
このため、
昨日までは8080が使えていた
↓
今日は突然WinError 10013
という現象が発生する。
原因まとめ
今回の原因は、
Hyper-V / HNS / WinNATが自動生成した除外ポート範囲に8080が入っていたこと
だった。
流れとしては以下。
WSL2 / Hyper-V系ネットワーク
↓
HNS / WinNAT
↓
WindowsがTCPポート帯を予約
↓
8080が予約範囲に入る
↓
アプリからbindできない
↓
WinError 10013
ポイントは、
8080を誰かが使っている
のではなく、
Windowsが8080を使用禁止にしている
ということ。
そのため netstat では発見できない。
対処方法
最も簡単なのは、除外されていない別ポートを使うこと。
まず確認。
netsh interface ipv4 show excludedportrange protocol=tcp
例えば9000が除外されていなければ、
X:\LLM\llama-cuda\llama-server.exe `
-m "X:\LLM\models\Qwen3.8-27B-UD-IQ3_XXS.gguf" `
-md "X:\LLM\models\MTP\mtp-Qwen3.8-27B-Q4_0.gguf" `
-ngl 50 `
-c 32768 `
--host 127.0.0.1 `
--port 9000
のように変更すればよい。
ただし、今回確認できた通り、HNSの除外範囲は移動する可能性がある。
そのため固定ポートを必ず使えるとは限らない。
AiderでローカルLLMを使う場合
llama-serverのポートを9000に変更した場合、Aider側も変更する。
aider `
--model openai/local `
--openai-api-base http://127.0.0.1:9000/v1 `
--openai-api-key dummy
構成は以下。
Aider
↓
http://127.0.0.1:9000/v1
↓
llama.cpp
↓
Qwen
Codex代替としてローカルLLMを使っている場合、こうしたポート問題はAider側の問題に見えやすいが、実際にはその手前のWindowsネットワーク設定が原因の場合がある。
同じエラーが出たら最初に確認するコマンド
今回一番役に立ったのはこれ。
netsh interface ipv4 show excludedportrange protocol=tcp
WinError 10013 が出た場合は、
-
netstatで使用中プロセスを確認 - 除外ポート範囲を確認
- Pythonなど別アプリでもbindできるか確認
の順で調べると早い。
まとめ
llama-server が、
couldn't bind HTTP server socket
で起動できず、
WinError 10013
が発生した場合、ポート競合だけでなく、
Windowsの除外ポート範囲
を確認する価値がある。
今回の環境では、Hyper-V / HNS / WinNATによって大量のTCPポートが予約されていた。
さらに、その予約範囲はサービス再起動によって、
7213 ~ 8565
から、
35059 ~ 36158
へ移動した。
そのため、
8080のような定番ポートでも、Windows環境によっては突然使えなくなる
ことがある。
ローカルLLM、Docker、WSL2、Hyper-V、開発用HTTPサーバーなどを同じWindows PCで利用している場合は覚えておくと切り分けがかなり楽になる。
Qiitaタグ候補
Windows11
WSL2
Hyper-V
llama.cpp
ローカルLLM
Aiderを強調したい場合は ローカルLLM の代わりに Aider でもよい。
個人的には検索性を考えると、
Windows11
WSL2
Hyper-V
llama.cpp
ローカルLLM
の5つが一番まとまりがいい。