mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-01 16:44:23 +08:00
🏅 Sync 2026-10-21 14:22:54
This commit is contained in:
1 parent
0b7c0117b8
commit
f608112d08
29 files changed
+752
-371
No files matched your search
+2
-5
@@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=gately
|
||||
PKG_VERSION:=0.5.3
|
||||
PKG_RELEASE:=2
|
||||
PKG_RELEASE:=3
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/wangwanjie/gately/tar.gz/v$(PKG_VERSION)?
|
||||
@@ -20,14 +20,11 @@ PKG_BUILD_DEPENDS:=golang/host node/host node-pnpm/host
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
PKG_BUILD_FLAGS:=no-mips16
|
||||
|
||||
BUILD_DATE:=$(shell date -u -d "@$(SOURCE_DATE_EPOCH)" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||
|
||||
GO_PKG:=github.com/wangwanjie/gately
|
||||
GO_PKG_BUILD_PKG:=$(GO_PKG)/cmd/gately
|
||||
GO_PKG_LDFLAGS_X:=\
|
||||
$(GO_PKG)/internal/version.Version=v$(PKG_VERSION) \
|
||||
$(GO_PKG)/internal/version.Commit=$(PKG_VERSION) \
|
||||
$(GO_PKG)/internal/version.BuildDate=$(BUILD_DATE)
|
||||
$(GO_PKG)/internal/version.Commit=$(PKG_VERSION)
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk
|
||||
|
||||
@@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-daede
|
||||
PKG_VERSION:=1.15
|
||||
PKG_RELEASE:=53
|
||||
PKG_RELEASE:=54
|
||||
PKG_MAINTAINER:=kenzok8
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
||||
|
||||
|
||||
@@ -425,14 +425,11 @@ return view.extend({
|
||||
btn.disabled = true;
|
||||
} else if (updatable) {
|
||||
meta = _('installed') + ': ' + entry.r.installed + ' → ' + _('latest') + ': ' + entry.r.latest;
|
||||
} else if (cmp < 0) {
|
||||
meta = _('installed') + ': ' + entry.r.installed + ' · ' + _('feed version older: %s').format(entry.r.latest);
|
||||
btn.disabled = true;
|
||||
} else {
|
||||
meta = _('installed') + ': ' + entry.r.installed + ' · ' + _('up to date');
|
||||
btn.disabled = true;
|
||||
}
|
||||
const uncertain = entry.r.installed && (indexState !== 'success' || !entry.r.latest || cmp < 0);
|
||||
const uncertain = entry.r.installed && (indexState !== 'success' || !entry.r.latest);
|
||||
pkgBody.appendChild(mkRow(
|
||||
updatable ? '↑' : (uncertain ? '⚠' : (entry.r.installed ? '✓' : '✗')),
|
||||
updatable ? 'dd-up-new' : (uncertain ? 'dd-up-warn' : (entry.r.installed ? 'dd-up-ok' : 'dd-up-err')),
|
||||
|
||||
@@ -329,9 +329,6 @@ msgstr "正在刷新软件源"
|
||||
msgid "package not found in configured feeds"
|
||||
msgstr "当前软件源中没有此包"
|
||||
|
||||
msgid "feed version older: %s"
|
||||
msgstr "软件源版本较旧:%s"
|
||||
|
||||
msgid "Unavailable"
|
||||
msgstr "不可用"
|
||||
|
||||
|
||||
@@ -8,20 +8,9 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-gately
|
||||
PKG_VERSION:=1.0.1
|
||||
PKG_RELEASE:=1
|
||||
|
||||
LUCI_TITLE:=LuCI Support for Gately
|
||||
LUCI_DEPENDS:=+gately
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
define Package/$(PKG_NAME)/postinst
|
||||
#!/bin/sh
|
||||
[ -n "$${IPKG_INSTROOT}" ] || {
|
||||
(sleep 1; /etc/init.d/rpcd reload) >/dev/null 2>&1 &
|
||||
}
|
||||
exit 0
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/prerm
|
||||
#!/bin/sh
|
||||
|
||||
@@ -41,6 +41,12 @@ return view.extend({
|
||||
return Promise.all(self.pendingTasks);
|
||||
}).then(function() {
|
||||
return uci.save();
|
||||
}).then(function() {
|
||||
return callSetConfig('commit_uci', '');
|
||||
}).then(function() {
|
||||
if (ui.changes && typeof ui.changes.setIndicator === 'function') {
|
||||
ui.changes.setIndicator(0);
|
||||
}
|
||||
}).catch(function(err) {
|
||||
ui.addNotification(null, E('p', err.message || String(err)), 'error');
|
||||
return Promise.reject(err);
|
||||
@@ -50,13 +56,14 @@ return view.extend({
|
||||
handleSaveApply: function(ev, mode) {
|
||||
var self = this;
|
||||
return this.handleSave(ev).then(function() {
|
||||
return ui.changes.apply(mode == '0');
|
||||
}).then(function() {
|
||||
var enabled = uci.get('gately', 'main', 'enabled');
|
||||
var action = (enabled === '1') ? 'restart' : 'stop';
|
||||
ui.showModal(null, [ E('p', { class: 'spinning' }, _('Updating configuration and restarting service...')) ]);
|
||||
return callService(action).then(function() {
|
||||
ui.hideModal();
|
||||
if (ui.changes && typeof ui.changes.setIndicator === 'function') {
|
||||
ui.changes.setIndicator(0);
|
||||
}
|
||||
ui.addNotification(null, E('p', _('Configuration updated successfully')), 'info');
|
||||
uci.unload('gately');
|
||||
return self.load().then(function(data) {
|
||||
@@ -69,32 +76,6 @@ return view.extend({
|
||||
});
|
||||
},
|
||||
|
||||
handleUpdate: function(key, value) {
|
||||
ui.showModal(null, [ E('p', { class: 'spinning' }, _('Updating configuration and restarting service...')) ]);
|
||||
var self = this;
|
||||
|
||||
return callSetConfig(key, value).then(function(res) {
|
||||
if (res && res.ret === 0) {
|
||||
var enabled = uci.get('gately', 'main', 'enabled');
|
||||
var action = (enabled === '1') ? 'restart' : 'stop';
|
||||
return callService(action).then(function() {
|
||||
ui.hideModal();
|
||||
ui.addNotification(null, E('p', _('Configuration updated successfully')), 'info');
|
||||
uci.unload('gately');
|
||||
return self.load().then(function(data) {
|
||||
return self.render(data);
|
||||
}).then(function(node) {
|
||||
var mapEl = document.querySelector('.cbi-map');
|
||||
if (mapEl && mapEl.parentNode) dom.content(mapEl.parentNode, node);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
ui.hideModal();
|
||||
ui.addNotification(null, E('p', (res && res.error) ? res.error : _('Failed to update configuration')), 'error');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
render: function(data) {
|
||||
var self = this;
|
||||
var baseConf = (data[1] && data[1].base_conf) ? data[1].base_conf : {};
|
||||
@@ -189,16 +170,6 @@ return view.extend({
|
||||
self.queueSetConfig('switch_Internetaccess', false);
|
||||
};
|
||||
|
||||
// Reset Auth
|
||||
o = s.option(form.Button, '_reset_auth', _('Reset Account and Password'));
|
||||
o.inputtitle = _('Reset to Default (admin / admin123456)');
|
||||
o.inputstyle = 'negative';
|
||||
o.onclick = ui.createHandlerFn(self, function() {
|
||||
if (confirm(_('Are you sure you want to reset the admin account and password to default (admin / admin123456)?'))) {
|
||||
return self.handleUpdate('reset_auth_info', '');
|
||||
}
|
||||
});
|
||||
|
||||
return m.render();
|
||||
}
|
||||
});
|
||||
@@ -9,35 +9,6 @@ var callGetInfo = rpc.declare({ object: 'luci.gately', method: 'get_info', expec
|
||||
var callGetStatus = rpc.declare({ object: 'luci.gately', method: 'get_status', expect: { } });
|
||||
var callService = rpc.declare({ object: 'luci.gately', method: 'service', params: ['action'], expect: { } });
|
||||
|
||||
function pad2(n) {
|
||||
return (n < 10 ? '0' : '') + n;
|
||||
}
|
||||
|
||||
function formatBuildDate(raw) {
|
||||
if (!raw || raw === '-' || raw === 'unknown') return '-';
|
||||
var str = String(raw).trim();
|
||||
var d = null;
|
||||
if (/^\d{9,13}$/.test(str)) {
|
||||
var ts = parseInt(str, 10);
|
||||
if (str.length <= 10) ts *= 1000;
|
||||
d = new Date(ts);
|
||||
} else {
|
||||
var parsed = Date.parse(str);
|
||||
if (!isNaN(parsed)) {
|
||||
d = new Date(parsed);
|
||||
}
|
||||
}
|
||||
if (d && !isNaN(d.getTime())) {
|
||||
return d.getFullYear() + '-' +
|
||||
pad2(d.getMonth() + 1) + '-' +
|
||||
pad2(d.getDate()) + ' ' +
|
||||
pad2(d.getHours()) + ':' +
|
||||
pad2(d.getMinutes()) + ':' +
|
||||
pad2(d.getSeconds());
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
return view.extend({
|
||||
load: function() {
|
||||
return callGetInfo();
|
||||
@@ -118,8 +89,11 @@ return view.extend({
|
||||
el = document.getElementById('_gatelyArch');
|
||||
if (el) dom.content(el, info.gatelyArch || '-');
|
||||
|
||||
el = document.getElementById('_gatelyDate');
|
||||
if (el) dom.content(el, formatBuildDate(gatelyInfo.Date));
|
||||
el = document.getElementById('_gatelyUser');
|
||||
if (el) dom.content(el, info.adminUser || 'admin');
|
||||
|
||||
el = document.getElementById('_gatelyPassword');
|
||||
if (el) dom.content(el, info.adminPassword || 'admin123456');
|
||||
|
||||
if (info.running && info.adminPort) {
|
||||
var url = 'http://' + window.location.hostname + ':' + info.adminPort + (info.adminSafeUrl || '');
|
||||
@@ -179,8 +153,12 @@ return view.extend({
|
||||
E('td', { class: 'td left', id: '_gatelyArch' }, info.gatelyArch || '-')
|
||||
]),
|
||||
E('tr', { class: 'tr' }, [
|
||||
E('td', { class: 'td left' }, _('Compile Time')),
|
||||
E('td', { class: 'td left', id: '_gatelyDate' }, formatBuildDate(gatelyInfo.Date))
|
||||
E('td', { class: 'td left' }, _('Admin Account')),
|
||||
E('td', { class: 'td left', id: '_gatelyUser' }, info.adminUser || 'admin')
|
||||
]),
|
||||
E('tr', { class: 'tr' }, [
|
||||
E('td', { class: 'td left' }, _('Admin Password')),
|
||||
E('td', { class: 'td left', id: '_gatelyPassword' }, info.adminPassword || 'admin123456')
|
||||
]),
|
||||
E('tr', { class: 'tr' }, [
|
||||
E('td', { class: 'td left' }, _('Admin Panel')),
|
||||
|
||||
@@ -52,7 +52,10 @@ msgstr ""
|
||||
msgid "Architecture"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compile Time"
|
||||
msgid "Admin Account"
|
||||
msgstr ""
|
||||
|
||||
msgid "Admin Password"
|
||||
msgstr ""
|
||||
|
||||
msgid "Admin Panel"
|
||||
@@ -109,15 +112,6 @@ msgstr ""
|
||||
msgid "Allow Internet Access"
|
||||
msgstr ""
|
||||
|
||||
msgid "Reset Account and Password"
|
||||
msgstr ""
|
||||
|
||||
msgid "Reset to Default (admin / admin123456)"
|
||||
msgstr ""
|
||||
|
||||
msgid "Are you sure you want to reset the admin account and password to default (admin / admin123456)?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Updating configuration and restarting service..."
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -52,8 +52,11 @@ msgstr "当前版本"
|
||||
msgid "Architecture"
|
||||
msgstr "系统架构"
|
||||
|
||||
msgid "Compile Time"
|
||||
msgstr "构建时间"
|
||||
msgid "Admin Account"
|
||||
msgstr "管理员账号"
|
||||
|
||||
msgid "Admin Password"
|
||||
msgstr "管理员密码"
|
||||
|
||||
msgid "Admin Panel"
|
||||
msgstr "管理后台"
|
||||
@@ -109,15 +112,6 @@ msgstr "安全入口不能以 /api 或 /assets 开头,且不能包含空格、
|
||||
msgid "Allow Internet Access"
|
||||
msgstr "允许外网访问管理后台"
|
||||
|
||||
msgid "Reset Account and Password"
|
||||
msgstr "重置账号与密码"
|
||||
|
||||
msgid "Reset to Default (admin / admin123456)"
|
||||
msgstr "恢复默认认证 (admin / admin123456)"
|
||||
|
||||
msgid "Are you sure you want to reset the admin account and password to default (admin / admin123456)?"
|
||||
msgstr "确定要将管理员账号和密码恢复为默认值 (admin / admin123456) 吗?"
|
||||
|
||||
msgid "Updating configuration and restarting service..."
|
||||
msgstr "正在更新配置并重启服务..."
|
||||
|
||||
|
||||
@@ -34,11 +34,11 @@ function is_running() {
|
||||
|
||||
function get_version_info() {
|
||||
if (!access(BIN_PATH, 'x')) {
|
||||
return { version: '-', commit: '-', buildDate: '-', go: '-' };
|
||||
return { version: '-', commit: '-', go: '-' };
|
||||
}
|
||||
let p = popen(BIN_PATH + ' -version 2>/dev/null');
|
||||
if (!p) {
|
||||
return { version: '-', commit: '-', buildDate: '-', go: '-' };
|
||||
return { version: '-', commit: '-', go: '-' };
|
||||
}
|
||||
let raw = trim(p.read('all') || '');
|
||||
p.close();
|
||||
@@ -84,6 +84,20 @@ function write_gately_json(configdir, settings) {
|
||||
}
|
||||
|
||||
// Gately stores admin account in <configdir>/account.json (accountName = "account")
|
||||
function read_account_json(configdir) {
|
||||
let path = configdir + '/account.json';
|
||||
if (!access(path, 'r')) {
|
||||
return {};
|
||||
}
|
||||
let content = readfile(path);
|
||||
if (!content) return {};
|
||||
try {
|
||||
return json(content);
|
||||
} catch (e) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
function clear_account_json(configdir) {
|
||||
let acc_file = configdir + '/account.json';
|
||||
if (access(acc_file, 'f')) {
|
||||
@@ -136,6 +150,7 @@ const methods = {
|
||||
let ver = get_version_info();
|
||||
let arch = get_arch();
|
||||
let settings = read_gately_json(uci_cfg.configdir);
|
||||
let account = read_account_json(uci_cfg.configdir);
|
||||
|
||||
let effective_listen = settings.listen || ':16680';
|
||||
let admin_port = parse_port_from_listen(effective_listen);
|
||||
@@ -144,15 +159,18 @@ const methods = {
|
||||
safe_path = '/' + safe_path;
|
||||
}
|
||||
let lan_only = (settings.lanOnly === true);
|
||||
let admin_user = account.username || 'admin';
|
||||
let admin_password = uci_cfg.initial_password || 'admin123456';
|
||||
|
||||
return {
|
||||
running: st.running,
|
||||
pid: st.pid,
|
||||
gatelyArch: arch,
|
||||
adminUser: admin_user,
|
||||
adminPassword: admin_password,
|
||||
gatelyInfo: sprintf('%J', {
|
||||
Version: ver.version || '-',
|
||||
Commit: ver.commit || '-',
|
||||
Date: ver.buildDate || '-',
|
||||
Go: ver.go || '-'
|
||||
}),
|
||||
adminPort: admin_port,
|
||||
@@ -222,12 +240,11 @@ const methods = {
|
||||
c.commit('gately');
|
||||
clear_account_json(configdir);
|
||||
return { ret: 0 };
|
||||
} else if (key === 'reset_auth_info') {
|
||||
} else if (key === 'commit_uci') {
|
||||
let c = cursor();
|
||||
c.load('gately');
|
||||
c.set('gately', 'main', 'initial_password', 'admin123456');
|
||||
c.commit('gately');
|
||||
clear_account_json(configdir);
|
||||
system('uci -q commit gately >/dev/null 2>&1');
|
||||
return { ret: 0 };
|
||||
}
|
||||
|
||||
@@ -239,6 +256,11 @@ const methods = {
|
||||
args: { action: 'action' },
|
||||
call: function(req) {
|
||||
let action = req.args?.action;
|
||||
let c = cursor();
|
||||
c.load('gately');
|
||||
c.commit('gately');
|
||||
system('uci -q commit gately >/dev/null 2>&1');
|
||||
|
||||
if (action === 'restart' || action === 'reload') {
|
||||
let res = system(INIT_SCRIPT + ' stop >/dev/null 2>&1; sleep 1; ' + INIT_SCRIPT + ' start >/dev/null 2>&1');
|
||||
return { result: (res === 0), ret: res };
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-open-box
|
||||
PKG_VERSION:=0.1.342
|
||||
PKG_RELEASE:=38
|
||||
PKG_VERSION:=0.1.343
|
||||
PKG_RELEASE:=39
|
||||
|
||||
PKG_MAINTAINER:=liandu2024
|
||||
PKG_LICENSE:=GPL-3.0-or-later
|
||||
|
||||
@@ -8,14 +8,13 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall
|
||||
PKG_VERSION:=26.10.16
|
||||
PKG_RELEASE:=342
|
||||
PKG_RELEASE:=343
|
||||
PKG_PO_VERSION:=$(PKG_VERSION)
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_Nftables_Transparent_Proxy \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Geoview \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_SmartDNS \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Haproxy \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy \
|
||||
@@ -39,7 +38,6 @@ LUCI_DEPENDS:=+coreutils +coreutils-base64 +coreutils-nohup +coreutils-timeout +
|
||||
+microsocks +resolveip +tcping +lyaml \
|
||||
+ipt2socks \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Geoview:geoview \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_SmartDNS:smartdns \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Haproxy:haproxy \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria:hysteria \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy:naiveproxy \
|
||||
@@ -88,10 +86,7 @@ config PACKAGE_$(PKG_NAME)_Nftables_Transparent_Proxy
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_Geoview
|
||||
bool "Include Geoview"
|
||||
default y if aarch64||i386||x86_64
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_SmartDNS
|
||||
bool "Include SmartDNS"
|
||||
select PACKAGE_geoview
|
||||
default y if aarch64||i386||x86_64
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_Haproxy
|
||||
|
||||
@@ -3,8 +3,8 @@ include $(TOPDIR)/rules.mk
|
||||
LUCI_TITLE:=luci-app-ssr-plus
|
||||
LUCI_PKGARCH:=all
|
||||
PKG_NAME:=luci-app-ssr-plus
|
||||
PKG_VERSION:=196
|
||||
PKG_RELEASE:=93
|
||||
PKG_VERSION:=197
|
||||
PKG_RELEASE:=94
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \
|
||||
@@ -119,7 +119,7 @@ endchoice
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_ChinaDNS_NG
|
||||
bool "Include ChinaDNS-NG"
|
||||
default y if aarch64||arm||i386||x86_64
|
||||
default n
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_MosDNS
|
||||
bool "Include MosDNS"
|
||||
@@ -164,7 +164,7 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_V2ray_Plugin
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client
|
||||
bool "Include ShadowsocksR Libev Client"
|
||||
default y
|
||||
default n
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Server
|
||||
bool "Include ShadowsocksR Libev Server"
|
||||
|
||||
@@ -474,11 +474,12 @@ if is_finded("xray") then
|
||||
o:value("wireguard", translate("WireGuard"))
|
||||
o:value("naive", "NaiveProxy (Xray / Cronet)")
|
||||
o:value("shadowsocksr", "ShadowsocksR (Xray)")
|
||||
o:value("tuic", "TUIC (Xray)")
|
||||
end
|
||||
if is_finded("xray") then
|
||||
o:value("hysteria2", translate("Hysteria2"))
|
||||
end
|
||||
if is_finded("mihomo") then
|
||||
if is_finded("xray") or is_finded("mihomo") then
|
||||
o:value("snell", translate("Snell"))
|
||||
end
|
||||
o:value("socks", translate("Socks"))
|
||||
@@ -926,6 +927,17 @@ end
|
||||
o.rmempty = true
|
||||
o.default="auto"
|
||||
|
||||
o = s:option(ListValue, "xray_tuic_version", "TUIC Version")
|
||||
o:value("5", "v5 (UUID / Password)")
|
||||
o:value("4", "v4 (Token)")
|
||||
o.default = "5"
|
||||
o:depends({type = "v2ray", v2ray_protocol = "tuic"})
|
||||
o = s:option(Value, "xray_tuic_token", "TUIC Token")
|
||||
o.password = true
|
||||
o:depends({type = "v2ray", v2ray_protocol = "tuic", xray_tuic_version = "4"})
|
||||
o = s:option(Value, "xray_tuic_ca", translate("Certificate File Path"))
|
||||
o:depends({type = "v2ray", v2ray_protocol = "tuic"})
|
||||
|
||||
-- [[ TUIC ]]
|
||||
-- TuicNameId
|
||||
o = s:option(Value, "tuic_uuid", translate("TUIC User UUID"))
|
||||
@@ -933,6 +945,7 @@ o.password = true
|
||||
o.rmempty = true
|
||||
o.default = uuid
|
||||
o:depends("type", "tuic")
|
||||
o:depends({type = "v2ray", v2ray_protocol = "tuic", xray_tuic_version = "5"})
|
||||
|
||||
--Tuic IP
|
||||
o = s:option(Value, "tuic_ip", translate("TUIC Server IP Address"))
|
||||
@@ -947,9 +960,11 @@ o.password = true
|
||||
o.rmempty = true
|
||||
o.default = ""
|
||||
o:depends("type", "tuic")
|
||||
o:depends({type = "v2ray", v2ray_protocol = "tuic", xray_tuic_version = "5"})
|
||||
|
||||
o = s:option(ListValue, "udp_relay_mode", translate("UDP relay mode"))
|
||||
o:depends("type", "tuic")
|
||||
o:depends({type = "v2ray", v2ray_protocol = "tuic"})
|
||||
o:value("native", translate("native UDP characteristics"))
|
||||
o:value("quic", translate("lossless UDP relay using QUIC streams"))
|
||||
o.default = "native"
|
||||
@@ -957,6 +972,7 @@ o.rmempty = true
|
||||
|
||||
o = s:option(ListValue, "congestion_control", translate("Congestion control algorithm"))
|
||||
o:depends("type", "tuic")
|
||||
o:depends({type = "v2ray", v2ray_protocol = "tuic"})
|
||||
o:value("bbr", translate("BBR"))
|
||||
o:value("cubic", translate("CUBIC"))
|
||||
o:value("new_reno", translate("New Reno"))
|
||||
@@ -965,12 +981,14 @@ o.rmempty = true
|
||||
|
||||
o = s:option(Value, "heartbeat", translate("Heartbeat interval(second)"))
|
||||
o:depends("type", "tuic")
|
||||
o:depends({type = "v2ray", v2ray_protocol = "tuic"})
|
||||
o.datatype = "uinteger"
|
||||
o.default = "3"
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(Value, "timeout", translate("Timeout for establishing a connection to server(second)"))
|
||||
o:depends("type", "tuic")
|
||||
o:depends({type = "v2ray", v2ray_protocol = "tuic"})
|
||||
o.datatype = "uinteger"
|
||||
o.default = "8"
|
||||
o.rmempty = true
|
||||
@@ -1006,6 +1024,7 @@ o.rmempty = true
|
||||
|
||||
o = s:option(Flag, "zero_rtt_handshake", translate("Enable 0-RTT QUIC handshake"))
|
||||
o:depends("type", "tuic")
|
||||
o:depends({type = "v2ray", v2ray_protocol = "tuic"})
|
||||
o.default = "0"
|
||||
o.rmempty = true
|
||||
|
||||
@@ -1087,10 +1106,17 @@ o = s:option(Value, "snell_obfs_host", translate("Snell Obfs Host"))
|
||||
o.rmempty = true
|
||||
o:depends({type = "v2ray", v2ray_protocol = "snell"})
|
||||
|
||||
o = s:option(Flag, "snell_reuse", translate("Connection reuse"))
|
||||
o.default = "0"
|
||||
for _, version in ipairs({"4", "5"}) do
|
||||
o:depends({type = "v2ray", v2ray_protocol = "snell", snell_version = version})
|
||||
end
|
||||
|
||||
-- 传输协议
|
||||
o = s:option(ListValue, "transport", translate("Transport"))
|
||||
o:value("raw", "RAW (TCP)")
|
||||
o:value("kcp", "mKCP")
|
||||
o:value("kcptun", "Kcptun (Xray)")
|
||||
o:value("ws", "WebSocket")
|
||||
o:value("httpupgrade", "HTTPUpgrade")
|
||||
o:value("xhttp", "XHTTP (SplitHTTP)")
|
||||
@@ -1105,6 +1131,43 @@ o:depends({type = "v2ray", v2ray_protocol = "shadowsocks"})
|
||||
o:depends({type = "v2ray", v2ray_protocol = "socks"})
|
||||
o:depends({type = "v2ray", v2ray_protocol = "http"})
|
||||
|
||||
-- Native Kcptun transport (separate from mKCP and the external Kcptun client).
|
||||
o = s:option(Value, "xray_kcptun_key", "Kcptun Key")
|
||||
o:depends("transport", "kcptun")
|
||||
o.password = true
|
||||
o.rmempty = false
|
||||
o = s:option(ListValue, "xray_kcptun_crypt", "Kcptun Encryption")
|
||||
o:depends("transport", "kcptun")
|
||||
for _, crypt in ipairs({"aes", "aes-128", "aes-192", "aes-128-gcm", "salsa20", "tea", "xor", "none", "null", "blowfish", "twofish", "cast5", "3des", "xtea"}) do o:value(crypt, crypt) end
|
||||
o.default = "aes"
|
||||
o = s:option(ListValue, "xray_kcptun_mode", "Kcptun Mode")
|
||||
o:depends("transport", "kcptun")
|
||||
for _, mode in ipairs({"normal", "fast", "fast2", "fast3", "manual"}) do o:value(mode, mode) end
|
||||
o.default = "fast"
|
||||
o = s:option(ListValue, "xray_kcptun_smuxver", "Kcptun smux Version")
|
||||
o:depends("transport", "kcptun")
|
||||
o:value("1", "v1")
|
||||
o:value("2", "v2")
|
||||
o.default = "1"
|
||||
o = s:option(Flag, "xray_kcptun_nocomp", translate("Disable Compression"))
|
||||
o:depends("transport", "kcptun")
|
||||
o.default = "0"
|
||||
o = s:option(Value, "xray_kcptun_conn", translate("Connections"))
|
||||
o:depends("transport", "kcptun")
|
||||
o.datatype = "range(1,256)"
|
||||
o.default = "1"
|
||||
o = s:option(TextValue, "xray_kcptun_options", "Kcptun Advanced Options (JSON)")
|
||||
o:depends("transport", "kcptun")
|
||||
o.rows = 4
|
||||
o.rmempty = true
|
||||
o.description = translate("Optional MTU, FEC, windows and expiry settings. Encryption, key, compression and smux version must match the server. This transports streams over UDP; native proxy UDP is separate.")
|
||||
function o.validate(self, value, section)
|
||||
if not value or value:match("^%s*$") then return "" end
|
||||
local ok, parsed = pcall(luci.jsonc.parse, value)
|
||||
if ok and type(parsed) == "table" and value:match("^%s*{") then return value end
|
||||
return nil, translate("Must be a JSON object")
|
||||
end
|
||||
|
||||
-- [[ RAW部分 ]]--
|
||||
-- TCP伪装
|
||||
o = s:option(ListValue, "tcp_guise", translate("Camouflage Type"))
|
||||
@@ -1437,7 +1500,7 @@ if protocols and type(protocols) == "table" and #protocols > 0 then
|
||||
if not proto:find("^_") then
|
||||
if proto == "hysteria2" then
|
||||
o:depends({type = "v2ray", v2ray_protocol = "hysteria2", hysteria2_realms = false})
|
||||
elseif proto ~= "socks" and proto ~= "http" and proto ~= "shadowsocksr" then
|
||||
elseif proto ~= "socks" and proto ~= "http" and proto ~= "shadowsocksr" and proto ~= "tuic" and proto ~= "snell" then
|
||||
o:depends({type = "v2ray", v2ray_protocol = proto})
|
||||
end
|
||||
end
|
||||
@@ -1468,6 +1531,39 @@ o.validate = function(self, value)
|
||||
end
|
||||
end
|
||||
|
||||
-- ShadowTLS wraps the existing TCP proxy protocol in Xray.
|
||||
o = s:option(Flag, "xray_shadowtls", "ShadowTLS (Xray)")
|
||||
o.default = "0"
|
||||
for _, proto in ipairs({"vmess", "vless", "trojan", "shadowsocks"}) do
|
||||
o:depends({type = "v2ray", v2ray_protocol = proto, transport = "raw", tls = false, reality = false})
|
||||
end
|
||||
o.description = translate("ShadowTLS protects TCP connections. The inner proxy protocol must provide encryption.")
|
||||
o = s:option(ListValue, "xray_shadowtls_version", "ShadowTLS Version")
|
||||
o:depends("xray_shadowtls", "1")
|
||||
o:value("3", "v3")
|
||||
o:value("2", "v2")
|
||||
o:value("1", "v1")
|
||||
o.default = "3"
|
||||
o = s:option(Value, "xray_shadowtls_password", "ShadowTLS Password")
|
||||
o:depends({xray_shadowtls = "1", xray_shadowtls_version = "2"})
|
||||
o:depends({xray_shadowtls = "1", xray_shadowtls_version = "3"})
|
||||
o.password = true
|
||||
o.rmempty = false
|
||||
o = s:option(Value, "xray_shadowtls_sni", "ShadowTLS SNI")
|
||||
o:depends("xray_shadowtls", "1")
|
||||
o.datatype = "hostname"
|
||||
o.rmempty = false
|
||||
o = s:option(ListValue, "xray_shadowtls_fingerprint", translate("TLS Client Fingerprint"))
|
||||
o:depends("xray_shadowtls", "1")
|
||||
for _, fp in ipairs({"chrome", "firefox", "safari", "ios", "android", "edge", "none"}) do o:value(fp, fp) end
|
||||
o.default = "chrome"
|
||||
o = s:option(Flag, "xray_shadowtls_strict", translate("TLS 1.3 Strict mode"))
|
||||
o:depends({xray_shadowtls = "1", xray_shadowtls_version = "3"})
|
||||
o.default = "1"
|
||||
o = s:option(Flag, "xray_shadowtls_insecure", translate("Allow Insecure"))
|
||||
o:depends("xray_shadowtls", "1")
|
||||
o.default = "0"
|
||||
|
||||
-- [[ TLS ]]--
|
||||
o = s:option(Flag, "tls", translate("TLS"))
|
||||
o.rmempty = true
|
||||
@@ -1602,6 +1698,7 @@ o:depends("tls", true)
|
||||
o:depends("xtls", true)
|
||||
o:depends("reality", true)
|
||||
o.rmempty = true
|
||||
o:depends({type = "v2ray", v2ray_protocol = "tuic"})
|
||||
|
||||
o:depends({type = "v2ray", v2ray_protocol = "naive"})
|
||||
|
||||
@@ -1631,6 +1728,7 @@ o:value("h3,h2,http/1.1")
|
||||
o:value("spdy/3.1")
|
||||
o:value("h3,spdy/3.1")
|
||||
o:depends("type", "tuic")
|
||||
o:depends({type = "v2ray", v2ray_protocol = "tuic"})
|
||||
|
||||
-- IP STACK PREFERENCE
|
||||
o = s:option(ListValue, "ipstack_prefer", translate("IP Stack Preference"))
|
||||
@@ -1648,6 +1746,7 @@ o:depends("type", "trojan")
|
||||
o:depends("type", "tuic")
|
||||
o.description = translate("If true, allowss insecure connection at TLS client, e.g., TLS server uses unverifiable certificates.")
|
||||
o:depends("tls", true)
|
||||
o:depends({type = "v2ray", v2ray_protocol = "tuic"})
|
||||
|
||||
if xray_version_val >= 260131 then
|
||||
-- Xray 版本大于等于 26.1.31
|
||||
|
||||
@@ -74,6 +74,10 @@ then
|
||||
end
|
||||
if nixio.fs.access("/usr/bin/xray") or nixio.fs.access("/usr/libexec/xray") then
|
||||
o:value("naive", "NaiveProxy (Xray)")
|
||||
o:value("tuic", "TUIC (Xray)")
|
||||
o:value("snell", "Snell (Xray)")
|
||||
o:value("anytls", "AnyTLS (Xray)")
|
||||
o:value("ssr-xray", "ShadowsocksR (Xray)")
|
||||
end
|
||||
o.default = "socks5"
|
||||
|
||||
@@ -105,6 +109,7 @@ o:depends("type", "ss")
|
||||
o:depends("type", "ssr")
|
||||
o:depends("type", "trojan")
|
||||
o:depends("type", "shadowsocks")
|
||||
o:depends("type", "ssr-xray")
|
||||
|
||||
-- ========== SS/SSR 协议特有 ==========
|
||||
o = s:option(ListValue, "encrypt_method", translate("Encrypt Method"))
|
||||
@@ -235,6 +240,8 @@ o = s:option(Value, "tls_certificateFile", translate("Certificate File Path"))
|
||||
o.description = translate("e.g.: /etc/ssl/fullchain.pem")
|
||||
o.rmempty = true
|
||||
o:depends("tls", "1")
|
||||
o:depends("type", "tuic")
|
||||
o:depends("type", "anytls")
|
||||
|
||||
o:depends("type", "naive")
|
||||
|
||||
@@ -242,6 +249,8 @@ o = s:option(Value, "tls_keyFile", translate("Private Key File Path"))
|
||||
o.description = translate("e.g.: /etc/ssl/private.key")
|
||||
o.rmempty = true
|
||||
o:depends("tls", "1")
|
||||
o:depends("type", "tuic")
|
||||
o:depends("type", "anytls")
|
||||
|
||||
-- ========== 传输层设置 (Transport) ==========
|
||||
o:depends("type", "naive")
|
||||
@@ -411,4 +420,61 @@ o:value("h2,h3", "HTTP/2 + HTTP/3")
|
||||
o.default = "h2"
|
||||
o:depends("type", "naive")
|
||||
|
||||
return m
|
||||
-- TUIC credentials are independent of the legacy server settings.
|
||||
for _, field in ipairs({{"tuic_uuid", "TUIC UUID"}, {"tuic_password", "TUIC Password"}, {"tuic_token", "TUIC v4 Token"}}) do
|
||||
o = s:option(Value, field[1], field[2])
|
||||
o.password = field[1] ~= "tuic_uuid"
|
||||
o:depends("type", "tuic")
|
||||
end
|
||||
|
||||
o = s:option(Value, "snell_psk", translate("Snell PSK"))
|
||||
o.password = true
|
||||
o:depends("type", "snell")
|
||||
o = s:option(ListValue, "snell_version", translate("Snell Version"))
|
||||
for _, version in ipairs({"1", "2", "3", "4", "5"}) do o:value(version, "v" .. version) end
|
||||
o.default = "4"
|
||||
o:depends("type", "snell")
|
||||
o = s:option(ListValue, "snell_obfs", translate("Snell Obfs"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("http", "HTTP")
|
||||
o:value("tls", "TLS")
|
||||
o:depends("type", "snell")
|
||||
o = s:option(Flag, "snell_udp", translate("UDP Relay"))
|
||||
o.default = "1"
|
||||
for _, version in ipairs({"3", "4", "5"}) do
|
||||
o:depends({type = "snell", snell_version = version})
|
||||
end
|
||||
|
||||
o = s:option(Value, "anytls_password", translate("Password"))
|
||||
o.password = true
|
||||
o:depends("type", "anytls")
|
||||
o = s:option(TextValue, "anytls_padding", "AnyTLS Padding Scheme")
|
||||
o.rows = 5
|
||||
o.rmempty = true
|
||||
o:depends("type", "anytls")
|
||||
|
||||
-- Xray SSR has its own validated registry; keep legacy libev choices intact.
|
||||
o = s:option(ListValue, "ssr_method", translate("Encrypt Method"))
|
||||
for _, v in ipairs({"aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", "rc4-md5", "chacha20", "chacha20-ietf", "xchacha20", "none"}) do o:value(v) end
|
||||
o.default = "aes-128-cfb"
|
||||
o.rmempty = false
|
||||
o:depends("type", "ssr-xray")
|
||||
o = s:option(ListValue, "ssr_protocol", translate("Protocol"))
|
||||
for _, v in ipairs({"origin", "auth_sha1_v4", "auth_aes128_md5", "auth_aes128_sha1", "auth_chain_a", "auth_chain_b"}) do o:value(v) end
|
||||
o.default = "auth_aes128_sha1"
|
||||
o.rmempty = false
|
||||
o:depends("type", "ssr-xray")
|
||||
o = s:option(Value, "ssr_protocol_param", "SSR Protocol Param")
|
||||
o.description = "1001:password1,1002:password2"
|
||||
o:depends("type", "ssr-xray")
|
||||
o = s:option(ListValue, "ssr_obfs", translate("Obfs"))
|
||||
for _, v in ipairs({"plain", "http_simple", "http_post", "random_head", "tls1.2_ticket_auth", "tls1.2_ticket_fastauth"}) do o:value(v) end
|
||||
o.default = "plain"
|
||||
o.rmempty = false
|
||||
o:depends("type", "ssr-xray")
|
||||
o = s:option(Value, "ssr_obfs_param", translate("Obfs param (optional)"))
|
||||
o.description = "HTTP Host: example.com,example.org"
|
||||
o:depends({type = "ssr-xray", ssr_obfs = "http_simple"})
|
||||
o:depends({type = "ssr-xray", ssr_obfs = "http_post"})
|
||||
|
||||
return m
|
||||
@@ -111,6 +111,7 @@ function o.cfgvalue(self, section)
|
||||
elseif val == "vless" then return "VLESS (Xray)"
|
||||
elseif val == "trojan" then return "Trojan (Xray)"
|
||||
elseif val == "shadowsocks" then return "Shadowsocks (Xray)"
|
||||
elseif val == "ssr-xray" then return "ShadowsocksR (Xray)"
|
||||
else return val end
|
||||
end
|
||||
|
||||
@@ -126,6 +127,7 @@ end
|
||||
|
||||
o = sec:option(DummyValue, "encrypt_method", translate("Encrypt Method"))
|
||||
function o.cfgvalue(self, section)
|
||||
if self.map:get(section, "type") == "ssr-xray" then return (self.map:get(section, "ssr_method") or "-"):upper() end
|
||||
local method = self.map:get(section, "encrypt_method") or self.map:get(section, "encrypt_method_ss")
|
||||
return method and method:upper() or "-"
|
||||
end
|
||||
|
||||
@@ -992,8 +992,10 @@ use_mihomo_for_ss_rust_server() {
|
||||
}
|
||||
|
||||
start_v2ray_with_mihomo() {
|
||||
[ "$(uci_get_by_name "$1" transport)" = "kcptun" ] && return 1
|
||||
[ "$(uci_get_by_name "$1" xray_shadowtls 0)" = "1" ] && return 1
|
||||
# These nodes use Xray-specific settings.
|
||||
case "$(uci_get_by_name "$1" v2ray_protocol)" in naive|shadowsocksr) return 1 ;; esac
|
||||
case "$(uci_get_by_name "$1" v2ray_protocol)" in naive|shadowsocksr|tuic) return 1 ;; esac
|
||||
local sid="$1"
|
||||
local local_port="$2"
|
||||
local socks_port="$3"
|
||||
@@ -1798,7 +1800,7 @@ start_udp() {
|
||||
;;
|
||||
v2ray)
|
||||
enable_mihomo=$(uci_get_by_type server_subscribe enable_mihomo "")
|
||||
if [ "$(uci_get_by_name "$UDP_RELAY_SERVER" v2ray_protocol)" != "naive" ] && [ "$(uci_get_by_name "$UDP_RELAY_SERVER" v2ray_protocol)" != "shadowsocksr" ] && [ "$enable_mihomo" = "1" ] && has_mihomo_binary; then
|
||||
if [ "$(uci_get_by_name "$UDP_RELAY_SERVER" v2ray_protocol)" != "naive" ] && [ "$(uci_get_by_name "$UDP_RELAY_SERVER" v2ray_protocol)" != "shadowsocksr" ] && [ "$(uci_get_by_name "$UDP_RELAY_SERVER" v2ray_protocol)" != "tuic" ] && [ "$enable_mihomo" = "1" ] && has_mihomo_binary; then
|
||||
redir_udp=0
|
||||
ARG_UDP=""
|
||||
echolog "UDP TPROXY Relay:V2Ray/Xray 单节点由主 Mihomo 实例处理。"
|
||||
@@ -1811,7 +1813,7 @@ start_udp() {
|
||||
echolog "UDP TPROXY Relay:$($(first_type xray) version | head -1) Started!"
|
||||
else
|
||||
# Xray 不存在但 Mihomo 存在,回退到 Mihomo(当 enable_mihomo=0 时)
|
||||
if [ "$(uci_get_by_name "$UDP_RELAY_SERVER" v2ray_protocol)" != "naive" ] && [ "$(uci_get_by_name "$UDP_RELAY_SERVER" v2ray_protocol)" != "shadowsocksr" ] && has_mihomo_binary; then
|
||||
if [ "$(uci_get_by_name "$UDP_RELAY_SERVER" v2ray_protocol)" != "naive" ] && [ "$(uci_get_by_name "$UDP_RELAY_SERVER" v2ray_protocol)" != "shadowsocksr" ] && [ "$(uci_get_by_name "$UDP_RELAY_SERVER" v2ray_protocol)" != "tuic" ] && has_mihomo_binary; then
|
||||
redir_udp=0
|
||||
ARG_UDP=""
|
||||
echolog "UDP TPROXY Relay:Xray 内核不存在,已回退到 Mihomo 内核启动。"
|
||||
@@ -1962,9 +1964,6 @@ start_local() {
|
||||
[ -n "$probe_instance_key" ] && instance_key="$probe_instance_key"
|
||||
if [ "$enable_mihomo" = "1" ] && start_v2ray_with_mihomo "$LOCAL_SERVER" "$local_port" "$local_port" "$instance_key" "socks" "v2ray-local" "Global_Socks5"; then
|
||||
:
|
||||
elif [ "$(uci_get_by_name "$LOCAL_SERVER" v2ray_protocol)" = "snell" ]; then
|
||||
echolog "Global_Socks5:Snell 需要 Mihomo 内核,且当前 Mihomo 启动失败。"
|
||||
return 1
|
||||
elif [ "$_local" = "2" ]; then
|
||||
# 尝试 Xray
|
||||
xray_bin="$(first_type xray)"
|
||||
@@ -2250,7 +2249,14 @@ get_udp_relay_mode() {
|
||||
;;
|
||||
v2ray)
|
||||
proto=$(uci_get_by_name "$node" v2ray_protocol)
|
||||
if [ "$(uci_get_by_name "$node" transport)" = "kcptun" ]; then
|
||||
case "$proto" in vmess|vless|trojan) echo "native" ;; *) echo "disabled" ;; esac
|
||||
return
|
||||
fi
|
||||
case "$proto" in
|
||||
snell)
|
||||
case "$(uci_get_by_name "$node" snell_version 4)" in 1|2) echo "disabled" ;; *) echo "native" ;; esac
|
||||
;;
|
||||
naive)
|
||||
[ "$(uci_get_by_name "$node" naive_udp_over_tcp 0)" = "1" ] && echo "native" || echo "disabled"
|
||||
;;
|
||||
@@ -2386,11 +2392,8 @@ Start_Run() {
|
||||
enable_mihomo=$(uci_get_by_type server_subscribe enable_mihomo "")
|
||||
if [ "$enable_mihomo" = "1" ] && start_v2ray_with_mihomo "$GLOBAL_SERVER" "$tcp_port" "$socks_port" "$GLOBAL_SERVER" "redir" "ssr-retcp" "Main node"; then
|
||||
:
|
||||
elif [ "$(uci_get_by_name "$GLOBAL_SERVER" v2ray_protocol)" = "snell" ]; then
|
||||
echolog "Main node:Snell 需要 Mihomo 内核,且当前 Mihomo 启动失败。"
|
||||
return 1
|
||||
else
|
||||
# enable_mihomo=0 或 Mihomo 启动失败(非 Snell)→ 优先使用 Xray
|
||||
# enable_mihomo=0 或 Mihomo 启动失败 → 优先使用 Xray
|
||||
xray_bin="$(first_type xray)"
|
||||
if [ -n "$xray_bin" ]; then
|
||||
gen_config_file "$GLOBAL_SERVER" "$type" 1 "$tcp_port" "$socks_port"
|
||||
@@ -2752,6 +2755,46 @@ start_server() {
|
||||
echolog "Server: Xray NaiveProxy Server$server_count Started!"
|
||||
;;
|
||||
|
||||
ssr-xray)
|
||||
xray_bin="$(first_type xray)"
|
||||
[ -x "$xray_bin" ] || return 1
|
||||
config_file="$TMP_PATH/xray-server-$server_count.json"
|
||||
lua /usr/share/shadowsocksr/gen_ssr_server.lua "$1" > "$config_file" || return 1
|
||||
"$xray_bin" run -test -c "$config_file" >> /var/ssrplus.log 2>&1 || return 1
|
||||
ln_start_bin "$xray_bin" xray-server-$server_count run -c "$config_file"
|
||||
echolog "Server: Xray ShadowsocksR Server$server_count Started!"
|
||||
;;
|
||||
|
||||
anytls)
|
||||
xray_bin="$(first_type xray)"
|
||||
[ -x "$xray_bin" ] || return 1
|
||||
config_file="$TMP_PATH/xray-server-$server_count.json"
|
||||
lua /usr/share/shadowsocksr/gen_anytls_server.lua "$1" > "$config_file" || return 1
|
||||
"$xray_bin" run -test -c "$config_file" >> /var/ssrplus.log 2>&1 || return 1
|
||||
ln_start_bin "$xray_bin" xray-server-$server_count run -c "$config_file"
|
||||
echolog "Server: Xray AnyTLS Server$server_count Started!"
|
||||
;;
|
||||
|
||||
snell)
|
||||
xray_bin="$(first_type xray)"
|
||||
[ -x "$xray_bin" ] || return 1
|
||||
config_file="$TMP_PATH/xray-server-$server_count.json"
|
||||
lua /usr/share/shadowsocksr/gen_snell_server.lua "$1" > "$config_file" || return 1
|
||||
"$xray_bin" run -test -c "$config_file" >> /var/ssrplus.log 2>&1 || return 1
|
||||
ln_start_bin "$xray_bin" xray-server-$server_count run -c "$config_file"
|
||||
echolog "Server: Xray Snell Server$server_count Started!"
|
||||
;;
|
||||
|
||||
tuic)
|
||||
xray_bin="$(first_type xray)"
|
||||
[ -x "$xray_bin" ] || return 1
|
||||
config_file="$TMP_PATH/xray-server-$server_count.json"
|
||||
lua /usr/share/shadowsocksr/gen_tuic_server.lua "$1" > "$config_file" || return 1
|
||||
"$xray_bin" run -test -c "$config_file" >> /var/ssrplus.log 2>&1 || return 1
|
||||
ln_start_bin "$xray_bin" xray-server-$server_count run -c "$config_file"
|
||||
echolog "Server: Xray TUIC Server$server_count Started!"
|
||||
;;
|
||||
|
||||
vmess|vless|trojan|shadowsocks)
|
||||
# Xray 服务端支持
|
||||
port=$(uci_get_by_name "$1" server_port)
|
||||
|
||||
@@ -928,7 +928,9 @@ local function build_v2ray_mihomo_proxy(sid)
|
||||
elseif protocol == "snell" then
|
||||
proxy.type = "snell"
|
||||
proxy.psk = get_server_field(sid, "snell_psk", "")
|
||||
proxy.version = number_or_nil(get_server_field(sid, "snell_version", ""))
|
||||
proxy.version = tonumber(get_server_field(sid, "snell_version", "4")) or 4
|
||||
proxy.reuse = get_server_field(sid, "snell_reuse", "0") == "1"
|
||||
proxy.udp = proxy.version >= 3
|
||||
local obfs_mode = string_or_nil(get_server_field(sid, "snell_obfs", ""))
|
||||
local obfs_host = string_or_nil(get_server_field(sid, "snell_obfs_host", ""))
|
||||
if obfs_mode or obfs_host then
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/lua
|
||||
local uci = require("luci.model.uci").cursor()
|
||||
local json = require "luci.jsonc"
|
||||
local s = assert(uci:get_all("shadowsocksr", arg[1]), "missing server section")
|
||||
local padding = {}
|
||||
for line in (s.anytls_padding or ""):gmatch("[^\r\n]+") do padding[#padding + 1] = line end
|
||||
print(json.stringify({
|
||||
log = {loglevel = "warning"},
|
||||
inbounds = {{listen = "::", port = assert(tonumber(s.server_port)), protocol = "anytls",
|
||||
settings = {users = {{email = "user", password = assert(s.anytls_password)}},
|
||||
paddingScheme = #padding > 0 and padding or nil},
|
||||
streamSettings = {network = "raw", security = "tls", tlsSettings = {
|
||||
certificates = {{oneTimeLoading = true, certificateFile = assert(s.tls_certificateFile), keyFile = assert(s.tls_keyFile)}}
|
||||
}}
|
||||
}},
|
||||
outbounds = {{protocol = "freedom", settings = {}}}
|
||||
}, 1))
|
||||
@@ -363,6 +363,34 @@ function outbound:handleIndex(index)
|
||||
trojan = function()
|
||||
trojan_shadowsocks()
|
||||
end,
|
||||
snell = function()
|
||||
outbound_settings = {
|
||||
address = server.server, port = tonumber(server.server_port),
|
||||
psk = server.snell_psk, version = tonumber(server.snell_version) or 4,
|
||||
obfs = server.snell_obfs or "", obfsHost = server.snell_obfs_host,
|
||||
reuse = server.snell_reuse == "1"
|
||||
}
|
||||
end,
|
||||
tuic = function()
|
||||
local version = tonumber(server.xray_tuic_version) or 5
|
||||
local alpn = {}
|
||||
for value in (server.tuic_alpn or ""):gmatch("[^,]+") do alpn[#alpn + 1] = value end
|
||||
if #alpn == 0 then alpn = {"h3"} end
|
||||
outbound_settings = {
|
||||
address = server.server, port = tonumber(server.server_port), version = version,
|
||||
token = version == 4 and server.xray_tuic_token or nil,
|
||||
uuid = version == 5 and server.tuic_uuid or nil,
|
||||
password = version == 5 and server.tuic_passwd or nil,
|
||||
serverName = server.tls_host, certificateFile = server.xray_tuic_ca,
|
||||
allowInsecure = server.insecure == "1",
|
||||
alpn = alpn,
|
||||
congestionControl = server.congestion_control or "cubic",
|
||||
udpRelayMode = server.udp_relay_mode or "native",
|
||||
heartbeatInterval = (tonumber(server.heartbeat) or 10) * 1000,
|
||||
requestTimeout = (tonumber(server.timeout) or 8) * 1000,
|
||||
reduceRtt = server.zero_rtt_handshake == "1"
|
||||
}
|
||||
end,
|
||||
shadowsocksr = function()
|
||||
outbound_settings = {
|
||||
address = server.server, port = tonumber(server.server_port),
|
||||
@@ -899,14 +927,53 @@ Xray.outbounds = {
|
||||
}
|
||||
}
|
||||
|
||||
-- Naive owns TLS/multiplexing; SSR owns obfuscation and uses native UDP.
|
||||
-- Preserve Xray socket marks and dialer chains for both.
|
||||
if server.v2ray_protocol == "naive" or server.v2ray_protocol == "shadowsocksr" then
|
||||
-- These protocols own their framing, obfuscation and multiplexing.
|
||||
-- Preserve Xray socket marks and dialer chains.
|
||||
if server.v2ray_protocol == "naive" or server.v2ray_protocol == "shadowsocksr" or server.v2ray_protocol == "tuic" or server.v2ray_protocol == "snell" then
|
||||
local ob = Xray.outbounds[1]
|
||||
ob.streamSettings = { network = "raw", sockopt = ob.streamSettings.sockopt }
|
||||
ob.mux = nil
|
||||
end
|
||||
|
||||
if server.type == "v2ray" and server.transport == "kcptun" then
|
||||
local supported = {vmess = true, vless = true, trojan = true, shadowsocks = true, socks = true, http = true}
|
||||
assert(supported[server.v2ray_protocol], "Kcptun requires a supported stream proxy protocol")
|
||||
assert(server.tls ~= "1" and server.reality ~= "1" and server.xtls ~= "1", "Kcptun cannot be combined with stream TLS or REALITY")
|
||||
assert(server.kcp_enable ~= "1", "Native Kcptun cannot be combined with the external Kcptun client")
|
||||
assert(not server.tls_flow or server.tls_flow == "", "Kcptun cannot be combined with XTLS flow")
|
||||
local options = {}
|
||||
if server.xray_kcptun_options and server.xray_kcptun_options:match("%S") then
|
||||
assert(server.xray_kcptun_options:match("^%s*{"), "Kcptun options must be a JSON object")
|
||||
options = json.parse(server.xray_kcptun_options)
|
||||
assert(type(options) == "table", "Kcptun options must be a JSON object")
|
||||
end
|
||||
options.key = server.xray_kcptun_key
|
||||
options.crypt = server.xray_kcptun_crypt or "aes"
|
||||
options.mode = server.xray_kcptun_mode or "fast"
|
||||
options.smuxver = tonumber(server.xray_kcptun_smuxver) or 1
|
||||
options.nocomp = server.xray_kcptun_nocomp == "1"
|
||||
options.conn = tonumber(server.xray_kcptun_conn) or 1
|
||||
Xray.outbounds[1].streamSettings.kcptunSettings = options
|
||||
end
|
||||
|
||||
if server.type == "v2ray" and server.xray_shadowtls == "1" then
|
||||
local supported = {vmess = true, vless = true, trojan = true, shadowsocks = true}
|
||||
assert(supported[server.v2ray_protocol], "ShadowTLS requires a supported TCP proxy protocol")
|
||||
assert((server.transport or "raw") == "raw" or server.transport == "tcp", "ShadowTLS requires RAW/TCP")
|
||||
assert(server.tls ~= "1" and server.reality ~= "1", "ShadowTLS cannot be combined with TLS or REALITY")
|
||||
assert(not server.tls_flow or server.tls_flow == "", "ShadowTLS cannot be combined with XTLS flow")
|
||||
local stream = Xray.outbounds[1].streamSettings
|
||||
stream.security = "shadowtls"
|
||||
stream.shadowtlsSettings = {
|
||||
version = tonumber(server.xray_shadowtls_version) or 3,
|
||||
password = server.xray_shadowtls_password,
|
||||
serverName = server.xray_shadowtls_sni,
|
||||
fingerprint = server.xray_shadowtls_fingerprint or "chrome",
|
||||
strictMode = server.xray_shadowtls_strict ~= "0",
|
||||
allowInsecure = server.xray_shadowtls_insecure == "1"
|
||||
}
|
||||
end
|
||||
|
||||
if xray_builtin_dns then
|
||||
table.insert(Xray.outbounds, {
|
||||
protocol = "dns",
|
||||
@@ -1322,6 +1389,14 @@ function config:handleIndex(index)
|
||||
chain_switch[ChainType]()
|
||||
end
|
||||
end,
|
||||
snell = function()
|
||||
outbound_settings = {
|
||||
address = server.server, port = tonumber(server.server_port),
|
||||
psk = server.snell_psk, version = tonumber(server.snell_version) or 4,
|
||||
obfs = server.snell_obfs or "", obfsHost = server.snell_obfs_host,
|
||||
reuse = server.snell_reuse == "1"
|
||||
}
|
||||
end,
|
||||
tuic = function()
|
||||
print(json.stringify(tuic, 1))
|
||||
end
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/lua
|
||||
local uci = require("luci.model.uci").cursor()
|
||||
local json = require "luci.jsonc"
|
||||
local s = assert(uci:get_all("shadowsocksr", arg[1]), "missing server section")
|
||||
local version = tonumber(s.snell_version) or 4
|
||||
print(json.stringify({
|
||||
log = {loglevel = "warning"},
|
||||
inbounds = {{listen = "::", port = assert(tonumber(s.server_port)), protocol = "snell",
|
||||
settings = {psk = assert(s.snell_psk), version = version,
|
||||
obfs = s.snell_obfs or "", udp = version >= 3 and s.snell_udp ~= "0"}
|
||||
}},
|
||||
outbounds = {{protocol = "freedom", settings = {}}}
|
||||
}, 1))
|
||||
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/lua
|
||||
local uci = require("luci.model.uci").cursor()
|
||||
local json = require "luci.jsonc"
|
||||
local s = assert(uci:get_all("shadowsocksr", arg[1]), "missing server section")
|
||||
print(json.stringify({
|
||||
log = {loglevel = "warning"},
|
||||
inbounds = {{listen = "::", port = assert(tonumber(s.server_port)), protocol = "shadowsocksr",
|
||||
settings = {password = assert(s.password), method = s.ssr_method or "aes-128-cfb",
|
||||
protocol = s.ssr_protocol or "auth_aes128_sha1", protocolParam = s.ssr_protocol_param or "",
|
||||
obfs = s.ssr_obfs or "plain", obfsParam = s.ssr_obfs_param or "", network = "tcp,udp"}
|
||||
}},
|
||||
outbounds = {{protocol = "freedom", settings = {}}}
|
||||
}, 1))
|
||||
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/lua
|
||||
local uci = require("luci.model.uci").cursor()
|
||||
local json = require "luci.jsonc"
|
||||
local s = assert(uci:get_all("shadowsocksr", arg[1]), "missing server section")
|
||||
local users, tokens = {}, {}
|
||||
if s.tuic_uuid and s.tuic_uuid ~= "" then
|
||||
users[s.tuic_uuid] = assert(s.tuic_password, "TUIC password required")
|
||||
end
|
||||
if s.tuic_token and s.tuic_token ~= "" then tokens[1] = s.tuic_token end
|
||||
assert(next(users) or #tokens > 0, "TUIC credentials required")
|
||||
print(json.stringify({
|
||||
log = {loglevel = "warning"},
|
||||
inbounds = {{listen = "::", port = assert(tonumber(s.server_port)), protocol = "tuic",
|
||||
settings = {users = next(users) and users or nil, tokens = #tokens > 0 and tokens or nil,
|
||||
certificateFile = assert(s.tls_certificateFile), keyFile = assert(s.tls_keyFile)},
|
||||
streamSettings = {network = "tuic"}
|
||||
}},
|
||||
outbounds = {{protocol = "freedom", settings = {}}}
|
||||
}, 1))
|
||||
@@ -824,7 +824,9 @@ local function to_mihomo_proxy(node)
|
||||
elseif node.type == "v2ray" and node.v2ray_protocol == "snell" then
|
||||
proxy.type = "snell"
|
||||
proxy.psk = node.snell_psk
|
||||
proxy.version = tonumber(node.snell_version) or nil
|
||||
proxy.version = tonumber(node.snell_version) or 4
|
||||
proxy.udp = proxy.version >= 3
|
||||
proxy.reuse = node.snell_reuse == "1"
|
||||
local obfs_mode = string_from_value(node.snell_obfs)
|
||||
local obfs_host = string_from_value(node.snell_obfs_host)
|
||||
if obfs_mode or obfs_host then
|
||||
@@ -1021,8 +1023,8 @@ local function processData(szType, content, cfgid)
|
||||
result.fast_open = params.tfo
|
||||
end
|
||||
elseif szType == "snell" then
|
||||
if not has_mihomo then
|
||||
log("跳过 Snell 节点:本地未安装 mihomo。")
|
||||
if not has_xray and not has_mihomo then
|
||||
log("跳过 Snell 节点:本地未安装 Xray 或 Mihomo。")
|
||||
return nil
|
||||
end
|
||||
|
||||
@@ -1041,6 +1043,7 @@ local function processData(szType, content, cfgid)
|
||||
result.snell_version = first_nonempty(params, {"version", "v"}) or "4"
|
||||
result.snell_obfs = first_nonempty(params, {"obfs", "obfs-mode", "obfs_mode"})
|
||||
result.snell_obfs_host = first_nonempty(params, {"obfs-host", "obfs_host", "host"})
|
||||
result.snell_reuse = (params.reuse == "1" or params.reuse == "true") and "1" or "0"
|
||||
if not result.snell_psk or result.snell_psk == "" then
|
||||
result.server = nil
|
||||
end
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-trafficctl
|
||||
PKG_VERSION:=1.23.0
|
||||
PKG_RELEASE:=13
|
||||
PKG_VERSION:=1.23.1
|
||||
PKG_RELEASE:=14
|
||||
|
||||
PKG_LICENSE:=Apache-2.0
|
||||
PKG_MAINTAINER:=Denis Iusupov <yusdyr@gmail.com>
|
||||
|
||||
@@ -13,6 +13,12 @@ msgstr ""
|
||||
msgid "%d pkts, %s dropped"
|
||||
msgstr ""
|
||||
|
||||
msgid "%s down / %s up"
|
||||
msgstr ""
|
||||
|
||||
msgid "%s down and %s up"
|
||||
msgstr ""
|
||||
|
||||
msgid "%s total"
|
||||
msgstr ""
|
||||
|
||||
@@ -46,9 +52,7 @@ msgstr ""
|
||||
msgid "50 Mbit/s"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Accelerates routing in the kernel via nftables flowtable. Speed monitoring and t"
|
||||
"raffic shaping work normally."
|
||||
msgid "Accelerates routing in the kernel via nftables flowtable. Speed monitoring and traffic shaping work normally."
|
||||
msgstr ""
|
||||
|
||||
msgid "Accumulated on the router"
|
||||
@@ -81,6 +85,9 @@ msgstr ""
|
||||
msgid "Adding to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Aggregate every stored period"
|
||||
msgstr ""
|
||||
|
||||
msgid "All"
|
||||
msgstr ""
|
||||
|
||||
@@ -96,9 +103,7 @@ msgstr ""
|
||||
msgid "App"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Applied once, the first time a device appears on the network. A device that alre"
|
||||
"ady has a limit is left alone."
|
||||
msgid "Applied once, the first time a device appears on the network. A device that already has a limit is left alone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Applied — firewall reloading"
|
||||
@@ -152,9 +157,7 @@ msgstr ""
|
||||
msgid "Bridge port — these bytes are also counted in its bridge"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Bridge ports, switch conduits and ifb mirrors. Their bytes are already counted i"
|
||||
"n the bridge or uplink above."
|
||||
msgid "Bridge ports, switch conduits and ifb mirrors. Their bytes are already counted in the bridge or uplink above."
|
||||
msgstr ""
|
||||
|
||||
msgid "Byte totals unavailable on this router."
|
||||
@@ -283,17 +286,10 @@ msgstr ""
|
||||
msgid "Devices already known:"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Devices keep talking to each other and to the router — only the way out is close"
|
||||
"d. Traffic is stopped on the way in, so a transparent proxy on the router (podko"
|
||||
"p, passwall) cannot carry it out either. Remote access that reaches the router t"
|
||||
"hrough a LAN host (Tailscale, a tunnel, a jump host) stops working while this is"
|
||||
" on."
|
||||
msgid "Devices keep talking to each other and to the router — only the way out is closed. Traffic is stopped on the way in, so a transparent proxy on the router (podkop, passwall) cannot carry it out either. Remote access that reaches the router through a LAN host (Tailscale, a tunnel, a jump host) stops working while this is on."
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Devices on the WiFi deny list that are still connected — those blocks are not in"
|
||||
" effect on the running radio."
|
||||
msgid "Devices on the WiFi deny list that are still connected — those blocks are not in effect on the running radio."
|
||||
msgstr ""
|
||||
|
||||
msgid "Disable hardware offload (keeps software offload):"
|
||||
@@ -311,6 +307,9 @@ msgstr ""
|
||||
msgid "Done"
|
||||
msgstr ""
|
||||
|
||||
msgid "Download"
|
||||
msgstr ""
|
||||
|
||||
msgid "Download · %s"
|
||||
msgstr ""
|
||||
|
||||
@@ -353,6 +352,12 @@ msgstr ""
|
||||
msgid "Every device this router forwards for"
|
||||
msgstr ""
|
||||
|
||||
msgid "Exact. Byte counts come from cumulative nftables counters, so they do not depend on how often the sampler runs. The TCP/UDP split is unavailable from this source."
|
||||
msgstr ""
|
||||
|
||||
msgid "Export CSV"
|
||||
msgstr ""
|
||||
|
||||
msgid "Ext. port"
|
||||
msgstr ""
|
||||
|
||||
@@ -374,11 +379,10 @@ msgstr ""
|
||||
msgid "Flow Offload"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Flow offload is active and the kernel does not support the nftables counter maps"
|
||||
" trafficctl uses in that mode, so byte counters stop updating for offloaded conn"
|
||||
"ections. Speeds and totals would be far too low, so they are not shown. Disablin"
|
||||
"g hardware offload in Settings → Flow Offload restores them."
|
||||
msgid "Flow offload is active and the kernel does not support the nftables counter maps trafficctl uses in that mode, so byte counters stop updating for offloaded connections. Speeds and totals would be far too low, so they are not shown. Disabling hardware offload in Settings → Flow Offload restores them."
|
||||
msgstr ""
|
||||
|
||||
msgid "Flow offloading is active."
|
||||
msgstr ""
|
||||
|
||||
msgid "Flow: /devices → select device → inline keyboard with enabled actions above"
|
||||
@@ -387,9 +391,16 @@ msgstr ""
|
||||
msgid "Flows"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Forwarded traffic only — this kernel cannot install the prerouting rule, so traf"
|
||||
"fic handled by a transparent proxy on the router would not be caught."
|
||||
msgid "Flush failed"
|
||||
msgstr ""
|
||||
|
||||
msgid "Flush now"
|
||||
msgstr ""
|
||||
|
||||
msgid "Flushing…"
|
||||
msgstr ""
|
||||
|
||||
msgid "Forwarded traffic only — this kernel cannot install the prerouting rule, so traffic handled by a transparent proxy on the router would not be caught."
|
||||
msgstr ""
|
||||
|
||||
msgid "Full control"
|
||||
@@ -398,6 +409,9 @@ msgstr ""
|
||||
msgid "Gbit/s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Give upload its own ceiling instead of matching download"
|
||||
msgstr ""
|
||||
|
||||
msgid "Global internet cut needs nftables (fw4). This router is running iptables."
|
||||
msgstr ""
|
||||
|
||||
@@ -428,15 +442,16 @@ msgstr ""
|
||||
msgid "Hardware offload"
|
||||
msgstr ""
|
||||
|
||||
msgid "History is not recorded by default: it writes to the router's flash on a schedule, and every other persistent store in this app was deliberately kept off that path. Enable it below."
|
||||
msgstr ""
|
||||
|
||||
msgid "Hostname"
|
||||
msgstr ""
|
||||
|
||||
msgid "Hostname / Dst IP"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"How often live data is polled: speeds, graphs, drop/backlog counters, and the co"
|
||||
"nnection table in device view"
|
||||
msgid "How often live data is polled: speeds, graphs, drop/backlog counters, and the connection table in device view"
|
||||
msgstr ""
|
||||
|
||||
msgid "How to get full functionality without disabling offload:"
|
||||
@@ -445,10 +460,10 @@ msgstr ""
|
||||
msgid "IP address"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"If your current firmware uses fw3 (iptables) or ships a kernel older than 5.7, a"
|
||||
" router with modern OpenWrt and fw4 support will have this working out of the bo"
|
||||
"x."
|
||||
msgid "IP-keyed"
|
||||
msgstr ""
|
||||
|
||||
msgid "If your current firmware uses fw3 (iptables) or ships a kernel older than 5.7, a router with modern OpenWrt and fw4 support will have this working out of the box."
|
||||
msgstr ""
|
||||
|
||||
msgid "Iface"
|
||||
@@ -457,18 +472,13 @@ msgstr ""
|
||||
msgid "In"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"In this mode the kernel's conntrack, firewall, and tc are bypassed for offloaded"
|
||||
" flows:"
|
||||
msgid "In this mode the kernel's conntrack, firewall, and tc are bypassed for offloaded flows:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Inbound rate limit (drops packets above the rate)"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Inbound traffic control for DNAT port forwards and router-local open ports confi"
|
||||
"gured in the firewall. Pause drops all inbound traffic on the port instantly (wi"
|
||||
"thout touching the firewall config); Limit polices the inbound rate."
|
||||
msgid "Inbound traffic control for DNAT port forwards and router-local open ports configured in the firewall. Pause drops all inbound traffic on the port instantly (without touching the firewall config); Limit polices the inbound rate."
|
||||
msgstr ""
|
||||
|
||||
msgid "Inet"
|
||||
@@ -501,6 +511,9 @@ msgstr ""
|
||||
msgid "LAN keeps working"
|
||||
msgstr ""
|
||||
|
||||
msgid "Last seen"
|
||||
msgstr ""
|
||||
|
||||
msgid "Last seen: %s, %s ago"
|
||||
msgstr ""
|
||||
|
||||
@@ -534,10 +547,7 @@ msgstr ""
|
||||
msgid "Limiter (nft drop)"
|
||||
msgstr ""
|
||||
|
||||
msgid "Limiting %s → %s (%s)…"
|
||||
msgstr ""
|
||||
|
||||
msgid "Limiting → %s…"
|
||||
msgid "Limiting"
|
||||
msgstr ""
|
||||
|
||||
msgid "Link"
|
||||
@@ -561,6 +571,9 @@ msgstr ""
|
||||
msgid "Logging & Persistence"
|
||||
msgstr ""
|
||||
|
||||
msgid "Lower bound, not a measurement. Flow offloading is active without counter support, so the kernel counters this history is built from stop moving while traffic keeps flowing. The real figures are higher by an unknown amount — use these only as a floor."
|
||||
msgstr ""
|
||||
|
||||
msgid "MAC address"
|
||||
msgstr ""
|
||||
|
||||
@@ -585,6 +598,9 @@ msgstr ""
|
||||
msgid "New devices"
|
||||
msgstr ""
|
||||
|
||||
msgid "No MAC address is known for this device, so its history is keyed on its IP address. If that address is reassigned, earlier traffic recorded here may belong to a different device."
|
||||
msgstr ""
|
||||
|
||||
msgid "No action buttons enabled"
|
||||
msgstr ""
|
||||
|
||||
@@ -597,9 +613,7 @@ msgstr ""
|
||||
msgid "No activity recorded yet."
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"No baseline recorded yet. It is taken from the current leases when you switch th"
|
||||
"is on."
|
||||
msgid "No baseline recorded yet. It is taken from the current leases when you switch this on."
|
||||
msgstr ""
|
||||
|
||||
msgid "No devices match filter."
|
||||
@@ -617,23 +631,19 @@ msgstr ""
|
||||
msgid "No port forwards or WAN-open ports are configured in the firewall."
|
||||
msgstr ""
|
||||
|
||||
msgid "No traffic has been recorded for this period yet. The first figures appear after the next flush."
|
||||
msgstr ""
|
||||
|
||||
msgid "None (per-flow)"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Not counted: flow offload is active and this router cannot provide the nftables "
|
||||
"counters trafficctl uses in that mode, so the kernel byte counters stop updating"
|
||||
" for offloaded connections. Any total here would be far too low. See Settings → "
|
||||
"Flow Offload."
|
||||
msgid "Not counted: flow offload is active and this router cannot provide the nftables counters trafficctl uses in that mode, so the kernel byte counters stop updating for offloaded connections. Any total here would be far too low. See Settings → Flow Offload."
|
||||
msgstr ""
|
||||
|
||||
msgid "Not enough data yet"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Not measurable while flow offload is active: in that mode the router counts byte"
|
||||
"s per address only, so traffic cannot be split by protocol. See Settings → Flow "
|
||||
"Offload."
|
||||
msgid "Not measurable while flow offload is active: in that mode the router counts bytes per address only, so traffic cannot be split by protocol. See Settings → Flow Offload."
|
||||
msgstr ""
|
||||
|
||||
msgid "Note: speed is measured before shaper — bursts above limit are normal"
|
||||
@@ -648,19 +658,16 @@ msgstr ""
|
||||
msgid "Off"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Offloads routing to the hardware engine (PPE/NPU). Requires software offload. ⚠ "
|
||||
"On many platforms (e.g. Mediatek Filogic) the driver does not report byte counte"
|
||||
"rs back to the kernel — real-time speed monitoring will show zero."
|
||||
msgid "Off."
|
||||
msgstr ""
|
||||
|
||||
msgid "Offloads routing to the hardware engine (PPE/NPU). Requires software offload. ⚠ On many platforms (e.g. Mediatek Filogic) the driver does not report byte counters back to the kernel — real-time speed monitoring will show zero."
|
||||
msgstr ""
|
||||
|
||||
msgid "On %s"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"On the WiFi deny list but still connected — the block is NOT in effect on the ru"
|
||||
"nning radio. Install hostapd-utils so blocks apply immediately, or restart WiFi "
|
||||
"(disconnects every client)."
|
||||
msgid "On the WiFi deny list but still connected — the block is NOT in effect on the running radio. Install hostapd-utils so blocks apply immediately, or restart WiFi (disconnects every client)."
|
||||
msgstr ""
|
||||
|
||||
msgid "One bucket for the whole subnet"
|
||||
@@ -711,6 +718,15 @@ msgstr ""
|
||||
msgid "Pause"
|
||||
msgstr ""
|
||||
|
||||
msgid "Per-device totals accumulated per accounting period, including devices that are not connected now. Figures survive reboots; the live view on the Devices tab does not."
|
||||
msgstr ""
|
||||
|
||||
msgid "Period"
|
||||
msgstr ""
|
||||
|
||||
msgid "Periods"
|
||||
msgstr ""
|
||||
|
||||
msgid "Persist rules"
|
||||
msgstr ""
|
||||
|
||||
@@ -738,13 +754,16 @@ msgstr ""
|
||||
msgid "Protocol"
|
||||
msgstr ""
|
||||
|
||||
msgid "Qualcomm NSS acceleration is active"
|
||||
msgstr ""
|
||||
|
||||
msgid "Queue"
|
||||
msgstr ""
|
||||
|
||||
msgid "Queue memory"
|
||||
msgstr ""
|
||||
|
||||
msgid "Queued: <b style=\\\"color:var(--tc-speed)\\\">%s</b>"
|
||||
msgid "Queued: <b style=\"color:var(--tc-speed)\">%s</b>"
|
||||
msgstr ""
|
||||
|
||||
msgid "Queues excess traffic (smoother streaming, lower jitter)"
|
||||
@@ -756,6 +775,9 @@ msgstr ""
|
||||
msgid "Rate limiting — applies only to new connections"
|
||||
msgstr ""
|
||||
|
||||
msgid "Rate limits and traffic shaping cannot be enforced while it is: accelerated flows bypass the Linux network stack, so rules are installed but have no effect. The toggles below do not control this — stop the ECM front end (front_end_ipv4_stop / front_end_ipv6_stop under /sys/kernel/debug/ecm) or set acceleration_engine in /etc/config/ecm, then re-apply the limit."
|
||||
msgstr ""
|
||||
|
||||
msgid "Ratelimits"
|
||||
msgstr ""
|
||||
|
||||
@@ -765,6 +787,9 @@ msgstr ""
|
||||
msgid "Recent"
|
||||
msgstr ""
|
||||
|
||||
msgid "Recording is paused: the last write failed."
|
||||
msgstr ""
|
||||
|
||||
msgid "Refresh"
|
||||
msgstr ""
|
||||
|
||||
@@ -810,6 +835,9 @@ msgstr ""
|
||||
msgid "Running…"
|
||||
msgstr ""
|
||||
|
||||
msgid "Sampled. Byte counts come from conntrack, which only reports flows that are alive when it is read — a connection that both starts and finishes between two samples is not counted. Shorten the sampling interval to narrow that gap."
|
||||
msgstr ""
|
||||
|
||||
msgid "Save"
|
||||
msgstr ""
|
||||
|
||||
@@ -849,7 +877,7 @@ msgstr ""
|
||||
msgid "Shaped:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Shaped: <b style=\\\"color:var(--tc-speed)\\\">🌊 %s</b>"
|
||||
msgid "Shaped: <b style=\"color:var(--tc-speed)\">🌊 %s</b>"
|
||||
msgstr ""
|
||||
|
||||
msgid "Shaper"
|
||||
@@ -861,12 +889,15 @@ msgstr ""
|
||||
msgid "Shapes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Shaping → %s…"
|
||||
msgid "Shaping"
|
||||
msgstr ""
|
||||
|
||||
msgid "Share:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show only this period"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show/hide token"
|
||||
msgstr ""
|
||||
|
||||
@@ -879,6 +910,9 @@ msgstr ""
|
||||
msgid "Software flow offload"
|
||||
msgstr ""
|
||||
|
||||
msgid "Software flow offloading is active, with counter sync."
|
||||
msgstr ""
|
||||
|
||||
msgid "Software flow offloading is active."
|
||||
msgstr ""
|
||||
|
||||
@@ -888,18 +922,19 @@ msgstr ""
|
||||
msgid "Software offload (counter)"
|
||||
msgstr ""
|
||||
|
||||
msgid "Sort by this column"
|
||||
msgstr ""
|
||||
|
||||
msgid "Speed Limit"
|
||||
msgstr ""
|
||||
|
||||
msgid "Speed graph. Window = avg time. Orange dashed line = speed limit"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Speed is measured via nftables counters installed at a higher priority (before t"
|
||||
"he flowtable), so graphs are accurate."
|
||||
msgid "Speed is measured via nftables counters installed at a higher priority (before the flowtable), so graphs are accurate."
|
||||
msgstr ""
|
||||
|
||||
msgid "Speed limit: <b style=\\\"color:var(--tc-warn)\\\">⚡ %s</b>"
|
||||
msgid "Speed limit: <b style=\"color:var(--tc-warn)\">⚡ %s</b>"
|
||||
msgstr ""
|
||||
|
||||
msgid "Speed limit: shaper (queue) or limiter (drop)"
|
||||
@@ -908,6 +943,9 @@ msgstr ""
|
||||
msgid "Speed monitoring — conntrack byte counters are not updated"
|
||||
msgstr ""
|
||||
|
||||
msgid "Split up/down"
|
||||
msgstr ""
|
||||
|
||||
msgid "State"
|
||||
msgstr ""
|
||||
|
||||
@@ -917,20 +955,25 @@ msgstr ""
|
||||
msgid "Stays off until you switch it back."
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Store the current Poll and Window as this router's defaults, for browsers that h"
|
||||
"ave not set their own"
|
||||
msgid "Store"
|
||||
msgstr ""
|
||||
|
||||
msgid "Store the current Poll and Window as this router's defaults, for browsers that have not set their own"
|
||||
msgstr ""
|
||||
|
||||
msgid "Switch it off"
|
||||
msgstr ""
|
||||
|
||||
msgid "Switch off"
|
||||
msgstr ""
|
||||
|
||||
msgid "Switch on"
|
||||
msgstr ""
|
||||
|
||||
msgid "Syslog"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"TCP bytes transferred, accumulated on the router. Not measurable while flow offl"
|
||||
"oad is active"
|
||||
msgid "TCP bytes transferred, accumulated on the router. Not measurable while flow offload is active"
|
||||
msgstr ""
|
||||
|
||||
msgid "TCP: <b>%d</b>"
|
||||
@@ -951,25 +994,34 @@ msgstr ""
|
||||
msgid "Test"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"The auto-revert helper is not running; this page re-checks the deadline while it"
|
||||
" is open."
|
||||
msgid "The accuracy of these figures could not be determined."
|
||||
msgstr ""
|
||||
|
||||
msgid "The auto-revert helper is not running; this page re-checks the deadline while it is open."
|
||||
msgstr ""
|
||||
|
||||
msgid "The flowtable"
|
||||
msgstr ""
|
||||
|
||||
msgid "The flowtable carries the"
|
||||
msgstr ""
|
||||
|
||||
msgid "The internet cut is switched on, but its firewall rule is missing."
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"The kernel fast-paths established connections through a flowtable, bypassing con"
|
||||
"ntrack byte updates for higher throughput."
|
||||
msgid "The kernel fast-paths established connections through a flowtable for higher throughput."
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"The router offloads established connections from the CPU to the hardware (NIC/So"
|
||||
"C), achieving 2–3× higher throughput and lower CPU usage."
|
||||
msgid "The kernel fast-paths established connections through a flowtable, bypassing conntrack byte updates for higher throughput."
|
||||
msgstr ""
|
||||
|
||||
msgid "The router offloads established connections from the CPU to the hardware (NIC/SoC), achieving 2–3× higher throughput and lower CPU usage."
|
||||
msgstr ""
|
||||
|
||||
msgid "The store directory is not writable yet."
|
||||
msgstr ""
|
||||
|
||||
msgid "This build of trafficctl does not have a description for the mode the router reported, so how it affects monitoring is not stated here rather than guessed at."
|
||||
msgstr ""
|
||||
|
||||
msgid "Throttle removed"
|
||||
@@ -993,9 +1045,10 @@ msgstr ""
|
||||
msgid "Top talkers"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Total bytes transferred (download + upload), accumulated on the router. Resets o"
|
||||
"n reboot; hover a cell for the start time"
|
||||
msgid "Total"
|
||||
msgstr ""
|
||||
|
||||
msgid "Total bytes transferred (download + upload), accumulated on the router. Resets on reboot; hover a cell for the start time"
|
||||
msgstr ""
|
||||
|
||||
msgid "Total dropped"
|
||||
@@ -1013,9 +1066,13 @@ msgstr ""
|
||||
msgid "Traffic Control"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Traffic is flowing right now. It is normally re-asserted within seconds — if thi"
|
||||
"s persists, switch it off and on again."
|
||||
msgid "Traffic History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Traffic history is switched off. Nothing is being recorded."
|
||||
msgstr ""
|
||||
|
||||
msgid "Traffic is flowing right now. It is normally re-asserted within seconds — if this persists, switch it off and on again."
|
||||
msgstr ""
|
||||
|
||||
msgid "Traffic shaping (tc/HTB) — bypassed for offloaded flows"
|
||||
@@ -1024,9 +1081,7 @@ msgstr ""
|
||||
msgid "Traffic shaping and blocking are not affected."
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"UDP bytes transferred, accumulated on the router. Not measurable while flow offl"
|
||||
"oad is active"
|
||||
msgid "UDP bytes transferred, accumulated on the router. Not measurable while flow offload is active"
|
||||
msgstr ""
|
||||
|
||||
msgid "UDP: <b>%d</b>"
|
||||
@@ -1050,6 +1105,9 @@ msgstr ""
|
||||
msgid "Until I switch it back"
|
||||
msgstr ""
|
||||
|
||||
msgid "Upload"
|
||||
msgstr ""
|
||||
|
||||
msgid "Upload · %s"
|
||||
msgstr ""
|
||||
|
||||
@@ -1071,6 +1129,12 @@ msgstr ""
|
||||
msgid "Waiting for the first byte sample."
|
||||
msgstr ""
|
||||
|
||||
msgid "When this device last moved any traffic, not when it was last connected"
|
||||
msgstr ""
|
||||
|
||||
msgid "While this total was being accumulated, flow offloading froze the counters it is built from. The figure is a floor, not a measurement."
|
||||
msgstr ""
|
||||
|
||||
msgid "Whole network"
|
||||
msgstr ""
|
||||
|
||||
@@ -1101,6 +1165,9 @@ msgstr ""
|
||||
msgid "Window"
|
||||
msgstr ""
|
||||
|
||||
msgid "Write the figures accumulated so far to the store now, without waiting for the next scheduled flush"
|
||||
msgstr ""
|
||||
|
||||
msgid "You will need LAN or physical access to undo this — a reboot will not clear it."
|
||||
msgstr ""
|
||||
|
||||
@@ -1110,9 +1177,15 @@ msgstr ""
|
||||
msgid "all active blocks, limits, and shapes"
|
||||
msgstr ""
|
||||
|
||||
msgid "at least"
|
||||
msgstr ""
|
||||
|
||||
msgid "between them — one bucket for the whole subnet."
|
||||
msgstr ""
|
||||
|
||||
msgid "between them — one bucket per direction for the whole subnet."
|
||||
msgstr ""
|
||||
|
||||
msgid "bit/s"
|
||||
msgstr ""
|
||||
|
||||
@@ -1146,6 +1219,9 @@ msgstr ""
|
||||
msgid "date + time"
|
||||
msgstr ""
|
||||
|
||||
msgid "days ago"
|
||||
msgstr ""
|
||||
|
||||
msgid "device connections"
|
||||
msgstr ""
|
||||
|
||||
@@ -1155,6 +1231,9 @@ msgstr ""
|
||||
msgid "device list → tap device → action buttons"
|
||||
msgstr ""
|
||||
|
||||
msgid "devices"
|
||||
msgstr ""
|
||||
|
||||
msgid "disabled"
|
||||
msgstr ""
|
||||
|
||||
@@ -1173,16 +1252,16 @@ msgstr ""
|
||||
msgid "failed"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"flag (Linux 5.7+, set automatically by fw4/nftables) periodically syncs hardware"
|
||||
" byte counts back to conntrack — trafficctl detects this and all features work n"
|
||||
"ormally."
|
||||
msgid "flag (Linux 5.7+, set automatically by fw4), so offloaded byte counts are synced back to conntrack. Speed and totals come from conntrack as usual and are accurate — the nftables counter fallback is not needed on this router."
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"flag should sync hardware byte counts back to conntrack, but on many platforms ("
|
||||
"e.g. Mediatek Filogic) the driver does not implement the stats callback, so conn"
|
||||
"track counters remain frozen for active flows."
|
||||
msgid "flag (Linux 5.7+, set automatically by fw4/nftables) periodically syncs hardware byte counts back to conntrack — trafficctl detects this and all features work normally."
|
||||
msgstr ""
|
||||
|
||||
msgid "flag should sync hardware byte counts back to conntrack, but on many platforms (e.g. Mediatek Filogic) the driver does not implement the stats callback, so conntrack counters remain frozen for active flows."
|
||||
msgstr ""
|
||||
|
||||
msgid "flush every"
|
||||
msgstr ""
|
||||
|
||||
msgid "groups from"
|
||||
@@ -1191,16 +1270,24 @@ msgstr ""
|
||||
msgid "h"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"is not one of the subnets this router monitors, so a limit on it would be accept"
|
||||
"ed but never enforced. A firewall zone other than \"lan\" with masq=1 (the usual g"
|
||||
"uest-VLAN setup) is excluded. Check with: uci show firewall | grep -E \"name=|mas"
|
||||
"q=\""
|
||||
msgid "h ago"
|
||||
msgstr ""
|
||||
|
||||
msgid "is not one of the subnets this router monitors, so a limit on it would be accepted but never enforced. A firewall zone other than \"lan\" with masq=1 (the usual guest-VLAN setup) is excluded. Check with: uci show firewall | grep -E \"name=|masq=\""
|
||||
msgstr ""
|
||||
|
||||
msgid "just now"
|
||||
msgstr ""
|
||||
|
||||
msgid "kbit/s"
|
||||
msgstr ""
|
||||
|
||||
msgid "keeping"
|
||||
msgstr ""
|
||||
|
||||
msgid "last flush"
|
||||
msgstr ""
|
||||
|
||||
msgid "line break"
|
||||
msgstr ""
|
||||
|
||||
@@ -1210,6 +1297,9 @@ msgstr ""
|
||||
msgid "min"
|
||||
msgstr ""
|
||||
|
||||
msgid "min ago"
|
||||
msgstr ""
|
||||
|
||||
msgid "network interface"
|
||||
msgstr ""
|
||||
|
||||
@@ -1249,6 +1339,12 @@ msgstr ""
|
||||
msgid "percentage of total traffic that was dropped"
|
||||
msgstr ""
|
||||
|
||||
msgid "period"
|
||||
msgstr ""
|
||||
|
||||
msgid "periods"
|
||||
msgstr ""
|
||||
|
||||
msgid "pkts"
|
||||
msgstr ""
|
||||
|
||||
@@ -1282,6 +1378,9 @@ msgstr ""
|
||||
msgid "s"
|
||||
msgstr ""
|
||||
|
||||
msgid "sampled every"
|
||||
msgstr ""
|
||||
|
||||
msgid "saved"
|
||||
msgstr ""
|
||||
|
||||
@@ -1312,26 +1411,23 @@ msgstr ""
|
||||
msgid "under a minute"
|
||||
msgstr ""
|
||||
|
||||
msgid "undercounted"
|
||||
msgstr ""
|
||||
|
||||
msgid "value"
|
||||
msgstr ""
|
||||
|
||||
msgid "↑ UL"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"↓ / ↑ are relative to the interface: on the WAN ↓ is your download, on a LAN bri"
|
||||
"dge ↓ is what the LAN sent upstream."
|
||||
msgid "↑ Upload"
|
||||
msgstr ""
|
||||
|
||||
msgid "↓ / ↑ are relative to the interface: on the WAN ↓ is your download, on a LAN bridge ↓ is what the LAN sent upstream."
|
||||
msgstr ""
|
||||
|
||||
msgid "↓ DL"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"🆕 <b>New device</b>\n"
|
||||
"{{ name }} ({{ ip }})\n"
|
||||
"MAC: <code>{{ mac }}</code>\n"
|
||||
"Link: {{ link }}\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "🆕 New device\\n{{ name }} ({{ ip }})\\nMAC: {{ mac }}\\nLink: {{ link }}"
|
||||
msgid "✕"
|
||||
msgstr ""
|
||||
@@ -758,8 +758,8 @@ msgstr "队列"
|
||||
msgid "Queue memory"
|
||||
msgstr "队列内存"
|
||||
|
||||
msgid "Queued: <b style=\\\"color:var(--tc-speed)\\\">%s</b>"
|
||||
msgstr "队列中:<b style=\\\"color:var(--tc-speed)\\\">%s</b>"
|
||||
msgid "Queued: <b style=\"color:var(--tc-speed)\">%s</b>"
|
||||
msgstr "队列中:<b style=\"color:var(--tc-speed)\">%s</b>"
|
||||
|
||||
msgid "Queues excess traffic (smoother streaming, lower jitter)"
|
||||
msgstr "对超额流量排队(更流畅流媒体、更低抖动)"
|
||||
@@ -863,8 +863,8 @@ msgstr "已整形设备通常不会被卸载(内核会检测到 HTB qdisc)
|
||||
msgid "Shaped:"
|
||||
msgstr "已整形:"
|
||||
|
||||
msgid "Shaped: <b style=\\\"color:var(--tc-speed)\\\">🌊 %s</b>"
|
||||
msgstr "已整形:<b style=\\\"color:var(--tc-speed)\\\">🌊 %s</b>"
|
||||
msgid "Shaped: <b style=\"color:var(--tc-speed)\">🌊 %s</b>"
|
||||
msgstr "已整形:<b style=\"color:var(--tc-speed)\">🌊 %s</b>"
|
||||
|
||||
msgid "Shaper"
|
||||
msgstr "整形器"
|
||||
@@ -913,8 +913,8 @@ msgid ""
|
||||
"he flowtable), so graphs are accurate."
|
||||
msgstr "速度通过安装在更高优先级(flowtable 之前)的 nftables 计数器测量,因此图表准确。"
|
||||
|
||||
msgid "Speed limit: <b style=\\\"color:var(--tc-warn)\\\">⚡ %s</b>"
|
||||
msgstr "速度限制:<b style=\\\"color:var(--tc-warn)\\\">⚡ %s</b>"
|
||||
msgid "Speed limit: <b style=\"color:var(--tc-warn)\">⚡ %s</b>"
|
||||
msgstr "速度限制:<b style=\"color:var(--tc-warn)\">⚡ %s</b>"
|
||||
|
||||
msgid "Speed limit: shaper (queue) or limiter (drop)"
|
||||
msgstr "速度限制:整形器(队列)或限速器(丢包)"
|
||||
|
||||
+2
-2
@@ -14,8 +14,8 @@ MISE_HASH_x86_64:=3832f39c325e343f81fe3d92b2447c5d1a5eea1bc85092bb7b6c2580622264
|
||||
MISE_HASH_aarch64:=06186cfbfe947049b21d58575fb0ea800cc26ed1375f20f4b678cb3a9d679437
|
||||
|
||||
PKG_NAME:=mise
|
||||
PKG_VERSION:=2026.10.15
|
||||
PKG_RELEASE:=39
|
||||
PKG_VERSION:=2026.10.17
|
||||
PKG_RELEASE:=40
|
||||
PKG_SOURCE:=$(PKG_NAME)-v$(PKG_VERSION)-linux-$(MISE_ARCH)-musl.tar.gz
|
||||
PKG_SOURCE_URL:=https://github.com/jdx/mise/releases/download/v$(PKG_VERSION)/
|
||||
PKG_HASH:=skip
|
||||
|
||||
+86
-87
@@ -1,58 +1,64 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# Copyright (c) 2018-2026 Nick Peng (pymumu@gmail.com)
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
#
|
||||
# Copyright (c) 2018-2023 Nick Peng (pymumu@gmail.com)
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=smartdns
|
||||
PKG_VERSION:=1.2026.48.4
|
||||
PKG_RELEASE:=7
|
||||
PKG_VERSION:=48.4
|
||||
PKG_RELEASE:=8
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://www.github.com/pymumu/smartdns.git
|
||||
PKG_MIRROR_HASH:=skip
|
||||
PKG_SOURCE_VERSION:=21c940edc65520849ba03544c5cf8d9cf326e680
|
||||
|
||||
SMARTDNS_WEBUI_VERSION:=1.0.0
|
||||
SMARTDNS_WEBUI_SOURCE_PROTO:=git
|
||||
SMARTDNS_WEBUI_SOURCE_URL:=https://github.com/pymumu/smartdns-webui.git
|
||||
SMARTDNS_WEBUI_SOURCE_VERSION:=1c06fee693434ec7c71f06010d3f87416baba9f0
|
||||
SMARTDNS_WEBUI_FILE:=smartdns-webui-$(SMARTDNS_WEBUI_VERSION).tar.gz
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/pymumu/smartdns/tar.gz/Release$(PKG_VERSION)?
|
||||
PKG_HASH:=skip
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-Release$(PKG_VERSION)
|
||||
|
||||
PKG_MAINTAINER:=Nick Peng <pymumu@gmail.com>
|
||||
PKG_LICENSE:=GPL-3.0-or-later
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
PKG_CPE_ID:=cpe:/a:pymumu:smartdns
|
||||
|
||||
PKG_CONFIG_DEPENDS:=CONFIG_PACKAGE_smartdns-ui
|
||||
PKG_BUILD_DEPENDS:=PACKAGE_smartdns-ui:node/host PACKAGE_smartdns-ui:rust-bindgen/host
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
||||
# node compile is slow, so do not use it, download node manually.
|
||||
# PACKAGE_smartdns-ui:node/host
|
||||
PKG_BUILD_DEPENDS:=PACKAGE_smartdns-ui:rust/host
|
||||
RUST_PKG_FEATURES:=build-release
|
||||
RUST_PKG_LOCKED:=0
|
||||
|
||||
include $(TOPDIR)/feeds/packages/lang/rust/rust-package.mk
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(TOPDIR)/feeds/packages/lang/rust/rust-package.mk
|
||||
|
||||
MAKE_VARS += VER=$(PKG_VERSION)
|
||||
MAKE_PATH:=src
|
||||
MAKE_VARS+= VER=$(PKG_VERSION) WITH_ZLIB=0
|
||||
|
||||
define Package/smartdns/default
|
||||
define Package/smartdns/Default
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=IP Addresses and Names
|
||||
TITLE:=smartdns
|
||||
URL:=https://www.github.com/pymumu/smartdns/
|
||||
endef
|
||||
|
||||
define Package/smartdns
|
||||
$(Package/smartdns/default)
|
||||
TITLE:=smartdns server
|
||||
DEPENDS:=+libpthread +libopenssl +libatomic +zlib
|
||||
$(call Package/smartdns/Default)
|
||||
TITLE+= server
|
||||
DEPENDS:=+i386:libatomic +libopenssl
|
||||
endef
|
||||
|
||||
define Package/smartdns/description
|
||||
SmartDNS is a local DNS server which accepts DNS query requests from local network clients,
|
||||
gets DNS query results from multiple upstream DNS servers concurrently, and returns the fastest IP to clients.
|
||||
Unlike dnsmasq's all-servers, smartdns returns the fastest IP, and encrypt DNS queries with DoT or DoH.
|
||||
Unlike dnsmasq's all-servers, smartdns returns the fastest IP, and encrypt DNS queries with DoT or DoH.
|
||||
endef
|
||||
|
||||
define Package/smartdns-ui
|
||||
$(call Package/smartdns/Default)
|
||||
TITLE+= dashboard
|
||||
DEPENDS:=+smartdns $(RUST_ARCH_DEPENDS) @!i386
|
||||
endef
|
||||
|
||||
define Package/smartdns-ui/description
|
||||
A dashboard ui for smartdns server.
|
||||
endef
|
||||
|
||||
define Package/smartdns/conffiles
|
||||
@@ -64,80 +70,73 @@ define Package/smartdns/conffiles
|
||||
/etc/smartdns/domain-forwarding.list
|
||||
endef
|
||||
|
||||
define Download/smartdns-webui
|
||||
PROTO:=git
|
||||
URL:=https://github.com/pymumu/smartdns-webui.git
|
||||
SOURCE_DATE:=2026-07-29
|
||||
SOURCE_VERSION:=1c06fee693434ec7c71f06010d3f87416baba9f0
|
||||
MIRROR_HASH:=1b718d1288f6ddbdd80e3a948dda1693fd7bc8079fdb65be121f64f23ce53849
|
||||
SUBDIR:=smartdns-webui-$$$$(subst -,.,$$$$(SOURCE_DATE))~$$$$(call version_abbrev,$$$$(SOURCE_VERSION))
|
||||
FILE:=$$(SUBDIR).tar.zst
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
$(call Build/Prepare/Default)
|
||||
|
||||
ifneq ($(CONFIG_PACKAGE_smartdns-ui),)
|
||||
$(eval $(call Download,smartdns-webui))
|
||||
$(eval $(Download/smartdns-webui))
|
||||
mkdir -p $(PKG_BUILD_DIR)/smartdns-webui
|
||||
zstdcat $(DL_DIR)/$(FILE) | tar -C $(PKG_BUILD_DIR)/smartdns-webui $(TAR_OPTIONS) --strip-components=1
|
||||
endif
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
$(call Build/Compile/Default)
|
||||
|
||||
ifneq ($(CONFIG_PACKAGE_smartdns-ui),)
|
||||
( \
|
||||
pushd $(PKG_BUILD_DIR) ; \
|
||||
pushd smartdns-webui ; \
|
||||
npm install ; \
|
||||
npm run build ; \
|
||||
popd ; \
|
||||
pushd plugin/smartdns-ui ; \
|
||||
$(CARGO_PKG_CONFIG_VARS) \
|
||||
MAKEFLAGS="$(PKG_JOBS)" \
|
||||
WITH_ZLIB=0 \
|
||||
TARGET_CFLAGS="$(filter-out -O%,$(TARGET_CFLAGS)) $(RUSTC_CFLAGS)" \
|
||||
BINDGEN_EXTRA_CLANG_ARGS="--sysroot=$(TOOLCHAIN_ROOT_DIR)" \
|
||||
cargo build -v --profile $(CARGO_PKG_PROFILE) \
|
||||
$(if $(strip $(RUST_PKG_FEATURES)),--features "$(strip $(RUST_PKG_FEATURES))") \
|
||||
$(if $(filter --jobserver%,$(PKG_JOBS)),,-j1) \
|
||||
$(CARGO_PKG_ARGS) ; \
|
||||
popd ; \
|
||||
popd ; \
|
||||
)
|
||||
endif
|
||||
endef
|
||||
|
||||
define Package/smartdns/install
|
||||
$(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/config $(1)/etc/init.d
|
||||
$(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/config $(1)/etc/init.d
|
||||
$(INSTALL_DIR) $(1)/etc/smartdns $(1)/etc/smartdns/domain-set $(1)/etc/smartdns/conf.d/
|
||||
$(INSTALL_DIR) $(1)/etc/smartdns/ip-set $(1)/etc/smartdns/download
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/smartdns $(1)/usr/sbin/smartdns
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/package/openwrt/files/etc/init.d/smartdns $(1)/etc/init.d/smartdns
|
||||
$(INSTALL_CONF) $(PKG_BUILD_DIR)/package/openwrt/address.conf $(1)/etc/smartdns/address.conf
|
||||
$(INSTALL_CONF) $(PKG_BUILD_DIR)/package/openwrt/blacklist-ip.conf $(1)/etc/smartdns/blacklist-ip.conf
|
||||
$(INSTALL_CONF) $(PKG_BUILD_DIR)/package/openwrt/custom.conf $(1)/etc/smartdns/custom.conf
|
||||
$(INSTALL_CONF) $(PKG_BUILD_DIR)/package/openwrt/domain-block.list $(1)/etc/smartdns/domain-block.list
|
||||
$(INSTALL_CONF) $(PKG_BUILD_DIR)/package/openwrt/domain-forwarding.list $(1)/etc/smartdns/domain-forwarding.list
|
||||
$(INSTALL_CONF) $(PKG_BUILD_DIR)/package/openwrt/files/etc/config/smartdns $(1)/etc/config/smartdns
|
||||
endef
|
||||
|
||||
define Package/smartdns-ui
|
||||
$(Package/smartdns/default)
|
||||
TITLE:=smartdns dashboard
|
||||
DEPENDS:=+smartdns $(RUST_ARCH_DEPENDS)
|
||||
endef
|
||||
|
||||
define Package/smartdns-ui/description
|
||||
A dashboard ui for smartdns server.
|
||||
endef
|
||||
|
||||
define Package/smartdns-ui/conffiles
|
||||
/etc/config/smartdns
|
||||
endef
|
||||
|
||||
define Package/smartdns-ui/install
|
||||
$(INSTALL_DIR) $(1)/usr/lib
|
||||
$(INSTALL_DIR) $(1)/etc/smartdns/conf.d/
|
||||
$(INSTALL_DIR) $(1)/usr/share/smartdns/wwwroot
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/plugin/smartdns-ui/target/smartdns_ui.so $(1)/usr/lib/smartdns_ui.so
|
||||
$(CP) $(PKG_BUILD_DIR)/smartdns-webui/out/* $(1)/usr/share/smartdns/wwwroot
|
||||
endef
|
||||
|
||||
define Build/Compile/smartdns-webui
|
||||
which npm || (echo "npm not found, please install npm first" && exit 1)
|
||||
npm install --prefix $(PKG_BUILD_DIR)/smartdns-webui/
|
||||
npm run build --prefix $(PKG_BUILD_DIR)/smartdns-webui/
|
||||
endef
|
||||
|
||||
define Build/Compile/smartdns-ui
|
||||
cargo install --force --locked bindgen-cli
|
||||
CARGO_BUILD_ARGS="$(if $(strip $(RUST_PKG_FEATURES)),--features "$(strip $(RUST_PKG_FEATURES))") --profile $(CARGO_PKG_PROFILE)"
|
||||
+$(CARGO_PKG_VARS) CARGO_BUILD_ARGS="$(CARGO_BUILD_ARGS)" CC=$(TARGET_CC) \
|
||||
PATH="$$(PATH):$(CARGO_HOME)/bin" \
|
||||
AWS_LC_SYS_CFLAGS="-O0" \
|
||||
make -C $(PKG_BUILD_DIR)/plugin/smartdns-ui
|
||||
endef
|
||||
|
||||
define Download/smartdns-webui
|
||||
FILE:=$(SMARTDNS_WEBUI_FILE)
|
||||
PROTO:=$(SMARTDNS_WEBUI_SOURCE_PROTO)
|
||||
URL:=$(SMARTDNS_WEBUI_SOURCE_URL)
|
||||
MIRROR_HASH:=88adb092ed7b0dc22b3964249f4969870d3b462c4d924aceb18784c0f664f16e
|
||||
VERSION:=$(SMARTDNS_WEBUI_SOURCE_VERSION)
|
||||
HASH:=skip
|
||||
SUBDIR:=smartdns-webui
|
||||
endef
|
||||
$(eval $(call Download,smartdns-webui))
|
||||
|
||||
ifdef CONFIG_PACKAGE_smartdns-ui
|
||||
define Build/Prepare
|
||||
$(call Build/Prepare/Default)
|
||||
$(TAR) -C $(PKG_BUILD_DIR)/ -xf $(DL_DIR)/$(SMARTDNS_WEBUI_FILE)
|
||||
endef
|
||||
endif
|
||||
|
||||
define Build/Compile
|
||||
$(call Build/Compile/Default,smartdns)
|
||||
ifdef CONFIG_PACKAGE_smartdns-ui
|
||||
$(call Build/Compile/smartdns-ui)
|
||||
$(call Build/Compile/smartdns-webui)
|
||||
endif
|
||||
$(INSTALL_DIR) $(1)/usr/share/smartdns
|
||||
$(CP) $(PKG_BUILD_DIR)/plugin/smartdns-ui/target/$(RUSTC_TARGET_ARCH)/$(CARGO_PKG_PROFILE)/libsmartdns_ui.so $(1)/usr/lib/smartdns_ui.so
|
||||
$(CP) $(PKG_BUILD_DIR)/smartdns-webui/out $(1)/usr/share/smartdns/wwwroot
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,smartdns))
|
||||
$(eval $(call RustBinPackage,smartdns-ui))
|
||||
$(eval $(call BuildPackage,smartdns-ui))
|
||||
$(eval $(call BuildPackage,smartdns-ui))
|
||||
Reference in new issue
Block a user