socat可在OpenWrt上实现灵活端口转发,支持TCP、UDP、串口等地址间中继,弥补iptables跨协议转发不足;教程讲解安装、常用写法、调试参数、procd自启和防火墙放行,并指出其性能不及DNAT,更适合跨协议与临时调试场景。

路由器上要做端口转发,很多人第一反应是防火墙的「端口转发」页面。但对一些特殊场景——跨协议、串口、临时调试——内核转发就不好使了,这时候 socat 才是顺手的工具。
这篇教程从 socat 是什么讲起,把 OpenWrt 上的安装、常用写法、开机自启和踩坑点一次讲透,所有命令都在 OpenWrt 24.10.5 上实测过。
一、socat 到底是什么
socat 的全称是 SOcket CAT,一个双向数据中继工具。你可以把它理解成「netcat 的加强版」:nc 主要用来读写 TCP/UDP,而 socat 能在几乎任意两种「地址类型」之间搭桥。
它支持的地址类型包括:
| 类型 | 写法 | 说明 |
|---|---|---|
| TCP | TCP:1.2.3.4:80 |
客户端连接 |
| TCP 监听 | TCP-LISTEN:8080 |
服务端监听 |
| UDP | UDP:1.2.3.4:53 |
UDP 客户端 |
| UDP 监听 | UDP-LISTEN:5353 |
UDP 服务端 |
| Unix Socket | UNIX-CONNECT:/var/run/x.sock |
本机进程通信 |
| 串口 | OPEN:/dev/ttyUSB0 |
串口设备 |
| 执行命令 | EXEC:cmd / SYSTEM:cmd |
把命令的输入输出当数据流 |
| TLS | OPENSSL:host:443 |
加密链路 |
只要两端是上面任意一种,socat 就能把它们接起来。这个能力决定了它和 iptables 的根本区别。
二、和 iptables 端口转发的区别
这是最容易搞混的地方,先讲清楚再动手。
| 对比项 | iptables/nftables DNAT | socat |
|---|---|---|
| 工作位置 | 内核 netfilter | 用户态进程 |
| 性能 | 极高,几乎无损 | 中等,每连接一个进程 |
| 协议转换 | 只能同协议 | TCP ↔ UDP 可以互转 |
| 能看到内容 | 看不到 | 可以 -v 打印流量 |
| 配置位置 | 防火墙规则 | 命令行 + 服务脚本 |
| 掉线影响 | 无进程,永远在 | 进程挂了就不转 |
| 适合场景 | 大流量端口映射 | 跨协议、串口、临时调试 |
一句话总结:要跑满带宽用 DNAT,要灵活用 socat。
三、在 OpenWrt 上安装
SSH 登录路由器,两条命令:
opkg update
opkg install socat
实测环境是 OpenWrt 24.10.5(x86_64),安装过程很干净:
Installing socat (1.8.0.3-r2) to root...
Downloading .../socat_1.8.0.3-r2_x86_64.ipk
Configuring socat.
验证一下:
socat -V
# socat version 1.8.0.3 on 22 Oct 2026 21:58:03
体积和内存占用都不大:
| 项目 | 实测值 |
|---|---|
| 二进制大小 | 304.9 KB(/usr/bin/socat) |
| 常驻内存 RSS | 876 KB |
| 依赖 | 无额外依赖包 |
在一台 512MB 内存的路由器上跑几个转发实例,完全感觉不到。
四、五种最常用的写法
1. 最经典的 TCP 转发
socat TCP-LISTEN:8080,fork,reuseaddr TCP:192.168.1.100:80
意思是:监听本机 8080,每来一个连接就转发到 192.168.1.100 的 80 端口。
2. UDP 转发
socat UDP-LISTEN:5353,fork,reuseaddr UDP:192.168.1.100:53
注意 UDP 也必须加 fork,否则只能服务一个客户端。
3. TCP 转 UDP
这是 socat 最有价值的能力,iptables 做不到:
socat TCP-LISTEN:5300,fork,reuseaddr UDP:192.168.1.100:53
客户端用 TCP 连 5300,socat 帮你换成 UDP 去问 DNS。
4. 串口转 TCP
socat TCP-LISTEN:2000,fork,reuseaddr OPEN:/dev/ttyUSB0,raw,echo=0,b115200
把串口设备(交换机、单片机、光猫 console)挂到网络上,用 telnet 就能连。
5. 本机 Unix Socket 暴露成 TCP
socat TCP-LISTEN:9000,fork,reuseaddr UNIX-CONNECT:/var/run/docker.sock
五、参数逐个说清楚
| 参数 | 作用 | 什么时候必须加 |
|---|---|---|
fork |
每个连接 fork 一个子进程 | 要支持多客户端,几乎必加 |
reuseaddr |
允许绑定处于 TIME_WAIT 的端口 | 服务重启时避免报错 |
nofork |
只服务一个连接就退出 | 临时调试 |
-d -d -d |
日志详细程度(越多越详细) | 排查连不上的问题 |
-v |
打印双向流量内容 | 看数据到底通没通 |
-lh |
把地址解析成可读格式 | 日志可读性 |
range=1.2.3.4/32 |
限制来源 IP | 安全加固 |
调试时的标准姿势是三层日志加流量打印:
socat -d -d -d -v TCP-LISTEN:8080,fork,reuseaddr TCP:192.168.1.100:80
日志会直接打在前台,能明确告诉你「监听成功没有」「对端连上没连上」。
六、让转发开机自启(procd)
命令行跑的 socat 一关 SSH 就没了。OpenWrt 用 procd 管理服务,写法如下。
新建 /etc/init.d/socat-nas:
#!/bin/sh /etc/rc.common
USE_PROCD=1
START=95
STOP=10
start_service() {
procd_open_instance
procd_set_param command /usr/bin/socat TCP-LISTEN:8080,fork,reuseaddr TCP:192.168.1.100:80
procd_set_param respawn 3600 5 0
procd_set_param stdout 1
procd_set_param stderr 1
procd_close_instance
}
授权并启用:
chmod +x /etc/init.d/socat-nas
/etc/init.d/socat-nas enable
/etc/init.d/socat-nas start
/etc/init.d/socat-nas status
实测这套模板在 24.10 上直接可用:
status → running
netstat -ltnp | grep 8080
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 5442/socat
curl 转发后返回 http=200
几个参数的含义:
respawn 3600 5 0:进程挂掉后 5 秒内最多重启 5 次,超过就停止(防止死循环刷日志)stdout 1/stderr 1:把输出交给系统日志,用logread能看
查日志:
logread -e socat | tail -20
如果只是临时用,也可以塞进 /etc/rc.local 的 exit 0 之前,但不推荐长期这么干——没有进程守护,挂了不会自己起来。
七、别忘了防火墙放行
socat 只是监听,能不能连进来由防火墙决定。OpenWrt 默认的 input 策略是 REJECT,所以你监听了 8080,从外面照样连不上。
命令行加规则:
uci add firewall rule
uci set firewall.@rule[-1].name='Allow-socat-8080'
uci set firewall.@rule[-1].src='lan'
uci set firewall.@rule[-1].proto='tcp'
uci set firewall.@rule[-1].dest_port='8080'
uci set firewall.@rule[-1].target='ACCEPT'
uci commit firewall
/etc/init.d/firewall reload
src 一定要写具体的区域(lan / wan),不要把 wan 直接放行,那等于把服务暴露到公网。
八、性能边界要说清楚
socat 是用户态转发,数据要从内核态拷到用户态再拷回去,中间还多一次进程调度。这意味着:
- 单连接吞吐主要受单核性能限制,一般跑不满千兆
- 并发连接多时,每个 fork 出来的子进程都占一份资源
- 万兆环境完全不适合,应该用 nftables DNAT
所以正确的用法是分工:
| 场景 | 推荐方案 |
|---|---|
| 内网大文件传输、媒体流 | nftables DNAT |
| 管理端口(Web、SSH、串口) | socat |
| TCP ↔ UDP 转换 | socat(唯一选择) |
| 临时抓包调试 | socat -v |
| 低频访问的小服务 | socat |
拿 socat 传 4K 视频流是自找麻烦,用它转发 NAS 管理页面就很合适。
九、六个常见坑
1. 端口被占用
netstat -ltnp | grep 8080
先看是谁占了,再决定换端口还是杀进程。
2. 重启时报 Address already in use
上一轮的连接还在 TIME_WAIT。加 reuseaddr 就能解决,这也是它几乎必加的原因。
3. OpenWrt 没有 pkill
busybox 精简掉了 pkill,习惯性敲会报 not found。改用:
kill $(pgrep socat)
4. EXEC 里写重定向不生效
EXEC:"dd ... 2>/dev/null" 不会按你预期工作,因为 EXEC 不经过 shell,重定向符号会被当成参数。需要 shell 特性就用 SYSTEM::
socat TCP-LISTEN:9000,fork,reuseaddr SYSTEM:"dd if=/dev/zero bs=64k count=100 2>/dev/null"
5. 连不上但进程在
九成是防火墙没放行,剩下一成是监听地址写成了 127.0.0.1。用 netstat -ltnp 确认监听的是 0.0.0.0 还是 127.0.0.1。
6. 进程越积越多
fork 模式下每个连接一个子进程,正常。但如果客户端异常断开后子进程不回收,检查是不是漏了 reuseaddr 或者对端把连接挂死了。ps w | grep socat 能看出一堆僵尸体。
十、卸载与清理
停用并删除自建服务:
/etc/init.d/socat-nas stop
/etc/init.d/socat-nas disable
rm /etc/init.d/socat-nas
卸载软件包:
opkg remove socat
结语
socat 的定位很清晰:它不是用来替代防火墙端口转发的,而是补上内核转发做不到的那些场景。
跨协议、串口、临时调试、低频管理端口,这四类需求用 socat 几分钟就能搞定;而需要跑满带宽的大流量,老老实实用 nftables DNAT。
装完之后体积 300 KB、内存不到 1 MB,几乎可以无脑装一台在路由器上备用——真遇到需要的时候,能省下不少折腾。
- 文章名称:Socat 端口转发:在 OpenWrt 上把 TCP/UDP 转明白
- 文章永久网址:https://www.997wan.com/socat-openwrt-tcp-udp/
- 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长 997笔记 进行删除处理。
- 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
- 本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
- 本站资源大多存储在云盘,如发现链接失效,请联系我们我们会第一时间更新。
- 如无特别声明本文即为原创文章仅代表个人观点,版权归《997笔记》所有,欢迎转载,转载请保留原文链接。