背景

家庭网络使用OpenWrt作为主路由。同时,使用DDNS实现外网访问家庭服务。原来的方案中,使用自带防火墙实现流量转发。但是,存在一个问题:局域网中无法访问流量转发的服务。此问题一般情况下影响较小,但是,最近在搭建rustdesk中继模式设置时由于这个问题,导致内网无法实现中继模式。

解决方案

使用socat代替防火墙实现流量转发。但是,官方源中的socat只是一个服务,没有图形化界面配置。因此,还需要基于luci实现图形化socat配置界面。

操作步骤

安装socat

在图形化界面中安装

也可以在命令行中安装

1
opkg update && opkg install socat

启动socat并设置开机自启

1
/etc/init.d/socat enable && /etc/init.d/socat start

实现图形化界面

新增/usr/lib/lua/luci/controller/socat.lua。功能是在服务菜单下注册一个socat的子菜单。

1
2
3
4
5
module("luci.controller.socat", package.seeall)

function index()
  entry({"admin","services","socat"}, cbi("socat"), "Socat", 100)
end

新增/usr/lib/lua/luci/model/cbi/socat.lua。这个是具体的页面代码。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
require("luci.sys")

m = Map("socat", translate("Socat Service"), translate("Configure socat service"))

s = m:section(TypedSection, "socat", "")
s.addremove = true
s.anonymous = false

enable = s:option(Flag, "enable", translate("Enable"))
enable.rmempty = false

run_as = s:option(Value, "user", translate("Run As"))
run_as.default = "root"
run_as.rmempty = false

options = s:option(TextValue, "SocatOptions", translate("Socat Options"))
options.default = "TCP-LISTEN:12345,fork,reuseaddr TCP:10.10.10.10:12345"
options.rmempty = false
options.size = 40

local apply = luci.http.formvalue("cbi.apply")
if apply then
  io.popen("/etc/init.d/socat restart")
end

return m

最终的效果:

配置示例

TCP

1
TCP-LISTEN:21115,fork,reuseaddr TCP:192.168.2.21:21115

UDP,注意-T5参数,表示在5秒内如果没有发生任何事情,则终止进程

1
-T5 UDP-LISTEN:21116,fork,reuseaddr UDP:192.168.2.21:21116

参考文档

https://dosk.win/2021/11/19/openwrt-tian-jia-yi-ge-socat-de-luci-web-jie-mian/

https://linux.die.net/man/1/socat