update 2026-06-04 00:28:20

This commit is contained in:
action committed 2026-06-04 00:28:20 +08:00
1 parent a3dfac28a4
commit 623cdab94c
36 files changed
+468 -228

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_VERSION:=1.2.0 PKG_VERSION:=1.2.1
LUCI_TITLE:=LuCI Support for momo LUCI_TITLE:=LuCI Support for momo
LUCI_DEPENDS:=+luci-base +momo LUCI_DEPENDS:=+luci-base +momo
@@ -134,6 +134,12 @@ return view.extend({
s.tab('rlimit', _('RLIMIT Config')); s.tab('rlimit', _('RLIMIT Config'));
o = s.taboption('rlimit', form.Value, 'rlimit_nproc_soft', _('Number of Processes Soft Limit'));
o.datatype = 'uinteger';
o = s.taboption('rlimit', form.Value, 'rlimit_nproc_hard', _('Number of Processes Hard Limit'));
o.datatype = 'uinteger';
o = s.taboption('rlimit', form.Value, 'rlimit_address_space_soft', _('Address Space Size Soft Limit')); o = s.taboption('rlimit', form.Value, 'rlimit_address_space_soft', _('Address Space Size Soft Limit'));
o.datatype = 'uinteger'; o.datatype = 'uinteger';
o.placeholder = _('Unlimited'); o.placeholder = _('Unlimited');
@@ -164,6 +170,16 @@ return view.extend({
o = s.taboption('rlimit', form.Value, 'rlimit_nofile_hard', _('Number of Open Files Hard Limit')); o = s.taboption('rlimit', form.Value, 'rlimit_nofile_hard', _('Number of Open Files Hard Limit'));
o.datatype = 'uinteger'; o.datatype = 'uinteger';
s.tab('environment_variable', _('Environment Variable Config'));
o = s.taboption('environment_variable', form.Value, 'env_go_max_procs', 'GOMAXPROCS');
o.datatype = 'uinteger';
o.placeholder = _('Unlimited');
o = s.taboption('environment_variable', form.Value, 'env_go_mem_limit', 'GOMEMLIMIT');
o.datatype = 'uinteger';
o.placeholder = _('Unlimited');
return m.render(); return m.render();
} }
}); });
@@ -28,6 +28,9 @@ return view.extend({
s.tab('log_config', _('Log Config')); s.tab('log_config', _('Log Config'));
o = s.taboption('log_config', form.Flag, 'clear_at_stop', _('Clear At Stop'));
o.rmempty = false;
o = s.taboption('log_config', form.Flag, 'scheduled_clear', _('Scheduled Clear')); o = s.taboption('log_config', form.Flag, 'scheduled_clear', _('Scheduled Clear'));
o.rmempty = false; o.rmempty = false;
+44 -26
View File
@@ -14,11 +14,11 @@ msgstr ""
msgid "Access Control" msgid "Access Control"
msgstr "" msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:141 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:147
msgid "Address Space Size Hard Limit" msgid "Address Space Size Hard Limit"
msgstr "" msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:137 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:143
msgid "Address Space Size Soft Limit" msgid "Address Space Size Soft Limit"
msgstr "" msgstr ""
@@ -32,7 +32,7 @@ msgstr ""
msgid "App Config" msgid "App Config"
msgstr "" msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:53 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:56
msgid "App Log" msgid "App Log"
msgstr "" msgstr ""
@@ -92,8 +92,12 @@ msgstr ""
msgid "Choose Profile" msgid "Choose Profile"
msgstr "" msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:57 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:31
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:90 msgid "Clear At Stop"
msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:60
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:93
msgid "Clear Log" msgid "Clear Log"
msgstr "" msgstr ""
@@ -102,7 +106,7 @@ msgstr ""
msgid "Commonly Used Port" msgid "Commonly Used Port"
msgstr "" msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:86 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:89
msgid "Core Log" msgid "Core Log"
msgstr "" msgstr ""
@@ -151,7 +155,7 @@ msgstr ""
msgid "DNS Strategy" msgid "DNS Strategy"
msgstr "" msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:119 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:122
msgid "Debug Log" msgid "Debug Log"
msgstr "" msgstr ""
@@ -206,6 +210,10 @@ msgstr ""
msgid "Enable" msgid "Enable"
msgstr "" msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:173
msgid "Environment Variable Config"
msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/profile.js:50 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/profile.js:50
msgid "Expire At" msgid "Expire At"
msgstr "" msgstr ""
@@ -231,7 +239,7 @@ msgstr ""
msgid "General Config" msgid "General Config"
msgstr "" msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:123 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:126
msgid "Generate & Download" msgid "Generate & Download"
msgstr "" msgstr ""
@@ -243,11 +251,11 @@ msgstr ""
msgid "Group" msgid "Group"
msgstr "" msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:149 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:155
msgid "Heap Size Hard Limit" msgid "Heap Size Hard Limit"
msgstr "" msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:145 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:151
msgid "Heap Size Soft Limit" msgid "Heap Size Soft Limit"
msgstr "" msgstr ""
@@ -358,14 +366,22 @@ msgstr ""
msgid "Not Running" msgid "Not Running"
msgstr "" msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:164 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:170
msgid "Number of Open Files Hard Limit" msgid "Number of Open Files Hard Limit"
msgstr "" msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:161 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:167
msgid "Number of Open Files Soft Limit" msgid "Number of Open Files Soft Limit"
msgstr "" msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:140
msgid "Number of Processes Hard Limit"
msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:137
msgid "Number of Processes Soft Limit"
msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:89 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:89
msgid "Open Dashboard" msgid "Open Dashboard"
msgstr "" msgstr ""
@@ -438,19 +454,19 @@ msgstr ""
msgid "Running" msgid "Running"
msgstr "" msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:31 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:34
msgid "Scheduled Clear" msgid "Scheduled Clear"
msgstr "" msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:34 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:37
msgid "Scheduled Clear Cron" msgid "Scheduled Clear Cron"
msgstr "" msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:39 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:42
msgid "Scheduled Clear Size Limit" msgid "Scheduled Clear Size Limit"
msgstr "" msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:45 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:48
msgid "Scheduled Clear Size Limit Unit" msgid "Scheduled Clear Size Limit Unit"
msgstr "" msgstr ""
@@ -462,16 +478,16 @@ msgstr ""
msgid "Scheduled Restart Cron" msgid "Scheduled Restart Cron"
msgstr "" msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:80 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:83
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:113 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:116
msgid "Scroll To Bottom" msgid "Scroll To Bottom"
msgstr "" msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:157 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:163
msgid "Stack Size Hard Limit" msgid "Stack Size Hard Limit"
msgstr "" msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:153 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:159
msgid "Stack Size Soft Limit" msgid "Stack Size Soft Limit"
msgstr "" msgstr ""
@@ -554,12 +570,14 @@ msgstr ""
msgid "UI Path" msgid "UI Path"
msgstr "" msgstr ""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:139 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:145
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:143 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:149
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:147 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:153
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:151 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:157
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:155 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:161
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:159 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:165
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:177
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:181
msgid "Unlimited" msgid "Unlimited"
msgstr "" msgstr ""
+46 -60
View File
@@ -21,11 +21,11 @@ msgstr "API 密码"
msgid "Access Control" msgid "Access Control"
msgstr "访问控制" msgstr "访问控制"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:141 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:147
msgid "Address Space Size Hard Limit" msgid "Address Space Size Hard Limit"
msgstr "地址空间大小硬限制" msgstr "地址空间大小硬限制"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:137 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:143
msgid "Address Space Size Soft Limit" msgid "Address Space Size Soft Limit"
msgstr "地址空间大小软限制" msgstr "地址空间大小软限制"
@@ -39,7 +39,7 @@ msgstr "全部端口"
msgid "App Config" msgid "App Config"
msgstr "插件配置" msgstr "插件配置"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:53 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:56
msgid "App Log" msgid "App Log"
msgstr "插件日志" msgstr "插件日志"
@@ -99,8 +99,12 @@ msgstr "选择文件"
msgid "Choose Profile" msgid "Choose Profile"
msgstr "选择配置文件" msgstr "选择配置文件"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:57 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:31
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:90 msgid "Clear At Stop"
msgstr "停止时清空"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:60
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:93
msgid "Clear Log" msgid "Clear Log"
msgstr "清空日志" msgstr "清空日志"
@@ -109,7 +113,7 @@ msgstr "清空日志"
msgid "Commonly Used Port" msgid "Commonly Used Port"
msgstr "常用端口" msgstr "常用端口"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:86 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:89
msgid "Core Log" msgid "Core Log"
msgstr "核心日志" msgstr "核心日志"
@@ -158,7 +162,7 @@ msgstr "DNS 反向映射"
msgid "DNS Strategy" msgid "DNS Strategy"
msgstr "DNS 策略" msgstr "DNS 策略"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:119 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:122
msgid "Debug Log" msgid "Debug Log"
msgstr "调试日志" msgstr "调试日志"
@@ -213,6 +217,10 @@ msgstr "编辑器"
msgid "Enable" msgid "Enable"
msgstr "启用" msgstr "启用"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:173
msgid "Environment Variable Config"
msgstr "环境变量配置"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/profile.js:50 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/profile.js:50
msgid "Expire At" msgid "Expire At"
msgstr "到期时间" msgstr "到期时间"
@@ -238,7 +246,7 @@ msgstr "文件:"
msgid "General Config" msgid "General Config"
msgstr "全局配置" msgstr "全局配置"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:123 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:126
msgid "Generate & Download" msgid "Generate & Download"
msgstr "生成并下载" msgstr "生成并下载"
@@ -250,11 +258,11 @@ msgstr "授予访问 momo 程序的权限"
msgid "Group" msgid "Group"
msgstr "用户组" msgstr "用户组"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:149 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:155
msgid "Heap Size Hard Limit" msgid "Heap Size Hard Limit"
msgstr "堆大小硬限制" msgstr "堆大小硬限制"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:145 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:151
msgid "Heap Size Soft Limit" msgid "Heap Size Soft Limit"
msgstr "堆大小软限制" msgstr "堆大小软限制"
@@ -365,14 +373,22 @@ msgstr "NTP 服务端口"
msgid "Not Running" msgid "Not Running"
msgstr "未在运行" msgstr "未在运行"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:164 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:170
msgid "Number of Open Files Hard Limit" msgid "Number of Open Files Hard Limit"
msgstr "打开文件数量硬限制" msgstr "打开文件数量硬限制"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:161 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:167
msgid "Number of Open Files Soft Limit" msgid "Number of Open Files Soft Limit"
msgstr "打开文件数量软限制" msgstr "打开文件数量软限制"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:140
msgid "Number of Processes Hard Limit"
msgstr "进程数硬限制"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:137
msgid "Number of Processes Soft Limit"
msgstr "进程数软限制"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:89 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:89
msgid "Open Dashboard" msgid "Open Dashboard"
msgstr "打开面板" msgstr "打开面板"
@@ -445,19 +461,19 @@ msgstr "路由器代理"
msgid "Running" msgid "Running"
msgstr "运行中" msgstr "运行中"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:31
msgid "Scheduled Clear"
msgstr "定时清除""
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:34 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:34
msgid "Scheduled Clear"
msgstr "定时清空"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:37
msgid "Scheduled Clear Cron" msgid "Scheduled Clear Cron"
msgstr "Cron 表达式" msgstr "Cron 表达式"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:39 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:42
msgid "Scheduled Clear Size Limit" msgid "Scheduled Clear Size Limit"
msgstr "日志大小上限" msgstr "日志大小上限"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:45 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:48
msgid "Scheduled Clear Size Limit Unit" msgid "Scheduled Clear Size Limit Unit"
msgstr "日志大小上限单位" msgstr "日志大小上限单位"
@@ -469,16 +485,16 @@ msgstr "定时重启"
msgid "Scheduled Restart Cron" msgid "Scheduled Restart Cron"
msgstr "Cron 表达式" msgstr "Cron 表达式"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:80 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:83
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:113 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:116
msgid "Scroll To Bottom" msgid "Scroll To Bottom"
msgstr "滚动到底部" msgstr "滚动到底部"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:157 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:163
msgid "Stack Size Hard Limit" msgid "Stack Size Hard Limit"
msgstr "栈大小硬限制" msgstr "栈大小硬限制"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:153 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:159
msgid "Stack Size Soft Limit" msgid "Stack Size Soft Limit"
msgstr "栈大小软限制" msgstr "栈大小软限制"
@@ -561,12 +577,14 @@ msgstr "UI 下载地址"
msgid "UI Path" msgid "UI Path"
msgstr "UI 路径" msgstr "UI 路径"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:139 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:145
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:143 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:149
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:147 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:153
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:151 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:157
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:155 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:161
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:159 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:165
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:177
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:181
msgid "Unlimited" msgid "Unlimited"
msgstr "无限制" msgstr "无限制"
@@ -626,35 +644,3 @@ msgstr "用户代理(UA)"
#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:128 #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:128
msgid "procd Config" msgid "procd Config"
msgstr "procd 配置" msgstr "procd 配置"
#~ msgid "Cron Expression"
#~ msgstr "Cron 表达式"
#~ msgid "Check log size at the configured cron schedule before cleaning up."
#~ msgstr "按设定的 Cron 周期检查日志大小,满足条件后再清理。"
#~ msgid ""
#~ "Clear app, core and debug logs when their total size reaches this "
#~ "threshold."
#~ msgstr "当插件日志、核心日志和调试日志总大小达到该阈值时自动清理。"
#~ msgid "Log Cleanup"
#~ msgstr "日志清理"
#~ msgid "Log Cleanup Cron Expression"
#~ msgstr "日志清理 Cron 表达式"
#~ msgid "Log Cleanup Size Threshold (MB)"
#~ msgstr "日志清理大小阈值(MB)"
#~ msgid "Log Size Check Cron Expression"
#~ msgstr "日志大小检查 Cron 表达式"
#~ msgid "Run unconditional log cleanup at the configured cron schedule."
#~ msgstr "按设定的 Cron 时间无条件执行日志清理。"
#~ msgid "Scheduled Log Cleanup"
#~ msgstr "定时日志清理"
#~ msgid "Size-based Log Cleanup"
#~ msgstr "按大小触发日志清理"
@@ -1067,10 +1067,12 @@ function fetch_certsha256()
local id = http.formvalue("id") or "" local id = http.formvalue("id") or ""
local address = (id ~= "") and uci:get(appname, id, "address") or "" local address = (id ~= "") and uci:get(appname, id, "address") or ""
local port = (id ~= "") and uci:get(appname, id, "port") or 0 local port = (id ~= "") and uci:get(appname, id, "port") or 0
if id == "" or address == "" or not api.datatypes.hostname(address) or port == 0 then local sni = (id ~= "") and uci:get(appname, id, "tls_serverName") or ""
sni = (sni ~= "") and sni or address
if address == "" or port == 0 then
http_write_json_error() http_write_json_error()
return return
end end
local data = api.fetch_cert_sha256(address, port, 5) local data = api.fetch_cert_sha256(address, port, sni, 5)
http_write_json(data ~= "" and { code = 1, data = data } or { code = 0 }) http_write_json(data ~= "" and { code = 1, data = data } or { code = 0 })
end end
+13 -21
View File
@@ -1570,31 +1570,23 @@ function cleanEmptyTables(t)
return next(t) and t or nil return next(t) and t or nil
end end
function fetch_cert_sha256(host, port, timeout) function fetch_cert_sha256(host, port, sni, timeout)
if not host or not datatypes.hostname(host) then return "" end if not host then return "" end
port = tonumber(port) or 443 port = tonumber(port) or 443
sni = sni or host
timeout = tonumber(timeout) or 5 timeout = tonumber(timeout) or 5
local xray = finded_com("xray") local cmd = string.format(
local cmd "timeout %d openssl s_client -connect %s:%d -servername %s -showcerts </dev/null 2>/dev/null " ..
if xray then "| awk 'BEGIN{c=0}/BEGIN CERT/{c++} c==1{print} /END CERT/{if(c==1)exit}' " ..
cmd = string.format( "| openssl x509 -outform der 2>/dev/null " ..
"timeout %d %q tls ping %s:%d 2>/dev/null " .. "| sha256sum 2>/dev/null",
"| awk 'tolower($0) ~ /without sni/ {f=1} tolower($0) ~ /with sni/ {f=0} " .. timeout, host, port, sni
"f && tolower($0) ~ /cert.*leaf.*sha256/ {sub(/.*:/,\"\"); gsub(/[[:space:]]/,\"\"); print; exit}'", )
timeout, xray, host, port
)
else
cmd = string.format(
"timeout %d openssl s_client -connect %s:%d -servername %s -showcerts </dev/null 2>/dev/null " ..
"| awk 'BEGIN{c=0}/BEGIN CERT/{c++} c==1{print} /END CERT/{if(c==1)exit}' " ..
"| openssl x509 -outform der 2>/dev/null " ..
"| sha256sum 2>/dev/null",
timeout, host, port, host
)
end
local out = trim(sys.exec(cmd)) local out = trim(sys.exec(cmd))
local fp = out:match("^([0-9a-fA-F]+)") local fp = out:match("^([0-9a-fA-F]+)")
if not fp then return "" end if not fp or fp:lower():match("^e3b0c44298fc1c149afbf4c8996fb924") then
return ""
end
return fp:upper() return fp:upper()
end end
@@ -1666,7 +1666,8 @@ function gen_config(var)
invert = e.invert == "1" and true or nil invert = e.invert == "1" and true or nil
} }
string.gsub(e.domain_list, '[^' .. "\r\n" .. ']+', function(w) string.gsub(e.domain_list, '[^' .. "\r\n" .. ']+', function(w)
if w:find("#") == 1 then return end w = api.trim(w)
if w == "" or w:find("#") == 1 then return end
if w:find("geosite:") == 1 then if w:find("geosite:") == 1 then
local _geosite = w:sub(1 + #"geosite:") --适配srs local _geosite = w:sub(1 + #"geosite:") --适配srs
local t = geo_rule_set("geosite", _geosite) local t = geo_rule_set("geosite", _geosite)
@@ -1703,7 +1704,7 @@ function gen_config(var)
domain_table.fakedns = true domain_table.fakedns = true
end end
if outboundTag then if outboundTag and (rule.domain or rule.domain_suffix or rule.domain_keyword or rule.domain_regex or rule.rule_set) then
table.insert(dns_domain_rules, api.clone(domain_table)) table.insert(dns_domain_rules, api.clone(domain_table))
end end
end end
@@ -1712,7 +1713,8 @@ function gen_config(var)
local ip_cidr = {} local ip_cidr = {}
local is_private = false local is_private = false
string.gsub(e.ip_list, '[^' .. "\r\n" .. ']+', function(w) string.gsub(e.ip_list, '[^' .. "\r\n" .. ']+', function(w)
if w:find("#") == 1 then return end w = api.trim(w)
if w == "" or w:find("#") == 1 then return end
if w:find("geoip:") == 1 then if w:find("geoip:") == 1 then
local _geoip = w:sub(1 + #"geoip:") --适配srs local _geoip = w:sub(1 + #"geoip:") --适配srs
if _geoip == "private" then if _geoip == "private" then
+19 -17
View File
@@ -498,9 +498,9 @@ function gen_config_server(node)
if node.protocol == "vmess" or node.protocol == "vless" then if node.protocol == "vmess" or node.protocol == "vless" then
if node.uuid then if node.uuid then
local clients = {} local users = {}
for i = 1, #node.uuid do for i = 1, #node.uuid do
clients[i] = { users[i] = {
id = node.uuid[i], id = node.uuid[i],
flow = (node.protocol == "vless" flow = (node.protocol == "vless"
and (node.tls == "1" or (node.decryption and node.decryption ~= "" and node.decryption ~= "none")) and (node.tls == "1" or (node.decryption and node.decryption ~= "" and node.decryption ~= "none"))
@@ -508,7 +508,7 @@ function gen_config_server(node)
} }
end end
settings = { settings = {
clients = clients, users = users,
decryption = (node.protocol == "vless") and ((node.decryption and node.decryption ~= "") and node.decryption or "none") or nil decryption = (node.protocol == "vless") and ((node.decryption and node.decryption ~= "") and node.decryption or "none") or nil
} }
end end
@@ -516,7 +516,7 @@ function gen_config_server(node)
settings = { settings = {
udp = ("1" == node.udp_forward) and true or false, udp = ("1" == node.udp_forward) and true or false,
auth = ("1" == node.auth) and "password" or "noauth", auth = ("1" == node.auth) and "password" or "noauth",
accounts = ("1" == node.auth) and { users = ("1" == node.auth) and {
{ {
user = node.username, user = node.username,
pass = node.password pass = node.password
@@ -526,7 +526,7 @@ function gen_config_server(node)
elseif node.protocol == "http" then elseif node.protocol == "http" then
settings = { settings = {
allowTransparent = false, allowTransparent = false,
accounts = ("1" == node.auth) and { users = ("1" == node.auth) and {
{ {
user = node.username, user = node.username,
pass = node.password pass = node.password
@@ -544,20 +544,20 @@ function gen_config_server(node)
} }
elseif node.protocol == "trojan" then elseif node.protocol == "trojan" then
if node.uuid then if node.uuid then
local clients = {} local users = {}
for i = 1, #node.uuid do for i = 1, #node.uuid do
clients[i] = { users[i] = {
password = node.uuid[i], password = node.uuid[i],
} }
end end
settings = { settings = {
clients = clients users = users
} }
end end
elseif node.protocol == "hysteria2" then elseif node.protocol == "hysteria2" then
settings = { settings = {
version = 2, version = 2,
clients = node.hysteria2_auth_password and { users = node.hysteria2_auth_password and {
{ auth = node.hysteria2_auth_password } { auth = node.hysteria2_auth_password }
} }
} }
@@ -946,7 +946,7 @@ function gen_config(var)
end end
if local_socks_username and local_socks_password and local_socks_username ~= "" and local_socks_password ~= "" then if local_socks_username and local_socks_password and local_socks_username ~= "" and local_socks_password ~= "" then
inbound.settings.auth = "password" inbound.settings.auth = "password"
inbound.settings.accounts = { inbound.settings.users = {
{ {
user = local_socks_username, user = local_socks_username,
pass = local_socks_password pass = local_socks_password
@@ -963,7 +963,7 @@ function gen_config(var)
settings = {allowTransparent = false} settings = {allowTransparent = false}
} }
if local_http_username and local_http_password and local_http_username ~= "" and local_http_password ~= "" then if local_http_username and local_http_password and local_http_username ~= "" and local_http_password ~= "" then
inbound.settings.accounts = { inbound.settings.users = {
{ {
user = local_http_username, user = local_http_username,
pass = local_http_password pass = local_http_password
@@ -1422,7 +1422,8 @@ function gen_config(var)
} }
domains = {} domains = {}
string.gsub(e.domain_list, '[^' .. "\r\n" .. ']+', function(w) string.gsub(e.domain_list, '[^' .. "\r\n" .. ']+', function(w)
if w:find("#") == 1 then return end w = api.trim(w)
if w == "" or w:find("#") == 1 then return end
if w:find("rule-set:", 1, true) == 1 or w:find("rs:") == 1 then return end if w:find("rule-set:", 1, true) == 1 or w:find("rs:") == 1 then return end
table.insert(domains, w) table.insert(domains, w)
table.insert(domain_table.domain, w) table.insert(domain_table.domain, w)
@@ -1430,16 +1431,17 @@ function gen_config(var)
if inner_fakedns == "1" and node[e[".name"] .. "_fakedns"] == "1" and #domains > 0 then if inner_fakedns == "1" and node[e[".name"] .. "_fakedns"] == "1" and #domains > 0 then
domain_table.fakedns = true domain_table.fakedns = true
end end
if outbound_tag then if #domains == 0 then domains = nil end
if outbound_tag and domains then
table.insert(dns_domain_rules, api.clone(domain_table)) table.insert(dns_domain_rules, api.clone(domain_table))
end end
if #domains == 0 then domains = nil end
end end
local ip = nil local ip = nil
if e.ip_list then if e.ip_list then
ip = {} ip = {}
string.gsub(e.ip_list, '[^' .. "\r\n" .. ']+', function(w) string.gsub(e.ip_list, '[^' .. "\r\n" .. ']+', function(w)
if w:find("#") == 1 then return end w = api.trim(w)
if w == "" or w:find("#") == 1 then return end
if w:find("rule-set:", 1, true) == 1 or w:find("rs:") == 1 then return end if w:find("rule-set:", 1, true) == 1 or w:find("rs:") == 1 then return end
table.insert(ip, w) table.insert(ip, w)
end) end)
@@ -2036,7 +2038,7 @@ function gen_proto_config(var)
} }
if local_socks_username and local_socks_password and local_socks_username ~= "" and local_socks_password ~= "" then if local_socks_username and local_socks_password and local_socks_username ~= "" and local_socks_password ~= "" then
inbound.settings.auth = "password" inbound.settings.auth = "password"
inbound.settings.accounts = { inbound.settings.users = {
{ {
user = local_socks_username, user = local_socks_username,
pass = local_socks_password pass = local_socks_password
@@ -2056,7 +2058,7 @@ function gen_proto_config(var)
} }
} }
if local_http_username and local_http_password and local_http_username ~= "" and local_http_password ~= "" then if local_http_username and local_http_password and local_http_username ~= "" and local_http_password ~= "" then
inbound.settings.accounts = { inbound.settings.users = {
{ {
user = local_http_username, user = local_http_username,
pass = local_http_password pass = local_http_password
+1 -1
View File
@@ -6,7 +6,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall2 PKG_NAME:=luci-app-passwall2
PKG_VERSION:=26.5.19 PKG_VERSION:=26.6.3
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_PO_VERSION:=$(PKG_VERSION) PKG_PO_VERSION:=$(PKG_VERSION)
@@ -22,7 +22,6 @@ function index()
local appname = api.appname -- global definitions not available local appname = api.appname -- global definitions not available
local uci = api.uci -- in function index() local uci = api.uci -- in function index()
entry({"admin", "services", appname}).dependent = true entry({"admin", "services", appname}).dependent = true
entry({"admin", "services", appname, "reset_config"}, call("reset_config")).leaf = true
entry({"admin", "services", appname, "show"}, call("show_menu")).leaf = true entry({"admin", "services", appname, "show"}, call("show_menu")).leaf = true
entry({"admin", "services", appname, "hide"}, call("hide_menu")).leaf = true entry({"admin", "services", appname, "hide"}, call("hide_menu")).leaf = true
local e local e
@@ -109,6 +108,7 @@ function index()
--[[Backup]] --[[Backup]]
entry({"admin", "services", appname, "create_backup"}, call("create_backup")).leaf = true entry({"admin", "services", appname, "create_backup"}, call("create_backup")).leaf = true
entry({"admin", "services", appname, "restore_backup"}, call("restore_backup")).leaf = true entry({"admin", "services", appname, "restore_backup"}, call("restore_backup")).leaf = true
entry({"admin", "services", appname, "reset_config"}, call("reset_config")).leaf = true
--[[geoview]] --[[geoview]]
entry({"admin", "services", appname, "geo_view"}, call("geo_view")).leaf = true entry({"admin", "services", appname, "geo_view"}, call("geo_view")).leaf = true
@@ -130,6 +130,8 @@ local function http_write_json_error(data)
end end
function reset_config() function reset_config()
uci:revert(appname)
luci.sys.call("echo '' > /tmp/log/passwall2.log")
luci.sys.call('/etc/init.d/passwall2 stop') luci.sys.call('/etc/init.d/passwall2 stop')
luci.sys.call('[ -f "/usr/share/passwall2/0_default_config" ] && cp -f /usr/share/passwall2/0_default_config /etc/config/passwall2') luci.sys.call('[ -f "/usr/share/passwall2/0_default_config" ] && cp -f /usr/share/passwall2/0_default_config /etc/config/passwall2')
http.redirect(api.url()) http.redirect(api.url())
@@ -745,6 +747,7 @@ function restore_backup()
fp:write(decoded) fp:write(decoded)
fp:close() fp:close()
if chunk_index + 1 == total_chunks then if chunk_index + 1 == total_chunks then
uci:revert(appname)
api.sys.call("echo '' > /tmp/log/passwall2.log") api.sys.call("echo '' > /tmp/log/passwall2.log")
api.log(0, string.format(" * PassWall2 %s", i18n.translate("Configuration file uploaded successfully…"))) api.log(0, string.format(" * PassWall2 %s", i18n.translate("Configuration file uploaded successfully…")))
local temp_dir = '/tmp/passwall2_bak' local temp_dir = '/tmp/passwall2_bak'
@@ -72,7 +72,7 @@ end
m:append(Template(appname .. "/global/status")) m:append(Template(appname .. "/global/status"))
global_cfgid = m:get("@global[0]")[".name"] global_cfgid = (m:get("@global[0]") or {})[".name"] or ""
s = m:section(TypedSection, "global") s = m:section(TypedSection, "global")
s.anonymous = true s.anonymous = true
@@ -59,11 +59,13 @@ o.rewrite_option = o.option
o = s:option(ListValue, _n("obfs_type"), translate("Obfs Type")) o = s:option(ListValue, _n("obfs_type"), translate("Obfs Type"))
o:value("", translate("Disable")) o:value("", translate("Disable"))
o:value("salamander") o:value("salamander")
o:value("gecko")
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Value, _n("obfs_password"), translate("Obfs Password")) o = s:option(Value, _n("obfs_password"), translate("Obfs Password"))
o.rewrite_option = o.option o.rewrite_option = o.option
o:depends({ [_n("obfs_type")] = "salamander" }) o:depends({ [_n("obfs_type")] = "salamander" })
o:depends({ [_n("obfs_type")] = "gecko" })
o = s:option(Flag, _n("fast_open"), translate("Fast Open")) o = s:option(Flag, _n("fast_open"), translate("Fast Open"))
o.default = "0" o.default = "0"
@@ -339,13 +339,28 @@ o:depends({ [_n("protocol")] = "vless" })
---- [[hysteria2]] ---- [[hysteria2]]
o = s:option(Value, _n("hysteria2_hop"), translate("Port hopping range")) o = s:option(Value, _n("hysteria2_hop"), translate("Port hopping range"))
o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).") o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).")
o:depends({ [_n("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
o = s:option(Value, _n("hysteria2_hop_interval"), translate("Hop Interval(second)"), translate("Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5.")) o = s:option(Value, _n("hysteria2_hop_interval"), translate("Hop Interval(second)"), translate("Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5."))
o.datatype = "or(uinteger,portrange)" o.datatype = "or(uinteger,portrange)"
o.placeholder = "30" o.placeholder = "30"
o.default = "30" o.default = "30"
o:depends({ [_n("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
o = s:option(Flag, _n("hysteria2_realms"), translate("Realms"))
o.default = "0"
if api.compare_versions(xray_version, ">", "26.5.9") then
o:depends({ [_n("protocol")] = "hysteria2"})
else
o:depends({ [_n("protocol")] = "__hide"})
end
o = s:option(Value, _n("hysteria2_realm_url"), translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name")
o:depends({ [_n("hysteria2_realms")] = "1" })
o = s:option(DynamicList, _n("hysteria2_realm_stun"), translate("Realm STUN"))
o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" }
o:depends({ [_n("hysteria2_realms")] = "1" })
o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password")) o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password"))
o.password = true o.password = true
@@ -354,10 +369,12 @@ o:depends({ [_n("protocol")] = "hysteria2"})
o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type")) o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
o:value("", translate("Disable")) o:value("", translate("Disable"))
o:value("salamander") o:value("salamander")
o:value("gecko")
o:depends({ [_n("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password")) o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
o:depends({ [_n("hysteria2_obfs_type")] = "salamander" }) o:depends({ [_n("hysteria2_obfs_type")] = "salamander" })
o:depends({ [_n("hysteria2_obfs_type")] = "gecko" })
o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps")) o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps"))
o:depends({ [_n("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
@@ -431,11 +448,26 @@ if api.compare_versions(xray_version, ">=", "26.1.31") then
o:depends({ [_n("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
end end
o = s:option(Flag, _n("ech"), translate("ECH")) o = s:option(Flag, _n("tls_certificate"), translate("TLS Certificate (PEM)"))
o.default = "0" o.default = "0"
o:depends({ [_n("tls")] = true, [_n("reality")] = false }) o:depends({ [_n("tls")] = true, [_n("reality")] = false })
o:depends({ [_n("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
o = s:option(TextValue, _n("tls_certificate_pem"), " ", translate("Full certificate (chain), PEM format."))
o.default = ""
o.rows = 5
o.wrap = "off"
o:depends({ [_n("tls_certificate")] = true })
o.validate = function(self, value)
value = api.trim(value):gsub("\r\n", "\n"):gsub("[ \t]*\n[ \t]*", "\n"):gsub("\n+", "\n")
return value
end
o = s:option(Flag, _n("ech"), translate("ECH"))
o.default = "0"
o:depends({ [_n("tls")] = true, [_n("reality")] = false })
o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
o = s:option(TextValue, _n("ech_config"), translate("ECH Config")) o = s:option(TextValue, _n("ech_config"), translate("ECH Config"))
o.default = "" o.default = ""
o.rows = 5 o.rows = 5
@@ -706,7 +738,7 @@ o:depends({ [_n("protocol")] = "vless" })
o:depends({ [_n("protocol")] = "trojan" }) o:depends({ [_n("protocol")] = "trojan" })
o:depends({ [_n("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o:depends({ [_n("protocol")] = "wireguard" }) o:depends({ [_n("protocol")] = "wireguard" })
o:depends({ [_n("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
o = s:option(TextValue, _n("finalmask"), " ") o = s:option(TextValue, _n("finalmask"), " ")
o:depends({ [_n("use_finalmask")] = true }) o:depends({ [_n("use_finalmask")] = true })
@@ -775,10 +807,14 @@ local protocols = s.fields[_n("protocol")].keylist
if #protocols > 0 then if #protocols > 0 then
for i, v in ipairs(protocols) do for i, v in ipairs(protocols) do
if not v:find("^_") then if not v:find("^_") then
s.fields[_n("address")]:depends({ [_n("protocol")] = v }) local depends_condition = { [_n("protocol")] = v }
s.fields[_n("port")]:depends({ [_n("protocol")] = v }) if v == "hysteria2" then
s.fields[_n("domain_resolver")]:depends({ [_n("protocol")] = v }) depends_condition[_n("hysteria2_realms")] = false
s.fields[_n("domain_strategy")]:depends({ [_n("protocol")] = v }) end
s.fields[_n("address")]:depends(depends_condition)
s.fields[_n("port")]:depends(depends_condition)
s.fields[_n("domain_resolver")]:depends(depends_condition)
s.fields[_n("domain_strategy")]:depends(depends_condition)
if v ~= "hysteria2" then if v ~= "hysteria2" then
s.fields[_n("tcp_fast_open")]:depends({ [_n("protocol")] = v }) s.fields[_n("tcp_fast_open")]:depends({ [_n("protocol")] = v })
@@ -801,7 +837,7 @@ if not load_shunt_options then
o:value("2", translate("Landing Node")) o:value("2", translate("Landing Node"))
o1 = s:option(ListValue, _n("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy.")) o1 = s:option(ListValue, _n("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy."))
o1:depends({ [_n("chain_proxy")] = "1" }) o1:depends({ [_n("chain_proxy")] = "1", [_n("hysteria2_realms")] = false })
o1.template = appname .. "/cbi/nodes_listvalue" o1.template = appname .. "/cbi/nodes_listvalue"
o1.group = {} o1.group = {}
@@ -813,7 +849,7 @@ if not load_shunt_options then
end end
o2 = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Only support a layer of proxy.")) o2 = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Only support a layer of proxy."))
o2:depends({ [_n("chain_proxy")] = "2" }) o2:depends({ [_n("chain_proxy")] = "2", [_n("hysteria2_realms")] = false })
o2.template = appname .. "/cbi/nodes_listvalue" o2.template = appname .. "/cbi/nodes_listvalue"
o2.group = {} o2.group = {}
@@ -423,10 +423,12 @@ if singbox_tags:find("with_quic") then
o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type")) o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
o:value("", translate("Disable")) o:value("", translate("Disable"))
o:value("salamander") o:value("salamander")
o:value("gecko")
o:depends({ [_n("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password")) o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
o:depends({ [_n("hysteria2_obfs_type")] = "salamander" }) o:depends({ [_n("hysteria2_obfs_type")] = "salamander" })
o:depends({ [_n("hysteria2_obfs_type")] = "gecko" })
o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps")) o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps"))
o:depends({ [_n("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
@@ -531,6 +533,24 @@ o:depends({ [_n("protocol")] = "hysteria"})
o:depends({ [_n("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "tuic" })
o:depends({ [_n("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
o = s:option(Flag, _n("tls_certificate"), translate("TLS Certificate (PEM)"))
o.default = "0"
o:depends({ [_n("tls")] = true, [_n("reality")] = false })
o:depends({ [_n("protocol")] = "hysteria"})
o:depends({ [_n("protocol")] = "tuic" })
o:depends({ [_n("protocol")] = "hysteria2" })
o:depends({ [_n("protocol")] = "naive" })
o = s:option(TextValue, _n("tls_certificate_pem"), " ", translate("Full certificate (chain), PEM format."))
o.default = ""
o.rows = 5
o.wrap = "off"
o:depends({ [_n("tls_certificate")] = true })
o.validate = function(self, value)
value = api.trim(value):gsub("\r\n", "\n"):gsub("[ \t]*\n[ \t]*", "\n"):gsub("\n+", "\n")
return value
end
o = s:option(Flag, _n("ech"), translate("ECH")) o = s:option(Flag, _n("ech"), translate("ECH"))
o.default = "0" o.default = "0"
o:depends({ [_n("tls")] = true, [_n("flow")] = "", [_n("reality")] = false }) o:depends({ [_n("tls")] = true, [_n("flow")] = "", [_n("reality")] = false })
@@ -48,12 +48,14 @@ o:depends({ [_n("custom")] = false })
o = s:option(ListValue, _n("obfs_type"), translate("Obfs Type")) o = s:option(ListValue, _n("obfs_type"), translate("Obfs Type"))
o:value("", translate("Disable")) o:value("", translate("Disable"))
o:value("salamander") o:value("salamander")
o:value("gecko")
o.rewrite_option = o.option o.rewrite_option = o.option
o:depends({ [_n("custom")] = false }) o:depends({ [_n("custom")] = false })
o = s:option(Value, _n("obfs_password"), translate("Obfs Password")) o = s:option(Value, _n("obfs_password"), translate("Obfs Password"))
o.rewrite_option = o.option o.rewrite_option = o.option
o:depends({ [_n("obfs_type")] = "salamander" }) o:depends({ [_n("obfs_type")] = "salamander" })
o:depends({ [_n("obfs_type")] = "gecko" })
o = s:option(Flag, _n("udp"), translate("UDP")) o = s:option(Flag, _n("udp"), translate("UDP"))
o.default = "1" o.default = "1"
@@ -127,6 +127,17 @@ o:value("xtls-rprx-vision")
o:depends({ [_n("protocol")] = "vless" }) o:depends({ [_n("protocol")] = "vless" })
---- [[ hysteria2 ]] ---- [[ hysteria2 ]]
o = s:option(Flag, _n("hysteria2_realms"), translate("Realms"))
o.default = "0"
o:depends({ [_n("protocol")] = "hysteria2"})
o = s:option(Value, _n("hysteria2_realm_url"), translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name")
o:depends({ [_n("hysteria2_realms")] = "1" })
o = s:option(DynamicList, _n("hysteria2_realm_stun"), translate("Realm STUN"))
o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" }
o:depends({ [_n("hysteria2_realms")] = "1" })
o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password")) o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password"))
o.password = true o.password = true
o:depends({ [_n("protocol")] = "hysteria2"}) o:depends({ [_n("protocol")] = "hysteria2"})
@@ -134,10 +145,12 @@ o:depends({ [_n("protocol")] = "hysteria2"})
o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type")) o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
o:value("", translate("Disable")) o:value("", translate("Disable"))
o:value("salamander") o:value("salamander")
o:value("gecko")
o:depends({ [_n("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password")) o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
o:depends({ [_n("hysteria2_obfs_type")] = "salamander" }) o:depends({ [_n("hysteria2_obfs_type")] = "salamander" })
o:depends({ [_n("hysteria2_obfs_type")] = "gecko" })
o = s:option(Flag, _n("hysteria2_ignore_client_bandwidth"), translate("Client BBR Flow Control")) o = s:option(Flag, _n("hysteria2_ignore_client_bandwidth"), translate("Client BBR Flow Control"))
o.default = 0 o.default = 0
@@ -210,7 +223,8 @@ function o.write(self, section, value)
end end
o = s:option(ListValue, _n("alpn"), translate("alpn")) o = s:option(ListValue, _n("alpn"), translate("alpn"))
o.default = "h2,http/1.1" o.default = "default"
o:value("default", translate("Default"))
o:value("h3") o:value("h3")
o:value("h2") o:value("h2")
o:value("h3,h2") o:value("h3,h2")
@@ -378,7 +392,7 @@ o:depends({ [_n("custom")] = false, [_n("protocol")] = "vless" })
o:depends({ [_n("custom")] = false, [_n("protocol")] = "trojan" }) o:depends({ [_n("custom")] = false, [_n("protocol")] = "trojan" })
o:depends({ [_n("custom")] = false, [_n("protocol")] = "shadowsocks" }) o:depends({ [_n("custom")] = false, [_n("protocol")] = "shadowsocks" })
o:depends({ [_n("custom")] = false, [_n("protocol")] = "wireguard" }) o:depends({ [_n("custom")] = false, [_n("protocol")] = "wireguard" })
o:depends({ [_n("custom")] = false, [_n("protocol")] = "hysteria2" }) o:depends({ [_n("custom")] = false, [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
o = s:option(TextValue, _n("finalmask"), "FinalMask JSON") o = s:option(TextValue, _n("finalmask"), "FinalMask JSON")
o:depends({ [_n("use_finalmask")] = true }) o:depends({ [_n("use_finalmask")] = true })
@@ -175,10 +175,12 @@ if singbox_tags:find("with_quic") then
o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type")) o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
o:value("", translate("Disable")) o:value("", translate("Disable"))
o:value("salamander") o:value("salamander")
o:value("gecko")
o:depends({ [_n("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password")) o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
o:depends({ [_n("hysteria2_obfs_type")] = "salamander" }) o:depends({ [_n("hysteria2_obfs_type")] = "salamander" })
o:depends({ [_n("hysteria2_obfs_type")] = "gecko" })
o = s:option(Flag, _n("hysteria2_ignore_client_bandwidth"), translate("Client BBR Flow Control"), translate("Commands the client to use the BBR flow control algorithm")) o = s:option(Flag, _n("hysteria2_ignore_client_bandwidth"), translate("Client BBR Flow Control"), translate("Commands the client to use the BBR flow control algorithm"))
o.default = 0 o.default = 0
@@ -154,12 +154,14 @@ function base64Encode(text)
end end
function UrlEncode(szText) function UrlEncode(szText)
if type(szText) ~= "string" then return "" end
return szText:gsub("([^%w%-_%.%~])", function(c) return szText:gsub("([^%w%-_%.%~])", function(c)
return string.format("%%%02X", string.byte(c)) return string.format("%%%02X", string.byte(c))
end) end)
end end
function UrlDecode(szText) function UrlDecode(szText)
if type(szText) ~= "string" then return "" end
return szText and szText:gsub("%+", " "):gsub("%%(%x%x)", function(h) return szText and szText:gsub("%+", " "):gsub("%%(%x%x)", function(h)
return string.char(tonumber(h, 16)) return string.char(tonumber(h, 16))
end) or nil end) or nil
@@ -20,8 +20,8 @@ function gen_config_server(node)
key = node.tls_keyFile, key = node.tls_keyFile,
}, },
obfs = (node.hysteria2_obfs_type and node.hysteria2_obfs_password) and { obfs = (node.hysteria2_obfs_type and node.hysteria2_obfs_password) and {
type = "salamander", type = node.hysteria2_obfs_type,
salamander = { [node.hysteria2_obfs_type] = {
password = node.hysteria2_obfs_password password = node.hysteria2_obfs_password
} }
} or nil, } or nil,
@@ -101,8 +101,8 @@ function gen_config(var)
end)() or nil end)() or nil
}, },
obfs = (node.hysteria2_obfs_type and node.hysteria2_obfs_password) and { obfs = (node.hysteria2_obfs_type and node.hysteria2_obfs_password) and {
type = "salamander", type = node.hysteria2_obfs_type,
salamander = { [node.hysteria2_obfs_type] = {
password = node.hysteria2_obfs_password password = node.hysteria2_obfs_password
} }
} or nil, } or nil,
@@ -255,6 +255,7 @@ function gen_outbound(flag, node, tag, proxy_table)
--max_version = "1.3", --max_version = "1.3",
fragment = fragment, fragment = fragment,
record_fragment = record_fragment, record_fragment = record_fragment,
certificate = (node.tls_certificate == "1" and node.tls_certificate_pem ~= "") and split(node.tls_certificate_pem, "\n") or nil,
ech = (node.ech == "1") and (function() ech = (node.ech == "1") and (function()
local function get_ech_domain(s) --兼容xray "域名+DNS" 格式ech local function get_ech_domain(s) --兼容xray "域名+DNS" 格式ech
local domain, dns = s:match("^([^+]+)%+(.+)$") local domain, dns = s:match("^([^+]+)%+(.+)$")
@@ -73,8 +73,8 @@ function gen_outbound(flag, node, tag, proxy_table)
local run_socks_instance = true local run_socks_instance = true
if proxy_table ~= nil and type(proxy_table) == "table" then if proxy_table ~= nil and type(proxy_table) == "table" then
proxy_tag = proxy_table.tag or nil proxy_tag = proxy_table.tag or nil
fragment = proxy_table.fragment or nil fragment = (proxy_table.fragment and not node.hysteria2_realms) and true or nil
noise = proxy_table.noise or nil noise = (proxy_table.noise and not node.hysteria2_realms) and true or nil
run_socks_instance = proxy_table.run_socks_instance run_socks_instance = proxy_table.run_socks_instance
end end
@@ -189,7 +189,11 @@ function gen_outbound(flag, node, tag, proxy_table)
if not node.tls_CertByName then return "" end if not node.tls_CertByName then return "" end
return node.tls_CertByName return node.tls_CertByName
end)(), end)(),
echConfigList = (node.ech == "1") and node.ech_config or nil echConfigList = (node.ech == "1") and node.ech_config or nil,
certificates = (node.tls_certificate == "1" and node.tls_certificate_pem ~= "") and {
certificate = api.split(node.tls_certificate_pem, "\n"),
usage = "verify"
} or nil
} or nil, } or nil,
realitySettings = (node.stream_security == "reality") and { realitySettings = (node.stream_security == "reality") and {
serverName = node.tls_serverName, serverName = node.tls_serverName,
@@ -298,14 +302,36 @@ function gen_outbound(flag, node, tag, proxy_table)
udp[#udp+1] = c udp[#udp+1] = c
finalmask.udp = udp finalmask.udp = udp
elseif TP == "hysteria" then elseif TP == "hysteria" then
local udp = {}
if node.hysteria2_obfs_type and node.hysteria2_obfs_type ~= "" then if node.hysteria2_obfs_type and node.hysteria2_obfs_type ~= "" then
finalmask.udp = {{ local o = {
type = node.hysteria2_obfs_type, type = "salamander",
settings = node.hysteria2_obfs_password and { settings = node.hysteria2_obfs_password and {
password = node.hysteria2_obfs_password password = node.hysteria2_obfs_password,
packetSize = node.hysteria2_obfs_type == "gecko" and "512-1200" or nil
} or nil } or nil
}} }
udp[#udp+1] = o
end end
if node.hysteria2_realms then
local realm = api.parse_realm_uri(node.hysteria2_realm_url)
local url, stun
if realm then
if realm.token and realm.server_url and realm.realm_id then
url = "realm://" .. realm.token .. "@" .. realm.server_url .. "/" .. realm.realm_id
end
stun = realm.stun_servers or node.hysteria2_realm_stun
end
local r = {
type = "realm",
settings = {
url = url,
stunServers = stun
}
}
udp[#udp+1] = r
end
finalmask.udp = udp
local up = tonumber(node.hysteria2_up_mbps) or 0 local up = tonumber(node.hysteria2_up_mbps) or 0
local down = tonumber(node.hysteria2_down_mbps) or 0 local down = tonumber(node.hysteria2_down_mbps) or 0
finalmask.quicParams = { finalmask.quicParams = {
@@ -415,6 +441,13 @@ function gen_outbound(flag, node, tag, proxy_table)
if node.protocol == "wireguard" then if node.protocol == "wireguard" then
result.settings.kernelMode = false result.settings.kernelMode = false
if node.finalmask and node.finalmask ~= "" then
local ok, fm = pcall(jsonc.parse, api.base64Decode(node.finalmask))
if ok and type(fm) == "table" then
result.streamSettings = result.streamSettings or {}
result.streamSettings.finalmask = fm
end
end
end end
local alpn = {} local alpn = {}
@@ -487,9 +520,9 @@ function gen_config_server(node)
if node.protocol == "vmess" or node.protocol == "vless" then if node.protocol == "vmess" or node.protocol == "vless" then
if node.uuid then if node.uuid then
local clients = {} local users = {}
for i = 1, #node.uuid do for i = 1, #node.uuid do
clients[i] = { users[i] = {
id = node.uuid[i], id = node.uuid[i],
flow = (node.protocol == "vless" flow = (node.protocol == "vless"
and (node.tls == "1" or (node.decryption and node.decryption ~= "" and node.decryption ~= "none")) and (node.tls == "1" or (node.decryption and node.decryption ~= "" and node.decryption ~= "none"))
@@ -497,7 +530,7 @@ function gen_config_server(node)
} }
end end
settings = { settings = {
clients = clients, users = users,
decryption = (node.protocol == "vless") and ((node.decryption and node.decryption ~= "") and node.decryption or "none") or nil decryption = (node.protocol == "vless") and ((node.decryption and node.decryption ~= "") and node.decryption or "none") or nil
} }
end end
@@ -505,7 +538,7 @@ function gen_config_server(node)
settings = { settings = {
udp = ("1" == node.udp_forward) and true or false, udp = ("1" == node.udp_forward) and true or false,
auth = ("1" == node.auth) and "password" or "noauth", auth = ("1" == node.auth) and "password" or "noauth",
accounts = ("1" == node.auth) and { users = ("1" == node.auth) and {
{ {
user = node.username, user = node.username,
pass = node.password pass = node.password
@@ -515,7 +548,7 @@ function gen_config_server(node)
elseif node.protocol == "http" then elseif node.protocol == "http" then
settings = { settings = {
allowTransparent = false, allowTransparent = false,
accounts = ("1" == node.auth) and { users = ("1" == node.auth) and {
{ {
user = node.username, user = node.username,
pass = node.password pass = node.password
@@ -533,20 +566,20 @@ function gen_config_server(node)
} }
elseif node.protocol == "trojan" then elseif node.protocol == "trojan" then
if node.uuid then if node.uuid then
local clients = {} local users = {}
for i = 1, #node.uuid do for i = 1, #node.uuid do
clients[i] = { users[i] = {
password = node.uuid[i] password = node.uuid[i],
} }
end end
settings = { settings = {
clients = clients users = users
} }
end end
elseif node.protocol == "hysteria2" then elseif node.protocol == "hysteria2" then
settings = { settings = {
version = 2, version = 2,
clients = node.hysteria2_auth_password and { users = node.hysteria2_auth_password and {
{ auth = node.hysteria2_auth_password } { auth = node.hysteria2_auth_password }
} }
} }
@@ -724,14 +757,36 @@ function gen_config_server(node)
udp[#udp+1] = c udp[#udp+1] = c
finalmask.udp = udp finalmask.udp = udp
elseif node.transport == "hysteria" then elseif node.transport == "hysteria" then
local udp = {}
if node.hysteria2_obfs_type and node.hysteria2_obfs_type ~= "" then if node.hysteria2_obfs_type and node.hysteria2_obfs_type ~= "" then
finalmask.udp = {{ local o = {
type = node.hysteria2_obfs_type, type = "salamander",
settings = node.hysteria2_obfs_password and { settings = node.hysteria2_obfs_password and {
password = node.hysteria2_obfs_password password = node.hysteria2_obfs_password,
packetSize = node.hysteria2_obfs_type == "gecko" and "512-1200" or nil
} or nil } or nil
}} }
udp[#udp+1] = o
end end
if node.hysteria2_realms then
local realm = api.parse_realm_uri(node.hysteria2_realm_url)
local url, stun
if realm then
if realm.token and realm.server_url and realm.realm_id then
url = "realm://" .. realm.token .. "@" .. realm.server_url .. "/" .. realm.realm_id
end
stun = realm.stun_servers or node.hysteria2_realm_stun
end
local r = {
type = "realm",
settings = {
url = url,
stunServers = stun
}
}
udp[#udp+1] = r
end
finalmask.udp = udp
local ignore = tonumber(node.hysteria2_ignore_client_bandwidth) == 1 local ignore = tonumber(node.hysteria2_ignore_client_bandwidth) == 1
local up = (not ignore) and tonumber(node.hysteria2_up_mbps) or 0 local up = (not ignore) and tonumber(node.hysteria2_up_mbps) or 0
local down = (not ignore) and tonumber(node.hysteria2_down_mbps) or 0 local down = (not ignore) and tonumber(node.hysteria2_down_mbps) or 0
@@ -761,7 +816,7 @@ function gen_config_server(node)
} }
local alpn = {} local alpn = {}
if node.alpn then if node.alpn and node.alpn ~= "default" then
string.gsub(node.alpn, '[^' .. "," .. ']+', function(w) string.gsub(node.alpn, '[^' .. "," .. ']+', function(w)
table.insert(alpn, w) table.insert(alpn, w)
end) end)
@@ -907,7 +962,7 @@ function gen_config(var)
end end
if local_socks_username and local_socks_password and local_socks_username ~= "" and local_socks_password ~= "" then if local_socks_username and local_socks_password and local_socks_username ~= "" and local_socks_password ~= "" then
inbound.settings.auth = "password" inbound.settings.auth = "password"
inbound.settings.accounts = { inbound.settings.users = {
{ {
user = local_socks_username, user = local_socks_username,
pass = local_socks_password pass = local_socks_password
@@ -925,7 +980,7 @@ function gen_config(var)
settings = {allowTransparent = false} settings = {allowTransparent = false}
} }
if local_http_username and local_http_password and local_http_username ~= "" and local_http_password ~= "" then if local_http_username and local_http_password and local_http_username ~= "" and local_http_password ~= "" then
inbound.settings.accounts = { inbound.settings.users = {
{ {
user = local_http_username, user = local_http_username,
pass = local_http_password pass = local_http_password
@@ -2047,7 +2102,7 @@ function gen_proto_config(var)
} }
if local_socks_username and local_socks_password and local_socks_username ~= "" and local_socks_password ~= "" then if local_socks_username and local_socks_password and local_socks_username ~= "" and local_socks_password ~= "" then
inbound.settings.auth = "password" inbound.settings.auth = "password"
inbound.settings.accounts = { inbound.settings.users = {
{ {
user = local_socks_username, user = local_socks_username,
pass = local_socks_password pass = local_socks_password
@@ -2067,7 +2122,7 @@ function gen_proto_config(var)
} }
} }
if local_http_username and local_http_password and local_http_username ~= "" and local_http_password ~= "" then if local_http_username and local_http_password and local_http_username ~= "" and local_http_password ~= "" then
inbound.settings.accounts = { inbound.settings.users = {
{ {
user = local_http_username, user = local_http_username,
pass = local_http_password pass = local_http_password
@@ -150,12 +150,9 @@ local api = require "luci.passwall2.api"
if (confirm("<%: Do you want to restore the client to default settings?%>")) { if (confirm("<%: Do you want to restore the client to default settings?%>")) {
setTimeout(function () { setTimeout(function () {
if (confirm("<%: Are you sure you want to restore the client to default settings?%>")) { if (confirm("<%: Are you sure you want to restore the client to default settings?%>")) {
var xhr1 = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
xhr1.open("GET",'<%= api.url("clear_log") %>', false); xhr.open("GET",'<%= api.url("reset_config") %>', false);
xhr1.send(); xhr.send();
var xhr2 = new XMLHttpRequest();
xhr2.open("GET",'<%= api.url("reset_config") %>', false);
xhr2.send();
window.location.href = '<%= api.url("log") %>' window.location.href = '<%= api.url("log") %>'
} }
}, 1000); }, 1000);
@@ -600,7 +600,7 @@ local current_node = map:get(section)
v_password = opt.get("hysteria2_auth_password"); v_password = opt.get("hysteria2_auth_password");
var dom_obfs = opt.get("hysteria2_obfs_password"); var dom_obfs = opt.get("hysteria2_obfs_password");
if (dom_obfs && dom_obfs.value != "") { if (dom_obfs && dom_obfs.value != "") {
params += "&obfs=" + "salamander"; params += opt.query("obfs", "hysteria2_obfs_type");
params += opt.query("obfs-password", "hysteria2_obfs_password"); params += opt.query("obfs-password", "hysteria2_obfs_password");
} }
params += opt.query("mport", "hysteria2_hop"); params += opt.query("mport", "hysteria2_hop");
@@ -1598,7 +1598,7 @@ local current_node = map:get(section)
opt.set(dom_prefix + 'protocol', "hysteria2"); opt.set(dom_prefix + 'protocol', "hysteria2");
opt.set(dom_prefix + 'hysteria2_auth_password', decodeURIComponent(password)); opt.set(dom_prefix + 'hysteria2_auth_password', decodeURIComponent(password));
if (queryParam["obfs-password"] || queryParam["obfs_password"]) { if (queryParam["obfs-password"] || queryParam["obfs_password"]) {
opt.set(dom_prefix + 'hysteria2_obfs_type', "salamander"); opt.set(dom_prefix + 'hysteria2_obfs_type', queryParam.obfs || "salamander");
opt.set(dom_prefix + 'hysteria2_obfs_password', queryParam["obfs-password"] || queryParam["obfs_password"]); opt.set(dom_prefix + 'hysteria2_obfs_password', queryParam["obfs-password"] || queryParam["obfs_password"]);
} }
opt.set(dom_prefix + 'hysteria2_hop', queryParam.mport || ""); opt.set(dom_prefix + 'hysteria2_hop', queryParam.mport || "");
@@ -1609,7 +1609,7 @@ local current_node = map:get(section)
dom_prefix = "hysteria2_" dom_prefix = "hysteria2_"
opt.set(dom_prefix + 'auth_password', decodeURIComponent(password)); opt.set(dom_prefix + 'auth_password', decodeURIComponent(password));
if (queryParam["obfs-password"] || queryParam["obfs_password"]) { if (queryParam["obfs-password"] || queryParam["obfs_password"]) {
opt.set(dom_prefix + 'obfs_type', "salamander"); opt.set(dom_prefix + 'obfs_type', queryParam.obfs || "salamander");
opt.set(dom_prefix + 'obfs_password', queryParam["obfs-password"] || queryParam["obfs_password"]); opt.set(dom_prefix + 'obfs_password', queryParam["obfs-password"] || queryParam["obfs_password"]);
} }
opt.set(dom_prefix + 'hop', queryParam.mport || ""); opt.set(dom_prefix + 'hop', queryParam.mport || "");
+8 -2
View File
@@ -1656,6 +1656,12 @@ msgstr "نام گواهی TLS (CertName)"
msgid "TLS is used to verify the leaf certificate name." msgid "TLS is used to verify the leaf certificate name."
msgstr "TLS برای تأیید نام گواهی برگ (Leaf Certificate) استفاده می‌شود." msgstr "TLS برای تأیید نام گواهی برگ (Leaf Certificate) استفاده می‌شود."
msgid "TLS Certificate (PEM)"
msgstr "گواهی TLS (PEM)"
msgid "Full certificate (chain), PEM format."
msgstr "گواهی کامل (زنجیره‌ای)، فرمت PEM."
msgid "ECH Config" msgid "ECH Config"
msgstr "پیکربندی ECH" msgstr "پیکربندی ECH"
@@ -2281,8 +2287,8 @@ msgstr "نادیده گرفتن گره %s به دلیل ناسازگاری با
msgid "Skip node: %s. Because Sing-Box does not support the %s protocol's %s transmission method, Xray needs to be used instead." msgid "Skip node: %s. Because Sing-Box does not support the %s protocol's %s transmission method, Xray needs to be used instead."
msgstr "صرف‌نظر از گره: %s. زیرا Sing-Box از روش انتقال %s پروتکل %s پشتیبانی نمی‌کند، باید به جای آن از Xray استفاده شود." msgstr "صرف‌نظر از گره: %s. زیرا Sing-Box از روش انتقال %s پروتکل %s پشتیبانی نمی‌کند، باید به جای آن از Xray استفاده شود."
msgid "Xray unsupport %s plugin." msgid "%s unsupport SS %s plugin."
msgstr "Xray از افزونه %s پشتیبانی نمی‌کند." msgstr "%s از افزونه %s پشتیبانی نمی‌کند."
msgid "Plugin options Incomplete." msgid "Plugin options Incomplete."
msgstr "گزینه‌های افزونه ناقص است." msgstr "گزینه‌های افزونه ناقص است."
+8 -2
View File
@@ -1657,6 +1657,12 @@ msgstr "Имя TLS-сертификата (CertName)"
msgid "TLS is used to verify the leaf certificate name." msgid "TLS is used to verify the leaf certificate name."
msgstr "Используется TLS для проверки имени конечного сертификата." msgstr "Используется TLS для проверки имени конечного сертификата."
msgid "TLS Certificate (PEM)"
msgstr "Сертификат TLS (PEM)"
msgid "Full certificate (chain), PEM format."
msgstr "Полный сертификат (цепочка), формат PEM."
msgid "ECH Config" msgid "ECH Config"
msgstr "Конфигурация ECH" msgstr "Конфигурация ECH"
@@ -2279,8 +2285,8 @@ msgstr "Пропуск сервера %s: несовместимость с яд
msgid "Skip node: %s. Because Sing-Box does not support the %s protocol's %s transmission method, Xray needs to be used instead." msgid "Skip node: %s. Because Sing-Box does not support the %s protocol's %s transmission method, Xray needs to be used instead."
msgstr "Пропуск сервера: %s. Sing-Box не поддерживает метод передачи %s протокола %s, необходимо использовать Xray." msgstr "Пропуск сервера: %s. Sing-Box не поддерживает метод передачи %s протокола %s, необходимо использовать Xray."
msgid "Xray unsupport %s plugin." msgid "%s unsupport SS %s plugin."
msgstr "Xray не поддерживает плагин %s." msgstr "%s не поддерживает плагин %s."
msgid "Plugin options Incomplete." msgid "Plugin options Incomplete."
msgstr "Опции плагина указаны не полностью." msgstr "Опции плагина указаны не полностью."
+8 -2
View File
@@ -1648,6 +1648,12 @@ msgstr "TLS 证书名称(CertName)"
msgid "TLS is used to verify the leaf certificate name." msgid "TLS is used to verify the leaf certificate name."
msgstr "TLS 用于验证 leaf 证书的 name。" msgstr "TLS 用于验证 leaf 证书的 name。"
msgid "TLS Certificate (PEM)"
msgstr "TLS 证书(PEM)"
msgid "Full certificate (chain), PEM format."
msgstr "完整证书(链),PEM 格式。"
msgid "ECH Config" msgid "ECH Config"
msgstr "ECH 配置" msgstr "ECH 配置"
@@ -2267,8 +2273,8 @@ msgstr "跳过 %s 节点,因未适配到 %s 核心程序,或未正确设置
msgid "Skip node: %s. Because Sing-Box does not support the %s protocol's %s transmission method, Xray needs to be used instead." msgid "Skip node: %s. Because Sing-Box does not support the %s protocol's %s transmission method, Xray needs to be used instead."
msgstr "跳过节点:%s,因 Sing-Box 不支持 %s 协议的 %s 传输方式,需更换 Xray。" msgstr "跳过节点:%s,因 Sing-Box 不支持 %s 协议的 %s 传输方式,需更换 Xray。"
msgid "Xray unsupport %s plugin." msgid "%s unsupport SS %s plugin."
msgstr "Xray 不支持 %s 插件。" msgstr "%s 不支持 %s 插件。"
msgid "Plugin options Incomplete." msgid "Plugin options Incomplete."
msgstr "插件选项不完整。" msgstr "插件选项不完整。"
+8 -2
View File
@@ -1648,6 +1648,12 @@ msgstr "TLS 憑證名稱(CertName)"
msgid "TLS is used to verify the leaf certificate name." msgid "TLS is used to verify the leaf certificate name."
msgstr "TLS 用於驗證 leaf 憑證的 name。" msgstr "TLS 用於驗證 leaf 憑證的 name。"
msgid "TLS Certificate (PEM)"
msgstr "TLS 憑證(PEM)"
msgid "Full certificate (chain), PEM format."
msgstr "完整憑證(鏈),PEM 格式。"
msgid "ECH Config" msgid "ECH Config"
msgstr "ECH 配置" msgstr "ECH 配置"
@@ -2273,8 +2279,8 @@ msgstr "跳過 %s 節點,因未適配到 %s 核心程序,或未正確設置
msgid "Skip node: %s. Because Sing-Box does not support the %s protocol's %s transmission method, Xray needs to be used instead." msgid "Skip node: %s. Because Sing-Box does not support the %s protocol's %s transmission method, Xray needs to be used instead."
msgstr "跳過節點:%s,因 Sing-Box 不支持 %s 協議的 %s 傳輸方式,需更換 Xray。" msgstr "跳過節點:%s,因 Sing-Box 不支持 %s 協議的 %s 傳輸方式,需更換 Xray。"
msgid "Xray unsupport %s plugin." msgid "%s unsupport SS %s plugin."
msgstr "Xray 不支持 %s 插件。" msgstr "%s 不支持 %s 插件。"
msgid "Plugin options Incomplete." msgid "Plugin options Incomplete."
msgstr "插件選項不完整。" msgstr "插件選項不完整。"
@@ -1012,9 +1012,10 @@ acl_app() {
[ -n "$items" ] && { [ -n "$items" ] && {
local index=0 local index=0
local item local item
local redir_port dns_port dnsmasq_port local redir_port dns_port dnsmasq_port socks_port
local ipt_tmp msg msg2 local ipt_tmp msg msg2
redir_port=11200 redir_port=11200
socks_port=11600
dns_port=11300 dns_port=11300
dnsmasq_port=${GLOBAL_DNSMASQ_PORT:-11400} dnsmasq_port=${GLOBAL_DNSMASQ_PORT:-11400}
for item in $items; do for item in $items; do
@@ -1098,12 +1099,13 @@ acl_app() {
set_cache_var "ACL_${sid}_default" "1" set_cache_var "ACL_${sid}_default" "1"
else else
redir_port=$(get_new_port $(expr $redir_port + 1)) redir_port=$(get_new_port $(expr $redir_port + 1))
socks_port=$(get_new_port $(expr $socks_port + 1))
local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z') local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z')
if [ -n "${type}" ]; then if [ -n "${type}" ]; then
config_file=$TMP_ACL_PATH/${node}_TCP_UDP_DNS_${redir_port}.json config_file=$TMP_ACL_PATH/${node}_TCP_UDP_DNS_${redir_port}.json
dns_port=$(get_new_port $(expr $dns_port + 1)) dns_port=$(get_new_port $(expr $dns_port + 1))
local acl_socks_port=$(get_new_port $(expr $redir_port + $index)) local acl_socks_port=$socks_port
local run_func local run_func
[ -n "${XRAY_BIN}" ] && run_func="run_xray" [ -n "${XRAY_BIN}" ] && run_func="run_xray"
[ -n "${SINGBOX_BIN}" ] && run_func="run_singbox" [ -n "${SINGBOX_BIN}" ] && run_func="run_singbox"
@@ -528,36 +528,50 @@ local function parseClashNode(node, add_mode, group, sub_cfg)
elseif node.plugin == "v2ray-plugin" then elseif node.plugin == "v2ray-plugin" then
result.plugin = "v2ray-plugin" result.plugin = "v2ray-plugin"
end end
if node["plugin-opts"] then if result.plugin then
if node.plugin == "obfs" then result.plugin_enabled = "1"
local plugin_opts = "" if result.type == 'Xray' then
local opts_mode = node["plugin-opts"].mode if result.plugin ~= "obfs-local" then
if opts_mode then result.plugin_enabled = nil
plugin_opts = plugin_opts .. "obfs=" .. opts_mode .. ";" result.error_msg = i18n.translatef("%s unsupport SS %s plugin.", "Xray", result.plugin)
end end
local opts_host = node["plugin-opts"].host elseif result.type == 'sing-box' then
if opts_host then if result.plugin ~= "obfs-local" and result.plugin ~= "v2ray-plugin" then
plugin_opts = plugin_opts .. "obfs-host=" .. opts_host result.plugin_enabled = nil
result.error_msg = i18n.translatef("%s unsupport SS %s plugin.", "Sing-Box", result.plugin)
end end
result.plugin_opts = plugin_opts end
elseif node.plugin == "v2ray-plugin" then if node["plugin-opts"] and result.plugin_enabled == "1" then
local plugin_opts = "" if node.plugin == "obfs" then
local opts_mode = node["plugin-opts"].mode local plugin_opts = ""
local opts_tls = node["plugin-opts"].tls local opts_mode = node["plugin-opts"].mode
if opts_tls then if opts_mode then
plugin_opts = plugin_opts .. "tls;" plugin_opts = plugin_opts .. "obfs=" .. opts_mode .. ";"
end
local opts_host = node["plugin-opts"].host
if opts_host then
plugin_opts = plugin_opts .. "obfs-host=" .. opts_host
end
result.plugin_opts = plugin_opts
elseif node.plugin == "v2ray-plugin" then
local plugin_opts = ""
local opts_mode = node["plugin-opts"].mode
local opts_tls = node["plugin-opts"].tls
if opts_tls then
plugin_opts = plugin_opts .. "tls;"
end
local opts_skip_cert_verify = node["plugin-opts"]["skip-cert-verify"]
local opts_host = node["plugin-opts"].host
if opts_host then
plugin_opts = plugin_opts .. "host=" .. opts_host .. ";"
end
local opts_path = node["plugin-opts"].path
local opts_mux = node["plugin-opts"].mux
if node["plugin-opts"].headers then
--todo
end
result.plugin_opts = plugin_opts
end end
local opts_skip_cert_verify = node["plugin-opts"]["skip-cert-verify"]
local opts_host = node["plugin-opts"].host
if opts_host then
plugin_opts = plugin_opts .. "host=" .. opts_host .. ";"
end
local opts_path = node["plugin-opts"].path
local opts_mux = node["plugin-opts"].mux
if node["plugin-opts"].headers then
--todo
end
result.plugin_opts = plugin_opts
end end
end end
elseif node.type == 'ssr' then elseif node.type == 'ssr' then
@@ -961,6 +975,11 @@ local function processData(szType, content, add_mode, group, sub_cfg)
result.tls = "0" result.tls = "0"
end end
if info.ech and info.ech ~= "" then
result.ech = "1"
result.ech_config = info.ech
end
result.tcp_fast_open = info.tfo result.tcp_fast_open = info.tfo
info.fm = (info.fm and info.fm ~= "") and UrlDecode(info.fm) or nil info.fm = (info.fm and info.fm ~= "") and UrlDecode(info.fm) or nil
@@ -1090,7 +1109,7 @@ local function processData(szType, content, add_mode, group, sub_cfg)
if result.type == 'Xray' then if result.type == 'Xray' then
-- The obfs-local plugin converts data to a format supported by xray. -- The obfs-local plugin converts data to a format supported by xray.
if result.plugin ~= "obfs-local" then if result.plugin ~= "obfs-local" then
result.error_msg = i18n.translatef("Xray unsupport %s plugin.", result.plugin) result.error_msg = i18n.translatef("%s unsupport SS %s plugin.", "Xray", result.plugin)
else else
local obfs = result.plugin_opts:match("obfs=([^;]+)") or "" local obfs = result.plugin_opts:match("obfs=([^;]+)") or ""
local obfs_host = result.plugin_opts:match("obfs%-host=([^;]+)") or "" local obfs_host = result.plugin_opts:match("obfs%-host=([^;]+)") or ""
@@ -1110,6 +1129,12 @@ local function processData(szType, content, add_mode, group, sub_cfg)
result.plugin = nil result.plugin = nil
result.plugin_opts = nil result.plugin_opts = nil
end end
elseif result.type == 'sing-box' then
if result.plugin ~= "obfs-local" and result.plugin ~= "v2ray-plugin" then
result.error_msg = i18n.translatef("%s unsupport SS %s plugin.", "Sing-Box", result.plugin)
else
result.plugin_enabled = "1"
end
else else
result.plugin_enabled = "1" result.plugin_enabled = "1"
end end
@@ -1223,7 +1248,7 @@ local function processData(szType, content, add_mode, group, sub_cfg)
local insecure = params.allowinsecure or params.allowInsecure or params.insecure local insecure = params.allowinsecure or params.allowInsecure or params.insecure
result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (sub_allowinsecure and "1" or "0") result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (sub_allowinsecure and "1" or "0")
result.uot = params.udp result.uot = params.udp
elseif (params.type ~= "tcp" and params.type ~= "raw") and (params.headerType and params.headerType ~= "none") then else
result.error_msg = i18n.translatef("Please replace Xray or Sing-Box to support more transmission methods in Shadowsocks.") result.error_msg = i18n.translatef("Please replace Xray or Sing-Box to support more transmission methods in Shadowsocks.")
end end
end end
@@ -1684,7 +1709,7 @@ local function processData(szType, content, add_mode, group, sub_cfg)
result.hysteria2_down_mbps = params.downmbps or sub_hy_down_mbps result.hysteria2_down_mbps = params.downmbps or sub_hy_down_mbps
result.hysteria2_hop = params.mport result.hysteria2_hop = params.mport
if params["obfs-password"] or params["obfs_password"] then if params["obfs-password"] or params["obfs_password"] then
result.hysteria2_obfs_type = "salamander" result.hysteria2_obfs_type = params.obfs or "salamander"
result.hysteria2_obfs_password = params["obfs-password"] or params["obfs_password"] result.hysteria2_obfs_password = params["obfs-password"] or params["obfs_password"]
end end
@@ -1818,6 +1843,10 @@ local function processData(szType, content, add_mode, group, sub_cfg)
result.reality_publicKey = params.pbk or nil result.reality_publicKey = params.pbk or nil
result.reality_shortId = params.sid or nil result.reality_shortId = params.sid or nil
end end
if params.ech and params.ech ~= "" then
result.ech = "1"
result.ech_config = params.ech
end
end end
result.port = port result.port = port
local insecure = params.allowinsecure or params.insecure local insecure = params.allowinsecure or params.insecure
+1 -1
View File
@@ -1,7 +1,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=momo PKG_NAME:=momo
PKG_VERSION:=2026.04.09 PKG_VERSION:=2026.06.03
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_LICENSE:=GPL-3.0+ PKG_LICENSE:=GPL-3.0+
+1
View File
@@ -121,6 +121,7 @@ config routing 'routing'
option 'dummy_device' 'momo-dummy' option 'dummy_device' 'momo-dummy'
config log 'log' config log 'log'
option 'clear_at_stop' '1'
option 'scheduled_clear' '1' option 'scheduled_clear' '1'
option 'scheduled_clear_cron' '*/5 * * * *' option 'scheduled_clear_cron' '*/5 * * * *'
option 'scheduled_clear_size_limit' '1' option 'scheduled_clear_size_limit' '1'
+23 -1
View File
@@ -67,7 +67,9 @@ start_service() {
local fast_reload local fast_reload
config_get_bool fast_reload "procd" "fast_reload" 0 config_get_bool fast_reload "procd" "fast_reload" 0
### rlimit ### rlimit
local rlimit_address_space_soft rlimit_address_space_hard rlimit_data_soft rlimit_data_hard rlimit_stack_soft rlimit_stack_hard rlimit_nofile_soft rlimit_nofile_hard local rlimit_nproc_soft rlimit_nproc_hard rlimit_address_space_soft rlimit_address_space_hard rlimit_data_soft rlimit_data_hard rlimit_stack_soft rlimit_stack_hard rlimit_nofile_soft rlimit_nofile_hard
config_get rlimit_nproc_soft "procd" "rlimit_nproc_soft" "$(ulimit -Su)"
config_get rlimit_nproc_hard "procd" "rlimit_nproc_hard" "$(ulimit -Hu)"
config_get rlimit_address_space_soft "procd" "rlimit_address_space_soft" config_get rlimit_address_space_soft "procd" "rlimit_address_space_soft"
config_get rlimit_address_space_hard "procd" "rlimit_address_space_hard" config_get rlimit_address_space_hard "procd" "rlimit_address_space_hard"
config_get rlimit_data_soft "procd" "rlimit_data_soft" config_get rlimit_data_soft "procd" "rlimit_data_soft"
@@ -76,6 +78,10 @@ start_service() {
config_get rlimit_stack_hard "procd" "rlimit_stack_hard" config_get rlimit_stack_hard "procd" "rlimit_stack_hard"
config_get rlimit_nofile_soft "procd" "rlimit_nofile_soft" "$(ulimit -Sn)" config_get rlimit_nofile_soft "procd" "rlimit_nofile_soft" "$(ulimit -Sn)"
config_get rlimit_nofile_hard "procd" "rlimit_nofile_hard" "$(ulimit -Hn)" config_get rlimit_nofile_hard "procd" "rlimit_nofile_hard" "$(ulimit -Hn)"
### environment variable
local env_go_max_procs env_go_mem_limit
config_get env_go_max_procs "procd" "env_go_max_procs"
config_get env_go_mem_limit "procd" "env_go_mem_limit"
## core config ## core config
local redirect_inbound_tag tproxy_inbound_tag tun_inbound_tag dns_inbound_tag fake_ip_dns_server_tag local redirect_inbound_tag tproxy_inbound_tag tun_inbound_tag dns_inbound_tag fake_ip_dns_server_tag
config_get redirect_inbound_tag "core" "redirect_inbound_tag" config_get redirect_inbound_tag "core" "redirect_inbound_tag"
@@ -133,6 +139,8 @@ start_service() {
log "Mixin" "Mixin config." log "Mixin" "Mixin config."
ucode -S "$MIXIN_UC" ucode -S "$MIXIN_UC"
fi fi
# format profile
$PROG -c "$RUN_PROFILE_PATH" format -w
# check profile # check profile
if [ "$core_only" = 0 ] && [ "$proxy_enabled" = 1 ]; then if [ "$core_only" = 0 ] && [ "$proxy_enabled" = 1 ]; then
log "Profile" "Checking..." log "Profile" "Checking..."
@@ -197,11 +205,16 @@ start_service() {
fi fi
procd_set_param pidfile "$PID_FILE_PATH" procd_set_param pidfile "$PID_FILE_PATH"
procd_set_param respawn procd_set_param respawn
procd_append_param limits nproc="${rlimit_nproc_soft} ${rlimit_nproc_hard}"
procd_append_param limits as="${rlimit_address_space_soft:-unlimited} ${rlimit_address_space_hard:-unlimited}" procd_append_param limits as="${rlimit_address_space_soft:-unlimited} ${rlimit_address_space_hard:-unlimited}"
procd_append_param limits data="${rlimit_data_soft:-unlimited} ${rlimit_data_hard:-unlimited}" procd_append_param limits data="${rlimit_data_soft:-unlimited} ${rlimit_data_hard:-unlimited}"
procd_append_param limits stack="${rlimit_stack_soft:-unlimited} ${rlimit_stack_hard:-unlimited}" procd_append_param limits stack="${rlimit_stack_soft:-unlimited} ${rlimit_stack_hard:-unlimited}"
procd_append_param limits nofile="${rlimit_nofile_soft} ${rlimit_nofile_hard}" procd_append_param limits nofile="${rlimit_nofile_soft} ${rlimit_nofile_hard}"
procd_append_param env GOMAXPROCS="$env_go_max_procs"
procd_append_param env GOMEMLIMIT="$env_go_mem_limit"
procd_close_instance procd_close_instance
# cron # cron
local reload_cron; reload_cron=0 local reload_cron; reload_cron=0
@@ -379,11 +392,20 @@ cleanup() {
# load config # load config
config_load momo config_load momo
# get config # get config
## log config
local log_clear_at_stop
config_get_bool log_clear_at_stop "log" "clear_at_stop" 0
## routing config ## routing config
local tproxy_route_table tun_route_table dummy_device local tproxy_route_table tun_route_table dummy_device
config_get tproxy_route_table "routing" "tproxy_route_table" "80" config_get tproxy_route_table "routing" "tproxy_route_table" "80"
config_get tun_route_table "routing" "tun_route_table" "81" config_get tun_route_table "routing" "tun_route_table" "81"
config_get dummy_device "routing" "dummy_device" "momo-dummy" config_get dummy_device "routing" "dummy_device" "momo-dummy"
# clear logs if needed
if [ "$log_clear_at_stop" = 1 ]; then
echo -n > "$APP_LOG_PATH"
echo -n > "$CORE_LOG_PATH"
log "Log" "Logs are cleared due to clear at stop is enabled."
fi
# delete routing policy # delete routing policy
ip -4 rule del table "$tproxy_route_table" > /dev/null 2>&1 ip -4 rule del table "$tproxy_route_table" > /dev/null 2>&1
ip -4 rule del table "$tun_route_table" > /dev/null 2>&1 ip -4 rule del table "$tun_route_table" > /dev/null 2>&1
+3
View File
@@ -51,6 +51,9 @@ section_mixin=$(uci -q get momo.mixin); [ -z "$section_mixin" ] && {
uci set momo.mixin.external_control_ui_download_url='https://github.com/Zephyruso/zashboard/releases/latest/download/dist-cdn-fonts.zip' uci set momo.mixin.external_control_ui_download_url='https://github.com/Zephyruso/zashboard/releases/latest/download/dist-cdn-fonts.zip'
} }
# since v1.2.1
config_clear_at_stop=$(uci -q get momo.log.clear_at_stop); [ -z "$config_clear_at_stop" ] && uci set momo.log.clear_at_stop=1
# commit # commit
uci commit momo uci commit momo
+4
View File
@@ -248,6 +248,7 @@ table inet momo {
} }
{% if (router_proxy): %} {% if (router_proxy): %}
{% if (length(dns_hijack_nfproto) > 0): %}
chain router_dns_hijack { chain router_dns_hijack {
{% for (let access_control in router_access_control): %} {% for (let access_control in router_access_control): %}
{% if (length(access_control['user']) == 0 && length(access_control['group']) == 0 && length(access_control['cgroup']) == 0): %} {% if (length(access_control['user']) == 0 && length(access_control['group']) == 0 && length(access_control['cgroup']) == 0): %}
@@ -267,6 +268,7 @@ table inet momo {
{% endif %} {% endif %}
{% endfor %} {% endfor %}
} }
{% endif %}
{% if (tcp_mode == 'redirect'): %} {% if (tcp_mode == 'redirect'): %}
chain router_redirect { chain router_redirect {
@@ -360,6 +362,7 @@ table inet momo {
{% endif %} {% endif %}
{% if (lan_proxy): %} {% if (lan_proxy): %}
{% if (length(dns_hijack_nfproto) > 0): %}
chain lan_dns_hijack { chain lan_dns_hijack {
{% for (let access_control in lan_access_control): %} {% for (let access_control in lan_access_control): %}
{% if (length(access_control['ip']) == 0 && length(access_control['ip6']) == 0 && length(access_control['mac']) == 0): %} {% if (length(access_control['ip']) == 0 && length(access_control['ip6']) == 0 && length(access_control['mac']) == 0): %}
@@ -381,6 +384,7 @@ table inet momo {
{% endif %} {% endif %}
{% endfor %} {% endfor %}
} }
{% endif %}
{% if (tcp_mode == 'redirect'): %} {% if (tcp_mode == 'redirect'): %}
chain lan_redirect { chain lan_redirect {
+2 -2
View File
@@ -21,13 +21,13 @@ define Download/geoip
HASH:=e9002979e0df72bce1c8751ff70725386594c551db684b7a232935b8b2bb8aa2 HASH:=e9002979e0df72bce1c8751ff70725386594c551db684b7a232935b8b2bb8aa2
endef endef
GEOSITE_VER:=20260602145358 GEOSITE_VER:=20260603121550
GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER) GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER)
define Download/geosite define Download/geosite
URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/ URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/
URL_FILE:=dlc.dat URL_FILE:=dlc.dat
FILE:=$(GEOSITE_FILE) FILE:=$(GEOSITE_FILE)
HASH:=92d535187e8a2eee0a3cfb3ed22e481884c4fb93a7ab903e30b26ca405fa530b HASH:=fab7cce3d3009121a88939d616f0366d3067741dce21424b627426cbd17f1e62
endef endef
GEOSITE_IRAN_VER:=202606010205 GEOSITE_IRAN_VER:=202606010205