nc / socat —— 连通性测试与临时数据通道
nc / socat —— 连通性测试与临时数据通道
分类:02 进程与网络诊断 适用:Linux / macOS(nc 有 OpenBSD 与 traditional 两个变体,参数不同) 一句话:
nc测端口通不通、临时传文件;socat做端口转发、协议转换、TLS 包装。
1. 它解决什么问题
- 目标端口通不通(不等应用层健康检查)。
- 两台机器之间临时传个文件,不想开 FTP/scp。
- 临时把某端口转发到另一台机器(
socat更稳)。 - 起一个裸 TCP/UDP 服务做联调。
2. 先确认你用的是哪个 nc
nc -h 2>&1 | head -5
readlink -f $(command -v nc)
| 变体 | 特征 | 常见系统 |
|---|---|---|
| OpenBSD netcat | -h 显示 OpenBSD netcat,支持 -z、-k、-N |
Ubuntu/Debian 默认 netcat-openbsd |
| traditional / GNU | 支持 -e、-c,不支持 -z 在部分版本 |
CentOS 的 nc(nmap-ncat 或 nc) |
| nmap-ncat | 支持 -z、--send-only、--recv-only |
RHEL 系装 nmap 时提供 |
参数差异会直接导致命令报错,先认清变体。
3. 安装
apt install -y netcat-openbsd socat
dnf install -y nmap-ncat socat
apk add netcat-openbsd socat
4. 端口连通性测试
nc -zv 10.0.0.5 3306 # 测 TCP(OpenBSD / nmap-ncat)
nc -zv -w 3 10.0.0.5 3306 # 3 秒超时
nc -zv 10.0.0.5 20-30 # 端口范围
nc -zuv 10.0.0.5 53 # 测 UDP
nc -zv -4 host 80 # 强制 IPv4
输出:
Connection to 10.0.0.5 3306 port [tcp/mysql] succeeded!
traditional 版没有 -z,用:
nc -w 2 10.0.0.5 3306 < /dev/null && echo open || echo closed
timeout 2 bash -c 'cat < /dev/null > /dev/tcp/10.0.0.5/3306' && echo open
/dev/tcp是 bash 内建,任何有 bash 的机器都能用,最省事。
5. 临时传文件
接收端
nc -l 9000 > received.tar.gz # OpenBSD:-l 直接跟端口
nc -l -p 9000 > received.tar.gz # traditional:需 -p
nc -lk 9000 # 持续监听(多连接,OpenBSD)
发送端
nc 10.0.0.5 9000 < file.tar.gz
tar czf - /data | nc 10.0.0.5 9000 # 边压边传
校验:
md5sum file.tar.gz
# 两端比对,避免传输截断
明文传输,不要用于敏感数据。跨公网用
scp/rsync/socat OPENSSL。
6. 起一个临时服务/客户端
# 服务端:任何连上来的请求都回一行
while true; do echo "HTTP/1.1 200 OK\r\n\r\nhello" | nc -l 8080; done
# 客户端手动说话(调试 SMTP/Redis 等文本协议)
nc 10.0.0.5 6379
PING
+ PONG
# 发原始 HTTP 请求(绕过 curl 的封装,看真实报文)
printf 'GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n' | nc example.com 80
调试 Redis 时这招很好用:printf '*1\r\n$4\r\nPING\r\n' | nc host 6379。
7. socat:更强的转发与协议转换
socat 的模型是"两个地址之间的双向管道":socat <地址1> <地址2>。
端口转发(临时,替代 iptables)
# 本机 8080 → 内网 10.0.0.9:80
socat TCP-LISTEN:8080,fork,reuseaddr TCP:10.0.0.9:80
# 后台常驻
nohup socat -d -d TCP-LISTEN:8080,fork,reuseaddr TCP:10.0.0.9:80 >> /var/log/socat.log 2>&1 &
fork:每个连接 fork 一个子进程,必须加,否则只能服务一个连接。reuseaddr:避免重启时Address already in use。
连通性测试
socat - TCP:10.0.0.5:3306 # 连上就打通,Ctrl-C 退出
socat - UDP:10.0.0.5:53
echo | socat - TCP:10.0.0.5:80
监听并回显(联调用)
socat -v TCP-LISTEN:9000,fork - # -v 打印双向数据
socat -x TCP-LISTEN:9000,fork - # -x 十六进制
Unix socket 与 TCP 互转
socat UNIX-LISTEN:/tmp/app.sock,fork TCP:127.0.0.1:8080
socat TCP-LISTEN:8080,fork UNIX-CONNECT:/var/run/docker.sock
后者常用于把 Docker socket 暴露给需要 TCP 的工具(注意安全,等于给 root)。
TLS 包装
# 明文服务套一层 TLS
socat OPENSSL-LISTEN:8443,cert=/etc/ssl/server.crt,key=/etc/ssl/server.key,verify=0,reuseaddr,fork \
TCP:127.0.0.1:8080
# 客户端连 TLS 后转本地明文
socat TCP-LISTEN:8080,fork,reuseaddr OPENSSL:remote.example.com:443,verify=1
串口/设备/文件
socat - /dev/ttyUSB0,b115200,raw,echo=0
socat FILE:/tmp/data.txt TCP-LISTEN:9000,reuseaddr
常用地址类型
| 地址 | 含义 |
|---|---|
TCP:host:port |
TCP 客户端 |
TCP-LISTEN:port,fork,reuseaddr |
TCP 服务端 |
UDP:host:port / UDP-LISTEN:port |
UDP |
UNIX-CONNECT:path / UNIX-LISTEN:path |
本地 socket |
OPENSSL:host:port / OPENSSL-LISTEN:... |
TLS |
EXEC:cmd |
执行命令,stdin/stdout 接入管道 |
SYSTEM:cmd |
同 EXEC,走 shell |
FILE:path |
文件 |
- |
标准输入输出 |
8. 实战场景
8.1 防火墙规则验证(不依赖应用)
nc -zv -w 3 <ip> <port>
# 或者批量
for p in 22 80 443 3306 6379; do
timeout 2 bash -c "cat < /dev/null > /dev/tcp/$IP/$p" 2>/dev/null \
&& echo "$p open" || echo "$p closed/filtered"
done
8.2 数据库端口通了但应用连不上
nc -zv 10.0.0.5 3306 # TCP 层通
socat - TCP:10.0.0.5:3306 # 能看到 MySQL 握手包开头(乱码即正常)
如果有握手包,说明网络没问题,问题在认证/权限/白名单。
8.3 临时把内网服务映射到跳板机
# 跳板机上
socat TCP-LISTEN:13306,fork,reuseaddr TCP:10.0.0.9:3306
# 本地连跳板机 13306 即可访问内网 MySQL
长期使用请用 SSH 隧道或 frp,socat 无认证、无加密。
8.4 抓明文协议交互
socat -v -x TCP-LISTEN:9000,fork TCP:10.0.0.9:80
# 客户端连 9000,-v 打印可读内容,-x 打印十六进制
9. 常见坑
-l与-p的差异:OpenBSD 用nc -l 9000,traditional 用nc -l -p 9000,混用会报错。-e被大多数发行版移除:出于安全考虑(反弹 shell),需要自己编译或改用socat EXEC:。- 传文件后另一端没退出:加
-N(OpenBSD)让对端关闭时关闭 socket。 socat不加fork只能服务一个连接,第二个连接会挂起。socat不加reuseaddr重启报端口占用。- 明文无认证:
nc/socat转发等于把服务暴露给能访问该端口的所有人。 - UDP 测试不可靠:UDP 无连接,
nc -zu成功只代表发出了包,不代表对端处理。 nc -z会建立完整 TCP 连接(connect 扫描),会被目标记录日志。- 容器内
socat转发要监听0.0.0.0,默认可能只绑 IPv6 或 localhost。 socat不支持多路复用高级特性,需要健康检查、负载均衡请用 nginx/haproxy。
10. 速查表
# nc
nc -zv <host> <port> # 测 TCP
nc -zv -w 3 <host> <port> # 带超时
nc -zuv <host> 53 # 测 UDP
nc -l 9000 > file # 接收(OpenBSD)
nc -l -p 9000 > file # 接收(traditional)
nc <host> 9000 < file # 发送
nc <host> 6379 # 手动对话
# bash 内建(无需装包)
timeout 2 bash -c 'cat < /dev/null > /dev/tcp/<host>/<port>' && echo open
# socat
socat - TCP:<host>:<port> # 连通测试
socat TCP-LISTEN:8080,fork,reuseaddr TCP:<host>:<port> # 转发
socat -v TCP-LISTEN:9000,fork - # 打印内容
socat TCP-LISTEN:8080,fork UNIX-CONNECT:/var/run/x.sock # socket 转 TCP
socat OPENSSL-LISTEN:8443,cert=c.pem,key=k.pem,verify=0,reuseaddr,fork TCP:127.0.0.1:8080