UDP 連接埠測試怎麼做?nc、nmap 與 iperf3 檢測 UDP 連接埠是否開放
UDP 連接埠測試不能用 telnet,telnet 只會發起 TCP 連線。UDP 沒有握手,“沒收到回應”既可能是連接埠開著、也可能是包被丟了,所以要換思路:用 nc 或應用自己的請求發包看有沒有回覆,用 nmap -sU 區分 closed 與 open|filtered,再在伺服器上抓包確認包有沒有到達。
UDP 連接埠測試的難點在於 UDP 沒有握手。測 TCP 連接埠時,SYN 發過去,收到 SYN-ACK 就是開放,收到 RST 就是關閉,結論很乾脆;UDP 包發出去之後,如果什麼都沒收到,可能是連接埠開著但程式不理會你發的內容,也可能是被防火牆悄悄丟了。所以“怎麼測試 UDP 連接埠是否開放”的答案不是某一條命令,而是三種手段配合:發一個對方會回應的包看有沒有回覆(nc、iperf3 或應用自己的客戶端),用 nmap -sU 看連接埠落在哪種狀態,以及在伺服器上抓包,確認請求到沒到、應答出沒出。下面分別給出 Linux 和 Windows 上的命令,最後講 DNS、遊戲、VPN 等服務怎樣驗證防火牆和安全組。
為什麼 UDP 連接埠不能用 telnet 測
telnet 只會建立 TCP 連線。telnet 203.0.113.10 53 測的是 TCP 53,和 UDP 53 是兩個互不相干的連接埠,它連通了也說明不了 UDP 53 的情況。Windows 上常用的 Test-NetConnection -Port 同樣只測 TCP。
UDP 包發出去之後,只會出現下面四種結果:
| 收到了什麼 | 說明 |
|---|---|
| UDP 應答 | 連接埠開放,而且服務認可了你發的內容 |
| ICMP 連接埠不可達(型別 3,程式碼 3) | 包到達了主機,但沒有程式監聽這個連接埠;iptables 的 REJECT 預設也回這種訊息 |
| 其他 ICMP 不可達(主機不可達、管理禁止等) | 路上的裝置或主機防火牆明確拒絕了這個包,firewalld 的預設拒絕就屬於這種 |
| 什麼都沒有 | 連接埠開著但程式不回應、包被防火牆靜默丟棄、應答在回程中丟失,三種情況無法區分 |
最後一行是 UDP 測試最常見、也最容易誤判的情況。很多 UDP 服務對看不懂的包一律不回:DNS 收到格式錯誤的查詢可能直接丟棄,WireGuard 對沒有透過認證的包不做任何回應,這是它們刻意的設計。所以 UDP 連接埠測試的原則是:能發應用自己的請求,就不要發空包;客戶端看不到結果,就去伺服器上抓包。
用 nc 測試 UDP 連接埠:-zuv 與收發測試
nc -zuv 是最常被搜到的寫法,但它的結果要會讀。以 Debian、Ubuntu 預設的 OpenBSD 版 nc 為例:
nc -zuv -w 2 203.0.113.10 9999
# Connection to 203.0.113.10 9999 port [udp/*] succeeded!
-z 表示只探測、不互動,-u 表示 UDP,-v 顯示結果。它的做法是向連接埠發幾個只含字元 X 的小資料包,只要沒有及時收到 ICMP 連接埠不可達,就報告 succeeded。所以這裡的 succeeded 只表示“沒有被明確拒絕”,被防火牆丟棄的連接埠同樣會顯示 succeeded;只有不顯示 succeeded 時,結論才是確定的:連接埠不可達。
更可靠的做法是兩端配合,發一段文字過去,看對方收沒收到、能不能回:
# 伺服器上:在要測試的連接埠臨時監聽(連接埠必須空閒,正式服務要先停掉)
nc -u -l 9999 # OpenBSD 版 nc
nc -u -l -p 9999 # 傳統版 nc 的寫法
ncat -u -l 9999 # RHEL、Rocky 等系統上的 nc 實際是 ncat
# 客戶端:以互動方式連線,然後輸入一行文字回車
nc -u 203.0.113.10 9999
客戶端輸入的那行字出現在伺服器視窗裡,說明去程是通的。接著在伺服器視窗裡輸入任意文字回車,nc 會把它發回給剛才的客戶端,客戶端視窗裡能看到,說明回程也通,測完兩邊按 Ctrl+C 退出。回程這一步不能省:狀態防火牆、NAT 閘道器和非對稱路由都可能讓應答回不去,而 UDP 服務能用,必須兩個方向都通。
不想手動輸入回覆時,可以用 socat 起一個回顯服務,收到什麼就原樣發回去:
socat -v UDP-LISTEN:9999,fork PIPE
客戶端執行 echo "probe-$(date +%s)" | nc -u -w 2 203.0.113.10 9999,2 秒內螢幕上列印出自己發的那行字,就說明一來一回都沒有問題;-v 讓伺服器一側同時把收到的內容列印出來。
nmap UDP 掃描:-sU 的四種結果怎麼讀
nmap 的 UDP 掃描要用 root 許可權執行。建議只掃你關心的連接埠,並加上 --reason,讓 nmap 說明每個判斷的依據:
sudo nmap -sU -p 53,123,161,500,1194,51820 --reason 203.0.113.10
# 對沒有回應的連接埠追加服務探測,儘量把 open|filtered 確認成 open
sudo nmap -sU -sV -p 1194 --reason 203.0.113.10
# 快速看最常用的 50 個 UDP 連接埠
sudo nmap -sU --top-ports 50 -T4 203.0.113.10
| 狀態 | --reason 顯示 |
含義 | 下一步 |
|---|---|---|---|
| open | udp-response | 收到了 UDP 應答,有服務在監聽 | 用應用客戶端測功能是否正常 |
| closed | port-unreach | 包到達主機,但沒有程式監聽(或被 REJECT) | 伺服器上 ss -ulnp 查程式是否在執行、監聽的位址對不對 |
| filtered | 其他 ICMP 不可達,如 admin-prohibited | 被防火牆明確拒絕 | 查安全組、主機防火牆的拒絕規則 |
| open|filtered | no-response | 重試後仍然沒有任何回應 | 加 -sV、改用應用請求,或在伺服器上抓包 |
nmap 對 53、123、161 這類知名連接埠會傳送符合協議格式的探測內容,所以 DNS、NTP、SNMP 服務通常能被識別為 open;對自定義的遊戲連接埠、業務連接埠,它發的是空資料包,服務不回應,結果就停在 open|filtered。看到 open|filtered 不要急著下結論,它只說明“沒有收到拒絕”。
closed 其實是個好訊息:它通常說明包已經到達伺服器、路上的安全組和 ACL 都放行了,剩下的只是程式沒在監聽,或本機防火牆以 REJECT 方式拒絕。filtered 和 open|filtered 才需要去查路上的規則。
只掃描你自己管理或已經獲得授權的位址。UDP 掃描會向大量連接埠發包,對他人的伺服器這樣做可能違反服務商的使用條款。
iperf3 -u:測通斷,也測丟包與抖動
nc 和 nmap 只能回答通不通。遊戲、語音、影片、VPN 這類業務還關心丟包和抖動,這要用 iperf3 的 UDP 模式在兩端實測:
# 伺服器端
iperf3 -s -p 5201
# 客戶端:UDP 模式,目標速率 20 Mbit/s,資料包 1200 位元組,測 10 秒
iperf3 -c 203.0.113.10 -p 5201 -u -b 20M -l 1200 -t 10
# 加 -R 反過來測伺服器發、客戶端收的方向
iperf3 -c 203.0.113.10 -p 5201 -u -b 20M -l 1200 -t 10 -R
有一點經常被忽略:iperf3 的 UDP 測試要同時放行 TCP 5201 和 UDP 5201。它先用 TCP 連線到伺服器的 5201 交換測試引數和結果,資料才走 UDP 5201。只放行了 UDP,客戶端會直接報連線失敗;只放行了 TCP,控制連線能建立,測試卻會卡在開始階段或報錯,拿不到丟包和抖動資料。
輸出的最後兩行是彙總,數字僅為範例:
[ ID] Interval Transfer Bitrate Jitter Lost/Total Datagrams
[ 5] 0.00-10.00 sec 23.8 MBytes 20.0 Mbits/sec 0.000 ms 0/20833 (0%) sender
[ 5] 0.00-10.04 sec 23.7 MBytes 19.8 Mbits/sec 0.215 ms 104/20833 (0.5%) receiver
看 receiver 那一行:Jitter 是抖動,Lost/Total Datagrams 是丟失數和總數。幾個判斷方法:
- 先看 receiver 一行的總數。這一行由伺服器統計後經 TCP 控制連線傳回,Total 大於 0 就說明這個方向的 UDP 已經放行;再加
-R測一次,確認另一個方向。 -l不要超過路徑 MTU。預設 1500 的乙太網 MTU 下,UDP 載荷超過 1472 位元組就會被分片,分片在部分網路裡會被丟棄,測出的丟包會偏高。用 1200 位元組比較穩妥。- 測通斷用低速,查丟包再加速。不加
-b時 UDP 只按 1 Mbit/s 傳送,足夠驗證放行;要排查丟包,再逐級調高-b:低速時也穩定丟包,問題線上路品質;某個速率之後丟包陡增,這個速率就接近連接埠的限速值或可用頻寬。
測試時注意流量:大速率、長時間的 UDP 測試會佔滿連接埠頻寬,影響同一台伺服器上的業務;按 95 計費的連接埠,持續的大流量還會抬高當月的計費值。先用小速率、短時間測,確認需要再加大。
Windows 上怎麼測試 UDP 連接埠
Windows 自帶的 Test-NetConnection 不支援 UDP,有三種替代辦法。
1. 微軟的 PortQry 命令列工具(需要從微軟官網單獨下載)。它會對 DNS、SNMP 等常見服務傳送協議格式的請求:
portqry -n 203.0.113.10 -e 53 -p udp
結果為 LISTENING 表示收到了應答,NOT LISTENING 表示收到 ICMP 連接埠不可達,LISTENING or FILTERED 對應 nmap 的 open|filtered。
2. 用 PowerShell 呼叫 .NET 的 UdpClient 發包。 Windows 有個便於判斷的特性:對已連線的 UDP 套接字,收到 ICMP 連接埠不可達後,接收操作會報“連線被重置”,因此能把“連接埠關閉”和“沒有回應”區分開:
$target = "203.0.113.10"; $port = 9999
$udp = New-Object System.Net.Sockets.UdpClient
$udp.Client.ReceiveTimeout = 3000
$udp.Connect($target, $port)
$data = [Text.Encoding]::ASCII.GetBytes("probe")
[void]$udp.Send($data, $data.Length)
$remote = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::Any, 0)
try {
$reply = $udp.Receive([ref]$remote)
"收到應答: " + [Text.Encoding]::ASCII.GetString($reply)
} catch {
$code = $_.Exception.InnerException.SocketErrorCode
if ($code -eq "ConnectionReset") { "收到 ICMP 連接埠不可達: 連接埠沒有程式監聽" }
elseif ($code -eq "TimedOut") { "3 秒內沒有回應: 可能開放但不回包, 也可能被丟棄" }
else { "其他錯誤: $code" }
} finally { $udp.Close() }
對端用上一節的 socat 回顯服務配合,能完整驗證往返兩個方向。
3. 安裝 Windows 版 nmap(安裝時一併裝上 Npcap 抓包驅動),用法與 Linux 相同;也可以在 WSL 裡使用 Linux 的 nc 和 nmap。
DNS、遊戲、VPN 等服務:用應用請求驗證放行
伺服器上開 UDP 服務時,最有說服力的測試是用這個服務自己的客戶端發一次真實請求。常見服務的驗證方法:
| 服務 | 常用連接埠 | 怎麼測 | 怎樣算通 |
|---|---|---|---|
| DNS | UDP 53 | dig @203.0.113.10 example.com +tries=1 +time=2 |
返回 NOERROR、NXDOMAIN、REFUSED 都說明連接埠可達,只有超時才是不通 |
| NTP | UDP 123 | sudo nmap -sU -p 123 --script ntp-info 203.0.113.10 |
連接埠顯示 open,並列出伺服器返回的時間資訊 |
| SNMP | UDP 161 | snmpget -v2c -c 團體名 203.0.113.10 SNMPv2-MIB::sysUpTime.0 |
返回執行時間;團體名錯誤時裝置不回應,表現和連接埠不通一樣,先核對團體名 |
| Syslog | UDP 514 | logger -n 203.0.113.10 -P 514 -d "udp-test" |
單向傳送,到伺服器日誌裡查這條記錄 |
| OpenVPN | 常用 UDP 1194 | 用客戶端連線,看日誌是否完成 TLS 握手 | 啟用 tls-auth 或 tls-crypt 時,伺服器對未透過校驗的包不回應,nmap 只能顯示 open|filtered |
| WireGuard | 常用 UDP 51820 | 客戶端發起連線後,在伺服器執行 wg show |
latest handshake 有更新;它對未認證的包一律不回應 |
| 遊戲服務端 | 按遊戲文件,常為一段 UDP 連接埠 | 用遊戲客戶端或伺服器查詢工具連線一次 | 能列出伺服器資訊或進入遊戲 |
| IPMI | UDP 623 | ipmitool -I lanplus -H 203.0.113.10 -U 使用者 -P 密碼 mc info |
返回 BMC 資訊 |
客戶端看不到結果時,在伺服器上抓包,一邊測一邊看:
tcpdump -nni any udp port 9999
| 客戶端結果 | 伺服器抓包看到 | 結論 |
|---|---|---|
| 收到應答 | 請求和應答都有 | 雙向都通 |
| 沒有回應 | 什麼都沒有 | 包在路上被攔:安全組、機房 ACL、客戶端所在網路的出口限制 |
| 沒有回應 | 有請求,沒有應答 | 程式沒在監聽或不回應,或者本機防火牆丟棄了請求:tcpdump 在本機防火牆之前抓包,看到請求不代表防火牆放行了它 |
| 沒有回應 | 請求和應答都有 | 應答在回程被攔:出方向規則、非對稱路由,或客戶端一側的 NAT 和防火牆 |
| 收到連接埠不可達 | 有請求,回了 ICMP | 連接埠沒有程式監聽,或者防火牆以 REJECT 方式拒絕 |
對應地檢查伺服器上的監聽和防火牆。監聽位址是 127.0.0.1 時,外部永遠連不上,要改成 0.0.0.0 或具體的網路卡位址:
ss -ulnp | grep 9999 # 程式是否在監聽,監聽在哪個位址
firewall-cmd --list-ports # firewalld,UDP 連接埠寫作 9999/udp
iptables -S INPUT | grep -- '-p udp' # iptables 中與 UDP 有關的規則
nft list ruleset | grep -n udp # nftables
# Windows:找出涉及 UDP 9999 的防火牆規則,看是否啟用、是允許還是阻止
Get-NetFirewallPortFilter -Protocol UDP | Where-Object LocalPort -contains '9999' |
Get-NetFirewallRule | Select-Object DisplayName, Enabled, Direction, Action
安全組一側最常見的三個疏漏:只加了 TCP 規則,沒加 UDP 規則(“全部 TCP”不包含任何 UDP 連接埠);遊戲、語音要的是一段連接埠,只放行了其中一個;源位址寫成了自己辦公網的位址,真實玩家或客戶端的位址不在其中。
在機房裡怎麼落地
UDP 測試裡“能通但丟包”的情況,很多時候不是防火牆的問題,而是伺服器所在的交換器連接埠被限了速:iperf3 的 -b 一超過連接埠限速值,丟包率就會陡然上升。Toplink DCIM 的 交換器管理 登記了每台伺服器接在哪台交換器的哪個連接埠,伺服器列表裡就能看到連接埠速率和 VLAN,進、出方向的速率上限在伺服器或交換器詳情裡設定;如果伺服器配置了 頻寬自動限速,按時間視窗統計的平均頻寬一旦越過閾值,連接埠就會被自動限速,面板上會顯示“限速中”。做 UDP 壓測或客戶反映遊戲、語音丟包時,先看一眼連接埠狀態,就能排除“測到的其實是限速”這種誤判。
常見問題
nmap 掃 UDP 連接埠為什麼這麼慢?
沒有回應的連接埠要等超時並重發,而很多系統還對 ICMP 連接埠不可達訊息限速,Linux 預設大約每秒只回一個,nmap 只能放慢速度等它。所以只掃需要的連接埠;用 -T4、--max-retries 1 可以加快,代價是結果更容易誤判為 open|filtered。
雲伺服器在同一個內網裡測通了,外網卻測不通?
內網測試的源位址是私網位址,命中的安全組規則可能和外網存取不同,有的規則只放行了內網網段;外網存取還要經過彈性公網 IP 或 NAT。驗證放行效果,要從真實客戶端所在的網路去測。
只在一端能把 UDP 連接埠測清楚嗎?
很難。想得到確定的結論,要麼對端有會回包的服務,要麼能在對端抓包或臨時起一個監聽。只在客戶端一側測試,多數時候只能得出“沒有被明確拒絕”這樣的弱結論。