update 2026-09-24 16:56:26

This commit is contained in:
action committed 2026-09-24 16:56:26 +08:00
1 parent b31a5c3878
commit e4cee331e9
6885 files changed
+3240523

No files matched your search

+21
View File
@@ -0,0 +1,21 @@
# Copyright (C) 2020 Lienol <lawlienol@gmail.com>
#
# This is free software, licensed under the GNU General Public License v3.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-socat
PKG_VERSION:=1.1
PKG_RELEASE:=1
PKG_MAINTAINER:=Lienol <lawlienol@gmail.com> \
sbwml <admin@cooluc.com>
LUCI_TITLE:=LuCI support for Socat
LUCI_DEPENDS:=+socat
LUCI_PKGARCH:=all
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature
@@ -0,0 +1,148 @@
'use strict';
'require view';
'require form';
'require rpc';
'require uci';
'require poll';
'require network';
const callServiceList = rpc.declare({
object: 'service',
method: 'list',
params: ['name'],
expect: { '': {} }
});
return view.extend({
load() {
return Promise.all([
network.getHostHints()
]);
},
render(data) {
let m, s, o;
const hostHints = data[0];
m = new form.Map('luci_socat', _('Socat'), _('Socat is a relay for bidirectional data transfer between two independent data channels.'));
s = m.section(form.NamedSection, 'global', 'global', _('Global Settings'));
s.addremove = false;
o = s.option(form.Flag, 'enable', _('Enabled'));
o.rmempty = true;
s = m.section(form.GridSection, 'config', _('Port Forwarding'));
s.addremove = true;
s.anonymous = true;
s.sortable = true;
s.nodescriptions = true;
const super_handleAdd = s.handleAdd;
s.handleAdd = function(ev) {
const uuid = Array.from({ length: 32 }, () => Math.floor(Math.random() * 16).toString(16)).join('');
return super_handleAdd.call(this, ev, uuid);
};
s.modaltitle = function(section_id) {
return _('Socat Configuration');
};
o = s.option(form.Flag, 'enable', _('Enabled'));
o.editable = true;
o.default = '1';
o.rmempty = false;
o = s.option(form.DummyValue, '_status', _('Status'));
o.modalonly = false;
o.cfgvalue = function() {
return '-';
};
poll.add(() => {
return callServiceList('luci_socat').then(res => {
const instances = (res && res.luci_socat && res.luci_socat.instances) ? res.luci_socat.instances : {};
document.querySelectorAll('tr[data-sid]').forEach(row => {
let sid = row.getAttribute('data-sid');
if (!sid) return;
sid = sid.trim();
const cell = row.querySelector('td[data-name="_status"]');
if (!cell) return;
const isRunning = !!instances[sid];
cell.innerHTML = isRunning ? '🟢' : '🔴';
});
});
});
o = s.option(form.Value, 'remarks', _('Remarks'));
o = s.option(form.ListValue, 'protocol', _('Protocol Type'));
o.value('port_forwards', _('Port Forwarding'));
o.modalonly = true;
o = s.option(form.ListValue, 'family', _('Listen Address Family'));
o.value('', _('IPv4 and IPv6'));
o.value('4', _('IPv4 Only'));
o.value('6', _('IPv6 Only'));
o.depends('protocol', 'port_forwards');
o.modalonly = true;
o = s.option(form.ListValue, 'proto', _('Listen Protocol'));
o.value('tcp', 'TCP');
o.value('udp', 'UDP');
o.depends('protocol', 'port_forwards');
o.textvalue = function(section_id) {
const family_val = uci.get('luci_socat', section_id, 'family');
const proto_val = uci.get('luci_socat', section_id, 'proto');
if (proto_val) {
if (family_val === '4') return `IPv4-${proto_val.toUpperCase()}`;
if (family_val === '6') return `IPv6-${proto_val.toUpperCase()}`;
return `ALL-${proto_val.toUpperCase()}`;
}
};
o = s.option(form.Value, 'listen_port', _('Listen Port'));
o.datatype = 'portrange';
o.rmempty = false;
o.depends('protocol', 'port_forwards');
o = s.option(form.Flag, 'reuseaddr', _('Reuse Port'), _('Allow binding to the port even when previous connections are in TIME_WAIT, preventing restart failures.'));
o.default = '1';
o.rmempty = false;
o.modalonly = true;
o = s.option(form.ListValue, 'dest_proto', _('Destination Protocol'));
o.value('tcp4', 'IPv4-TCP');
o.value('udp4', 'IPv4-UDP');
o.value('tcp6', 'IPv6-TCP');
o.value('udp6', 'IPv6-UDP');
o.depends('protocol', 'port_forwards');
o = s.option(form.Value, 'dest_ip', _('Destination Address'));
o.rmempty = false;
o.depends('protocol', 'port_forwards');
o.value('127.0.0.1', '127.0.0.1 (localhost)');
hostHints.getMACHints().forEach(entry => {
const mac = entry[0];
const hint = entry[1] || mac;
const ip = hostHints.getIPAddrByMACAddr(mac);
if (ip)
o.value(ip, `${ip} (${hint})`);
});
o = s.option(form.Value, 'dest_port', _('Destination Port'));
o.datatype = 'portrange';
o.rmempty = false;
o = s.option(form.Flag, 'firewall_accept', _('Open Firewall Port'));
o.editable = true;
o.default = '0';
o.rmempty = false;
return m.render();
}
});
+97
View File
@@ -0,0 +1,97 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:113
msgid ""
"Allow binding to the port even when previous connections are in TIME_WAIT, "
"preventing restart failures."
msgstr ""
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:125
msgid "Destination Address"
msgstr ""
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:137
msgid "Destination Port"
msgstr ""
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:118
msgid "Destination Protocol"
msgstr ""
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:32
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:51
msgid "Enabled"
msgstr ""
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:29
msgid "Global Settings"
msgstr ""
#: luci-app-socat/root/usr/share/rpcd/acl.d/luci-app-socat.json:3
msgid "Grant UCI access for luci-app-socat"
msgstr ""
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:89
msgid "IPv4 Only"
msgstr ""
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:88
msgid "IPv4 and IPv6"
msgstr ""
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:90
msgid "IPv6 Only"
msgstr ""
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:87
msgid "Listen Address Family"
msgstr ""
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:108
msgid "Listen Port"
msgstr ""
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:94
msgid "Listen Protocol"
msgstr ""
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:141
msgid "Open Firewall Port"
msgstr ""
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:35
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:84
msgid "Port Forwarding"
msgstr ""
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:83
msgid "Protocol Type"
msgstr ""
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:81
msgid "Remarks"
msgstr ""
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:113
msgid "Reuse Port"
msgstr ""
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:27
#: luci-app-socat/root/usr/share/luci/menu.d/luci-app-socat.json:3
msgid "Socat"
msgstr ""
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:48
msgid "Socat Configuration"
msgstr ""
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:27
msgid ""
"Socat is a relay for bidirectional data transfer between two independent "
"data channels."
msgstr ""
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:56
msgid "Status"
msgstr ""
+107
View File
@@ -0,0 +1,107 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-22 03:12+0800\n"
"PO-Revision-Date: 2026-03-22 03:13+0800\n"
"Last-Translator: sbwml <admin@cooluc.com>\n"
"Language-Team: Chinese\n"
"Language: zh_Hans\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:113
msgid ""
"Allow binding to the port even when previous connections are in TIME_WAIT, "
"preventing restart failures."
msgstr "允许在端口处于 TIME_WAIT 状态时立即重新绑定,避免服务重启失败。"
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:125
msgid "Destination Address"
msgstr "目标地址"
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:137
msgid "Destination Port"
msgstr "目标端口"
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:118
msgid "Destination Protocol"
msgstr "目标协议"
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:32
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:51
msgid "Enabled"
msgstr "启用"
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:29
msgid "Global Settings"
msgstr "全局设置"
#: luci-app-socat/root/usr/share/rpcd/acl.d/luci-app-socat.json:3
msgid "Grant UCI access for luci-app-socat"
msgstr ""
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:89
msgid "IPv4 Only"
msgstr "仅 IPv4"
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:88
msgid "IPv4 and IPv6"
msgstr "IPv4 和 IPv6"
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:90
msgid "IPv6 Only"
msgstr "仅 IPv6"
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:87
msgid "Listen Address Family"
msgstr "监听地址族"
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:108
msgid "Listen Port"
msgstr "监听端口"
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:94
msgid "Listen Protocol"
msgstr "监听协议"
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:141
msgid "Open Firewall Port"
msgstr "打开防火墙端口"
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:35
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:84
msgid "Port Forwarding"
msgstr "端口转发"
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:83
msgid "Protocol Type"
msgstr "协议类型"
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:81
msgid "Remarks"
msgstr "备注"
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:113
msgid "Reuse Port"
msgstr "重用端口"
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:27
#: luci-app-socat/root/usr/share/luci/menu.d/luci-app-socat.json:3
msgid "Socat"
msgstr ""
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:48
msgid "Socat Configuration"
msgstr "Socat 配置"
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:27
msgid ""
"Socat is a relay for bidirectional data transfer between two independent "
"data channels."
msgstr "Socat 是一个在两个独立数据通道之间进行双向数据转发的工具。"
#: luci-app-socat/htdocs/luci-static/resources/view/socat.js:56
msgid "Status"
msgstr "状态"
@@ -0,0 +1,4 @@
config global 'global'
option enable '1'
+118
View File
@@ -0,0 +1,118 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2020 Lienol <lawlienol@gmail.com>
# Copyright (C) 2026 sbwml <admin@cooluc.com>
USE_PROCD=1
START=99
STOP=10
CONFIG="socat"
CONFIG_PATH="/var/etc/${CONFIG}"
firewall_add_rule() {
local ports="$1"
[ -z "$ports" ] && return 1
uci -q delete firewall.socat
uci set firewall.socat=rule
uci set firewall.socat.name="socat"
uci set firewall.socat.target="ACCEPT"
uci set firewall.socat.src="wan"
uci set firewall.socat.dest_port="$ports"
uci set firewall.socat.enabled="1"
uci commit firewall
/etc/init.d/firewall reload >/dev/null 2>&1
}
firewall_del_rule() {
uci -q delete firewall.socat
uci commit firewall 2>/dev/null
/etc/init.d/firewall reload >/dev/null 2>&1
}
start_instance() {
local cfg="$1"
local enable remarks protocol family proto listen_port reuseaddr
local dest_proto dest_ip dest_port firewall_accept listen socat_opts
config_get_bool enable "$cfg" "enable" 0
[ "$enable" -eq 0 ] && return 0
config_get remarks "$cfg" "remarks" ""
config_get protocol "$cfg" "protocol" ""
config_get family "$cfg" "family" ""
config_get proto "$cfg" "proto" ""
config_get listen_port "$cfg" "listen_port" ""
config_get_bool reuseaddr "$cfg" "reuseaddr" 0
config_get dest_proto "$cfg" "dest_proto" ""
config_get dest_ip "$cfg" "dest_ip" ""
config_get dest_port "$cfg" "dest_port" ""
config_get_bool firewall_accept "$cfg" "firewall_accept" 0
if [ -z "$listen_port" ] || [ -z "$dest_ip" ] || [ -z "$dest_port" ]; then
return 1
fi
ln -sf /usr/bin/socat "${CONFIG_PATH}/${cfg}"
socat_opts=""
[ "$reuseaddr" -eq 1 ] && socat_opts="${socat_opts},reuseaddr"
[ "$family" = "6" ] && socat_opts="${socat_opts},ipv6-v6only"
socat_opts="${socat_opts},fork"
if [ "$protocol" = "port_forwards" ]; then
listen="${proto}${family}"
[ -z "$family" ] && listen="${proto}6"
procd_open_instance "$cfg"
procd_set_param command "${CONFIG_PATH}/${cfg}"
procd_append_param command "${listen}-listen:${listen_port}${socat_opts}"
procd_append_param command "${dest_proto}:${dest_ip}:${dest_port}"
procd_set_param respawn 3600 5 3
procd_set_param stdout 0
procd_set_param stderr 0
procd_close_instance
if [ "$firewall_accept" -eq 1 ]; then
echo "$listen_port" >> "/var/etc/${CONFIG}.port"
fi
fi
}
start_service() {
local global_enable accept_ports
config_load "luci_socat"
config_get_bool global_enable "global" "enable" 0
if [ "$global_enable" -eq 0 ]; then
return 0
fi
mkdir -p "$CONFIG_PATH"
rm -f "/var/etc/${CONFIG}.port"
config_foreach start_instance "config"
accept_ports=$(cat "/var/etc/${CONFIG}.port" 2>/dev/null | tr '\n' ' ')
if [ -n "$accept_ports" ]; then
firewall_add_rule "$accept_ports"
fi
}
stop_service() {
firewall_del_rule
rm -rf "$CONFIG_PATH" "/var/etc/${CONFIG}.port"
}
service_triggers() {
procd_add_reload_trigger "luci_socat"
}
reload_service() {
stop
sleep 1
start
}
@@ -0,0 +1,12 @@
{
"admin/services/socat": {
"title": "Socat",
"action": {
"type": "view",
"path": "socat"
},
"depends": {
"acl": [ "luci-app-socat" ]
}
}
}
@@ -0,0 +1,14 @@
{
"luci-app-socat": {
"description": "Grant UCI access for luci-app-socat",
"read": {
"ubus": {
"service": [ "list" ]
},
"uci": [ "luci_socat" ]
},
"write": {
"uci": [ "luci_socat" ]
}
}
}
@@ -0,0 +1,4 @@
{
"config": "luci_socat",
"init": "luci_socat"
}