diff --git a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/client.js b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/client.js
index afe7b3e21..b9a2d296d 100644
--- a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/client.js
+++ b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/client.js
@@ -48,13 +48,13 @@ function getServiceStatus() {
});
}
-function renderStatus(isRunning) {
- var spanTemp = '%s %s';
+function renderStatus(isRunning, version) {
+ var spanTemp = '%s (sing-box v%s) %s';
var renderHTML;
if (isRunning)
- renderHTML = spanTemp.format('green', _('HomeProxy'), _('RUNNING'));
+ renderHTML = spanTemp.format('green', _('HomeProxy'), version, _('RUNNING'));
else
- renderHTML = spanTemp.format('red', _('HomeProxy'), _('NOT RUNNING'));
+ renderHTML = spanTemp.format('red', _('HomeProxy'), version, _('NOT RUNNING'));
return renderHTML;
}
@@ -125,7 +125,7 @@ return view.extend({
poll.add(function () {
return L.resolveDefault(getServiceStatus()).then((res) => {
var view = document.getElementById('service_status');
- view.innerHTML = renderStatus(res);
+ view.innerHTML = renderStatus(res, features.version);
});
});
@@ -480,10 +480,30 @@ return view.extend({
so = ss.taboption('field_other', form.MultiValue, 'protocol', _('Protocol'),
_('Sniffed protocol, see Sniff for details.'));
+ if (features.version.localeCompare('1.10.0', undefined, { numeric: true, sensitivity: 'base' }) >= 0) {
+ so.value('bittorrent', _('BitTorrent'));
+ so.value('dtls', _('DTLS'));
+ }
so.value('http', _('HTTP'));
- so.value('tls', _('TLS'));
so.value('quic', _('QUIC'));
+ if (features.version.localeCompare('1.10.0', undefined, { numeric: true, sensitivity: 'base' }) >= 0) {
+ so.value('rdp', _('RDP'));
+ so.value('ssh', _('SSH'));
+ }
so.value('stun', _('STUN'));
+ so.value('tls', _('TLS'));
+
+ if (features.version.localeCompare('1.10.0', undefined, { numeric: true, sensitivity: 'base' }) >= 0) {
+ so = ss.taboption('field_other', form.Value, 'client', _('Client'),
+ _('Sniffed client type (QUIC client type or SSH client name).'));
+ so.value('chromium', _('Chromium / Cronet'));
+ so.value('firefox', _('Firefox / uquic firefox'));
+ so.value('quic-go', _('quic-go / uquic chrome'));
+ so.value('safari', _('Safari / Apple Network API'));
+ so.depends('protocol', 'quic');
+ so.depends('protocol', 'ssh');
+ so.modalonly = true;
+ }
so = ss.taboption('field_other', form.ListValue, 'network', _('Network'));
so.value('tcp', _('TCP'));
@@ -557,6 +577,12 @@ return view.extend({
_('Match process path.'));
so.modalonly = true;
+ if (features.version.localeCompare('1.10.0', undefined, { numeric: true, sensitivity: 'base' }) >= 0) {
+ so = ss.taboption('field_other', form.DynamicList, 'process_path_regex', _('Process path (regex)'),
+ _('Match process path using regular expression.'));
+ so.modalonly = true;
+ }
+
so = ss.taboption('field_other', form.DynamicList, 'user', _('User'),
_('Match user name.'));
so.modalonly = true;
@@ -577,10 +603,9 @@ return view.extend({
}
so.modalonly = true;
- so = ss.taboption('field_other', form.Flag, 'rule_set_ipcidr_match_source', _('Match source IP via rule set'),
+ so = ss.taboption('field_other', form.Flag, 'rule_set_ip_cidr_match_source', _('Match source IP via rule set'),
_('Make IP CIDR in rule set used to match the source IP.'));
so.default = so.disabled;
- so.rmempty = false;
so.modalonly = true;
so = ss.taboption('field_other', form.Flag, 'invert', _('Invert'),
@@ -820,11 +845,18 @@ return view.extend({
so = ss.taboption('field_other', form.MultiValue, 'protocol', _('Protocol'),
_('Sniffed protocol, see Sniff for details.'));
+ if (features.version.localeCompare('1.10.0', undefined, { numeric: true, sensitivity: 'base' }) >= 0) {
+ so.value('bittorrent', _('BitTorrent'));
+ so.value('dtls', _('DTLS'));
+ }
so.value('http', _('HTTP'));
- so.value('tls', _('TLS'));
so.value('quic', _('QUIC'));
- so.value('dns', _('DNS'));
+ if (features.version.localeCompare('1.10.0', undefined, { numeric: true, sensitivity: 'base' }) >= 0) {
+ so.value('rdp', _('RDP'));
+ so.value('ssh', _('SSH'));
+ }
so.value('stun', _('STUN'));
+ so.value('tls', _('TLS'));
so = ss.taboption('field_host', form.DynamicList, 'domain', _('Domain name'),
_('Match full domain.'));
@@ -891,6 +923,12 @@ return view.extend({
_('Match process path.'));
so.modalonly = true;
+ if (features.version.localeCompare('1.10.0', undefined, { numeric: true, sensitivity: 'base' }) >= 0) {
+ so = ss.taboption('field_other', form.DynamicList, 'process_path_regex', _('Process path (regex)'),
+ _('Match process path using regular expression.'));
+ so.modalonly = true;
+ }
+
so = ss.taboption('field_other', form.DynamicList, 'user', _('User'),
_('Match user name.'));
so.modalonly = true;
@@ -911,18 +949,25 @@ return view.extend({
}
so.modalonly = true;
- so = ss.taboption('field_other', form.Flag, 'rule_set_ipcidr_match_source', _('Rule set IP CIDR as source IP'),
- _('Make ipcidr
in rule sets match the source IP.'));
+ so = ss.taboption('field_other', form.Flag, 'rule_set_ip_cidr_match_source', _('Rule set IP CIDR as source IP'),
+ _('Make IP CIDR in rule sets match the source IP.'));
so.default = so.disabled;
so.modalonly = true;
+ if (features.version.localeCompare('1.10.0', undefined, { numeric: true, sensitivity: 'base' }) >= 0) {
+ so = ss.taboption('field_other', form.Flag, 'rule_set_ip_cidr_accept_empty', _('Accept empty query response.'),
+ _('Make IP CIDR in rule-sets accept empty query response.'));
+ so.default = so.disabled;
+ so.modalonly = true;
+ }
+
so = ss.taboption('field_other', form.Flag, 'invert', _('Invert'),
_('Invert match result.'));
so.default = so.disabled;
so.modalonly = true;
so = ss.taboption('field_other', form.MultiValue, 'outbound', _('Outbound'),
- _('Match .outbounds[].server
domains.'));
+ _('Match the server name of outbound.'));
so.load = function(section_id) {
delete this.keylist;
delete this.vallist;
diff --git a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/node.js b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/node.js
index fcc110aa2..98691e331 100644
--- a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/node.js
+++ b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/node.js
@@ -1,7 +1,7 @@
/*
* SPDX-License-Identifier: GPL-2.0-only
*
- * Copyright (C) 2022 ImmortalWrt.org
+ * Copyright (C) 2022-2024 ImmortalWrt.org
*/
'use strict';
@@ -404,7 +404,7 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
o.value('trojan', _('Trojan'));
if (features.with_quic)
o.value('tuic', _('Tuic'));
- if (features.with_wireguard)
+ if (features.with_wireguard && features.with_gvisor)
o.value('wireguard', _('WireGuard'));
o.value('vless', _('VLESS'));
o.value('vmess', _('VMess'));
@@ -874,9 +874,8 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
o = s.option(form.Value, 'wireguard_mtu', _('MTU'));
o.datatype = 'range(0,9000)';
- o.default = '1408';
+ o.placeholder = '1408';
o.depends('type', 'wireguard');
- o.rmempty = false;
o.modalonly = true;
/* Wireguard config end */
@@ -1062,11 +1061,13 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
o.value('360');
o.value('android');
o.value('chrome');
- o.value('chrome_psk');
- o.value('chrome_psk_shuffle');
- o.value('chrome_padding_psk_shuffle');
- o.value('chrome_pq');
- o.value('chrome_pq_psk');
+ if (features.version.localeCompare('1.10.0', undefined, { numeric: true, sensitivity: 'base' }) < 0) {
+ o.value('chrome_psk');
+ o.value('chrome_psk_shuffle');
+ o.value('chrome_padding_psk_shuffle');
+ o.value('chrome_pq');
+ o.value('chrome_pq_psk');
+ }
o.value('edge');
o.value('firefox');
o.value('ios');
diff --git a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/server.js b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/server.js
index 9436cb83f..88a0756c9 100644
--- a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/server.js
+++ b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/server.js
@@ -31,13 +31,13 @@ function getServiceStatus() {
});
}
-function renderStatus(isRunning) {
- var spanTemp = '%s %s';
+function renderStatus(isRunning, version) {
+ var spanTemp = '%s (sing-box v%s) %s';
var renderHTML;
if (isRunning)
- renderHTML = spanTemp.format('green', _('HomeProxy Server'), _('RUNNING'));
+ renderHTML = spanTemp.format('green', _('HomeProxy Server'), version, _('RUNNING'));
else
- renderHTML = spanTemp.format('red', _('HomeProxy Server'), _('NOT RUNNING'));
+ renderHTML = spanTemp.format('red', _('HomeProxy Server'), version, _('NOT RUNNING'));
return renderHTML;
}
@@ -102,7 +102,7 @@ return view.extend({
poll.add(function () {
return L.resolveDefault(getServiceStatus()).then((res) => {
var view = document.getElementById('service_status');
- view.innerHTML = renderStatus(res);
+ view.innerHTML = renderStatus(res, features.version);
});
});
@@ -265,6 +265,17 @@ return view.extend({
o = s.option(form.Value, 'hysteria_obfs_password', _('Obfuscate password'));
o.depends('type', 'hysteria');
o.depends({'type': 'hysteria2', 'hysteria_obfs_type': /[\s\S]/});
+ o.renderWidget = function() {
+ var node = form.Value.prototype.renderWidget.apply(this, arguments);
+
+ (node.querySelector('.control-group') || node).appendChild(E('button', {
+ 'class': 'cbi-button cbi-button-apply',
+ 'title': _('Generate'),
+ 'click': ui.createHandlerFn(this, handleGenKey, this.option)
+ }, [ _('Generate') ]));
+
+ return node;
+ }
o.modalonly = true;
o = s.option(form.Value, 'hysteria_recv_window_conn', _('QUIC stream receive window'),
diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_client.uc b/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_client.uc
index 032443953..aafba8d91 100755
--- a/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_client.uc
+++ b/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_client.uc
@@ -2,7 +2,7 @@
/*
* SPDX-License-Identifier: GPL-2.0-only
*
- * Copyright (C) 2023 ImmortalWrt.org
+ * Copyright (C) 2023-2024 ImmortalWrt.org
*/
'use strict';
@@ -20,6 +20,8 @@ import {
const ubus = connect();
+const features = ubus.call('luci.homeproxy', 'singbox_get_features') || {};
+
/* UCI config start */
const uci = cursor();
@@ -205,9 +207,7 @@ function generate_outbound(node) {
authenticated_length: node.vmess_authenticated_length ? (node.vmess_authenticated_length === '1') : null,
packet_encoding: node.packet_encoding,
/* WireGuard */
- system_interface: (node.type === 'wireguard') || null,
gso: (node.wireguard_gso === '1') || null,
- interface_name: (node.type === 'wireguard') ? 'wg-' + node['.name'] + '-out' : null,
local_address: node.wireguard_local_address,
private_key: node.wireguard_private_key,
peer_public_key: node.wireguard_peer_public_key,
@@ -454,9 +454,12 @@ if (!isEmpty(main_node)) {
source_port_range: cfg.source_port_range,
process_name: cfg.process_name,
process_path: cfg.process_path,
+ process_path_regex: cfg.process_path_regex,
user: cfg.user,
rule_set: get_ruleset(cfg.rule_set),
- rule_set_ipcidr_match_source: (cfg.rule_set_ipcidr_match_source === '1') || null,
+ /* rule_set_ipcidr_match_source is deprecated in sing-box 1.10.0 */
+ rule_set_ipcidr_match_source: (features.version < '1.10.0' && cfg.rule_set_ip_cidr_match_source === '1') || null,
+ rule_set_ip_cidr_match_source: (features.version >= '1.10.0' && cfg.rule_set_ip_cidr_match_source === '1') || null,
invert: (cfg.invert === '1') || null,
outbound: get_outbound(cfg.outbound),
server: get_resolver(cfg.server),
@@ -525,8 +528,10 @@ if (match(proxy_mode, /tun/))
tag: 'tun-in',
interface_name: tun_name,
- inet4_address: tun_addr4,
- inet6_address: (ipv6_support === '1') ? tun_addr6 : null,
+ /* inet4_address and inet6_address are deprecated in sing-box 1.10.0 */
+ inet4_address: (features.version < '1.10.0') ? tun_addr4 : null,
+ inet6_address: (features.version < '1.10.0' && ipv6_support === '1') ? tun_addr6 : null,
+ address: (features.version >= '1.10.0') ? ((ipv6_support === '1') ? [tun_addr4, tun_addr6] : [tun_addr4]) : null,
mtu: strToInt(tun_mtu),
gso: (tun_gso === '1'),
auto_route: false,
@@ -639,9 +644,13 @@ if (!isEmpty(main_node)) {
port_range: cfg.port_range,
process_name: cfg.process_name,
process_path: cfg.process_path,
+ process_path_regex: cfg.process_path_regex,
user: cfg.user,
rule_set: get_ruleset(cfg.rule_set),
- rule_set_ipcidr_match_source: (cfg.rule_set_ipcidr_match_source === '1') || null,
+ /* rule_set_ipcidr_match_source is deprecated in sing-box 1.10.0 */
+ rule_set_ipcidr_match_source: (features.version < '1.10.0' && cfg.rule_set_ip_cidr_match_source === '1') || null,
+ rule_set_ip_cidr_match_source: (features.version >= '1.10.0' && cfg.rule_set_ip_cidr_match_source === '1') || null,
+ rule_set_ip_cidr_accept_empty: (cfg.rule_set_ip_cidr_accept_empty === '1') || null,
invert: (cfg.invert === '1') || null,
outbound: get_outbound(cfg.outbound)
});
diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/update_resources.sh b/luci-app-homeproxy/root/etc/homeproxy/scripts/update_resources.sh
index 576293d01..49d14606e 100755
--- a/luci-app-homeproxy/root/etc/homeproxy/scripts/update_resources.sh
+++ b/luci-app-homeproxy/root/etc/homeproxy/scripts/update_resources.sh
@@ -67,8 +67,7 @@ check_list_update() {
log "[$(to_upper "$listtype")] Local version: $local_list_ver, latest version: $list_ver."
fi
- $wget "https://fastly.jsdelivr.net/gh/$listrepo@$list_sha/$listname" -O "$RUN_DIR/$listname"
- if [ ! -s "$RUN_DIR/$listname" ]; then
+ if ! $wget "https://fastly.jsdelivr.net/gh/$listrepo@$list_sha/$listname" -O "$RUN_DIR/$listname" || [ ! -s "$RUN_DIR/$listname" ]; then
rm -f "$RUN_DIR/$listname"
log "[$(to_upper "$listtype")] Update failed."
diff --git a/luci-app-homeproxy/root/etc/uci-defaults/luci-homeproxy-migration b/luci-app-homeproxy/root/etc/uci-defaults/luci-homeproxy-migration
index e3a268eda..7b2d3f746 100644
--- a/luci-app-homeproxy/root/etc/uci-defaults/luci-homeproxy-migration
+++ b/luci-app-homeproxy/root/etc/uci-defaults/luci-homeproxy-migration
@@ -18,4 +18,6 @@ fi
[ -z "$(uci -q changes "homeproxy")" ] || uci -q commit "homeproxy"
+sed -i "s/rule_set_ipcidr_match_source/rule_set_ip_cidr_match_source/g" "/etc/config/homeproxy"
+
exit 0
diff --git a/luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy b/luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy
index 34754c525..28b94a6db 100755
--- a/luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy
+++ b/luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy
@@ -2,7 +2,7 @@
/*
* SPDX-License-Identifier: GPL-2.0-only
*
- * Copyright (C) 2023 ImmortalWrt.org
+ * Copyright (C) 2023-2024 ImmortalWrt.org
*/
'use strict';
@@ -161,12 +161,13 @@ const methods = {
const fd = popen('/usr/bin/sing-box version');
if (fd) {
for (let line = fd.read('line'); length(line); line = fd.read('line')) {
- let tags = match(trim(line), /Tags: (.*)/);
- if (!tags)
- continue;
+ if (match(trim(line), /^sing-box version (.*)/))
+ features.version = match(trim(line), /^sing-box version (.*)/)[1];
- for (let i in split(tags[1], ','))
- features[i] = true;
+ let tags = match(trim(line), /^Tags: (.*)/);
+ if (tags)
+ for (let i in split(tags[1], ','))
+ features[i] = true;
}
fd.close();