一、socat 是什么?
socat 的全名是 Socket CAT。它是一个 Linux 网络工具。它的作用是在两个数据流之间建立双向通道,让数据在两端之间传输。
socat 是 netcat 的增强版。netcat 大家也叫它"网络瑞士军刀"。和 netcat 相比,socat 有这些优点:
- 支持的协议多:支持 TCP、UDP、IPv6、SSL/TLS、UNIX 套接字、串口、管道、文件等 100 多种地址类型
- 能同时处理多个连接 :通过
fork选项实现 - 还在持续更新:netcat 从 2007 年后基本不更新了,socat 还在持续开发
- 组合灵活:任意两种地址类型之间都能建立通道
简单来说,socat 就是一个"协议转换器",它能把任意两种数据通道连在一起。
二、在 Ubuntu 上安装 socat
2.1 用 APT 安装
Ubuntu 的官方软件源里已经包含了 socat。我们直接用 apt 安装就行:
bash
sudo apt update
sudo apt install -y socat
2.2 检查安装是否成功
安装完成后,运行下面的命令查看版本信息:
bash
socat -V
如果安装成功,会看到类似这样的输出:
socat version 1.7.4.1 on Jun 4 2026 11:22:33
2.3 查看帮助
bash
socat -h # 查看帮助
man socat # 查看完整手册
三、socat 基本语法
3.1 命令格式
bash
socat [选项] <地址1> <地址2>
socat 的工作原理很简单:它在地址1 和地址2之间建立一条双向数据通道。数据从一端进来,从另一端出去。两边的地址类型可以是不同的,比如一边是 TCP,另一边是文件。
3.2 常用全局选项
| 选项 | 说明 |
|---|---|
-d |
增加一级调试输出,最多用 -d -d |
-u |
单向模式:数据从地址1流向地址2 |
-U |
单向模式:数据从地址2流向地址1 |
-v |
显示数据传输的内容 |
-T <秒> |
设置空闲超时时间 |
-t <秒> |
设置超时时间 |
3.3 常用地址类型
| 地址类型 | 格式 | 说明 |
|---|---|---|
| TCP 连接 | TCP:<host>:<port> |
作为客户端连接远程 TCP 端口 |
| TCP 监听 | TCP-LISTEN:<port> |
作为服务端监听 TCP 端口 |
| UDP 连接 | UDP:<host>:<port> |
作为客户端连接远程 UDP 端口 |
| UDP 监听 | UDP-LISTEN:<port> |
作为服务端监听 UDP 端口 |
| 标准输入输出 | - 或 STDIO |
标准输入输出流 |
| 文件 | FILE:<path> |
读写文件 |
| 打开文件 | OPEN:<path> |
打开文件 |
| 执行命令 | EXEC:<cmd> |
执行程序并和它交互 |
| Shell | SHELL: |
通过 shell 执行命令 |
| SSL 监听 | OPENSSL-LISTEN:<port> |
监听 SSL/TLS 加密端口 |
| SSL 连接 | OPENSSL:<host>:<port> |
连接 SSL/TLS 加密端口 |
| UNIX 套接字 | UNIX-CONNECT:<path> |
连接 UNIX 域套接字 |
| 串口 | FILE:/dev/ttyUSB0 |
读写串口设备 |
| 虚拟串口 | PTY,link=/path |
创建虚拟串口(伪终端) |
| TUN 设备 | TUN:<ip>/<mask> |
创建 TUN 隧道接口 |
| SOCKS 代理 | SOCKS:<host>:<port> |
通过 SOCKS 代理连接 |
3.4 常用地址选项
| 选项 | 说明 |
|---|---|
fork |
为每个连接创建子进程,让服务端能同时处理多个连接 |
reuseaddr |
允许端口复用,避免出现 "Address already in use" 错误 |
bind=<ip> |
绑定到指定的网卡 IP |
range=<网段> |
限制只有指定 IP 范围的客户端才能连接 |
retry=<次数> |
连接失败时的重试次数 |
interval=<秒> |
两次重试之间的等待时间 |
四、实战教程
4.1 回显服务(Echo Server)
这是最简单的例子。我们用 socat 做一个回显服务,输入什么,它就返回什么。
服务端:监听 1234 端口
bash
socat - TCP-LISTEN:1234,fork
客户端:连接服务端
bash
socat - TCP:127.0.0.1:1234
在客户端输入任意文字,服务端会把内容原样显示出来。这就是 socat 的基本工作方式:两端之间建立通道,数据双向流动。
4.2 TCP 端口转发
这是 socat 最常用的场景。它可以替代 nginx 的 stream 模块来做端口转发。
场景:把本机的 8080 端口转发到远程服务器 192.168.1.100 的 3306 端口(MySQL)
客户端 → 本机:8080 → socat → 192.168.1.100:3306
运行命令:
bash
socat -d TCP-LISTEN:8080,fork,reuseaddr TCP:192.168.1.100:3306
TCP-LISTEN:8080:监听本机的 8080 端口fork:支持多个客户端同时连接reuseaddr:端口复用TCP:192.168.1.100:3306:转发目标
验证转发是否生效:
bash
mysql -h 127.0.0.1 -P 8080 -u root -p
如果只想监听某一块网卡(比如内网网卡 10.0.0.1):
bash
socat TCP-LISTEN:8080,bind=10.0.0.1,fork,reuseaddr TCP:192.168.1.100:3306
如果只想让某些 IP 访问(只允许 192.168.1.0/24 这个网段):
bash
socat TCP-LISTEN:8080,fork,reuseaddr,range=192.168.1.0/24 TCP:192.168.1.100:3306
4.3 UDP 端口转发
场景:把本机 UDP 53 端口转发到内网 DNS 服务器 192.168.1.10:53
bash
socat -d UDP-LISTEN:53,fork,reuseaddr UDP:192.168.1.10:53
验证:
bash
dig @本机IP www.example.com
如果需要指定只用 IPv4,把 UDP-LISTEN 换成 UDP4-LISTEN,把 UDP 换成 UDP4:
bash
socat -T5 UDP4-LISTEN:53,reuseaddr,fork UDP4:192.168.1.10:53
-T5 表示空闲 5 秒后自动断开。
4.4 文件传输
场景:两台服务器之间临时传文件,不需要 SSH 或 FTP。
接收端(IP: 10.0.0.5)先启动监听,把收到的数据写入文件:
bash
socat -u TCP-LISTEN:9876,reuseaddr OPEN:/tmp/big.iso,create
-u:单向模式,数据从网络流向文件create:文件不存在时自动创建
发送端读取文件并发送:
bash
socat -u FILE:/data/big.iso TCP:10.0.0.5:9876
文件传完后 socat 会自动退出。
查看传输进度:
bash
# 在接收端实时查看文件大小
watch -n 1 'ls -lh /tmp/big.iso'
4.5 串口远程访问
场景:通过 TCP 远程访问串口设备,比如路由器或树莓派的调试串口。
串口主机 :把 /dev/ttyUSB0 映射到 TCP 端口 2000
bash
socat -d -d TCP-LISTEN:2000,fork,reuseaddr FILE:/dev/ttyUSB0,nonblock=1,raw,echo=0,b9600
参数说明:
nonblock=1:非阻塞模式raw:原始数据模式,不做转换echo=0:关闭本地回显b9600:波特率设为 9600(根据的设备修改,比如 b115200)
远程客户端:连接串口
bash
socat - TCP:串口主机IP:2000
连上之后,就可以像本地一样操作串口设备了。
4.6 虚拟串口
场景:没有物理串口硬件,但是需要测试串口程序。比如在开发一个串口通信程序,手边没有设备,可以用 socat 创建一对虚拟串口来模拟。
socat 使用 PTY 地址类型来创建虚拟串口。PTY 是 Linux 的伪终端(Pseudo Terminal),socat 把它包装成串口设备。
创建一对互相连通的虚拟串口:
bash
socat -d -d PTY,link=/tmp/vport0,raw,echo=0 PTY,link=/tmp/vport1,raw,echo=0
参数说明:
PTY:创建一个伪终端设备link=/tmp/vport0:创建一个软链接指向真实的 PTY 设备,方便程序打开raw:原始数据模式,不做转换echo=0:关闭回显,否则发送的数据会被原样返回
运行后,socat 会输出类似这样的信息:
2026/06/04 12:00:00 socat[12345] N PTY is /dev/pts/2
2026/06/04 12:00:00 socat[12345] N PTY is /dev/pts/3
2026/06/04 12:00:00 socat[12345] N starting data transfer loop with FDs [5,5] and [7,7]
这表示两个虚拟串口已经连通了。/tmp/vport0 和 /tmp/vport1 就像一根串口线的两端,在一端写入的数据,另一端就能读出来。
测试虚拟串口:
打开两个终端窗口。
终端 A:用 screen 连接 vport0
bash
sudo apt install -y screen
screen /tmp/vport0
终端 B:用 screen 连接 vport1
bash
screen /tmp/vport1
在终端 A 中输入文字,终端 B 中就能看到。反过来也一样。
也可以用 Python 或 C 写的串口程序来打开 /tmp/vport0 和 /tmp/vport1 进行测试。
让虚拟串口在后台运行:
如果不想占用终端窗口,可以加 -d -d 并把日志重定向,然后用 & 放到后台:
bash
socat -d -d PTY,link=/tmp/vport0,raw,echo=0 PTY,link=/tmp/vport1,raw,echo=0 2>/var/log/socat-vserial.log &
把虚拟串口映射到 TCP 端口:
如果想让远程机器也能访问这个虚拟串口:
bash
socat -d -d PTY,link=/tmp/vport0,raw,echo=0 TCP-LISTEN:2000,fork,reuseaddr
远程机器连接 TCP 2000 端口,就等于连上了 /tmp/vport0。
注意 :
link创建的是软链接,指向的是/dev/pts/x这样的真实设备。如果的程序对设备路径有要求(比如只接受/dev/ttyUSB*),可以把 link 改成对应的路径,比如link=/dev/ttyUSB99,但需要 root 权限。
4.7 SSL/TLS 加密隧道
场景:给一个不支持 HTTPS 的 HTTP 服务加上 SSL 加密。
第一步:生成自签名证书
bash
openssl req -newkey rsa:2048 -nodes -keyout cert.key \
-x509 -days 365 -out cert.crt
cat cert.key cert.crt > server.pem
第二步:启动 SSL 代理
bash
socat OPENSSL-LISTEN:8443,fork,reuseaddr,cert=server.pem,verify=0 \
TCP:127.0.0.1:80
OPENSSL-LISTEN:8443:监听 8443 端口,启用 SSL/TLScert=server.pem:指定证书文件verify=0:不验证客户端证书(仅用于测试)TCP:127.0.0.1:80:转发到本地 HTTP 服务
第三步:客户端通过 HTTPS 访问
bash
curl -k https://localhost:8443
-k 表示跳过证书验证,因为自签名证书默认不被信任。
如果是非 HTTP 场景,可以用 socat 直接连 SSL 端口:
bash
socat - OPENSSL:127.0.0.1:8443,verify=0
注意 :在正式使用时,不要用
verify=0。应该用 CA 签名的证书做双向验证,防止中间人攻击。
4.8 正向 Shell(远程执行命令)
场景:在远程服务器上提供一个交互式 Shell。
服务端:监听端口,把输入交给 bash 执行
bash
socat TCP-LISTEN:1234,fork,reuseaddr EXEC:/bin/bash
客户端:连接后就能执行命令
bash
socat - TCP:服务器IP:1234
安全提醒:这种方式没有任何认证,只能用于内网调试。千万不要在公网使用。
4.9 提供静态文件下载
场景:快速让其他人下载一个文件。
bash
socat -U TCP-LISTEN:8080,fork,reuseaddr OPEN:/path/to/file.txt
-U 表示单向模式,数据从文件流向网络客户端。
客户端连接后就能获取文件内容:
bash
socat -u TCP:服务器IP:8080 OPEN:downloaded.txt,create
4.10 TUN 隧道组网
场景:通过 TUN 设备把两台机器连到同一个虚拟网络里。
服务端:
bash
socat TCP-LISTEN:1234,fork TUN:192.168.100.1/24,up
客户端:
bash
socat TCP:服务器IP:1234 TUN:192.168.100.2/24,up
连上之后,两端各自拥有 192.168.100.x 的 IP 地址,可以直接互相通信。
五、用 systemd 管理 socat 服务
如果直接在终端运行 socat,终端关了服务就停了。所以我们用 systemd 来管理 socat 进程,这样更可靠。
5.1 TCP 端口转发服务
创建服务文件:
bash
sudo vim /etc/systemd/system/socat-tcp-forward.service
写入以下内容:
ini
[Unit]
Description=socat TCP Port Forward
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
Group=root
ExecStart=/usr/bin/socat -d -d TCP4-LISTEN:8080,reuseaddr,fork TCP4:192.168.1.100:3306
Restart=always
RestartSec=3
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
5.2 UDP 端口转发服务
创建服务文件:
bash
sudo vim /etc/systemd/system/socat-udp-forward.service
写入以下内容:
ini
[Unit]
Description=socat UDP Port Forward
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
Group=root
ExecStart=/usr/bin/socat -d -d -T5 UDP4-LISTEN:53,reuseaddr,fork UDP4:192.168.1.10:53
Restart=always
RestartSec=3
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
5.3 启动和管理服务
bash
# 重新加载 systemd 配置
sudo systemctl daemon-reload
# 启动服务
sudo systemctl start socat-tcp-forward
# 设置开机自启
sudo systemctl enable socat-tcp-forward
# 查看服务状态
sudo systemctl status socat-tcp-forward
# 查看服务日志
sudo journalctl -u socat-tcp-forward -f
# 停止服务
sudo systemctl stop socat-tcp-forward
# 重启服务
sudo systemctl restart socat-tcp-forward
六、常用技巧
6.1 调试
如果遇到问题,加上 -d -d 可以看到详细信息,比如连接建立、数据传输、断开等:
bash
socat -d -d TCP-LISTEN:8080,fork TCP:192.168.1.100:3306
把调试日志保存到文件:
bash
socat -d -d TCP-LISTEN:8080,fork TCP:192.168.1.100:3306 2>/var/log/socat.log
6.2 自动重连
客户端断线后自动重连:
bash
socat - TCP:server:8080,retry=10,interval=2
retry=10:最多重试 10 次interval=2:每次间隔 2 秒
6.3 限制访问来源
只允许指定网段访问:
bash
socat TCP-LISTEN:8080,fork,reuseaddr,range=10.0.0.0/8 TCP:192.168.1.100:3306
6.4 指定 IPv4 或 IPv6
有时候 TCP-LISTEN 可能只监听了 IPv6。如果想明确用 IPv4:
bash
socat TCP4-LISTEN:8080,fork,reuseaddr TCP4:192.168.1.100:3306
如果想明确用 IPv6:
bash
socat TCP6-LISTEN:8080,fork,reuseaddr TCP6:[::1]:3306
6.5 查看传输的数据
用 -v 选项可以看到传输的数据内容,适合调试:
bash
socat -v - TCP-LISTEN:8080,fork
七、常见问题
| 问题 | 原因 | 解决方法 |
|---|---|---|
E bind: Address already in use |
端口被占用 | 加 reuseaddr,或换端口,或用 ss -tlnp 查看哪个进程占了端口 |
| 客户端连上后马上断开(EOF) | 没加 fork |
服务端加 fork 选项 |
| 传大文件中途断开 | 版本太旧或 IPv6 映射问题 | 升级到 1.7.x 以上,加 pf=ip4 选项 |
| 串口输出乱码 | 波特率或数据位不匹配 | 指定 b115200,raw,echo=0 |
| 连接超时 | 防火墙挡了 | 开放端口:sudo ufw allow 8080/tcp |
| SSL 连接失败 | 证书有问题 | 检查证书路径,测试时加 verify=0 |
| 服务端只接受一个连接 | 缺少 fork |
加 fork 选项 |
八、socat 和 netcat 的对比
| 特性 | socat | netcat (nc) |
|---|---|---|
| 协议支持 | 100 多种地址类型 | 只有 TCP/UDP |
| IPv6 | 支持 | 支持有限 |
| SSL/TLS | 原生支持 | 不支持 |
| 同时处理多个连接 | fork 原生支持 |
需要脚本配合 |
| 串口通信 | 支持 | 不支持 |
| 自动重连 | retry/interval |
不支持 |
| 维护状态 | 还在更新 | 基本不更新了 |
九、总结
socat 的核心思路很简单:在任意两个数据流之间建立双向通道。正因为这个设计足够简单,所以它的组合方式非常多。
记住这个公式:
socat [选项] <数据源A> <数据源B>
A 和 B 可以是 TCP、UDP、文件、串口、Shell、SSL......,可以任意组合。
日常最常用的几个场景:
- 端口转发 :
socat TCP-LISTEN:端口,fork TCP:目标IP:目标端口 - 文件传输 :
socat -u FILE:文件 TCP:IP:端口 - SSL 加壳 :
socat OPENSSL-LISTEN:端口,cert=证书,fork TCP:本地端口 - 串口远程 :
socat TCP-LISTEN:端口,fork FILE:/dev/ttyUSB0,raw
学会 socat,就拥有了一个"任意协议、任意方向、可加加密"的数据传输工具。
参考链接:
- "socat -- Multipurpose Relay." dest-unreach.org, http://www.dest-unreach.org/socat/.
- "socat(1) - Linux man page." linux.die.net, https://linux.die.net/man/1/socat.
- "Ubuntu使用socat进行端口转发." 腾讯云开发者社区, 21 July 2021, https://cloud.tencent.com/developer/article/1850929.
- "Socat 命令总结." 博客园, 24 Dec. 2024, https://www.cnblogs.com/kqdssheng/p/18628559.
- "socat命令." Linux命令手册, https://www.linux-man.cn/command/socat/.
- "Mastering Socat in Linux." linuxvox, https://linuxvox.com/blog/socat-linux/.