Ubuntu 系统 socat 详细介绍与使用教程 - 映射任意两种数据通道

一、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/TLS
  • cert=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,就拥有了一个"任意协议、任意方向、可加加密"的数据传输工具。


参考链接

相关推荐
小此方1 小时前
Re:Linux系统篇(二十八)文件篇·一:理解 Linux 文件基础I/O、Linux 文件操作与系统调用机制
linux·运维·服务器
likerhood2 小时前
Linux 服务器基础资源查看:CPU、GPU、内存、磁盘与一键检测脚本
linux·运维·服务器
AOwhisky2 小时前
学习自测与解析:MySQL 系列第三期与第四期
linux·运维·数据库·学习·mysql·云计算
流浪0012 小时前
Linux系统篇(三):Linux 命令行参数 & 环境变量:程序和系统沟通的底层逻辑
linux·运维·服务器
Ameilide2 小时前
Linux 应用软件编程 多任务并发
linux·运维·服务器
cjhbachelor2 小时前
___信号
linux
无限进步_3 小时前
【Linux】环境变量:系统运行参数的“备忘录”
linux·运维·服务器
YYRAN_ZZU3 小时前
Ubuntu22.04搭建QEMU嵌入式开发环境全攻略
linux·嵌入式硬件·ubuntu
无忧.芙桃3 小时前
Linux信号机制(上)
linux·运维·服务器