update 2025-08-23 09:17:17

This commit is contained in:
actions-user 2025-08-23 09:17:17 +08:00
parent 32f4bb1b24
commit 6927bde2c6
48 changed files with 3750 additions and 2577 deletions

View File

@ -48,17 +48,17 @@ else ifeq ($(ARCH),mips64el)
else ifeq ($(ARCH),i386) else ifeq ($(ARCH),i386)
ifneq ($(CONFIG_TARGET_x86_geode)$(CONFIG_TARGET_x86_legacy),) ifneq ($(CONFIG_TARGET_x86_geode)$(CONFIG_TARGET_x86_legacy),)
PKG_ARCH:=chinadns-ng+wolfssl@i386-linux-musl@i686@fast+lto PKG_ARCH:=chinadns-ng+wolfssl@i386-linux-musl@i686@fast+lto
PKG_HASH:=25a215e1b5c18f8b4f0e7f0a0925fd1c959bbfdfeb3383830d2b645a94077fc6 PKG_HASH:=85e057dd0a0e8913b30471737436ab8b71834c494ed9f9e53544261b1ffdc8d6
else else
PKG_ARCH:=chinadns-ng+wolfssl@i386-linux-musl@pentium4@fast+lto PKG_ARCH:=chinadns-ng+wolfssl@i386-linux-musl@pentium4@fast+lto
PKG_HASH:=e78feedf8fafc60749dfca576acd05b3df8e4b99912aa77a320971011ca77b1d PKG_HASH:=2d0f1a05c82f2e21e71a6618c7f1d2e7f46aa6a21535d774d517e87ec00c989b
endif endif
else ifeq ($(ARCH),x86_64) else ifeq ($(ARCH),x86_64)
PKG_ARCH:=chinadns-ng+wolfssl@x86_64-linux-musl@x86_64@fast+lto PKG_ARCH:=chinadns-ng+wolfssl@x86_64-linux-musl@x86_64@fast+lto
PKG_HASH:=9ad100ef18f7acaecad1aaa07b07029e9e50679fc8f119977878211b1ceb96f0 PKG_HASH:=842ea4e9816efd91d39bc76ead5c4a42e79011757e37c521b4270b675cfcb30c
else ifeq ($(ARCH),riscv64) else ifeq ($(ARCH),riscv64)
PKG_ARCH:=chinadns-ng+wolfssl@riscv64-linux-musl@baseline_rv64@fast+lto PKG_ARCH:=chinadns-ng+wolfssl@riscv64-linux-musl@baseline_rv64@fast+lto
PKG_HASH:=ed4d2cf72c2d48f19dd7678f419ce726bc2a793afc62afd6345e735dd262ca96 PKG_HASH:=7056f47f4d6b20109e007792694dc83e5eac44c9265d7be20f6dc10375b35a9b
else else
PKG_HASH:=dummy PKG_HASH:=dummy
endif endif

View File

@ -6,15 +6,15 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=dns2socks-rust PKG_NAME:=dns2socks-rust
PKG_VERSION:=0.2.0 PKG_VERSION:=0.2.1
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git PKG_SOURCE_PROTO:=git
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://github.com/tun2proxy/dns2socks.git PKG_SOURCE_URL:=https://github.com/tun2proxy/dns2socks.git
PKG_SOURCE_DATE:=2025-03-19 PKG_SOURCE_DATE:=2025-08-18
PKG_SOURCE_VERSION:=5f5805bc5eba6530cec27f76860db1e19c1f2382 PKG_SOURCE_VERSION:=a23fe67ff4e2a218fcd4726055514c8c2b5299c9
PKG_MIRROR_HASH:=f45ff9bff184f6eddbc444fc9a0611a47043e3b3422b7c33459bf7e03f37c37e PKG_MIRROR_HASH:=7d2829cc0da6e9eacc5ed97f51f37ee0ce1ea1a10f38f1e4d2a30ae80d237289
PKG_MAINTAINER:=Zxlhhyccc <zxlhhyccc@gmail.com> PKG_MAINTAINER:=Zxlhhyccc <zxlhhyccc@gmail.com>
PKG_LICENSE:=MIT PKG_LICENSE:=MIT

View File

@ -9,7 +9,8 @@ LUCI_PKGARCH:=all
LUCI_DEPENDS:= \ LUCI_DEPENDS:= \
+sing-box \ +sing-box \
+firewall4 \ +firewall4 \
+kmod-nft-tproxy +kmod-nft-tproxy \
+ucode-mod-digest
PKG_NAME:=luci-app-homeproxy PKG_NAME:=luci-app-homeproxy

View File

@ -333,13 +333,12 @@ return view.extend({
so.rmempty = false; so.rmempty = false;
so = ss.option(form.Value, 'udp_timeout', _('UDP NAT expiration time'), so = ss.option(form.Value, 'udp_timeout', _('UDP NAT expiration time'),
_('In seconds. <code>300</code> is used by default.')); _('In seconds.'));
so.datatype = 'uinteger'; so.datatype = 'uinteger';
so.default = '300'; so.placeholder = '300';
so.depends('homeproxy.config.proxy_mode', 'redirect_tproxy'); so.depends('homeproxy.config.proxy_mode', 'redirect_tproxy');
so.depends('homeproxy.config.proxy_mode', 'redirect_tun'); so.depends('homeproxy.config.proxy_mode', 'redirect_tun');
so.depends('homeproxy.config.proxy_mode', 'tun'); so.depends('homeproxy.config.proxy_mode', 'tun');
so.rmempty = false;
so = ss.option(form.Flag, 'bypass_cn_traffic', _('Bypass CN traffic'), so = ss.option(form.Flag, 'bypass_cn_traffic', _('Bypass CN traffic'),
_('Bypass mainland China traffic via firewall rules by default.')); _('Bypass mainland China traffic via firewall rules by default.'));
@ -348,19 +347,20 @@ return view.extend({
so = ss.option(form.ListValue, 'domain_strategy', _('Domain strategy'), so = ss.option(form.ListValue, 'domain_strategy', _('Domain strategy'),
_('If set, the requested domain name will be resolved to IP before routing.')); _('If set, the requested domain name will be resolved to IP before routing.'));
for (let i in hp.dns_strategy) for (let i in hp.dns_strategy)
so.value(i, hp.dns_strategy[i]) so.value(i, hp.dns_strategy[i]);
so = ss.option(form.Flag, 'sniff_override', _('Override destination'), so = ss.option(form.Flag, 'sniff_override', _('Override destination'),
_('Override the connection destination address with the sniffed domain.')); _('Override the connection destination address with the sniffed domain.'));
so.default = so.enabled; so.default = so.enabled;
so.rmempty = false; so.rmempty = false;
so = ss.option(form.ListValue, 'default_outbound', _('Default outbound')); so = ss.option(form.ListValue, 'default_outbound', _('Default outbound'),
_('Default outbound for connections not matched by any routing rules.'));
so.load = function(section_id) { so.load = function(section_id) {
delete this.keylist; delete this.keylist;
delete this.vallist; delete this.vallist;
this.value('nil', _('Disable')); this.value('nil', _('Disable (the service)'));
this.value('direct-out', _('Direct')); this.value('direct-out', _('Direct'));
this.value('block-out', _('Block')); this.value('block-out', _('Block'));
uci.sections(data[0], 'routing_node', (res) => { uci.sections(data[0], 'routing_node', (res) => {
@ -372,6 +372,24 @@ return view.extend({
} }
so.default = 'nil'; so.default = 'nil';
so.rmempty = false; so.rmempty = false;
so = ss.option(form.ListValue, 'default_outbound_dns', _('Default outbound DNS'),
_('Default DNS server for resolving domain name in the server address.'));
so.load = function(section_id) {
delete this.keylist;
delete this.vallist;
this.value('default-dns', _('Default DNS (issued by WAN)'));
this.value('system-dns', _('System DNS'));
uci.sections(data[0], 'dns_server', (res) => {
if (res.enabled === '1')
this.value(res['.name'], res.label);
});
return this.super('load', section_id);
}
so.default = 'default-dns';
so.rmempty = false;
/* Routing settings end */ /* Routing settings end */
/* Routing nodes start */ /* Routing nodes start */
@ -406,8 +424,27 @@ return view.extend({
so.validate = L.bind(hp.validateUniqueValue, this, data[0], 'routing_node', 'node'); so.validate = L.bind(hp.validateUniqueValue, this, data[0], 'routing_node', 'node');
so.editable = true; so.editable = true;
so = ss.option(form.ListValue, 'domain_resolver', _('Domain resolver'),
_('For resolving domain name in the server address.'));
so.load = function(section_id) {
delete this.keylist;
delete this.vallist;
this.value('', _('Default'));
this.value('default-dns', _('Default DNS (issued by WAN)'));
this.value('system-dns', _('System DNS'));
uci.sections(data[0], 'dns_server', (res) => {
if (res.enabled === '1')
this.value(res['.name'], res.label);
});
return this.super('load', section_id);
}
so.depends({'node': 'urltest', '!reverse': true});
so.modalonly = true;
so = ss.option(form.ListValue, 'domain_strategy', _('Domain strategy'), so = ss.option(form.ListValue, 'domain_strategy', _('Domain strategy'),
_('If set, the server domain name will be resolved to IP before connecting.<br/>')); _('The domain strategy for resolving the domain name in the address.'));
for (let i in hp.dns_strategy) for (let i in hp.dns_strategy)
so.value(i, hp.dns_strategy[i]); so.value(i, hp.dns_strategy[i]);
so.depends({'node': 'urltest', '!reverse': true}); so.depends({'node': 'urltest', '!reverse': true});
@ -629,6 +666,15 @@ return view.extend({
_('Invert match result.')); _('Invert match result.'));
so.modalonly = true; so.modalonly = true;
so = ss.taboption('field_other', form.ListValue, 'action', _('Action'));
so.value('route', _('Route'));
so.value('route-options', _('Route options'));
so.value('reject', _('Reject'));
so.value('resolve', _('Resolve'));
so.default = 'route';
so.rmempty = false;
so.editable = true;
so = ss.taboption('field_other', form.ListValue, 'outbound', _('Outbound'), so = ss.taboption('field_other', form.ListValue, 'outbound', _('Outbound'),
_('Tag of the target outbound.')); _('Tag of the target outbound.'));
so.load = function(section_id) { so.load = function(section_id) {
@ -636,7 +682,6 @@ return view.extend({
delete this.vallist; delete this.vallist;
this.value('direct-out', _('Direct')); this.value('direct-out', _('Direct'));
this.value('block-out', _('Block'));
uci.sections(data[0], 'routing_node', (res) => { uci.sections(data[0], 'routing_node', (res) => {
if (res.enabled === '1') if (res.enabled === '1')
this.value(res['.name'], res.label); this.value(res['.name'], res.label);
@ -645,16 +690,116 @@ return view.extend({
return this.super('load', section_id); return this.super('load', section_id);
} }
so.rmempty = false; so.rmempty = false;
so.depends('action', 'route');
so.editable = true; so.editable = true;
so = ss.taboption('field_other', form.Value, 'override_address', _('Override address'), so = ss.taboption('field_other', form.Value, 'override_address', _('Override address'),
_('Override the connection destination address.')); _('Override the connection destination address.'));
so.datatype = 'ipaddr'; so.datatype = 'ipaddr';
so.depends('action', 'route');
so.depends('action', 'route-options');
so.modalonly = true; so.modalonly = true;
so = ss.taboption('field_other', form.Value, 'override_port', _('Override port'), so = ss.taboption('field_other', form.Value, 'override_port', _('Override port'),
_('Override the connection destination port.')); _('Override the connection destination port.'));
so.datatype = 'port'; so.datatype = 'port';
so.depends('action', 'route');
so.depends('action', 'route-options');
so.modalonly = true;
so = ss.taboption('field_other', form.Flag, 'udp_disable_domain_unmapping', _('Disable UDP domain unmapping'),
_('If enabled, for UDP proxy requests addressed to a domain, the original packet address will be sent in the response instead of the mapped domain.'));
so.depends('action', 'route');
so.depends('action', 'route-options');
so.modalonly = true;
so = ss.taboption('field_other', form.Flag, 'udp_connect', _('connect UDP connections'),
_('If enabled, attempts to connect UDP connection to the destination instead of listen.'));
so.depends('action', 'route');
so.depends('action', 'route-options');
so.modalonly = true;
so = ss.taboption('field_other', form.Value, 'udp_timeout', _('UDP timeout'),
_('Timeout for UDP connections.<br/>Setting a larger value than the UDP timeout in inbounds will have no effect.'));
so.datatype = 'uinteger';
so.depends('action', 'route');
so.depends('action', 'route-options');
so.modalonly = true;
so = ss.taboption('field_other', form.Flag, 'tls_record_fragment', _('TLS record fragment'),
_('Fragment TLS handshake into multiple TLS records.'));
so.depends('action', 'route');
so.depends('action', 'route-options');
so.modalonly = true;
so = ss.taboption('field_other', form.Flag, 'tls_fragment', _('TLS fragment'),
_('Fragment TLS handshakes. Due to poor performance, try <code>%s</code> first.').format(
_('TLS record fragment')));
so.depends('action', 'route');
so.depends('action', 'route-options');
so.modalonly = true;
so = ss.taboption('field_other', form.Value, 'tls_fragment_fallback_delay', _('Fragment fallback delay'),
_('The fallback value in milliseconds used when TLS segmentation cannot automatically determine the wait time.'));
so.datatype = 'uinteger';
so.placeholder = '500';
so.depends('tls_fragment', '1');
so.modalonly = true;
so = ss.taboption('field_other', form.ListValue, 'resolve_server', _('DNS server'),
_('Specifies DNS server tag to use instead of selecting through DNS routing.'));
so.load = function(section_id) {
delete this.keylist;
delete this.vallist;
this.value('', _('Default'));
this.value('default-dns', _('Default DNS (issued by WAN)'));
this.value('system-dns', _('System DNS'));
uci.sections(data[0], 'dns_server', (res) => {
if (res.enabled === '1')
this.value(res['.name'], res.label);
});
return this.super('load', section_id);
}
so.depends('action', 'resolve');
so.modalonly = true;
so = ss.taboption('field_other', form.ListValue, 'reject_method', _('Method'));
so.value('default', _('Reply with TCP RST / ICMP port unreachable'));
so.value('drop', _('Drop packets'));
so.depends('action', 'reject');
so.modalonly = true;
so = ss.taboption('field_other', form.Flag, 'reject_no_drop', _('Don\'t drop packets'),
_('<code>%s</code> will be temporarily overwritten to <code>%s</code> after 50 triggers in 30s if not enabled.').format(
_('Method'), _('Drop packets')));
so.depends('reject_method', 'default');
so.modalonly = true;
so = ss.taboption('field_other', form.ListValue, 'resolve_strategy', _('Resolve strategy'),
_('Domain strategy for resolving the domain names.'));
for (let i in hp.dns_strategy)
so.value(i, hp.dns_strategy[i]);
so.depends('action', 'resolve');
so.modalonly = true;
so = ss.taboption('field_other', form.Flag, 'resolve_disable_cache', _('Disable DNS cache'),
_('Disable DNS cache in this query.'));
so.depends('action', 'resolve');
so.modalonly = true;
so = ss.taboption('field_other', form.Value, 'resolve_rewrite_ttl', _('Rewrite TTL'),
_('Rewrite TTL in DNS responses.'));
so.datatype = 'uinteger';
so.depends('action', 'resolve');
so.modalonly = true;
so = ss.taboption('field_other', form.Value, 'resolve_client_subnet', _('EDNS Client subnet'),
_('Append a <code>edns0-subnet</code> OPT extra record with the specified IP prefix to every query by default.<br/>' +
'If value is an IP address instead of prefix, <code>/32</code> or <code>/128</code> will be appended automatically.'));
so.datatype = 'or(cidr, ipaddr)';
so.depends('action', 'resolve');
so.modalonly = true; so.modalonly = true;
so = ss.taboption('field_host', form.DynamicList, 'domain', _('Domain name'), so = ss.taboption('field_host', form.DynamicList, 'domain', _('Domain name'),
@ -741,7 +886,6 @@ return view.extend({
this.value('default-dns', _('Default DNS (issued by WAN)')); this.value('default-dns', _('Default DNS (issued by WAN)'));
this.value('system-dns', _('System DNS')); this.value('system-dns', _('System DNS'));
this.value('block-dns', _('Block DNS queries'));
uci.sections(data[0], 'dns_server', (res) => { uci.sections(data[0], 'dns_server', (res) => {
if (res.enabled === '1') if (res.enabled === '1')
this.value(res['.name'], res.label); this.value(res['.name'], res.label);
@ -800,32 +944,45 @@ return view.extend({
so.rmempty = false; so.rmempty = false;
so.editable = true; so.editable = true;
so = ss.option(form.Value, 'address', _('Address'), so = ss.option(form.ListValue, 'type', _('Type'));
_('The address of the dns server. Support UDP, TCP, DoH, DoQ, DoT and RCode.')); so.value('udp', _('UDP'));
so.value('tcp', _('TCP'));
so.value('tls', _('TLS'));
so.value('https', _('HTTPS'));
so.value('http3', _('HTTP3'));
so.value('quic', _('QUIC'));
so.default = 'udp';
so.rmempty = false; so.rmempty = false;
so.validate = function(section_id, value) {
if (section_id) {
if (!value)
return _('Expecting: %s').format(_('non-empty value'));
try { so = ss.option(form.Value, 'server', _('Address'),
let url = new URL(value.replace(/^.*:\/\//, 'http://')); _('The address of the dns server.'));
if (stubValidator.apply('hostname', url.hostname)) so.datatype = 'or(hostname, ipaddr)';
return true; so.rmempty = false;
else if (stubValidator.apply('ip4addr', url.hostname))
return true;
else if (stubValidator.apply('ip6addr', url.hostname.match(/^\[(.+)\]$/)?.[1]))
return true;
else
return _('Expecting: %s').format(_('valid DNS server address'));
} catch(e) {}
if (!stubValidator.apply('ipaddr', value)) so = ss.option(form.Value, 'server_port', _('Port'),
return _('Expecting: %s').format(_('valid DNS server address')); _('The port of the DNS server.'));
} so.datatype = 'port';
return true; so = ss.option(form.Value, 'path', _('Path'),
} _('The path of the DNS server.'));
so.placeholder = '/dns-query';
so.depends('type', 'https');
so.depends('type', 'http3');
so.modalonly = true;
so = ss.option(form.DynamicList, 'headers', _('Headers'),
_('Additional headers to be sent to the DNS server.'));
so.depends('type', 'https');
so.depends('type', 'http3');
so.modalonly = true;
so = ss.option(form.Value, 'tls_sni', _('TLS SNI'),
_('Used to verify the hostname on the returned certificates.'));
so.depends('type', 'tls');
so.depends('type', 'https');
so.depends('type', 'http3');
so.depends('type', 'quic');
so.modalonly = true;
so = ss.option(form.ListValue, 'address_resolver', _('Address resolver'), so = ss.option(form.ListValue, 'address_resolver', _('Address resolver'),
_('Tag of a another server to resolve the domain name in the address. Required if address contains domain.')); _('Tag of a another server to resolve the domain name in the address. Required if address contains domain.'));
@ -865,12 +1022,6 @@ return view.extend({
so.value(i, hp.dns_strategy[i]); so.value(i, hp.dns_strategy[i]);
so.modalonly = true; so.modalonly = true;
so = ss.option(form.ListValue, 'resolve_strategy', _('Resolve strategy'),
_('Default domain strategy for resolving the domain names.'));
for (let i in hp.dns_strategy)
so.value(i, hp.dns_strategy[i]);
so.editable = true;
so = ss.option(form.ListValue, 'outbound', _('Outbound'), so = ss.option(form.ListValue, 'outbound', _('Outbound'),
_('Tag of an outbound for connecting to the dns server.')); _('Tag of an outbound for connecting to the dns server.'));
so.load = function(section_id) { so.load = function(section_id) {
@ -888,11 +1039,6 @@ return view.extend({
so.default = 'direct-out'; so.default = 'direct-out';
so.rmempty = false; so.rmempty = false;
so.editable = true; so.editable = true;
so = ss.option(form.Value, 'client_subnet', _('EDNS Client subnet'),
_('Append a <code>edns0-subnet</code> OPT extra record with the specified IP prefix to every query by default.<br/>' +
'If value is an IP address instead of prefix, <code>/32</code> or <code>/128</code> will be appended automatically.'));
so.datatype = 'or(cidr, ipaddr)';
/* DNS servers end */ /* DNS servers end */
/* DNS rules start */ /* DNS rules start */
@ -936,6 +1082,7 @@ return view.extend({
so.default = 'default'; so.default = 'default';
so.rmempty = false; so.rmempty = false;
so.readonly = true; so.readonly = true;
so.modalonly = true;
so = ss.taboption('field_other', form.ListValue, 'ip_version', _('IP version')); so = ss.taboption('field_other', form.ListValue, 'ip_version', _('IP version'));
so.value('4', _('IPv4')); so.value('4', _('IPv4'));
@ -994,23 +1141,14 @@ return view.extend({
_('Invert match result.')); _('Invert match result.'));
so.modalonly = true; so.modalonly = true;
so = ss.taboption('field_other', form.MultiValue, 'outbound', _('Outbound'), so = ss.taboption('field_other', form.ListValue, 'action', _('Action'));
_('Match the server name of outbound.')); so.value('route', _('Route'));
so.load = function(section_id) { so.value('route-options', _('Route options'));
delete this.keylist; so.value('reject', _('Reject'));
delete this.vallist; so.value('predefined', _('Predefined'));
so.default = 'route';
this.value('any-out', _('Any')); so.rmempty = false;
this.value('direct-out', _('Direct')); so.editable = true;
this.value('block-out', _('Block'));
uci.sections(data[0], 'routing_node', (res) => {
if (res.enabled === '1')
this.value(res['.name'], res.label);
});
return this.super('load', section_id);
}
so.modalonly = true;
so = ss.taboption('field_other', form.ListValue, 'server', _('Server'), so = ss.taboption('field_other', form.ListValue, 'server', _('Server'),
_('Tag of the target dns server.')); _('Tag of the target dns server.'));
@ -1020,7 +1158,6 @@ return view.extend({
this.value('default-dns', _('Default DNS (issued by WAN)')); this.value('default-dns', _('Default DNS (issued by WAN)'));
this.value('system-dns', _('System DNS')); this.value('system-dns', _('System DNS'));
this.value('block-dns', _('Block DNS queries'));
uci.sections(data[0], 'dns_server', (res) => { uci.sections(data[0], 'dns_server', (res) => {
if (res.enabled === '1') if (res.enabled === '1')
this.value(res['.name'], res.label); this.value(res['.name'], res.label);
@ -1030,23 +1167,75 @@ return view.extend({
} }
so.rmempty = false; so.rmempty = false;
so.editable = true; so.editable = true;
so.depends('action', 'route');
so = ss.taboption('field_other', form.ListValue, 'domain_strategy', _('Domain strategy'),
_('Set domain strategy for this query.'));
for (let i in hp.dns_strategy)
so.value(i, hp.dns_strategy[i]);
so.depends('action', 'route');
so.modalonly = true;
so = ss.taboption('field_other', form.Flag, 'dns_disable_cache', _('Disable dns cache'), so = ss.taboption('field_other', form.Flag, 'dns_disable_cache', _('Disable dns cache'),
_('Disable cache and save cache in this query.')); _('Disable cache and save cache in this query.'));
so.depends({'server': 'block-dns', '!reverse': true}); so.depends('action', 'route');
so.depends('action', 'route-options');
so.modalonly = true; so.modalonly = true;
so = ss.taboption('field_other', form.Value, 'rewrite_ttl', _('Rewrite TTL'), so = ss.taboption('field_other', form.Value, 'rewrite_ttl', _('Rewrite TTL'),
_('Rewrite TTL in DNS responses.')); _('Rewrite TTL in DNS responses.'));
so.datatype = 'uinteger'; so.datatype = 'uinteger';
so.depends({'server': 'block-dns', '!reverse': true}); so.depends('action', 'route');
so.depends('action', 'route-options');
so.modalonly = true; so.modalonly = true;
so = ss.taboption('field_other', form.Value, 'client_subnet', _('EDNS Client subnet'), so = ss.taboption('field_other', form.Value, 'client_subnet', _('EDNS Client subnet'),
_('Append a <code>edns0-subnet</code> OPT extra record with the specified IP prefix to every query by default.<br/>' + _('Append a <code>edns0-subnet</code> OPT extra record with the specified IP prefix to every query by default.<br/>' +
'If value is an IP address instead of prefix, <code>/32</code> or <code>/128</code> will be appended automatically.')); 'If value is an IP address instead of prefix, <code>/32</code> or <code>/128</code> will be appended automatically.'));
so.datatype = 'or(cidr, ipaddr)'; so.datatype = 'or(cidr, ipaddr)';
so.depends({'server': 'block-dns', '!reverse': true}); so.depends('action', 'route');
so.depends('action', 'route-options');
so.modalonly = true;
so = ss.taboption('field_other', form.ListValue, 'reject_method', _('Method'));
so.value('default', _('Reply with REFUSED'));
so.value('drop', _('Drop requests'));
so.default = 'default';
so.depends('action', 'reject');
so.modalonly = true;
so = ss.taboption('field_other', form.Flag, 'reject_no_drop', _('Don\'t drop requests'),
_('<code>%s</code> will be temporarily overwritten to <code>%s</code> after 50 triggers in 30s if not enabled.').format(
_('Method'), _('Drop requests')));
so.depends('reject_method', 'default');
so.modalonly = true;
so = ss.taboption('field_other', form.ListValue, 'predefined_rcode', _('RCode'),
_('The response code.'));
so.value('NOERROR');
so.value('FORMERR');
so.value('SERVFAIL');
so.value('NXDOMAIN');
so.value('NOTIMP');
so.value('REFUSED');
so.default = 'NOERROR';
so.depends('action', 'predefined');
so.modalonly = true;
so = ss.taboption('field_other', form.DynamicList, 'predefined_answer', _('Answer'),
_('List of text DNS record to respond as answers.'));
so.depends('action', 'predefined');
so.modalonly = true;
so = ss.taboption('field_other', form.DynamicList, 'predefined_ns', _('NS'),
_('List of text DNS record to respond as name servers.'));
so.depends('action', 'predefined');
so.modalonly = true;
so = ss.taboption('field_other', form.DynamicList, 'predefined_extra', _('Extra records'),
_('List of text DNS record to respond as extra records.'));
so.depends('action', 'predefined');
so.modalonly = true;
so = ss.taboption('field_host', form.DynamicList, 'domain', _('Domain name'), so = ss.taboption('field_host', form.DynamicList, 'domain', _('Domain name'),
_('Match full domain.')); _('Match full domain.'));

View File

@ -25,6 +25,27 @@ function parseShareLink(uri, features) {
uri = uri.split('://'); uri = uri.split('://');
if (uri[0] && uri[1]) { if (uri[0] && uri[1]) {
switch (uri[0]) { switch (uri[0]) {
case 'anytls':
/* https://github.com/anytls/anytls-go/blob/v0.0.8/docs/uri_scheme.md */
url = new URL('http://' + uri[1]);
params = url.searchParams;
/* Check if password exists */
if (!url.username)
return null;
config = {
label: url.hash ? decodeURIComponent(url.hash.slice(1)) : null,
type: 'anytls',
address: url.hostname,
port: url.port || '80',
password: url.username ? decodeURIComponent(url.username) : null,
tls: '1',
tls_sni: params.get('sni'),
tls_insecure: (params.get('insecure') === '1') ? '1' : '0'
};
break;
case 'http': case 'http':
case 'https': case 'https':
url = new URL('http://' + uri[1]); url = new URL('http://' + uri[1]);
@ -404,6 +425,7 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
o = s.option(form.ListValue, 'type', _('Type')); o = s.option(form.ListValue, 'type', _('Type'));
o.value('direct', _('Direct')); o.value('direct', _('Direct'));
o.value('anytls', _('AnyTLS'));
o.value('http', _('HTTP')); o.value('http', _('HTTP'));
if (features.with_quic) { if (features.with_quic) {
o.value('hysteria', _('Hysteria')); o.value('hysteria', _('Hysteria'));
@ -440,6 +462,7 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
o = s.option(form.Value, 'password', _('Password')); o = s.option(form.Value, 'password', _('Password'));
o.password = true; o.password = true;
o.depends('type', 'anytls');
o.depends('type', 'http'); o.depends('type', 'http');
o.depends('type', 'hysteria2'); o.depends('type', 'hysteria2');
o.depends('type', 'shadowsocks'); o.depends('type', 'shadowsocks');
@ -452,7 +475,7 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
o.validate = function(section_id, value) { o.validate = function(section_id, value) {
if (section_id) { if (section_id) {
let type = this.section.formvalue(section_id, 'type'); let type = this.section.formvalue(section_id, 'type');
let required_type = [ 'shadowsocks', 'shadowtls', 'trojan' ]; let required_type = [ 'anytls', 'shadowsocks', 'shadowtls', 'trojan' ];
if (required_type.includes(type)) { if (required_type.includes(type)) {
if (type === 'shadowsocks') { if (type === 'shadowsocks') {
@ -478,6 +501,29 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
o.depends('type', 'direct'); o.depends('type', 'direct');
o.modalonly = true; o.modalonly = true;
/* AnyTLS config start */
o = s.option(form.Value, 'anytls_idle_session_check_interval', _('Idle session check interval'),
_('Interval checking for idle sessions, in seconds.'));
o.datatype = 'uinteger';
o.placeholder = '30';
o.depends('type', 'anytls');
o.modalonly = true;
o = s.option(form.Value, 'anytls_idle_session_timeout', _('Idle session check timeout'),
_('In the check, close sessions that have been idle for longer than this, in seconds.'));
o.datatype = 'uinteger';
o.placeholder = '30';
o.depends('type', 'anytls');
o.modalonly = true;
o = s.option(form.Value, 'anytls_min_idle_session', _('Minimum idle sessions'),
_('In the check, at least the first <code>n</code> idle sessions are kept open.'));
o.datatype = 'uinteger';
o.placeholder = '0';
o.depends('type', 'anytls');
o.modalonly = true;
/* AnyTLS config end */
/* Hysteria (2) config start */ /* Hysteria (2) config start */
o = s.option(form.DynamicList, 'hysteria_hopping_port', _('Hopping port')); o = s.option(form.DynamicList, 'hysteria_hopping_port', _('Hopping port'));
o.depends('type', 'hysteria'); o.depends('type', 'hysteria');
@ -555,7 +601,6 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
o = s.option(form.Flag, 'hysteria_disable_mtu_discovery', _('Disable Path MTU discovery'), o = s.option(form.Flag, 'hysteria_disable_mtu_discovery', _('Disable Path MTU discovery'),
_('Disables Path MTU Discovery (RFC 8899). Packets will then be at most 1252 (IPv4) / 1232 (IPv6) bytes in size.')); _('Disables Path MTU Discovery (RFC 8899). Packets will then be at most 1252 (IPv4) / 1232 (IPv6) bytes in size.'));
o.default = o.disabled;
o.depends('type', 'hysteria'); o.depends('type', 'hysteria');
o.modalonly = true; o.modalonly = true;
/* Hysteria (2) config end */ /* Hysteria (2) config end */
@ -666,14 +711,12 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
o = s.option(form.Flag, 'tuic_udp_over_stream', _('UDP over stream'), o = s.option(form.Flag, 'tuic_udp_over_stream', _('UDP over stream'),
_('This is the TUIC port of the UDP over TCP protocol, designed to provide a QUIC stream based UDP relay mode that TUIC does not provide.')); _('This is the TUIC port of the UDP over TCP protocol, designed to provide a QUIC stream based UDP relay mode that TUIC does not provide.'));
o.default = o.disabled;
o.depends({'type': 'tuic','tuic_udp_relay_mode': ''}); o.depends({'type': 'tuic','tuic_udp_relay_mode': ''});
o.modalonly = true; o.modalonly = true;
o = s.option(form.Flag, 'tuic_enable_zero_rtt', _('Enable 0-RTT handshake'), o = s.option(form.Flag, 'tuic_enable_zero_rtt', _('Enable 0-RTT handshake'),
_('Enable 0-RTT QUIC connection handshake on the client side. This is not impacting much on the performance, as the protocol is fully multiplexed.<br/>' + _('Enable 0-RTT QUIC connection handshake on the client side. This is not impacting much on the performance, as the protocol is fully multiplexed.<br/>' +
'Disabling this is highly recommended, as it is vulnerable to replay attacks.')); 'Disabling this is highly recommended, as it is vulnerable to replay attacks.'));
o.default = o.disabled;
o.depends('type', 'tuic'); o.depends('type', 'tuic');
o.modalonly = true; o.modalonly = true;
@ -718,7 +761,6 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
o = s.option(form.Flag, 'vmess_authenticated_length', _('Authenticated length'), o = s.option(form.Flag, 'vmess_authenticated_length', _('Authenticated length'),
_('Protocol parameter. Enable length block encryption.')); _('Protocol parameter. Enable length block encryption.'));
o.default = o.disabled;
o.depends('type', 'vmess'); o.depends('type', 'vmess');
o.modalonly = true; o.modalonly = true;
/* VMess config end */ /* VMess config end */
@ -771,7 +813,6 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
if (features.with_grpc) { if (features.with_grpc) {
o = s.option(form.Flag, 'grpc_permit_without_stream', _('gRPC permit without stream'), o = s.option(form.Flag, 'grpc_permit_without_stream', _('gRPC permit without stream'),
_('If enabled, the client transport sends keepalive pings even with no active connections.')); _('If enabled, the client transport sends keepalive pings even with no active connections.'));
o.default = o.disabled;
o.depends('transport', 'grpc'); o.depends('transport', 'grpc');
o.modalonly = true; o.modalonly = true;
} }
@ -897,7 +938,6 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
/* Mux config start */ /* Mux config start */
o = s.option(form.Flag, 'multiplex', _('Multiplex')); o = s.option(form.Flag, 'multiplex', _('Multiplex'));
o.default = o.disabled;
o.depends('type', 'shadowsocks'); o.depends('type', 'shadowsocks');
o.depends('type', 'trojan'); o.depends('type', 'trojan');
o.depends('type', 'vless'); o.depends('type', 'vless');
@ -927,19 +967,18 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
o = s.option(form.Value, 'multiplex_max_streams', _('Maximum streams'), o = s.option(form.Value, 'multiplex_max_streams', _('Maximum streams'),
_('Maximum multiplexed streams in a connection before opening a new connection.<br/>' + _('Maximum multiplexed streams in a connection before opening a new connection.<br/>' +
'Conflict with <code>Maximum connections</code> and <code>Minimum streams</code>.')); 'Conflict with <code>%s</code> and <code>%s</code>.').format(
_('Maximum connections'), _('Minimum streams')));
o.datatype = 'uinteger'; o.datatype = 'uinteger';
o.depends({'multiplex': '1', 'multiplex_max_connections': '', 'multiplex_min_streams': ''}); o.depends({'multiplex': '1', 'multiplex_max_connections': '', 'multiplex_min_streams': ''});
o.modalonly = true; o.modalonly = true;
o = s.option(form.Flag, 'multiplex_padding', _('Enable padding')); o = s.option(form.Flag, 'multiplex_padding', _('Enable padding'));
o.default = o.disabled;
o.depends('multiplex', '1'); o.depends('multiplex', '1');
o.modalonly = true; o.modalonly = true;
o = s.option(form.Flag, 'multiplex_brutal', _('Enable TCP Brutal'), o = s.option(form.Flag, 'multiplex_brutal', _('Enable TCP Brutal'),
_('Enable TCP Brutal congestion control algorithm')); _('Enable TCP Brutal congestion control algorithm'));
o.default = o.disabled;
o.depends('multiplex', '1'); o.depends('multiplex', '1');
o.modalonly = true; o.modalonly = true;
@ -958,7 +997,7 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
/* TLS config start */ /* TLS config start */
o = s.option(form.Flag, 'tls', _('TLS')); o = s.option(form.Flag, 'tls', _('TLS'));
o.default = o.disabled; o.depends('type', 'anytls');
o.depends('type', 'http'); o.depends('type', 'http');
o.depends('type', 'hysteria'); o.depends('type', 'hysteria');
o.depends('type', 'hysteria2'); o.depends('type', 'hysteria2');
@ -972,7 +1011,7 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
let type = this.map.lookupOption('type', section_id)[0].formvalue(section_id); let type = this.map.lookupOption('type', section_id)[0].formvalue(section_id);
let tls = this.map.findElement('id', 'cbid.homeproxy.%s.tls'.format(section_id)).firstElementChild; let tls = this.map.findElement('id', 'cbid.homeproxy.%s.tls'.format(section_id)).firstElementChild;
if (['hysteria', 'hysteria2', 'shadowtls', 'tuic'].includes(type)) { if (['anytls', 'hysteria', 'hysteria2', 'shadowtls', 'tuic'].includes(type)) {
tls.checked = true; tls.checked = true;
tls.disabled = true; tls.disabled = true;
} else { } else {
@ -998,7 +1037,6 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
_('Allow insecure connection at TLS client.') + _('Allow insecure connection at TLS client.') +
'<br/>' + '<br/>' +
_('This is <strong>DANGEROUS</strong>, your traffic is almost like <strong>PLAIN TEXT</strong>! Use at your own risk!')); _('This is <strong>DANGEROUS</strong>, your traffic is almost like <strong>PLAIN TEXT</strong>! Use at your own risk!'));
o.default = o.disabled;
o.depends('tls', '1'); o.depends('tls', '1');
o.onchange = allowInsecureConfirm; o.onchange = allowInsecureConfirm;
o.modalonly = true; o.modalonly = true;
@ -1029,7 +1067,6 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
o = s.option(form.Flag, 'tls_self_sign', _('Append self-signed certificate'), o = s.option(form.Flag, 'tls_self_sign', _('Append self-signed certificate'),
_('If you have the root certificate, use this option instead of allowing insecure.')); _('If you have the root certificate, use this option instead of allowing insecure.'));
o.default = o.disabled;
o.depends('tls_insecure', '0'); o.depends('tls_insecure', '0');
o.modalonly = true; o.modalonly = true;
@ -1053,12 +1090,10 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
o = s.option(form.Flag, 'tls_ech', _('Enable ECH'), o = s.option(form.Flag, 'tls_ech', _('Enable ECH'),
_('ECH (Encrypted Client Hello) is a TLS extension that allows a client to encrypt the first part of its ClientHello message.')); _('ECH (Encrypted Client Hello) is a TLS extension that allows a client to encrypt the first part of its ClientHello message.'));
o.depends('tls', '1'); o.depends('tls', '1');
o.default = o.disabled;
o.modalonly = true; o.modalonly = true;
o = s.option(form.Flag, 'tls_ech_enable_pqss', _('Enable PQ signature schemes')); o = s.option(form.Flag, 'tls_ech_enable_pqss', _('Enable PQ signature schemes'));
o.depends('tls_ech', '1'); o.depends('tls_ech', '1');
o.default = o.disabled;
o.modalonly = true; o.modalonly = true;
o = s.option(form.Value, 'tls_ech_config_path', _('ECH config path'), o = s.option(form.Value, 'tls_ech_config_path', _('ECH config path'),
@ -1107,7 +1142,6 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
o.modalonly = true; o.modalonly = true;
o = s.option(form.Flag, 'tls_reality', _('REALITY')); o = s.option(form.Flag, 'tls_reality', _('REALITY'));
o.default = o.disabled;
o.depends({'tls': '1', 'type': 'vless'}); o.depends({'tls': '1', 'type': 'vless'});
o.modalonly = true; o.modalonly = true;
@ -1124,21 +1158,17 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) {
/* Extra settings start */ /* Extra settings start */
o = s.option(form.Flag, 'tcp_fast_open', _('TCP fast open')); o = s.option(form.Flag, 'tcp_fast_open', _('TCP fast open'));
o.default = o.disabled;
o.modalonly = true; o.modalonly = true;
o = s.option(form.Flag, 'tcp_multi_path', _('MultiPath TCP')); o = s.option(form.Flag, 'tcp_multi_path', _('MultiPath TCP'));
o.default = o.disabled;
o.modalonly = true; o.modalonly = true;
o = s.option(form.Flag, 'udp_fragment', _('UDP Fragment'), o = s.option(form.Flag, 'udp_fragment', _('UDP Fragment'),
_('Enable UDP fragmentation.')); _('Enable UDP fragmentation.'));
o.default = o.disabled;
o.modalonly = true; o.modalonly = true;
o = s.option(form.Flag, 'udp_over_tcp', _('UDP over TCP'), o = s.option(form.Flag, 'udp_over_tcp', _('UDP over TCP'),
_('Enable the SUoT protocol, requires server support. Conflict with multiplex.')); _('Enable the SUoT protocol, requires server support. Conflict with multiplex.'));
o.default = o.disabled;
o.depends('type', 'socks'); o.depends('type', 'socks');
o.depends({'type': 'shadowsocks', 'multiplex': '0'}); o.depends({'type': 'shadowsocks', 'multiplex': '0'});
o.modalonly = true; o.modalonly = true;
@ -1303,7 +1333,6 @@ return view.extend({
o = s.taboption('subscription', form.Flag, 'auto_update', _('Auto update'), o = s.taboption('subscription', form.Flag, 'auto_update', _('Auto update'),
_('Auto update subscriptions and geodata.')); _('Auto update subscriptions and geodata.'));
o.default = o.disabled;
o.rmempty = false; o.rmempty = false;
o = s.taboption('subscription', form.ListValue, 'auto_update_time', _('Update time')); o = s.taboption('subscription', form.ListValue, 'auto_update_time', _('Update time'));
@ -1314,7 +1343,6 @@ return view.extend({
o = s.taboption('subscription', form.Flag, 'update_via_proxy', _('Update via proxy'), o = s.taboption('subscription', form.Flag, 'update_via_proxy', _('Update via proxy'),
_('Update subscriptions via proxy.')); _('Update subscriptions via proxy.'));
o.default = o.disabled;
o.rmempty = false; o.rmempty = false;
o = s.taboption('subscription', form.DynamicList, 'subscription_url', _('Subscription URL-s'), o = s.taboption('subscription', form.DynamicList, 'subscription_url', _('Subscription URL-s'),
@ -1354,7 +1382,6 @@ return view.extend({
_('Allow insecure connection by default when add nodes from subscriptions.') + _('Allow insecure connection by default when add nodes from subscriptions.') +
'<br/>' + '<br/>' +
_('This is <strong>DANGEROUS</strong>, your traffic is almost like <strong>PLAIN TEXT</strong>! Use at your own risk!')); _('This is <strong>DANGEROUS</strong>, your traffic is almost like <strong>PLAIN TEXT</strong>! Use at your own risk!'));
o.default = o.disabled;
o.rmempty = false; o.rmempty = false;
o.onchange = allowInsecureConfirm; o.onchange = allowInsecureConfirm;

View File

@ -13,6 +13,7 @@
'require view'; 'require view';
'require homeproxy as hp'; 'require homeproxy as hp';
'require tools.widgets as widgets';
const callServiceList = rpc.declare({ const callServiceList = rpc.declare({
object: 'service', object: 'service',
@ -125,7 +126,6 @@ return view.extend({
s = m.section(form.NamedSection, 'server', 'homeproxy', _('Global settings')); s = m.section(form.NamedSection, 'server', 'homeproxy', _('Global settings'));
o = s.option(form.Flag, 'enabled', _('Enable')); o = s.option(form.Flag, 'enabled', _('Enable'));
o.default = o.disabled;
o.rmempty = false; o.rmempty = false;
s = m.section(form.GridSection, 'server', _('Server settings')); s = m.section(form.GridSection, 'server', _('Server settings'));
@ -153,6 +153,7 @@ return view.extend({
o.editable = true; o.editable = true;
o = s.option(form.ListValue, 'type', _('Type')); o = s.option(form.ListValue, 'type', _('Type'));
o.value('anytls', _('AnyTLS'));
o.value('http', _('HTTP')); o.value('http', _('HTTP'));
if (features.with_quic) { if (features.with_quic) {
o.value('hysteria', _('Hysteria')); o.value('hysteria', _('Hysteria'));
@ -188,6 +189,7 @@ return view.extend({
o = s.option(form.Value, 'password', _('Password')); o = s.option(form.Value, 'password', _('Password'));
o.password = true; o.password = true;
o.depends('type', 'anytls');
o.depends({'type': /^(http|mixed|naive|socks)$/, 'username': /[\s\S]/}); o.depends({'type': /^(http|mixed|naive|socks)$/, 'username': /[\s\S]/});
o.depends('type', 'hysteria2'); o.depends('type', 'hysteria2');
o.depends('type', 'shadowsocks'); o.depends('type', 'shadowsocks');
@ -207,7 +209,7 @@ return view.extend({
o.validate = function(section_id, value) { o.validate = function(section_id, value) {
if (section_id) { if (section_id) {
let type = this.section.formvalue(section_id, 'type'); let type = this.section.formvalue(section_id, 'type');
let required_type = [ 'http', 'mixed', 'naive', 'socks', 'shadowsocks' ]; let required_type = [ 'anytls', 'http', 'mixed', 'naive', 'socks', 'shadowsocks', 'trojan' ];
if (required_type.includes(type)) { if (required_type.includes(type)) {
if (type === 'shadowsocks') { if (type === 'shadowsocks') {
@ -229,6 +231,12 @@ return view.extend({
} }
o.modalonly = true; o.modalonly = true;
/* AnyTLS config */
o = s.option(form.DynamicList, 'anytls_padding_scheme', _('Padding scheme'),
_('AnyTLS padding scheme in array.'));
o.depends('type', 'anytls');
o.modalonly = true;
/* Hysteria (2) config start */ /* Hysteria (2) config start */
o = s.option(form.ListValue, 'hysteria_protocol', _('Protocol')); o = s.option(form.ListValue, 'hysteria_protocol', _('Protocol'));
o.value('udp'); o.value('udp');
@ -312,13 +320,11 @@ return view.extend({
o = s.option(form.Flag, 'hysteria_disable_mtu_discovery', _('Disable Path MTU discovery'), o = s.option(form.Flag, 'hysteria_disable_mtu_discovery', _('Disable Path MTU discovery'),
_('Disables Path MTU Discovery (RFC 8899). Packets will then be at most 1252 (IPv4) / 1232 (IPv6) bytes in size.')); _('Disables Path MTU Discovery (RFC 8899). Packets will then be at most 1252 (IPv4) / 1232 (IPv6) bytes in size.'));
o.default = o.disabled;
o.depends('type', 'hysteria'); o.depends('type', 'hysteria');
o.modalonly = true; o.modalonly = true;
o = s.option(form.Flag, 'hysteria_ignore_client_bandwidth', _('Ignore client bandwidth'), o = s.option(form.Flag, 'hysteria_ignore_client_bandwidth', _('Ignore client bandwidth'),
_('Tell the client to use the BBR flow control algorithm instead of Hysteria CC.')); _('Tell the client to use the BBR flow control algorithm instead of Hysteria CC.'));
o.default = o.disabled;
o.depends({'type': 'hysteria2', 'hysteria_down_mbps': '', 'hysteria_up_mbps': ''}); o.depends({'type': 'hysteria2', 'hysteria_down_mbps': '', 'hysteria_up_mbps': ''});
o.modalonly = true; o.modalonly = true;
@ -374,7 +380,6 @@ return view.extend({
o = s.option(form.Flag, 'tuic_enable_zero_rtt', _('Enable 0-RTT handshake'), o = s.option(form.Flag, 'tuic_enable_zero_rtt', _('Enable 0-RTT handshake'),
_('Enable 0-RTT QUIC connection handshake on the client side. This is not impacting much on the performance, as the protocol is fully multiplexed.<br/>' + _('Enable 0-RTT QUIC connection handshake on the client side. This is not impacting much on the performance, as the protocol is fully multiplexed.<br/>' +
'Disabling this is highly recommended, as it is vulnerable to replay attacks.')); 'Disabling this is highly recommended, as it is vulnerable to replay attacks.'));
o.default = o.disabled;
o.depends('type', 'tuic'); o.depends('type', 'tuic');
o.modalonly = true; o.modalonly = true;
@ -503,7 +508,6 @@ return view.extend({
/* Mux config start */ /* Mux config start */
o = s.option(form.Flag, 'multiplex', _('Multiplex')); o = s.option(form.Flag, 'multiplex', _('Multiplex'));
o.default = o.disabled;
o.depends('type', 'shadowsocks'); o.depends('type', 'shadowsocks');
o.depends('type', 'trojan'); o.depends('type', 'trojan');
o.depends('type', 'vless'); o.depends('type', 'vless');
@ -511,14 +515,12 @@ return view.extend({
o.modalonly = true; o.modalonly = true;
o = s.option(form.Flag, 'multiplex_padding', _('Enable padding')); o = s.option(form.Flag, 'multiplex_padding', _('Enable padding'));
o.default = o.disabled;
o.depends('multiplex', '1'); o.depends('multiplex', '1');
o.modalonly = true; o.modalonly = true;
if (features.hp_has_tcp_brutal) { if (features.hp_has_tcp_brutal) {
o = s.option(form.Flag, 'multiplex_brutal', _('Enable TCP Brutal'), o = s.option(form.Flag, 'multiplex_brutal', _('Enable TCP Brutal'),
_('Enable TCP Brutal congestion control algorithm')); _('Enable TCP Brutal congestion control algorithm'));
o.default = o.disabled;
o.depends('multiplex', '1'); o.depends('multiplex', '1');
o.modalonly = true; o.modalonly = true;
@ -538,7 +540,7 @@ return view.extend({
/* TLS config start */ /* TLS config start */
o = s.option(form.Flag, 'tls', _('TLS')); o = s.option(form.Flag, 'tls', _('TLS'));
o.default = o.disabled; o.depends('type', 'anytls');
o.depends('type', 'http'); o.depends('type', 'http');
o.depends('type', 'hysteria'); o.depends('type', 'hysteria');
o.depends('type', 'hysteria2'); o.depends('type', 'hysteria2');
@ -602,7 +604,6 @@ return view.extend({
if (features.with_acme) { if (features.with_acme) {
o = s.option(form.Flag, 'tls_acme', _('Enable ACME'), o = s.option(form.Flag, 'tls_acme', _('Enable ACME'),
_('Use ACME TLS certificate issuer.')); _('Use ACME TLS certificate issuer.'));
o.default = o.disabled;
o.depends('tls', '1'); o.depends('tls', '1');
o.modalonly = true; o.modalonly = true;
@ -642,7 +643,6 @@ return view.extend({
o.modalonly = true; o.modalonly = true;
o = s.option(form.Flag, 'tls_dns01_challenge', _('DNS01 challenge')) o = s.option(form.Flag, 'tls_dns01_challenge', _('DNS01 challenge'))
o.default = o.disabled;
o.depends('tls_acme', '1'); o.depends('tls_acme', '1');
o.modalonly = true; o.modalonly = true;
@ -675,12 +675,10 @@ return view.extend({
o.modalonly = true; o.modalonly = true;
o = s.option(form.Flag, 'tls_acme_dhc', _('Disable HTTP challenge')); o = s.option(form.Flag, 'tls_acme_dhc', _('Disable HTTP challenge'));
o.default = o.disabled;
o.depends('tls_dns01_challenge', '0'); o.depends('tls_dns01_challenge', '0');
o.modalonly = true; o.modalonly = true;
o = s.option(form.Flag, 'tls_acme_dtac', _('Disable TLS ALPN challenge')); o = s.option(form.Flag, 'tls_acme_dtac', _('Disable TLS ALPN challenge'));
o.default = o.disabled;
o.depends('tls_dns01_challenge', '0'); o.depends('tls_dns01_challenge', '0');
o.modalonly = true; o.modalonly = true;
@ -699,7 +697,6 @@ return view.extend({
o = s.option(form.Flag, 'tls_acme_external_account', _('External Account Binding'), o = s.option(form.Flag, 'tls_acme_external_account', _('External Account Binding'),
_('EAB (External Account Binding) contains information necessary to bind or map an ACME account to some other account known by the CA.' + _('EAB (External Account Binding) contains information necessary to bind or map an ACME account to some other account known by the CA.' +
'<br/>External account bindings are "used to associate an ACME account with an existing account in a non-ACME system, such as a CA customer database.')); '<br/>External account bindings are "used to associate an ACME account with an existing account in a non-ACME system, such as a CA customer database.'));
o.default = o.disabled;
o.depends('tls_acme', '1'); o.depends('tls_acme', '1');
o.modalonly = true; o.modalonly = true;
@ -716,7 +713,6 @@ return view.extend({
if (features.with_reality_server) { if (features.with_reality_server) {
o = s.option(form.Flag, 'tls_reality', _('REALITY')); o = s.option(form.Flag, 'tls_reality', _('REALITY'));
o.default = o.disabled;
o.depends({'tls': '1', 'tls_acme': '0', 'type': 'vless'}); o.depends({'tls': '1', 'tls_acme': '0', 'type': 'vless'});
o.depends({'tls': '1', 'tls_acme': null, 'type': 'vless'}); o.depends({'tls': '1', 'tls_acme': null, 'type': 'vless'});
o.modalonly = true; o.modalonly = true;
@ -838,18 +834,15 @@ return view.extend({
/* Extra settings start */ /* Extra settings start */
o = s.option(form.Flag, 'tcp_fast_open', _('TCP fast open'), o = s.option(form.Flag, 'tcp_fast_open', _('TCP fast open'),
_('Enable tcp fast open for listener.')); _('Enable tcp fast open for listener.'));
o.default = o.disabled;
o.depends({'network': 'udp', '!reverse': true}); o.depends({'network': 'udp', '!reverse': true});
o.modalonly = true; o.modalonly = true;
o = s.option(form.Flag, 'tcp_multi_path', _('MultiPath TCP')); o = s.option(form.Flag, 'tcp_multi_path', _('MultiPath TCP'));
o.default = o.disabled;
o.depends({'network': 'udp', '!reverse': true}); o.depends({'network': 'udp', '!reverse': true});
o.modalonly = true; o.modalonly = true;
o = s.option(form.Flag, 'udp_fragment', _('UDP Fragment'), o = s.option(form.Flag, 'udp_fragment', _('UDP Fragment'),
_('Enable UDP fragmentation.')); _('Enable UDP fragmentation.'));
o.default = o.disabled;
o.depends({'network': 'tcp', '!reverse': true}); o.depends({'network': 'tcp', '!reverse': true});
o.modalonly = true; o.modalonly = true;
@ -867,6 +860,16 @@ return view.extend({
o.depends('type', 'naive'); o.depends('type', 'naive');
o.depends('type', 'shadowsocks'); o.depends('type', 'shadowsocks');
o.modalonly = true; o.modalonly = true;
o = s.option(widgets.DeviceSelect, 'bind_interface', _('Bind interface'),
_('The network interface to bind to.'));
o.multiple = false;
o.noaliases = true;
o.modalonly = true;
o = s.option(form.Flag, 'reuse_addr', _('Reuse address'),
_('Reuse listener address.'));
o.modalonly = true;
/* Extra settings end */ /* Extra settings end */
return m.render(); return m.render();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -41,7 +41,8 @@
8.144.0.0/14 8.144.0.0/14
8.148.0.0/19 8.148.0.0/19
8.148.36.0/22 8.148.36.0/22
8.148.40.0/22 8.148.40.0/23
8.148.43.0/24
8.148.64.0/18 8.148.64.0/18
8.148.128.0/17 8.148.128.0/17
8.149.0.0/16 8.149.0.0/16
@ -88,7 +89,6 @@
27.192.0.0/11 27.192.0.0/11
27.224.0.0/14 27.224.0.0/14
31.56.124.0/24 31.56.124.0/24
31.57.10.0/24
36.1.0.0/16 36.1.0.0/16
36.4.0.0/14 36.4.0.0/14
36.16.0.0/12 36.16.0.0/12
@ -205,7 +205,8 @@
42.248.0.0/15 42.248.0.0/15
43.102.128.0/21 43.102.128.0/21
43.102.136.0/22 43.102.136.0/22
43.102.144.0/20 43.102.144.0/21
43.102.152.0/22
43.136.0.0/13 43.136.0.0/13
43.144.0.0/15 43.144.0.0/15
43.192.0.0/16 43.192.0.0/16
@ -227,7 +228,6 @@
43.225.120.0/22 43.225.120.0/22
43.225.180.0/22 43.225.180.0/22
43.225.208.0/22 43.225.208.0/22
43.225.216.0/22
43.225.255.0/24 43.225.255.0/24
43.226.32.0/19 43.226.32.0/19
43.226.64.0/20 43.226.64.0/20
@ -255,7 +255,6 @@
43.229.48.0/22 43.229.48.0/22
43.229.184.0/23 43.229.184.0/23
43.229.216.0/22 43.229.216.0/22
43.230.72.0/22
43.230.136.0/22 43.230.136.0/22
43.230.220.0/22 43.230.220.0/22
43.231.41.0/24 43.231.41.0/24
@ -296,7 +295,6 @@
43.242.164.0/22 43.242.164.0/22
43.242.180.0/22 43.242.180.0/22
43.242.192.0/21 43.242.192.0/21
43.242.204.0/22
43.242.252.0/22 43.242.252.0/22
43.243.4.0/22 43.243.4.0/22
43.243.12.0/22 43.243.12.0/22
@ -374,7 +372,6 @@
43.255.84.0/22 43.255.84.0/22
43.255.96.0/22 43.255.96.0/22
43.255.184.0/22 43.255.184.0/22
43.255.192.0/22
43.255.200.0/22 43.255.200.0/22
43.255.212.0/22 43.255.212.0/22
43.255.224.0/21 43.255.224.0/21
@ -388,7 +385,9 @@
44.32.188.0/24 44.32.188.0/24
45.9.11.0/24 45.9.11.0/24
45.40.192.0/18 45.40.192.0/18
45.59.106.0/24
45.65.20.0/22 45.65.20.0/22
45.112.232.0/22
45.113.20.0/22 45.113.20.0/22
45.113.24.0/22 45.113.24.0/22
45.113.40.0/22 45.113.40.0/22
@ -405,6 +404,8 @@
45.116.152.0/22 45.116.152.0/22
45.116.208.0/22 45.116.208.0/22
45.117.8.0/22 45.117.8.0/22
45.117.68.0/24
45.117.70.0/23
45.119.60.0/22 45.119.60.0/22
45.119.68.0/22 45.119.68.0/22
45.119.105.0/24 45.119.105.0/24
@ -413,8 +414,6 @@
45.120.164.0/22 45.120.164.0/22
45.120.241.0/24 45.120.241.0/24
45.120.243.0/24 45.120.243.0/24
45.121.52.0/24
45.121.55.0/24
45.123.128.0/22 45.123.128.0/22
45.123.168.0/21 45.123.168.0/21
45.123.176.0/21 45.123.176.0/21
@ -521,6 +520,7 @@
49.112.0.0/13 49.112.0.0/13
49.120.0.0/14 49.120.0.0/14
49.128.203.0/24 49.128.203.0/24
49.128.220.0/24
49.128.223.0/24 49.128.223.0/24
49.140.0.0/15 49.140.0.0/15
49.208.0.0/14 49.208.0.0/14
@ -561,7 +561,8 @@
54.222.70.0/23 54.222.70.0/23
54.222.72.0/21 54.222.72.0/21
54.222.80.0/21 54.222.80.0/21
54.222.88.0/22 54.222.88.0/24
54.222.90.0/23
54.222.96.0/23 54.222.96.0/23
54.222.100.0/22 54.222.100.0/22
54.222.104.0/21 54.222.104.0/21
@ -605,8 +606,7 @@
59.81.102.0/23 59.81.102.0/23
59.81.104.0/22 59.81.104.0/22
59.82.0.0/17 59.82.0.0/17
59.82.128.0/21 59.82.128.0/20
59.82.136.0/23
59.83.192.0/19 59.83.192.0/19
59.83.224.0/21 59.83.224.0/21
59.83.232.0/22 59.83.232.0/22
@ -679,7 +679,31 @@
60.200.0.0/24 60.200.0.0/24
60.204.0.0/14 60.204.0.0/14
60.208.0.0/12 60.208.0.0/12
60.232.0.0/16 60.232.0.0/24
60.232.130.0/23
60.232.132.0/24
60.232.136.0/24
60.232.140.0/24
60.232.144.0/24
60.232.148.0/24
60.232.152.0/24
60.232.156.0/23
60.232.160.0/24
60.232.164.0/24
60.232.172.0/24
60.232.176.0/23
60.232.178.0/24
60.232.180.0/24
60.232.184.0/24
60.232.188.0/24
60.232.192.0/24
60.232.200.0/24
60.232.224.0/24
60.232.244.0/24
60.232.246.0/23
60.232.251.0/24
60.232.252.0/24
60.232.254.0/24
60.235.0.0/16 60.235.0.0/16
60.245.128.0/17 60.245.128.0/17
60.247.0.0/16 60.247.0.0/16
@ -830,7 +854,9 @@
101.204.0.0/14 101.204.0.0/14
101.224.0.0/13 101.224.0.0/13
101.234.76.0/22 101.234.76.0/22
101.236.0.0/16 101.236.0.0/18
101.236.64.0/20
101.236.128.0/17
101.237.0.0/19 101.237.0.0/19
101.237.33.0/24 101.237.33.0/24
101.237.34.0/23 101.237.34.0/23
@ -840,9 +866,13 @@
101.240.0.0/14 101.240.0.0/14
101.245.0.0/22 101.245.0.0/22
101.245.8.0/23 101.245.8.0/23
101.245.16.0/22 101.245.12.0/22
101.245.16.0/21
101.245.32.0/19 101.245.32.0/19
101.245.64.0/18 101.245.64.0/18
101.245.128.0/22
101.245.136.0/22
101.245.144.0/22
101.246.172.0/22 101.246.172.0/22
101.246.176.0/20 101.246.176.0/20
101.247.0.0/18 101.247.0.0/18
@ -870,7 +900,7 @@
103.4.56.0/22 103.4.56.0/22
103.5.192.0/22 103.5.192.0/22
103.6.220.0/22 103.6.220.0/22
103.7.140.0/22 103.7.140.0/23
103.8.8.0/22 103.8.8.0/22
103.8.32.0/22 103.8.32.0/22
103.8.52.0/22 103.8.52.0/22
@ -889,7 +919,6 @@
103.14.132.0/22 103.14.132.0/22
103.14.136.0/22 103.14.136.0/22
103.15.4.0/22 103.15.4.0/22
103.15.96.0/22
103.16.124.0/22 103.16.124.0/22
103.17.40.0/22 103.17.40.0/22
103.17.228.0/22 103.17.228.0/22
@ -921,7 +950,6 @@
103.26.0.0/22 103.26.0.0/22
103.26.64.0/22 103.26.64.0/22
103.26.76.0/22 103.26.76.0/22
103.27.4.0/22
103.27.24.0/22 103.27.24.0/22
103.27.240.0/22 103.27.240.0/22
103.28.8.0/24 103.28.8.0/24
@ -939,11 +967,11 @@
103.35.254.0/24 103.35.254.0/24
103.36.28.0/22 103.36.28.0/22
103.36.36.0/22 103.36.36.0/22
103.36.60.0/22 103.36.63.0/24
103.36.96.0/22 103.36.96.0/22
103.36.132.0/22 103.36.132.0/22
103.36.136.0/22 103.36.136.0/22
103.36.164.0/22 103.36.165.0/24
103.36.168.0/24 103.36.168.0/24
103.36.172.0/22 103.36.172.0/22
103.36.192.0/20 103.36.192.0/20
@ -951,7 +979,7 @@
103.36.220.0/22 103.36.220.0/22
103.37.7.0/24 103.37.7.0/24
103.37.12.0/22 103.37.12.0/22
103.37.16.0/22 103.37.18.0/23
103.37.44.0/23 103.37.44.0/23
103.37.46.0/24 103.37.46.0/24
103.37.72.0/22 103.37.72.0/22
@ -961,8 +989,6 @@
103.37.160.0/21 103.37.160.0/21
103.37.172.0/22 103.37.172.0/22
103.38.40.0/22 103.38.40.0/22
103.38.76.0/22
103.38.84.0/22
103.38.92.0/23 103.38.92.0/23
103.38.116.0/22 103.38.116.0/22
103.38.224.0/22 103.38.224.0/22
@ -982,7 +1008,6 @@
103.41.116.0/22 103.41.116.0/22
103.41.164.0/22 103.41.164.0/22
103.41.232.0/23 103.41.232.0/23
103.42.8.0/22
103.42.76.0/22 103.42.76.0/22
103.42.104.0/22 103.42.104.0/22
103.43.134.0/23 103.43.134.0/23
@ -993,7 +1018,6 @@
103.44.144.0/22 103.44.144.0/22
103.44.168.0/23 103.44.168.0/23
103.44.171.0/24 103.44.171.0/24
103.44.176.0/22
103.44.236.0/22 103.44.236.0/22
103.44.240.0/20 103.44.240.0/20
103.45.72.0/21 103.45.72.0/21
@ -1010,14 +1034,12 @@
103.46.168.0/22 103.46.168.0/22
103.47.48.0/22 103.47.48.0/22
103.47.80.0/22 103.47.80.0/22
103.48.232.0/22
103.49.12.0/22 103.49.12.0/22
103.49.108.0/22
103.49.196.0/24 103.49.196.0/24
103.49.198.0/23 103.49.198.0/23
103.50.36.0/22 103.50.36.0/22
103.50.253.0/24
103.51.62.0/23 103.51.62.0/23
103.52.100.0/22
103.52.104.0/23 103.52.104.0/23
103.52.172.0/22 103.52.172.0/22
103.52.176.0/22 103.52.176.0/22
@ -1033,8 +1055,8 @@
103.56.100.0/22 103.56.100.0/22
103.56.104.0/22 103.56.104.0/22
103.56.152.0/22 103.56.152.0/22
103.56.184.0/22
103.57.12.0/22 103.57.12.0/22
103.57.136.0/23
103.57.139.0/24 103.57.139.0/24
103.59.112.0/22 103.59.112.0/22
103.59.124.0/22 103.59.124.0/22
@ -1079,7 +1101,7 @@
103.73.204.0/22 103.73.204.0/22
103.74.24.0/21 103.74.24.0/21
103.74.48.0/22 103.74.48.0/22
103.75.104.0/22 103.75.107.0/24
103.75.152.0/22 103.75.152.0/22
103.76.60.0/22 103.76.60.0/22
103.76.220.0/22 103.76.220.0/22
@ -1151,7 +1173,6 @@
103.98.127.0/24 103.98.127.0/24
103.98.220.0/22 103.98.220.0/22
103.98.248.0/21 103.98.248.0/21
103.99.104.0/22
103.100.64.0/22 103.100.64.0/22
103.101.124.0/23 103.101.124.0/23
103.101.180.0/22 103.101.180.0/22
@ -1174,7 +1195,6 @@
103.106.36.0/22 103.106.36.0/22
103.106.252.0/22 103.106.252.0/22
103.107.0.0/22 103.107.0.0/22
103.107.188.0/22
103.107.216.0/21 103.107.216.0/21
103.108.244.0/24 103.108.244.0/24
103.108.247.0/24 103.108.247.0/24
@ -1186,7 +1206,6 @@
103.113.4.0/22 103.113.4.0/22
103.114.100.0/22 103.114.100.0/22
103.114.158.0/23 103.114.158.0/23
103.114.212.0/23
103.114.236.0/22 103.114.236.0/22
103.115.92.0/22 103.115.92.0/22
103.115.120.0/22 103.115.120.0/22
@ -1225,13 +1244,11 @@
103.131.168.0/22 103.131.168.0/22
103.131.179.0/24 103.131.179.0/24
103.132.22.0/23 103.132.22.0/23
103.132.80.0/23
103.132.212.0/23 103.132.212.0/23
103.133.128.0/23 103.133.128.0/23
103.134.136.0/22 103.134.136.0/22
103.135.160.0/22 103.135.160.0/22
103.135.192.0/21 103.135.192.0/21
103.135.236.0/24
103.137.60.0/24 103.137.60.0/24
103.138.156.0/23 103.138.156.0/23
103.139.136.0/23 103.139.136.0/23
@ -1364,7 +1381,7 @@
103.212.12.0/22 103.212.12.0/22
103.212.48.0/23 103.212.48.0/23
103.212.109.0/24 103.212.109.0/24
103.213.48.0/23 103.213.49.0/24
103.213.50.0/24 103.213.50.0/24
103.213.62.0/23 103.213.62.0/23
103.213.64.0/19 103.213.64.0/19
@ -1430,12 +1447,10 @@
103.233.4.0/22 103.233.4.0/22
103.233.52.0/22 103.233.52.0/22
103.233.128.0/22 103.233.128.0/22
103.233.138.0/24
103.233.162.0/23 103.233.162.0/23
103.234.20.0/22 103.234.20.0/22
103.234.56.0/22 103.234.56.0/22
103.234.128.0/22 103.234.128.0/22
103.235.85.0/24
103.235.102.0/23 103.235.102.0/23
103.235.136.0/22 103.235.136.0/22
103.235.144.0/24 103.235.144.0/24
@ -1443,6 +1458,10 @@
103.235.224.0/20 103.235.224.0/20
103.235.244.0/22 103.235.244.0/22
103.235.248.0/21 103.235.248.0/21
103.236.52.0/22
103.236.56.0/21
103.236.64.0/19
103.236.96.0/22
103.236.120.0/22 103.236.120.0/22
103.236.244.0/22 103.236.244.0/22
103.236.248.0/21 103.236.248.0/21
@ -1459,6 +1478,7 @@
103.238.52.0/22 103.238.52.0/22
103.238.96.0/23 103.238.96.0/23
103.238.98.0/24 103.238.98.0/24
103.238.130.0/24
103.238.132.0/22 103.238.132.0/22
103.238.144.0/22 103.238.144.0/22
103.238.160.0/22 103.238.160.0/22
@ -1468,7 +1488,7 @@
103.238.204.0/22 103.238.204.0/22
103.239.68.0/22 103.239.68.0/22
103.239.152.0/22 103.239.152.0/22
103.239.184.0/24 103.239.184.0/23
103.239.187.0/24 103.239.187.0/24
103.239.192.0/22 103.239.192.0/22
103.239.204.0/22 103.239.204.0/22
@ -1480,7 +1500,6 @@
103.240.124.0/22 103.240.124.0/22
103.240.244.0/22 103.240.244.0/22
103.241.95.0/24 103.241.95.0/24
103.241.208.0/23
103.242.128.0/24 103.242.128.0/24
103.242.130.0/24 103.242.130.0/24
103.242.168.0/23 103.242.168.0/23
@ -1518,7 +1537,7 @@
103.251.204.0/24 103.251.204.0/24
103.251.207.0/24 103.251.207.0/24
103.251.240.0/22 103.251.240.0/22
103.252.36.0/22 103.252.36.0/24
103.252.172.0/22 103.252.172.0/22
103.252.248.0/22 103.252.248.0/22
103.253.60.0/22 103.253.60.0/22
@ -1564,7 +1583,11 @@
106.3.80.0/22 106.3.80.0/22
106.3.88.0/21 106.3.88.0/21
106.3.96.0/22 106.3.96.0/22
106.3.128.0/19 106.3.128.0/20
106.3.144.0/22
106.3.148.0/23
106.3.151.0/24
106.3.152.0/21
106.3.192.0/20 106.3.192.0/20
106.3.208.0/21 106.3.208.0/21
106.3.224.0/21 106.3.224.0/21
@ -1583,7 +1606,6 @@
106.14.0.0/15 106.14.0.0/15
106.16.0.0/14 106.16.0.0/14
106.32.0.0/12 106.32.0.0/12
106.48.0.0/21
106.48.16.0/21 106.48.16.0/21
106.52.0.0/14 106.52.0.0/14
106.56.0.0/14 106.56.0.0/14
@ -1745,6 +1767,7 @@
112.132.0.0/16 112.132.0.0/16
112.192.0.0/14 112.192.0.0/14
112.196.208.0/24 112.196.208.0/24
112.196.220.0/24
112.224.0.0/11 112.224.0.0/11
113.0.0.0/13 113.0.0.0/13
113.8.0.0/15 113.8.0.0/15
@ -1858,7 +1881,17 @@
114.112.4.0/23 114.112.4.0/23
114.112.24.0/21 114.112.24.0/21
114.112.32.0/19 114.112.32.0/19
114.112.64.0/19 114.112.64.0/24
114.112.66.0/24
114.112.70.0/24
114.112.72.0/21
114.112.81.0/24
114.112.82.0/24
114.112.85.0/24
114.112.86.0/24
114.112.88.0/24
114.112.91.0/24
114.112.94.0/23
114.112.96.0/21 114.112.96.0/21
114.112.104.0/22 114.112.104.0/22
114.112.136.0/21 114.112.136.0/21
@ -1908,7 +1941,7 @@
115.120.144.0/23 115.120.144.0/23
115.120.148.0/22 115.120.148.0/22
115.120.152.0/21 115.120.152.0/21
115.120.184.0/21 115.120.176.0/20
115.120.192.0/18 115.120.192.0/18
115.124.16.0/20 115.124.16.0/20
115.148.0.0/14 115.148.0.0/14
@ -1920,6 +1953,8 @@
115.174.64.0/19 115.174.64.0/19
115.175.0.0/18 115.175.0.0/18
115.175.64.0/19 115.175.64.0/19
115.175.104.0/22
115.175.108.0/23
115.175.120.0/21 115.175.120.0/21
115.175.128.0/18 115.175.128.0/18
115.175.192.0/19 115.175.192.0/19
@ -1945,7 +1980,8 @@
116.66.48.0/23 116.66.48.0/23
116.66.53.0/24 116.66.53.0/24
116.66.98.0/24 116.66.98.0/24
116.66.120.0/22 116.66.120.0/24
116.66.123.0/24
116.68.136.0/21 116.68.136.0/21
116.68.176.0/21 116.68.176.0/21
116.70.64.0/18 116.70.64.0/18
@ -2035,7 +2071,7 @@
117.32.0.0/13 117.32.0.0/13
117.40.0.0/14 117.40.0.0/14
117.44.0.0/15 117.44.0.0/15
117.48.0.0/18 117.48.32.0/19
117.48.64.0/20 117.48.64.0/20
117.48.80.0/21 117.48.80.0/21
117.48.88.0/22 117.48.88.0/22
@ -2231,7 +2267,7 @@
118.242.24.0/22 118.242.24.0/22
118.242.32.0/22 118.242.32.0/22
118.242.40.0/24 118.242.40.0/24
118.242.236.0/22 118.242.238.0/24
118.244.0.0/21 118.244.0.0/21
118.244.128.0/17 118.244.128.0/17
118.247.0.0/16 118.247.0.0/16
@ -2243,9 +2279,8 @@
119.15.136.0/23 119.15.136.0/23
119.15.140.0/23 119.15.140.0/23
119.18.208.0/21 119.18.208.0/21
119.18.224.0/22 119.18.224.0/24
119.18.231.0/24 119.18.226.0/24
119.18.232.0/24
119.18.234.0/24 119.18.234.0/24
119.18.236.0/23 119.18.236.0/23
119.23.0.0/16 119.23.0.0/16
@ -2368,10 +2403,7 @@
119.253.0.0/20 119.253.0.0/20
119.253.32.0/19 119.253.32.0/19
119.253.64.0/19 119.253.64.0/19
119.253.249.0/24
119.253.252.0/24
119.254.0.0/16 119.254.0.0/16
119.255.63.0/24
119.255.128.0/17 119.255.128.0/17
120.0.0.0/12 120.0.0.0/12
120.24.0.0/14 120.24.0.0/14
@ -2440,6 +2472,7 @@
121.39.255.0/24 121.39.255.0/24
121.40.0.0/14 121.40.0.0/14
121.46.0.0/20 121.46.0.0/20
121.46.20.0/22
121.46.128.0/21 121.46.128.0/21
121.46.141.0/24 121.46.141.0/24
121.46.192.0/21 121.46.192.0/21
@ -2449,7 +2482,6 @@
121.46.248.0/22 121.46.248.0/22
121.46.252.0/23 121.46.252.0/23
121.46.254.0/24 121.46.254.0/24
121.47.0.0/16
121.48.0.0/15 121.48.0.0/15
121.51.0.0/16 121.51.0.0/16
121.52.160.0/19 121.52.160.0/19
@ -2580,9 +2612,6 @@
123.8.0.0/13 123.8.0.0/13
123.49.192.0/23 123.49.192.0/23
123.49.194.0/24 123.49.194.0/24
123.49.224.0/24
123.49.229.0/24
123.49.232.0/24
123.49.240.0/24 123.49.240.0/24
123.49.242.0/23 123.49.242.0/23
123.52.0.0/14 123.52.0.0/14
@ -2826,7 +2855,22 @@
140.210.8.0/21 140.210.8.0/21
140.210.16.0/20 140.210.16.0/20
140.210.32.0/22 140.210.32.0/22
140.210.64.0/18 140.210.65.0/24
140.210.67.0/24
140.210.69.0/24
140.210.70.0/24
140.210.72.0/23
140.210.75.0/24
140.210.77.0/24
140.210.78.0/23
140.210.80.0/24
140.210.83.0/24
140.210.84.0/24
140.210.87.0/24
140.210.88.0/22
140.210.92.0/24
140.210.94.0/24
140.210.96.0/19
140.210.128.0/19 140.210.128.0/19
140.210.192.0/19 140.210.192.0/19
140.210.224.0/20 140.210.224.0/20
@ -2838,7 +2882,6 @@
140.249.0.0/16 140.249.0.0/16
140.250.0.0/16 140.250.0.0/16
140.255.0.0/16 140.255.0.0/16
141.11.50.0/23
143.64.0.0/16 143.64.0.0/16
144.0.0.0/16 144.0.0.0/16
144.7.0.0/17 144.7.0.0/17
@ -2891,6 +2934,7 @@
150.242.244.0/22 150.242.244.0/22
150.242.248.0/22 150.242.248.0/22
150.255.0.0/16 150.255.0.0/16
151.241.174.0/24
151.242.65.0/24 151.242.65.0/24
152.104.128.0/17 152.104.128.0/17
152.136.0.0/16 152.136.0.0/16
@ -2903,24 +2947,12 @@
153.118.0.0/15 153.118.0.0/15
154.8.48.0/20 154.8.48.0/20
154.8.128.0/17 154.8.128.0/17
154.19.43.0/24
154.38.104.0/22 154.38.104.0/22
154.48.226.0/24 154.48.237.0/24
154.48.231.0/24
154.48.235.0/24
154.48.236.0/22
154.48.240.0/24
154.48.247.0/24
154.48.248.0/24
154.48.250.0/23
154.72.42.0/24 154.72.42.0/24
154.72.44.0/24 154.72.44.0/24
154.72.47.0/24 154.72.47.0/24
154.89.32.0/20 154.89.32.0/20
154.89.49.0/24
154.89.50.0/23
154.89.52.0/22
154.89.56.0/21
154.91.158.0/23 154.91.158.0/23
154.208.140.0/22 154.208.140.0/22
154.208.144.0/20 154.208.144.0/20
@ -2940,28 +2972,36 @@
155.102.26.0/23 155.102.26.0/23
155.102.28.0/22 155.102.28.0/22
155.102.32.0/19 155.102.32.0/19
155.102.72.0/24
155.102.111.0/24 155.102.111.0/24
155.102.112.0/21 155.102.112.0/21
155.102.120.0/23 155.102.120.0/23
155.102.127.0/24
155.102.128.0/22 155.102.128.0/22
155.102.132.0/23 155.102.132.0/23
155.102.135.0/24 155.102.135.0/24
155.102.136.0/21 155.102.136.0/21
155.102.144.0/20 155.102.144.0/20
155.102.160.0/22 155.102.160.0/22
155.102.165.0/24 155.102.164.0/23
155.102.166.0/24 155.102.166.0/24
155.102.168.0/23 155.102.168.0/23
155.102.176.0/23 155.102.176.0/23
155.102.180.0/22
155.102.193.0/24 155.102.193.0/24
155.102.194.0/23 155.102.194.0/23
155.102.196.0/23 155.102.196.0/23
155.102.198.0/24 155.102.198.0/24
155.102.201.0/24 155.102.200.0/23
155.102.202.0/24
155.102.204.0/23 155.102.204.0/23
155.102.208.0/23 155.102.208.0/23
155.102.211.0/24
155.102.216.0/22 155.102.216.0/22
155.102.220.0/23 155.102.220.0/23
155.102.224.0/20
155.102.240.0/23
155.102.242.0/24
155.102.247.0/24 155.102.247.0/24
155.102.248.0/23 155.102.248.0/23
155.102.253.0/24 155.102.253.0/24
@ -3006,11 +3046,11 @@
160.19.208.0/22 160.19.208.0/22
160.20.18.0/23 160.20.18.0/23
160.22.188.0/24 160.22.188.0/24
160.22.244.0/23
160.25.194.0/23 160.25.194.0/23
160.30.230.0/23 160.30.230.0/23
160.83.110.0/24 160.83.110.0/24
160.191.0.0/24 160.191.0.0/24
160.202.152.0/22
160.202.212.0/22 160.202.212.0/22
160.202.224.0/19 160.202.224.0/19
160.250.14.0/23 160.250.14.0/23
@ -3039,7 +3079,8 @@
163.181.0.0/23 163.181.0.0/23
163.181.2.0/24 163.181.2.0/24
163.181.15.0/24 163.181.15.0/24
163.181.16.0/22 163.181.17.0/24
163.181.18.0/23
163.181.22.0/23 163.181.22.0/23
163.181.25.0/24 163.181.25.0/24
163.181.26.0/24 163.181.26.0/24
@ -3098,8 +3139,7 @@
163.181.200.0/21 163.181.200.0/21
163.181.209.0/24 163.181.209.0/24
163.181.210.0/23 163.181.210.0/23
163.181.212.0/23 163.181.212.0/22
163.181.214.0/24
163.181.216.0/21 163.181.216.0/21
163.181.224.0/23 163.181.224.0/23
163.181.228.0/22 163.181.228.0/22
@ -3143,9 +3183,6 @@
175.16.0.0/13 175.16.0.0/13
175.24.0.0/15 175.24.0.0/15
175.27.0.0/16 175.27.0.0/16
175.29.107.0/24
175.29.108.0/24
175.29.110.0/23
175.30.0.0/15 175.30.0.0/15
175.42.0.0/15 175.42.0.0/15
175.44.0.0/16 175.44.0.0/16
@ -3183,8 +3220,6 @@
180.89.64.0/19 180.89.64.0/19
180.91.192.0/20 180.91.192.0/20
180.92.176.0/23 180.92.176.0/23
180.94.192.0/20
180.94.208.0/21
180.95.128.0/17 180.95.128.0/17
180.96.0.0/11 180.96.0.0/11
180.129.128.0/17 180.129.128.0/17
@ -3220,7 +3255,8 @@
180.188.32.0/20 180.188.32.0/20
180.200.252.0/22 180.200.252.0/22
180.201.0.0/16 180.201.0.0/16
180.203.0.0/22 180.203.0.0/23
180.203.3.0/24
180.208.0.0/15 180.208.0.0/15
180.210.212.0/22 180.210.212.0/22
180.212.0.0/15 180.212.0.0/15
@ -3258,7 +3294,6 @@
182.174.0.0/15 182.174.0.0/15
182.200.0.0/13 182.200.0.0/13
182.236.160.0/19 182.236.160.0/19
182.238.0.0/16
182.240.0.0/13 182.240.0.0/13
182.254.0.0/16 182.254.0.0/16
183.0.0.0/10 183.0.0.0/10
@ -3283,12 +3318,11 @@
183.192.0.0/10 183.192.0.0/10
185.75.173.0/24 185.75.173.0/24
185.75.174.0/24 185.75.174.0/24
185.78.105.0/24
185.234.212.0/24 185.234.212.0/24
188.131.128.0/17 188.131.128.0/17
192.55.46.0/24 192.55.46.0/24
192.55.68.0/22 192.55.68.0/22
192.102.204.0/22 192.102.204.0/23
192.140.160.0/19 192.140.160.0/19
192.140.208.0/21 192.140.208.0/21
192.144.128.0/17 192.144.128.0/17
@ -3312,6 +3346,7 @@
194.127.229.0/24 194.127.229.0/24
194.138.202.0/23 194.138.202.0/23
194.138.245.0/24 194.138.245.0/24
195.114.203.0/24
198.175.100.0/22 198.175.100.0/22
198.208.17.0/24 198.208.17.0/24
198.208.19.0/24 198.208.19.0/24
@ -3404,7 +3439,8 @@
202.111.230.0/24 202.111.230.0/24
202.111.240.0/23 202.111.240.0/23
202.111.242.0/24 202.111.242.0/24
202.111.244.0/24 202.111.244.0/23
202.111.246.0/24
202.112.0.0/13 202.112.0.0/13
202.120.0.0/15 202.120.0.0/15
202.122.32.0/21 202.122.32.0/21
@ -3427,7 +3463,6 @@
202.130.0.0/19 202.130.0.0/19
202.130.224.0/20 202.130.224.0/20
202.130.240.0/21 202.130.240.0/21
202.136.48.0/20
202.136.208.0/21 202.136.208.0/21
202.136.216.0/23 202.136.216.0/23
202.136.218.0/24 202.136.218.0/24
@ -3441,7 +3476,7 @@
202.143.100.0/22 202.143.100.0/22
202.144.198.0/23 202.144.198.0/23
202.148.96.0/19 202.148.96.0/19
202.149.224.0/19 202.149.224.0/20
202.150.16.0/20 202.150.16.0/20
202.153.48.0/20 202.153.48.0/20
202.158.160.0/19 202.158.160.0/19
@ -3461,7 +3496,6 @@
202.189.8.0/21 202.189.8.0/21
202.189.16.0/21 202.189.16.0/21
202.192.0.0/12 202.192.0.0/12
202.222.32.0/19
203.0.104.0/21 203.0.104.0/21
203.2.64.0/21 203.2.64.0/21
203.2.112.0/21 203.2.112.0/21
@ -3624,7 +3658,6 @@
203.86.60.0/23 203.86.60.0/23
203.86.62.0/24 203.86.62.0/24
203.86.64.0/19 203.86.64.0/19
203.86.112.0/24
203.86.116.0/24 203.86.116.0/24
203.86.254.0/23 203.86.254.0/23
203.88.32.0/19 203.88.32.0/19
@ -3745,7 +3778,7 @@
203.194.124.0/24 203.194.124.0/24
203.195.64.0/19 203.195.64.0/19
203.195.113.0/24 203.195.113.0/24
203.195.114.0/23 203.195.114.0/24
203.195.118.0/23 203.195.118.0/23
203.195.128.0/17 203.195.128.0/17
203.196.0.0/21 203.196.0.0/21
@ -3776,7 +3809,6 @@
206.54.9.0/24 206.54.9.0/24
206.54.10.0/23 206.54.10.0/23
206.54.12.0/22 206.54.12.0/22
206.237.112.0/20
207.226.153.0/24 207.226.153.0/24
207.226.154.0/24 207.226.154.0/24
210.2.0.0/23 210.2.0.0/23
@ -3822,7 +3854,10 @@
210.72.128.0/18 210.72.128.0/18
210.72.192.0/19 210.72.192.0/19
210.72.224.0/20 210.72.224.0/20
210.72.240.0/21 210.72.240.0/23
210.72.243.0/24
210.72.245.0/24
210.72.246.0/24
210.73.0.0/16 210.73.0.0/16
210.74.0.0/20 210.74.0.0/20
210.74.35.0/24 210.74.35.0/24
@ -3845,7 +3880,12 @@
210.77.0.0/18 210.77.0.0/18
210.77.64.0/19 210.77.64.0/19
210.77.128.0/19 210.77.128.0/19
210.77.176.0/20 210.77.176.0/22
210.77.180.0/23
210.77.182.0/24
210.77.184.0/23
210.77.189.0/24
210.77.190.0/23
210.77.192.0/18 210.77.192.0/18
210.78.128.0/24 210.78.128.0/24
210.78.134.0/23 210.78.134.0/23
@ -3903,13 +3943,11 @@
211.98.0.0/16 211.98.0.0/16
211.99.8.0/21 211.99.8.0/21
211.99.16.0/23 211.99.16.0/23
211.99.24.0/21 211.99.24.0/23
211.99.26.0/24
211.99.28.0/22
211.99.32.0/19 211.99.32.0/19
211.99.64.0/19 211.99.64.0/18
211.99.96.0/20
211.99.112.0/22
211.99.116.0/24
211.99.122.0/24
211.99.128.0/18 211.99.128.0/18
211.99.192.0/19 211.99.192.0/19
211.100.0.0/17 211.100.0.0/17
@ -4006,22 +4044,23 @@
211.159.128.0/17 211.159.128.0/17
211.160.0.0/22 211.160.0.0/22
211.160.4.0/23 211.160.4.0/23
211.160.8.0/22 211.160.9.0/24
211.160.14.0/23 211.160.10.0/23
211.160.16.0/21 211.160.16.0/21
211.160.24.0/22 211.160.24.0/24
211.160.26.0/23
211.160.28.0/23 211.160.28.0/23
211.160.36.0/23 211.160.36.0/23
211.160.46.0/23 211.160.46.0/24
211.160.62.0/23 211.160.62.0/23
211.160.72.0/21 211.160.72.0/21
211.160.80.0/20 211.160.80.0/20
211.160.112.0/22 211.160.112.0/22
211.160.120.0/23 211.160.120.0/23
211.160.160.0/19 211.160.160.0/19
211.160.194.0/23 211.160.195.0/24
211.160.196.0/24 211.160.196.0/24
211.160.202.0/23 211.160.203.0/24
211.160.204.0/23 211.160.204.0/23
211.160.240.0/20 211.160.240.0/20
211.161.0.0/20 211.161.0.0/20
@ -4121,7 +4160,6 @@
219.83.160.0/19 219.83.160.0/19
219.100.148.0/22 219.100.148.0/22
219.117.16.0/20 219.117.16.0/20
219.121.224.0/19
219.128.0.0/12 219.128.0.0/12
219.144.0.0/14 219.144.0.0/14
219.148.0.0/15 219.148.0.0/15
@ -4167,7 +4205,7 @@
219.236.0.0/14 219.236.0.0/14
219.242.0.0/15 219.242.0.0/15
219.244.0.0/14 219.244.0.0/14
220.101.192.0/18 220.101.192.0/19
220.112.0.0/22 220.112.0.0/22
220.112.8.0/24 220.112.8.0/24
220.112.40.0/21 220.112.40.0/21
@ -4232,11 +4270,16 @@
220.207.176.0/22 220.207.176.0/22
220.207.184.0/22 220.207.184.0/22
220.207.254.0/23 220.207.254.0/23
220.231.0.0/18 220.231.32.0/20
220.231.128.0/17 220.231.128.0/17
220.232.64.0/18 220.232.64.0/18
220.234.0.0/16 220.234.0.0/16
220.243.128.0/18 220.242.180.0/24
220.243.128.0/20
220.243.153.0/24
220.243.154.0/23
220.243.156.0/23
220.243.176.0/20
220.248.0.0/16 220.248.0.0/16
220.249.0.0/17 220.249.0.0/17
220.249.128.0/18 220.249.128.0/18

View File

@ -1 +1 @@
20250808035959 20250822033443

View File

@ -2,6 +2,7 @@
2001:254::/31 2001:254::/31
2001:256:100::/48 2001:256:100::/48
2001:678:120::/48 2001:678:120::/48
2001:678:10d0::/48
2001:67c:ebc::/48 2001:67c:ebc::/48
2001:7fa:5::/48 2001:7fa:5::/48
2001:c68::/32 2001:c68::/32
@ -95,6 +96,7 @@
2400:9620::/32 2400:9620::/32
2400:a860:1::/48 2400:a860:1::/48
2400:a860:2::/47 2400:a860:2::/47
2400:a860:4::/47
2400:a980::/29 2400:a980::/29
2400:ae00:1981::/48 2400:ae00:1981::/48
2400:b200::/32 2400:b200::/32
@ -117,7 +119,6 @@
2401:800::/32 2401:800::/32
2401:1160::/32 2401:1160::/32
2401:11a0:10::/44 2401:11a0:10::/44
2401:11a0:1500::/40
2401:11a0:d150::/48 2401:11a0:d150::/48
2401:11a0:d152::/48 2401:11a0:d152::/48
2401:11a0:d158::/48 2401:11a0:d158::/48
@ -159,7 +160,7 @@
2401:cb80::/32 2401:cb80::/32
2401:cc00::/32 2401:cc00::/32
2401:ce00::/32 2401:ce00::/32
2401:d0e0:2::/48 2401:d0e0:2::/47
2401:d180::/46 2401:d180::/46
2401:d180:10::/47 2401:d180:10::/47
2401:d180:111::/48 2401:d180:111::/48
@ -169,8 +170,7 @@
2401:ec00::/32 2401:ec00::/32
2401:f860:86::/47 2401:f860:86::/47
2401:f860:88::/47 2401:f860:88::/47
2401:f860:90::/47 2401:f860:90::/46
2401:f860:93::/48
2401:f860:94::/48 2401:f860:94::/48
2401:f860:100::/40 2401:f860:100::/40
2401:f860:f100::/40 2401:f860:f100::/40
@ -178,6 +178,7 @@
2402:840:d000::/46 2402:840:d000::/46
2402:840:e000::/46 2402:840:e000::/46
2402:840:f000::/38 2402:840:f000::/38
2402:c60::/48
2402:1440::/32 2402:1440::/32
2402:2000::/32 2402:2000::/32
2402:3180::/46 2402:3180::/46
@ -223,7 +224,9 @@
2402:f000::/32 2402:f000::/32
2402:f140:ff10::/46 2402:f140:ff10::/46
2402:f140:ff14::/48 2402:f140:ff14::/48
2402:f8c0::/32 2402:f8c0::/47
2402:f8c0:2::/48
2402:f8c0:5::/48
2403:600::/32 2403:600::/32
2403:c80::/32 2403:c80::/32
2403:1b80::/48 2403:1b80::/48
@ -257,7 +260,6 @@
2403:b400::/32 2403:b400::/32
2403:c980::/32 2403:c980::/32
2403:d400::/32 2403:d400::/32
2403:e7c0:1::/48
2403:f4c0::/48 2403:f4c0::/48
2403:ffc0:1100::/40 2403:ffc0:1100::/40
2403:ffc0:1200::/39 2403:ffc0:1200::/39
@ -287,7 +289,7 @@
2404:2280:12e::/48 2404:2280:12e::/48
2404:2280:130::/48 2404:2280:130::/48
2404:2280:134::/48 2404:2280:134::/48
2404:2280:136::/47 2404:2280:137::/48
2404:2280:138::/48 2404:2280:138::/48
2404:2280:13b::/48 2404:2280:13b::/48
2404:2280:13c::/47 2404:2280:13c::/47
@ -346,13 +348,19 @@
2404:2280:20e::/48 2404:2280:20e::/48
2404:2280:210::/46 2404:2280:210::/46
2404:2280:214::/48 2404:2280:214::/48
2404:2280:217::/48 2404:2280:216::/47
2404:2280:218::/48 2404:2280:218::/48
2404:2280:21a::/48 2404:2280:21a::/48
2404:2280:21d::/48
2404:2280:221::/48 2404:2280:221::/48
2404:2280:265::/48
2404:2280:266::/47
2404:2280:268::/46
2404:2280:26c::/48
2404:2280:271::/48 2404:2280:271::/48
2404:2280:272::/48
2404:2280:27a::/48 2404:2280:27a::/48
2404:2280:27c::/48 2404:2280:27c::/47
2404:3700::/48 2404:3700::/48
2404:4dc0::/32 2404:4dc0::/32
2404:6380::/48 2404:6380::/48
@ -361,7 +369,6 @@
2404:6500:dcb3::/48 2404:6500:dcb3::/48
2404:7180:a000::/48 2404:7180:a000::/48
2404:7180:a010::/48 2404:7180:a010::/48
2404:7180:a021::/48
2404:7180:aa00::/48 2404:7180:aa00::/48
2404:7180:aa10::/48 2404:7180:aa10::/48
2404:7180:b001::/48 2404:7180:b001::/48
@ -390,7 +397,6 @@
2404:c2c0:c000::/36 2404:c2c0:c000::/36
2404:c300::/32 2404:c300::/32
2404:c940::/48 2404:c940::/48
2404:d7c0:2::/48
2404:e280::/47 2404:e280::/47
2404:e5c0::/32 2404:e5c0::/32
2404:e8c0::/32 2404:e8c0::/32
@ -520,7 +526,6 @@
2407:6c40:1210::/48 2407:6c40:1210::/48
2407:6c40:1500::/48 2407:6c40:1500::/48
2407:6c40:1600::/40 2407:6c40:1600::/40
2407:6c40:1810::/48
2407:8f40:2::/48 2407:8f40:2::/48
2407:9f00::/32 2407:9f00::/32
2407:ad80::/32 2407:ad80::/32
@ -590,7 +595,6 @@
2408:8181:a000::/40 2408:8181:a000::/40
2408:8181:a220::/44 2408:8181:a220::/44
2408:8181:e000::/40 2408:8181:e000::/40
2408:8182:6000::/40
2408:8182:c000::/40 2408:8182:c000::/40
2408:8183:4000::/40 2408:8183:4000::/40
2408:8183:8000::/40 2408:8183:8000::/40
@ -1106,7 +1110,6 @@
2409:27fb::/48 2409:27fb::/48
2409:27fc::/48 2409:27fc::/48
2409:27fe::/33 2409:27fe::/33
2409:6100::/44
2409:8000::/20 2409:8000::/20
240a:2000::/40 240a:2000::/40
240a:2001:100::/40 240a:2001:100::/40
@ -1184,6 +1187,7 @@
240e::/20 240e::/20
2602:2e0:ff::/48 2602:2e0:ff::/48
2602:f7ee:ee::/48 2602:f7ee:ee::/48
2602:f92a:e100::/44
2602:f93b:400::/38 2602:f93b:400::/38
2602:f9ba:a8::/48 2602:f9ba:a8::/48
2602:f9ba:10c::/48 2602:f9ba:10c::/48
@ -1235,8 +1239,8 @@
2a04:f580:9280::/48 2a04:f580:9280::/48
2a04:f580:9290::/48 2a04:f580:9290::/48
2a06:1180:1000::/48 2a06:1180:1000::/48
2a06:3605::/32 2a06:3603::/32
2a06:3606::/31 2a06:3604::/30
2a06:9f81:4600::/43 2a06:9f81:4600::/43
2a06:9f81:4640::/44 2a06:9f81:4640::/44
2a06:a005:260::/43 2a06:a005:260::/43
@ -1251,10 +1255,9 @@
2a09:b280:ff81::/48 2a09:b280:ff81::/48
2a09:b280:ff83::/48 2a09:b280:ff83::/48
2a09:b280:ff84::/47 2a09:b280:ff84::/47
2a0a:2840:20::/43 2a0a:2840::/30
2a0a:2840:2000::/48
2a0a:2842::/32
2a0a:2845:aab8::/46 2a0a:2845:aab8::/46
2a0a:2845:d647::/48
2a0a:2846::/48 2a0a:2846::/48
2a0a:6040:ec00::/40 2a0a:6040:ec00::/40
2a0a:6044:6600::/40 2a0a:6044:6600::/40
@ -1262,6 +1265,7 @@
2a0b:2542::/48 2a0b:2542::/48
2a0b:4340:a6::/48 2a0b:4340:a6::/48
2a0b:4e07:b8::/47 2a0b:4e07:b8::/47
2a0c:9a40:84e0::/48
2a0c:9a40:9e00::/43 2a0c:9a40:9e00::/43
2a0c:b641:571::/48 2a0c:b641:571::/48
2a0e:97c0:83f::/48 2a0e:97c0:83f::/48
@ -1319,6 +1323,7 @@
2a0f:7803:fe82::/48 2a0f:7803:fe82::/48
2a0f:7d07::/32 2a0f:7d07::/32
2a0f:85c1:ba5::/48 2a0f:85c1:ba5::/48
2a0f:85c1:ca0::/44
2a0f:9400:6110::/48 2a0f:9400:6110::/48
2a0f:9400:7700::/48 2a0f:9400:7700::/48
2a0f:ac00::/29 2a0f:ac00::/29
@ -1327,30 +1332,34 @@
2a10:ccc0:d00::/46 2a10:ccc0:d00::/46
2a10:ccc0:d0a::/47 2a10:ccc0:d0a::/47
2a10:ccc0:d0c::/47 2a10:ccc0:d0c::/47
2a10:ccc6:66c4::/48
2a10:ccc6:66c6::/48 2a10:ccc6:66c6::/48
2a10:ccc6:66c9::/48 2a10:ccc6:66c9::/48
2a10:ccc6:66ca::/48 2a10:ccc6:66ca::/48
2a10:ccc6:66cd::/48 2a10:ccc6:66cc::/47
2a12:f8c3::/36 2a12:f8c3::/36
2a13:1800::/48 2a13:1800::/48
2a13:1800:10::/48 2a13:1800:10::/48
2a13:1800:80::/44 2a13:1800:80::/44
2a13:1800:300::/44 2a13:1800:300::/44
2a13:1801:180::/43 2a13:1801:180::/43
2a13:a5c3:ff10::/44
2a13:a5c3:ff21::/48 2a13:a5c3:ff21::/48
2a13:a5c3:ff50::/44 2a13:a5c3:ff50::/44
2a13:a5c7:1800::/40 2a13:a5c7:1800::/40
2a13:a5c7:2100::/48 2a13:a5c7:2100::/48
2a13:a5c7:2102::/48 2a13:a5c7:2102::/48
2a13:a5c7:2121::/48 2a13:a5c7:2121::/48
2a13:a5c7:2801::/48
2a13:a5c7:2803::/48 2a13:a5c7:2803::/48
2a13:a5c7:3100::/43 2a13:a5c7:3108::/48
2a13:a5c7:31a0::/43 2a13:a5c7:31a0::/43
2a13:aac4:f000::/44 2a13:aac4:f000::/44
2a14:7c0:4a01::/48 2a14:7c0:4a01::/48
2a14:4c41::/32 2a14:4c41::/32
2a14:67c1:20::/44 2a14:67c1:20::/44
2a14:67c1:70::/47 2a14:67c1:70::/47
2a14:67c1:73::/48
2a14:67c1:74::/48 2a14:67c1:74::/48
2a14:67c1:702::/47 2a14:67c1:702::/47
2a14:67c1:704::/48 2a14:67c1:704::/48
@ -1364,7 +1373,8 @@
2a14:67c1:a061::/48 2a14:67c1:a061::/48
2a14:67c1:a064::/48 2a14:67c1:a064::/48
2a14:67c1:a090::/46 2a14:67c1:a090::/46
2a14:67c1:a094::/47 2a14:67c1:a095::/48
2a14:67c1:a096::/48
2a14:67c1:a099::/48 2a14:67c1:a099::/48
2a14:67c1:a100::/43 2a14:67c1:a100::/43
2a14:67c1:b000::/48 2a14:67c1:b000::/48
@ -1374,17 +1384,24 @@
2a14:67c1:b100::/46 2a14:67c1:b100::/46
2a14:67c1:b105::/48 2a14:67c1:b105::/48
2a14:67c1:b107::/48 2a14:67c1:b107::/48
2a14:67c1:b130::/47 2a14:67c1:b130::/48
2a14:67c1:b132::/48 2a14:67c1:b132::/47
2a14:67c1:b134::/47
2a14:67c1:b4a1::/48
2a14:67c1:b4a2::/48
2a14:67c1:b4c0::/45 2a14:67c1:b4c0::/45
2a14:67c1:b4d0::/44
2a14:67c1:b4e0::/43 2a14:67c1:b4e0::/43
2a14:67c1:b500::/48 2a14:67c1:b500::/48
2a14:67c1:b549::/48
2a14:67c1:b561::/48 2a14:67c1:b561::/48
2a14:67c1:b563::/48 2a14:67c1:b563::/48
2a14:67c1:b566::/48 2a14:67c1:b566::/48
2a14:67c1:b581::/48
2a14:67c1:b582::/48 2a14:67c1:b582::/48
2a14:67c1:b588::/47 2a14:67c1:b588::/47
2a14:67c1:b590::/48 2a14:67c1:b590::/48
2a14:67c1:b599::/48
2a14:67c5:1900::/40 2a14:67c5:1900::/40
2a14:7580:9200::/40 2a14:7580:9200::/40
2a14:7580:9400::/39 2a14:7580:9400::/39

View File

@ -1 +1 @@
20250808035959 20250822033443

View File

@ -54617,7 +54617,6 @@ itiankong.com
itiankong.net itiankong.net
itianliao.com itianliao.com
itiexue.net itiexue.net
itiger.com
itigergrowth.com itigergrowth.com
itigergrowtha.com itigergrowtha.com
itigerup.com itigerup.com
@ -61793,7 +61792,6 @@ kovemoto.com
kowa-dental.com kowa-dental.com
kowa103.com kowa103.com
kowloonhospital.com kowloonhospital.com
kox.moe
koyuki.cc koyuki.cc
kpblw.com kpblw.com
kpbyd.com kpbyd.com
@ -70630,7 +70628,6 @@ mowan123.com
moweather.com moweather.com
mowgz.com mowgz.com
mowowo.com mowowo.com
mox.moe
moxfive.xyz moxfive.xyz
moxiai.com moxiai.com
moxian.com moxian.com
@ -71461,8 +71458,6 @@ mypharma.com
mypian.com mypian.com
mypiao.com mypiao.com
mypiaojia.com mypiaojia.com
mypikpak.com
mypikpak.net
mypitaya.com mypitaya.com
mypity.com mypity.com
mypiwik.com mypiwik.com
@ -71729,7 +71724,6 @@ naitta.com
naiveadmin.com naiveadmin.com
naiveblue.com naiveblue.com
naiwch.com naiwch.com
naixi.net
naixuecha.com naixuecha.com
naiyouxuexi.com naiyouxuexi.com
najingtech.com najingtech.com
@ -97561,7 +97555,6 @@ ustarl.com
ustbtc.com ustbtc.com
ustc.edu ustc.edu
ustcers.com ustcers.com
ustclug.org
ustui.com ustui.com
usuredata.com usuredata.com
usuuu.com usuuu.com
@ -98607,7 +98600,6 @@ voidking.com
voip366.com voip366.com
vojs.tv vojs.tv
vokop.com vokop.com
vol.moe
volc-dns.com volc-dns.com
volc-dns.net volc-dns.net
volc-dns.pub volc-dns.pub
@ -104816,7 +104808,6 @@ xiaomei.cc
xiaomeiti.com xiaomeiti.com
xiaomeng1235.com xiaomeng1235.com
xiaomi.com xiaomi.com
xiaomi.eu
xiaomi.hk xiaomi.hk
xiaomi.net xiaomi.net
xiaomi.org xiaomi.org
@ -106602,6 +106593,7 @@ xn--4xup5j.com
xn--54q23ckxiyx0e.com xn--54q23ckxiyx0e.com
xn--54q249denfzw9a.net xn--54q249denfzw9a.net
xn--54q40czz0g7xp.com xn--54q40czz0g7xp.com
xn--55qw42g
xn--55qw7biqf7g3d004h8yuw1ctrt04sep1cjfb.com xn--55qw7biqf7g3d004h8yuw1ctrt04sep1cjfb.com
xn--55qwa79fh6ku8czve.com xn--55qwa79fh6ku8czve.com
xn--55qx2ag79c1iq.com xn--55qx2ag79c1iq.com

View File

@ -1 +1 @@
202508072216 202508212214

View File

@ -511,6 +511,7 @@ bestvpnusa.com
bet365.com bet365.com
betaclouds.net betaclouds.net
betfair.com betfair.com
betterhash.net
betternet.co betternet.co
bettervpn.com bettervpn.com
bettween.com bettween.com
@ -537,6 +538,7 @@ bild.de
biliworld.com biliworld.com
billypan.com billypan.com
binance.com binance.com
binance.org
binancezh.cc binancezh.cc
binux.me binux.me
bird.so bird.so
@ -548,6 +550,7 @@ bitchute.com
bitcointalk.org bitcointalk.org
bitcoinworld.com bitcoinworld.com
bitfinex.com bitfinex.com
bitget.com
bithumb.com bithumb.com
bitmex.com bitmex.com
bitshare.com bitshare.com
@ -1043,6 +1046,7 @@ clipconverter.cc
clipfish.de clipfish.de
cloud.dify.ai cloud.dify.ai
cloud.mail.ru cloud.mail.ru
cloudflare-dns.com
cloudflare-ipfs.com cloudflare-ipfs.com
cloudfunctions.net cloudfunctions.net
club1069.com club1069.com
@ -1266,6 +1270,7 @@ delicious.com
demo.unlock-music.dev demo.unlock-music.dev
democrats.org democrats.org
demosisto.hk demosisto.hk
deno.dev
depositphotos.com depositphotos.com
desc.se desc.se
desipro.de desipro.de
@ -1334,6 +1339,7 @@ dnvod.tv
doc.new doc.new
docker.com docker.com
docker.io docker.io
docs.deno.com
docs.new docs.new
doctorvoice.org doctorvoice.org
documentingreality.com documentingreality.com
@ -1856,6 +1862,7 @@ fuq.com
furbo.org furbo.org
furhhdl.org furhhdl.org
furinkan.com furinkan.com
furrybar.com
futurechinaforum.org futurechinaforum.org
futuremessage.org futuremessage.org
fux.com fux.com
@ -2366,6 +2373,7 @@ hentaivideoworld.com
heqinglian.net heqinglian.net
heritage.org heritage.org
herokuapp.com herokuapp.com
herominers.com
hexieshe.com hexieshe.com
hexieshe.xyz hexieshe.xyz
hexxeh.net hexxeh.net
@ -2662,6 +2670,7 @@ indiatoday.in
indiemerch.com indiemerch.com
inews-api.tvb.com inews-api.tvb.com
info-graf.fr info-graf.fr
infura.io
inherit.live inherit.live
initiativesforchina.org initiativesforchina.org
inkbunny.net inkbunny.net
@ -2735,9 +2744,11 @@ isupportuyghurs.org
itaiwan.gov.tw itaiwan.gov.tw
italiatibet.org italiatibet.org
itasoftware.com itasoftware.com
itch.io
itemdb.com itemdb.com
itemfix.com itemfix.com
ithelp.ithome.com.tw ithelp.ithome.com.tw
itiger.com
itsaol.com itsaol.com
itshidden.com itshidden.com
itsky.it itsky.it
@ -3086,6 +3097,7 @@ lsmwebcast.com
lsxszzg.com lsxszzg.com
ltn.com.tw ltn.com.tw
luckydesigner.space luckydesigner.space
luckymobile.ca
ludepress.com ludepress.com
luke54.com luke54.com
luke54.org luke54.org
@ -3159,6 +3171,7 @@ matters.news
matters.town matters.town
matthewdgreen.wordpress.com matthewdgreen.wordpress.com
mattwilcox.net mattwilcox.net
maven.neoforged.net
maxing.jp maxing.jp
mayimayi.com mayimayi.com
mcadforums.com mcadforums.com
@ -3207,6 +3220,7 @@ mesotw.com
messenger.com messenger.com
meta.com meta.com
metafilter.com metafilter.com
metamask.io
metart.com metart.com
metarthunter.com metarthunter.com
meteorshowersonline.com meteorshowersonline.com
@ -3429,6 +3443,7 @@ nationalreview.com
nationsonline.org nationsonline.org
nationwide.com nationwide.com
naughtyamerica.com naughtyamerica.com
naver.com
navyfamily.navy.mil navyfamily.navy.mil
navyreserve.navy.mil navyreserve.navy.mil
naweeklytimes.com naweeklytimes.com
@ -3753,6 +3768,7 @@ palacemoon.com
paljorpublications.com paljorpublications.com
paltalk.com paltalk.com
panamapapers.sueddeutsche.de panamapapers.sueddeutsche.de
pancakeswap.finance
pandafan.pub pandafan.pub
pandapow.co pandapow.co
pandapow.net pandapow.net
@ -3819,6 +3835,7 @@ periscope.tv
perplexity.ai perplexity.ai
persecutionblog.com persecutionblog.com
persiankitty.com persiankitty.com
pewresearch.org
phapluan.org phapluan.org
phayul.com phayul.com
philborges.com philborges.com
@ -3948,6 +3965,7 @@ prism-break.org
prisoneralert.com prisoneralert.com
pritunl.com pritunl.com
privacybox.de privacybox.de
privacyguides.org
private.com private.com
privateinternetaccess.com privateinternetaccess.com
privatepaste.com privatepaste.com
@ -4601,6 +4619,7 @@ suroot.com
surrenderat20.net surrenderat20.net
svsfx.com svsfx.com
swagbucks.com swagbucks.com
swapspace.co
swissinfo.ch swissinfo.ch
swissvpn.net swissvpn.net
switch1.jp switch1.jp
@ -5130,6 +5149,7 @@ uderzo.it
udn.com udn.com
udn.com.tw udn.com.tw
udnbkk.com udnbkk.com
udomain.hk
uforadio.com.tw uforadio.com.tw
ufreevpn.com ufreevpn.com
ugo.com ugo.com
@ -5170,6 +5190,7 @@ unseen.is
unstable.icu unstable.icu
unwire.hk unwire.hk
uocn.org uocn.org
upbit.com
updates.tdesktop.com updates.tdesktop.com
upghsbc.com upghsbc.com
upholdjustice.org upholdjustice.org
@ -5591,7 +5612,6 @@ www.monlamit.org
www.moztw.org www.moztw.org
www.msn.com www.msn.com
www.nbc.com www.nbc.com
www.nodeloc.com
www.owind.com www.owind.com
www.oxid.it www.oxid.it
www.powerpointninja.com www.powerpointninja.com

View File

@ -1 +1 @@
202508072216 202508212214

View File

@ -13,9 +13,8 @@ import { connect } from 'ubus';
import { cursor } from 'uci'; import { cursor } from 'uci';
import { import {
isEmpty, strToBool, strToInt, isEmpty, parseURL, strToBool, strToInt, strToTime,
removeBlankAttrs, validation, removeBlankAttrs, validation, HP_DIR, RUN_DIR
HP_DIR, RUN_DIR
} from 'homeproxy'; } from 'homeproxy';
const ubus = connect(); const ubus = connect();
@ -53,10 +52,13 @@ const dns_port = uci.get(uciconfig, uciinfra, 'dns_port') || '5333';
const ntp_server = uci.get(uciconfig, uciinfra, 'ntp_server') || 'time.apple.com'; const ntp_server = uci.get(uciconfig, uciinfra, 'ntp_server') || 'time.apple.com';
let main_node, main_udp_node, dedicated_udp_node, default_outbound, domain_strategy, sniff_override, const ipv6_support = uci.get(uciconfig, ucimain, 'ipv6_support') || '0';
dns_server, china_dns_server, dns_default_strategy, dns_default_server, dns_disable_cache,
dns_disable_cache_expire, dns_independent_cache, dns_client_subnet, cache_file_store_rdrc, let main_node, main_udp_node, dedicated_udp_node, default_outbound, default_outbound_dns,
cache_file_rdrc_timeout, direct_domain_list, proxy_domain_list; domain_strategy, sniff_override, dns_server, china_dns_server, dns_default_strategy,
dns_default_server, dns_disable_cache, dns_disable_cache_expire, dns_independent_cache,
dns_client_subnet, cache_file_store_rdrc, cache_file_rdrc_timeout, direct_domain_list,
proxy_domain_list;
if (routing_mode !== 'custom') { if (routing_mode !== 'custom') {
main_node = uci.get(uciconfig, ucimain, 'main_node') || 'nil'; main_node = uci.get(uciconfig, ucimain, 'main_node') || 'nil';
@ -72,6 +74,7 @@ if (routing_mode !== 'custom') {
if (isEmpty(china_dns_server) || type(china_dns_server) !== 'string' || china_dns_server === 'wan') if (isEmpty(china_dns_server) || type(china_dns_server) !== 'string' || china_dns_server === 'wan')
china_dns_server = wan_dns; china_dns_server = wan_dns;
} }
dns_default_strategy = (ipv6_support !== '1') ? 'ipv4_only' : null;
direct_domain_list = trim(readfile(HP_DIR + '/resources/direct_list.txt')); direct_domain_list = trim(readfile(HP_DIR + '/resources/direct_list.txt'));
if (direct_domain_list) if (direct_domain_list)
@ -95,21 +98,25 @@ if (routing_mode !== 'custom') {
/* Routing settings */ /* Routing settings */
default_outbound = uci.get(uciconfig, uciroutingsetting, 'default_outbound') || 'nil'; default_outbound = uci.get(uciconfig, uciroutingsetting, 'default_outbound') || 'nil';
default_outbound_dns = uci.get(uciconfig, uciroutingsetting, 'default_outbound_dns') || 'default-dns';
domain_strategy = uci.get(uciconfig, uciroutingsetting, 'domain_strategy'); domain_strategy = uci.get(uciconfig, uciroutingsetting, 'domain_strategy');
sniff_override = uci.get(uciconfig, uciroutingsetting, 'sniff_override'); sniff_override = uci.get(uciconfig, uciroutingsetting, 'sniff_override');
} }
const proxy_mode = uci.get(uciconfig, ucimain, 'proxy_mode') || 'redirect_tproxy', const proxy_mode = uci.get(uciconfig, ucimain, 'proxy_mode') || 'redirect_tproxy',
ipv6_support = uci.get(uciconfig, ucimain, 'ipv6_support') || '0',
default_interface = uci.get(uciconfig, ucicontrol, 'bind_interface'); default_interface = uci.get(uciconfig, ucicontrol, 'bind_interface');
const mixed_port = uci.get(uciconfig, uciinfra, 'mixed_port') || '5330'; const mixed_port = uci.get(uciconfig, uciinfra, 'mixed_port') || '5330';
let self_mark, redirect_port, tproxy_port,
tun_name, tun_addr4, tun_addr6, tun_mtu, let self_mark, redirect_port, tproxy_port, tun_name,
tcpip_stack, endpoint_independent_nat, udp_timeout; tun_addr4, tun_addr6, tun_mtu, tcpip_stack,
udp_timeout = uci.get(uciconfig, 'infra', 'udp_timeout'); endpoint_independent_nat, udp_timeout;
if (routing_mode === 'custom') if (routing_mode === 'custom')
udp_timeout = uci.get(uciconfig, uciroutingsetting, 'udp_timeout'); udp_timeout = uci.get(uciconfig, uciroutingsetting, 'udp_timeout');
else
udp_timeout = uci.get(uciconfig, 'infra', 'udp_timeout');
if (match(proxy_mode, /redirect/)) { if (match(proxy_mode, /redirect/)) {
self_mark = uci.get(uciconfig, 'infra', 'self_mark') || '100'; self_mark = uci.get(uciconfig, 'infra', 'self_mark') || '100';
redirect_port = uci.get(uciconfig, 'infra', 'redirect_port') || '5331'; redirect_port = uci.get(uciconfig, 'infra', 'redirect_port') || '5331';
@ -143,6 +150,22 @@ function parse_port(strport) {
} }
function parse_dnserver(server_addr, default_protocol) {
if (isEmpty(server_addr))
return null;
if (!match(server_addr, /:\/\//))
server_addr = (default_protocol || 'udp') + '://' + server_addr;
server_addr = parseURL(server_addr);
return {
type: server_addr.protocol,
server: server_addr.hostname,
server_port: strToInt(server_addr.port),
path: (server_addr.pathname !== '/') ? server_addr.pathname : null,
}
}
function parse_dnsquery(strquery) { function parse_dnsquery(strquery) {
if (type(strquery) !== 'array' || isEmpty(strquery)) if (type(strquery) !== 'array' || isEmpty(strquery))
return null; return null;
@ -210,8 +233,12 @@ function generate_outbound(node) {
override_address: node.override_address, override_address: node.override_address,
override_port: strToInt(node.override_port), override_port: strToInt(node.override_port),
proxy_protocol: strToInt(node.proxy_protocol), proxy_protocol: strToInt(node.proxy_protocol),
/* AnyTLS */
idle_session_check_interval: strToTime(node.anytls_idle_session_check_interval),
idle_session_timeout: strToTime(node.anytls_idle_session_timeout),
min_idle_session: strToInt(node.anytls_min_idle_session),
/* Hysteria (2) */ /* Hysteria (2) */
hop_interval: node.hysteria_hop_interval ? (node.hysteria_hop_interval + 's') : null, hop_interval: strToTime(node.hysteria_hop_interval),
up_mbps: strToInt(node.hysteria_up_mbps), up_mbps: strToInt(node.hysteria_up_mbps),
down_mbps: strToInt(node.hysteria_down_mbps), down_mbps: strToInt(node.hysteria_down_mbps),
obfs: node.hysteria_obfs_type ? { obfs: node.hysteria_obfs_type ? {
@ -241,13 +268,13 @@ function generate_outbound(node) {
udp_relay_mode: node.tuic_udp_relay_mode, udp_relay_mode: node.tuic_udp_relay_mode,
udp_over_stream: strToBool(node.tuic_udp_over_stream), udp_over_stream: strToBool(node.tuic_udp_over_stream),
zero_rtt_handshake: strToBool(node.tuic_enable_zero_rtt), zero_rtt_handshake: strToBool(node.tuic_enable_zero_rtt),
heartbeat: node.tuic_heartbeat ? (node.tuic_heartbeat + 's') : null, heartbeat: strToTime(node.tuic_heartbeat),
/* VLESS / VMess */ /* VLESS / VMess */
flow: node.vless_flow, flow: node.vless_flow,
alter_id: strToInt(node.vmess_alterid), alter_id: strToInt(node.vmess_alterid),
security: node.vmess_encrypt, security: node.vmess_encrypt,
global_padding: node.vmess_global_padding ? (node.vmess_global_padding === '1') : null, global_padding: strToBool(node.vmess_global_padding),
authenticated_length: node.vmess_authenticated_length ? (node.vmess_authenticated_length === '1') : null, authenticated_length: strToBool(node.vmess_authenticated_length),
packet_encoding: node.packet_encoding, packet_encoding: node.packet_encoding,
multiplex: (node.multiplex === '1') ? { multiplex: (node.multiplex === '1') ? {
@ -256,7 +283,7 @@ function generate_outbound(node) {
max_connections: strToInt(node.multiplex_max_connections), max_connections: strToInt(node.multiplex_max_connections),
min_streams: strToInt(node.multiplex_min_streams), min_streams: strToInt(node.multiplex_min_streams),
max_streams: strToInt(node.multiplex_max_streams), max_streams: strToInt(node.multiplex_max_streams),
padding: (node.multiplex_padding === '1'), padding: strToBool(node.multiplex_padding),
brutal: (node.multiplex_brutal === '1') ? { brutal: (node.multiplex_brutal === '1') ? {
enabled: true, enabled: true,
up_mbps: strToInt(node.multiplex_brutal_up), up_mbps: strToInt(node.multiplex_brutal_up),
@ -266,7 +293,7 @@ function generate_outbound(node) {
tls: (node.tls === '1') ? { tls: (node.tls === '1') ? {
enabled: true, enabled: true,
server_name: node.tls_sni, server_name: node.tls_sni,
insecure: (node.tls_insecure === '1'), insecure: strToBool(node.tls_insecure),
alpn: node.tls_alpn, alpn: node.tls_alpn,
min_version: node.tls_min_version, min_version: node.tls_min_version,
max_version: node.tls_max_version, max_version: node.tls_max_version,
@ -274,7 +301,7 @@ function generate_outbound(node) {
certificate_path: node.tls_cert_path, certificate_path: node.tls_cert_path,
ech: (node.tls_ech === '1') ? { ech: (node.tls_ech === '1') ? {
enabled: true, enabled: true,
pq_signature_schemes_enabled: (node.tls_ech_enable_pqss === '1'), pq_signature_schemes_enabled: strToBool(node.tls_ech_enable_pqss),
config: node.tls_ech_config, config: node.tls_ech_config,
config_path: node.tls_ech_config_path config_path: node.tls_ech_config_path
} : null, } : null,
@ -299,8 +326,8 @@ function generate_outbound(node) {
max_early_data: strToInt(node.websocket_early_data), max_early_data: strToInt(node.websocket_early_data),
early_data_header_name: node.websocket_early_data_header, early_data_header_name: node.websocket_early_data_header,
service_name: node.grpc_servicename, service_name: node.grpc_servicename,
idle_timeout: node.http_idle_timeout ? (node.http_idle_timeout + 's') : null, idle_timeout: (node.http_idle_timeout),
ping_timeout: node.http_ping_timeout ? (node.http_ping_timeout + 's') : null, ping_timeout: (node.http_ping_timeout),
permit_without_stream: strToBool(node.grpc_permit_without_stream) permit_without_stream: strToBool(node.grpc_permit_without_stream)
} : null, } : null,
udp_over_tcp: (node.udp_over_tcp === '1') ? { udp_over_tcp: (node.udp_over_tcp === '1') ? {
@ -349,7 +376,6 @@ function get_resolver(cfg) {
return null; return null;
switch (cfg) { switch (cfg) {
case 'block-dns':
case 'default-dns': case 'default-dns':
case 'system-dns': case 'system-dns':
return cfg; return cfg;
@ -384,8 +410,7 @@ config.ntp = {
enabled: true, enabled: true,
server: ntp_server, server: ntp_server,
detour: 'direct-out', detour: 'direct-out',
/* TODO: disable this until we have sing-box 1.12 */ domain_resolver: 'default-dns',
/* domain_resolver: 'default-dns', */
}; };
/* DNS start */ /* DNS start */
@ -394,32 +419,21 @@ config.dns = {
servers: [ servers: [
{ {
tag: 'default-dns', tag: 'default-dns',
address: wan_dns, type: 'udp',
server: wan_dns,
detour: 'direct-out' detour: 'direct-out'
}, },
{ {
tag: 'system-dns', tag: 'system-dns',
address: 'local', type: 'local',
detour: 'direct-out' detour: 'direct-out'
},
{
tag: 'block-dns',
address: 'rcode://refused'
}
],
rules: [
/* TODO: remove this once we have sing-box 1.12 */
/* NTP domain must be resolved by default DNS */
{
domain: ntp_server,
action: 'route',
server: 'default-dns'
} }
], ],
rules: [],
strategy: dns_default_strategy, strategy: dns_default_strategy,
disable_cache: (dns_disable_cache === '1'), disable_cache: strToBool(dns_disable_cache),
disable_expire: (dns_disable_cache_expire === '1'), disable_expire: strToBool(dns_disable_cache_expire),
independent_cache: (dns_independent_cache === '1'), independent_cache: strToBool(dns_independent_cache),
client_subnet: dns_client_subnet client_subnet: dns_client_subnet
}; };
@ -427,21 +441,15 @@ if (!isEmpty(main_node)) {
/* Main DNS */ /* Main DNS */
push(config.dns.servers, { push(config.dns.servers, {
tag: 'main-dns', tag: 'main-dns',
address: !match(dns_server, /:\/\//) ? 'tcp://' + (validation('ip6addr', dns_server) ? `[${dns_server}]` : dns_server) : dns_server, domain_resolver: {
strategy: (ipv6_support !== '1') ? 'ipv4_only' : null, server: 'default-dns',
address_resolver: 'default-dns', strategy: (ipv6_support !== '1') ? 'ipv4_only' : null
address_strategy: (ipv6_support !== '1') ? 'ipv4_only' : null, },
detour: 'main-out' detour: 'main-out',
...parse_dnserver(dns_server, 'tcp')
}); });
config.dns.final = 'main-dns'; config.dns.final = 'main-dns';
/* Avoid DNS loop */
push(config.dns.rules, {
outbound: 'any',
action: 'route',
server: 'default-dns'
});
if (length(direct_domain_list)) if (length(direct_domain_list))
push(config.dns.rules, { push(config.dns.rules, {
rule_set: 'direct-domain', rule_set: 'direct-domain',
@ -460,9 +468,12 @@ if (!isEmpty(main_node)) {
if (routing_mode === 'bypass_mainland_china') { if (routing_mode === 'bypass_mainland_china') {
push(config.dns.servers, { push(config.dns.servers, {
tag: 'china-dns', tag: 'china-dns',
address: china_dns_server, domain_resolver: {
address_resolver: 'default-dns', server: 'default-dns',
detour: 'direct-out' strategy: 'prefer_ipv6'
},
detour: 'direct-out',
...parse_dnserver(china_dns_server)
}); });
if (length(proxy_domain_list)) if (length(proxy_domain_list))
@ -475,7 +486,8 @@ if (!isEmpty(main_node)) {
push(config.dns.rules, { push(config.dns.rules, {
rule_set: 'geosite-cn', rule_set: 'geosite-cn',
action: 'route', action: 'route',
server: 'china-dns' server: 'china-dns',
strategy: 'prefer_ipv6'
}); });
push(config.dns.rules, { push(config.dns.rules, {
type: 'logical', type: 'logical',
@ -490,7 +502,8 @@ if (!isEmpty(main_node)) {
} }
], ],
action: 'route', action: 'route',
server: 'china-dns' server: 'china-dns',
strategy: 'prefer_ipv6'
}); });
} }
} else if (!isEmpty(default_outbound)) { } else if (!isEmpty(default_outbound)) {
@ -501,13 +514,20 @@ if (!isEmpty(main_node)) {
push(config.dns.servers, { push(config.dns.servers, {
tag: 'cfg-' + cfg['.name'] + '-dns', tag: 'cfg-' + cfg['.name'] + '-dns',
address: cfg.address, type: cfg.type,
address: cfg.address, server: cfg.server,
address_resolver: get_resolver(cfg.address_resolver), server_port: strToInt(cfg.server_port),
address_strategy: cfg.address_strategy, path: cfg.path,
strategy: cfg.resolve_strategy, headers: cfg.headers,
detour: get_outbound(cfg.outbound), tls: cfg.tls_sni ? {
client_subnet: cfg.client_subnet enabled: true,
server_name: cfg.tls_sni
} : null,
domain_resolver: {
server: get_resolver(cfg.address_resolver),
strategy: cfg.address_strategy
},
detour: get_outbound(cfg.outbound)
}); });
}); });
@ -528,9 +548,9 @@ if (!isEmpty(main_node)) {
port: parse_port(cfg.port), port: parse_port(cfg.port),
port_range: cfg.port_range, port_range: cfg.port_range,
source_ip_cidr: cfg.source_ip_cidr, source_ip_cidr: cfg.source_ip_cidr,
source_ip_is_private: (cfg.source_ip_is_private === '1') || null, source_ip_is_private: strToBool(cfg.source_ip_is_private),
ip_cidr: cfg.ip_cidr, ip_cidr: cfg.ip_cidr,
ip_is_private: (cfg.ip_is_private === '1') || null, ip_is_private: strToBool(cfg.ip_is_private),
source_port: parse_port(cfg.source_port), source_port: parse_port(cfg.source_port),
source_port_range: cfg.source_port_range, source_port_range: cfg.source_port_range,
process_name: cfg.process_name, process_name: cfg.process_name,
@ -538,15 +558,21 @@ if (!isEmpty(main_node)) {
process_path_regex: cfg.process_path_regex, process_path_regex: cfg.process_path_regex,
user: cfg.user, user: cfg.user,
rule_set: get_ruleset(cfg.rule_set), rule_set: get_ruleset(cfg.rule_set),
rule_set_ip_cidr_match_source: (cfg.rule_set_ip_cidr_match_source === '1') || null, rule_set_ip_cidr_match_source: strToBool(cfg.rule_set_ip_cidr_match_source),
invert: (cfg.invert === '1') || null, invert: strToBool(cfg.invert),
outbound: get_outbound(cfg.outbound), outbound: get_outbound(cfg.outbound),
action: (cfg.server === 'block-dns') ? 'reject' : 'route', action: cfg.action,
server: get_resolver(cfg.server), server: get_resolver(cfg.server),
disable_cache: (cfg.dns_disable_cache === '1') || null, strategy: cfg.domain_strategy,
disable_cache: strToBool(cfg.dns_disable_cache),
rewrite_ttl: strToInt(cfg.rewrite_ttl), rewrite_ttl: strToInt(cfg.rewrite_ttl),
client_subnet: cfg.client_subnet client_subnet: cfg.client_subnet,
method: cfg.reject_method,
no_drop: strToBool(cfg.reject_no_drop),
rcode: cfg.predefined_rcode,
answer: cfg.predefined_answer,
ns: cfg.predefined_ns,
extra: cfg.predefined_extra
}); });
}); });
@ -572,9 +598,9 @@ push(config.inbounds, {
tag: 'mixed-in', tag: 'mixed-in',
listen: '::', listen: '::',
listen_port: int(mixed_port), listen_port: int(mixed_port),
udp_timeout: udp_timeout ? (udp_timeout + 's') : null, udp_timeout: strToTime(udp_timeout),
sniff: true, sniff: true,
sniff_override_destination: (sniff_override === '1'), sniff_override_destination: strToBool(sniff_override),
set_system_proxy: false set_system_proxy: false
}); });
@ -586,7 +612,7 @@ if (match(proxy_mode, /redirect/))
listen: '::', listen: '::',
listen_port: int(redirect_port), listen_port: int(redirect_port),
sniff: true, sniff: true,
sniff_override_destination: (sniff_override === '1') sniff_override_destination: strToBool(sniff_override)
}); });
if (match(proxy_mode, /tproxy/)) if (match(proxy_mode, /tproxy/))
push(config.inbounds, { push(config.inbounds, {
@ -596,9 +622,9 @@ if (match(proxy_mode, /tproxy/))
listen: '::', listen: '::',
listen_port: int(tproxy_port), listen_port: int(tproxy_port),
network: 'udp', network: 'udp',
udp_timeout: udp_timeout ? (udp_timeout + 's') : null, udp_timeout: strToTime(udp_timeout),
sniff: true, sniff: true,
sniff_override_destination: (sniff_override === '1') sniff_override_destination: strToBool(sniff_override)
}); });
if (match(proxy_mode, /tun/)) if (match(proxy_mode, /tun/))
push(config.inbounds, { push(config.inbounds, {
@ -610,10 +636,10 @@ if (match(proxy_mode, /tun/))
mtu: strToInt(tun_mtu), mtu: strToInt(tun_mtu),
auto_route: false, auto_route: false,
endpoint_independent_nat: strToBool(endpoint_independent_nat), endpoint_independent_nat: strToBool(endpoint_independent_nat),
udp_timeout: udp_timeout ? (udp_timeout + 's') : null, udp_timeout: strToTime(udp_timeout),
stack: tcpip_stack, stack: tcpip_stack,
sniff: true, sniff: true,
sniff_override_destination: (sniff_override === '1') sniff_override_destination: strToBool(sniff_override)
}); });
/* Inbound end */ /* Inbound end */
@ -646,7 +672,7 @@ if (!isEmpty(main_node)) {
type: 'urltest', type: 'urltest',
tag: 'main-out', tag: 'main-out',
outbounds: map(main_urltest_nodes, (k) => `cfg-${k}-out`), outbounds: map(main_urltest_nodes, (k) => `cfg-${k}-out`),
interval: main_urltest_interval ? (main_urltest_interval + 's') : null, interval: strToTime(main_urltest_interval),
tolerance: strToInt(main_urltest_tolerance), tolerance: strToInt(main_urltest_tolerance),
idle_timeout: (strToInt(main_urltest_interval) > 1800) ? `${main_urltest_interval * 2}s` : null, idle_timeout: (strToInt(main_urltest_interval) > 1800) ? `${main_urltest_interval * 2}s` : null,
}); });
@ -658,7 +684,6 @@ if (!isEmpty(main_node)) {
config.endpoints[length(config.endpoints)-1].tag = 'main-out'; config.endpoints[length(config.endpoints)-1].tag = 'main-out';
} else { } else {
push(config.outbounds, generate_outbound(main_node_cfg)); push(config.outbounds, generate_outbound(main_node_cfg));
config.outbounds[length(config.outbounds)-1].domain_strategy = (ipv6_support !== '1') ? 'prefer_ipv4' : null;
config.outbounds[length(config.outbounds)-1].tag = 'main-out'; config.outbounds[length(config.outbounds)-1].tag = 'main-out';
} }
} }
@ -672,7 +697,7 @@ if (!isEmpty(main_node)) {
type: 'urltest', type: 'urltest',
tag: 'main-udp-out', tag: 'main-udp-out',
outbounds: map(main_udp_urltest_nodes, (k) => `cfg-${k}-out`), outbounds: map(main_udp_urltest_nodes, (k) => `cfg-${k}-out`),
interval: main_udp_urltest_interval ? (main_udp_urltest_interval + 's') : null, interval: strToTime(main_udp_urltest_interval),
tolerance: strToInt(main_udp_urltest_tolerance), tolerance: strToInt(main_udp_urltest_tolerance),
idle_timeout: (strToInt(main_udp_urltest_interval) > 1800) ? `${main_udp_urltest_interval * 2}s` : null, idle_timeout: (strToInt(main_udp_urltest_interval) > 1800) ? `${main_udp_urltest_interval * 2}s` : null,
}); });
@ -681,11 +706,9 @@ if (!isEmpty(main_node)) {
const main_udp_node_cfg = uci.get_all(uciconfig, main_udp_node) || {}; const main_udp_node_cfg = uci.get_all(uciconfig, main_udp_node) || {};
if (main_udp_node_cfg.type === 'wireguard') { if (main_udp_node_cfg.type === 'wireguard') {
push(config.endpoints, generate_endpoint(main_udp_node_cfg)); push(config.endpoints, generate_endpoint(main_udp_node_cfg));
config.endpoints[length(config.endpoints)-1].domain_strategy = (ipv6_support !== '1') ? 'prefer_ipv4' : null;
config.endpoints[length(config.endpoints)-1].tag = 'main-udp-out'; config.endpoints[length(config.endpoints)-1].tag = 'main-udp-out';
} else { } else {
push(config.outbounds, generate_outbound(main_udp_node_cfg)); push(config.outbounds, generate_outbound(main_udp_node_cfg));
config.outbounds[length(config.outbounds)-1].domain_strategy = (ipv6_support !== '1') ? 'prefer_ipv4' : null;
config.outbounds[length(config.outbounds)-1].tag = 'main-udp-out'; config.outbounds[length(config.outbounds)-1].tag = 'main-udp-out';
} }
} }
@ -694,11 +717,9 @@ if (!isEmpty(main_node)) {
const urltest_node = uci.get_all(uciconfig, i) || {}; const urltest_node = uci.get_all(uciconfig, i) || {};
if (urltest_node.type === 'wireguard') { if (urltest_node.type === 'wireguard') {
push(config.endpoints, generate_endpoint(urltest_node)); push(config.endpoints, generate_endpoint(urltest_node));
config.endpoints[length(config.endpoints)-1].domain_strategy = (ipv6_support !== '1') ? 'prefer_ipv4' : null;
config.endpoints[length(config.endpoints)-1].tag = 'cfg-' + i + '-out'; config.endpoints[length(config.endpoints)-1].tag = 'cfg-' + i + '-out';
} else { } else {
push(config.outbounds, generate_outbound(urltest_node)); push(config.outbounds, generate_outbound(urltest_node));
config.outbounds[length(config.outbounds)-1].domain_strategy = (ipv6_support !== '1') ? 'prefer_ipv4' : null;
config.outbounds[length(config.outbounds)-1].tag = 'cfg-' + i + '-out'; config.outbounds[length(config.outbounds)-1].tag = 'cfg-' + i + '-out';
} }
} }
@ -716,24 +737,32 @@ if (!isEmpty(main_node)) {
tag: 'cfg-' + cfg['.name'] + '-out', tag: 'cfg-' + cfg['.name'] + '-out',
outbounds: map(cfg.urltest_nodes, (k) => `cfg-${k}-out`), outbounds: map(cfg.urltest_nodes, (k) => `cfg-${k}-out`),
url: cfg.urltest_url, url: cfg.urltest_url,
interval: cfg.urltest_interval ? (cfg.urltest_interval + 's') : null, interval: strToTime(cfg.urltest_interval),
tolerance: strToInt(cfg.urltest_tolerance), tolerance: strToInt(cfg.urltest_tolerance),
idle_timeout: cfg.urltest_idle_timeout ? (cfg.urltest_idle_timeout + 's') : null, idle_timeout: strToTime(cfg.urltest_idle_timeout),
interrupt_exist_connections: (cfg.urltest_interrupt_exist_connections === '1') interrupt_exist_connections: strToBool(cfg.urltest_interrupt_exist_connections)
}); });
urltest_nodes = [...urltest_nodes, ...filter(cfg.urltest_nodes, (l) => !~index(urltest_nodes, l))]; urltest_nodes = [...urltest_nodes, ...filter(cfg.urltest_nodes, (l) => !~index(urltest_nodes, l))];
} else { } else {
const outbound = uci.get_all(uciconfig, cfg.node) || {}; const outbound = uci.get_all(uciconfig, cfg.node) || {};
if (outbound.type === 'wireguard') { if (outbound.type === 'wireguard') {
push(config.endpoints, generate_endpoint(outbound)); push(config.endpoints, generate_endpoint(outbound));
config.endpoints[length(config.endpoints)-1].domain_strategy = cfg.domain_strategy;
config.endpoints[length(config.endpoints)-1].bind_interface = cfg.bind_interface; config.endpoints[length(config.endpoints)-1].bind_interface = cfg.bind_interface;
config.endpoints[length(config.endpoints)-1].detour = get_outbound(cfg.outbound); config.endpoints[length(config.endpoints)-1].detour = get_outbound(cfg.outbound);
if (cfg.domain_resolver || cfg.domain_strategy)
config.endpoints[length(config.endpoints)-1].domain_resolver = {
server: get_resolver(cfg.domain_resolver || default_outbound_dns),
strategy: cfg.domain_strategy
};
} else { } else {
push(config.outbounds, generate_outbound(outbound)); push(config.outbounds, generate_outbound(outbound));
config.outbounds[length(config.outbounds)-1].domain_strategy = cfg.domain_strategy;
config.outbounds[length(config.outbounds)-1].bind_interface = cfg.bind_interface; config.outbounds[length(config.outbounds)-1].bind_interface = cfg.bind_interface;
config.outbounds[length(config.outbounds)-1].detour = get_outbound(cfg.outbound); config.outbounds[length(config.outbounds)-1].detour = get_outbound(cfg.outbound);
if (cfg.domain_resolver || cfg.domain_strategy)
config.outbounds[length(config.outbounds)-1].domain_resolver = {
server: get_resolver(cfg.domain_resolver || default_outbound_dns),
strategy: cfg.domain_strategy
};
} }
push(routing_nodes, cfg.node); push(routing_nodes, cfg.node);
} }
@ -774,6 +803,13 @@ config.route = {
/* Routing rules */ /* Routing rules */
if (!isEmpty(main_node)) { if (!isEmpty(main_node)) {
/* Avoid DNS loop */
config.route.default_domain_resolver = {
action: 'route',
server: 'default-dns',
strategy: (ipv6_support !== '1') ? 'prefer_ipv4' : null
};
/* Direct list */ /* Direct list */
if (length(direct_domain_list)) if (length(direct_domain_list))
push(config.route.rules, { push(config.route.rules, {
@ -844,6 +880,11 @@ if (!isEmpty(main_node)) {
if (isEmpty(config.route.rule_set)) if (isEmpty(config.route.rule_set))
config.route.rule_set = null; config.route.rule_set = null;
} else if (!isEmpty(default_outbound)) { } else if (!isEmpty(default_outbound)) {
config.route.default_domain_resolver = {
action: 'resolve',
server: get_resolver(default_outbound_dns)
};
if (domain_strategy) if (domain_strategy)
push(config.route.rules, { push(config.route.rules, {
action: 'resolve', action: 'resolve',
@ -863,9 +904,9 @@ if (!isEmpty(main_node)) {
domain_keyword: cfg.domain_keyword, domain_keyword: cfg.domain_keyword,
domain_regex: cfg.domain_regex, domain_regex: cfg.domain_regex,
source_ip_cidr: cfg.source_ip_cidr, source_ip_cidr: cfg.source_ip_cidr,
source_ip_is_private: (cfg.source_ip_is_private === '1') || null, source_ip_is_private: strToBool(cfg.source_ip_is_private),
ip_cidr: cfg.ip_cidr, ip_cidr: cfg.ip_cidr,
ip_is_private: (cfg.ip_is_private === '1') || null, ip_is_private: strToBool(cfg.ip_is_private),
source_port: parse_port(cfg.source_port), source_port: parse_port(cfg.source_port),
source_port_range: cfg.source_port_range, source_port_range: cfg.source_port_range,
port: parse_port(cfg.port), port: parse_port(cfg.port),
@ -875,13 +916,19 @@ if (!isEmpty(main_node)) {
process_path_regex: cfg.process_path_regex, process_path_regex: cfg.process_path_regex,
user: cfg.user, user: cfg.user,
rule_set: get_ruleset(cfg.rule_set), rule_set: get_ruleset(cfg.rule_set),
rule_set_ip_cidr_match_source: (cfg.rule_set_ip_cidr_match_source === '1') || null, rule_set_ip_cidr_match_source: strToBool(cfg.rule_set_ip_cidr_match_source),
rule_set_ip_cidr_accept_empty: (cfg.rule_set_ip_cidr_accept_empty === '1') || null, rule_set_ip_cidr_accept_empty: strToBool(cfg.rule_set_ip_cidr_accept_empty),
invert: (cfg.invert === '1') || null, invert: strToBool(cfg.invert),
action: (cfg.outbound === 'block-out') ? 'reject' : 'route', action: cfg.action,
outbound: get_outbound(cfg.outbound),
override_address: cfg.override_address, override_address: cfg.override_address,
override_port: strToInt(cfg.override_port), override_port: strToInt(cfg.override_port),
outbound: get_outbound(cfg.outbound), udp_disable_domain_unmapping: strToBool(cfg.udp_disable_domain_unmapping),
udp_connect: strToBool(cfg.udp_connect),
udp_timeout: strToTime(cfg.udp_timeout),
tls_fragment: strToBool(cfg.tls_fragment),
tls_fragment_fallback_delay: strToTime(cfg.tls_fragment_fallback_delay),
tls_record_fragment: strToBool(cfg.tls_record_fragment)
}); });
}); });
@ -911,8 +958,8 @@ if (routing_mode in ['bypass_mainland_china', 'custom']) {
cache_file: { cache_file: {
enabled: true, enabled: true,
path: RUN_DIR + '/cache.db', path: RUN_DIR + '/cache.db',
store_rdrc: (cache_file_store_rdrc === '1') || null, store_rdrc: strToBool(cache_file_store_rdrc),
rdrc_timeout: cache_file_rdrc_timeout ? (cache_file_rdrc_timeout + 's') : null, rdrc_timeout: strToTime(cache_file_rdrc_timeout),
} }
}; };
} }

View File

@ -11,7 +11,7 @@ import { writefile } from 'fs';
import { cursor } from 'uci'; import { cursor } from 'uci';
import { import {
isEmpty, strToBool, strToInt, isEmpty, strToBool, strToInt, strToTime,
removeBlankAttrs, HP_DIR, RUN_DIR removeBlankAttrs, HP_DIR, RUN_DIR
} from 'homeproxy'; } from 'homeproxy';
@ -45,12 +45,17 @@ uci.foreach(uciconfig, uciserver, (cfg) => {
listen: cfg.address || '::', listen: cfg.address || '::',
listen_port: strToInt(cfg.port), listen_port: strToInt(cfg.port),
bind_interface: cfg.bind_interface,
reuse_addr: strToBool(cfg.reuse_addr),
tcp_fast_open: strToBool(cfg.tcp_fast_open), tcp_fast_open: strToBool(cfg.tcp_fast_open),
tcp_multi_path: strToBool(cfg.tcp_multi_path), tcp_multi_path: strToBool(cfg.tcp_multi_path),
udp_fragment: strToBool(cfg.udp_fragment), udp_fragment: strToBool(cfg.udp_fragment),
udp_timeout: cfg.udp_timeout ? (cfg.udp_timeout + 's') : null, udp_timeout: strToTime(cfg.udp_timeout),
network: cfg.network, network: cfg.network,
/* AnyTLS */
padding_scheme: cfg.anytls_padding_scheme,
/* Hysteria */ /* Hysteria */
up_mbps: strToInt(cfg.hysteria_up_mbps), up_mbps: strToInt(cfg.hysteria_up_mbps),
down_mbps: strToInt(cfg.hysteria_down_mbps), down_mbps: strToInt(cfg.hysteria_down_mbps),
@ -71,11 +76,11 @@ uci.foreach(uciconfig, uciserver, (cfg) => {
/* Tuic */ /* Tuic */
congestion_control: cfg.tuic_congestion_control, congestion_control: cfg.tuic_congestion_control,
auth_timeout: cfg.tuic_auth_timeout ? (cfg.tuic_auth_timeout + 's') : null, auth_timeout: strToTime(cfg.tuic_auth_timeout),
zero_rtt_handshake: strToBool(cfg.tuic_enable_zero_rtt), zero_rtt_handshake: strToBool(cfg.tuic_enable_zero_rtt),
heartbeat: cfg.tuic_heartbeat ? (cfg.tuic_heartbeat + 's') : null, heartbeat: strToTime(cfg.tuic_heartbeat),
/* HTTP / Hysteria (2) / Mixed / Socks / Trojan / Tuic / VLESS / VMess */ /* AnyTLS / HTTP / Hysteria (2) / Mixed / Socks / Trojan / Tuic / VLESS / VMess */
users: (cfg.type !== 'shadowsocks') ? [ users: (cfg.type !== 'shadowsocks') ? [
{ {
name: !(cfg.type in ['http', 'mixed', 'naive', 'socks']) ? 'cfg-' + cfg['.name'] + '-server' : null, name: !(cfg.type in ['http', 'mixed', 'naive', 'socks']) ? 'cfg-' + cfg['.name'] + '-server' : null,
@ -97,7 +102,7 @@ uci.foreach(uciconfig, uciserver, (cfg) => {
multiplex: (cfg.multiplex === '1') ? { multiplex: (cfg.multiplex === '1') ? {
enabled: true, enabled: true,
padding: (cfg.multiplex_padding === '1'), padding: strToBool(cfg.multiplex_padding),
brutal: (cfg.multiplex_brutal === '1') ? { brutal: (cfg.multiplex_brutal === '1') ? {
enabled: true, enabled: true,
up_mbps: strToInt(cfg.multiplex_brutal_up), up_mbps: strToInt(cfg.multiplex_brutal_up),
@ -120,8 +125,8 @@ uci.foreach(uciconfig, uciserver, (cfg) => {
default_server_name: cfg.tls_acme_dsn, default_server_name: cfg.tls_acme_dsn,
email: cfg.tls_acme_email, email: cfg.tls_acme_email,
provider: cfg.tls_acme_provider, provider: cfg.tls_acme_provider,
disable_http_challenge: (cfg.tls_acme_dhc === '1'), disable_http_challenge: strToBool(cfg.tls_acme_dhc),
disable_tls_alpn_challenge: (cfg.tls_acme_dtac === '1'), disable_tls_alpn_challenge: (cfg.tls_acme_dtac),
alternative_http_port: strToInt(cfg.tls_acme_ahp), alternative_http_port: strToInt(cfg.tls_acme_ahp),
alternative_tls_port: strToInt(cfg.tls_acme_atp), alternative_tls_port: strToInt(cfg.tls_acme_atp),
external_account: (cfg.tls_acme_external_account === '1') ? { external_account: (cfg.tls_acme_external_account === '1') ? {
@ -145,7 +150,7 @@ uci.foreach(uciconfig, uciserver, (cfg) => {
enabled: true, enabled: true,
private_key: cfg.tls_reality_private_key, private_key: cfg.tls_reality_private_key,
short_id: cfg.tls_reality_short_id, short_id: cfg.tls_reality_short_id,
max_time_difference: cfg.tls_reality_max_time_difference ? (cfg.max_time_difference + 's') : null, max_time_difference: strToTime(cfg.tls_reality_max_time_difference),
handshake: { handshake: {
server: cfg.tls_reality_server_addr, server: cfg.tls_reality_server_addr,
server_port: strToInt(cfg.tls_reality_server_port) server_port: strToInt(cfg.tls_reality_server_port)
@ -164,8 +169,8 @@ uci.foreach(uciconfig, uciserver, (cfg) => {
max_early_data: strToInt(cfg.websocket_early_data), max_early_data: strToInt(cfg.websocket_early_data),
early_data_header_name: cfg.websocket_early_data_header, early_data_header_name: cfg.websocket_early_data_header,
service_name: cfg.grpc_servicename, service_name: cfg.grpc_servicename,
idle_timeout: cfg.http_idle_timeout ? (cfg.http_idle_timeout + 's') : null, idle_timeout: strToTime(cfg.http_idle_timeout),
ping_timeout: cfg.http_ping_timeout ? (cfg.http_ping_timeout + 's') : null ping_timeout: strToTime(cfg.http_ping_timeout)
} : null } : null
}); });
}); });

View File

@ -52,14 +52,6 @@ export function executeCommand(...args) {
}; };
}; };
export function calcStringMD5(str) {
if (!str || type(str) !== 'string')
return null;
const output = executeCommand(`/bin/echo -n ${shellQuote(str)} | /usr/bin/md5sum | /usr/bin/awk '{print $1}'`) || {};
return trim(output.stdout);
};
export function getTime(epoch) { export function getTime(epoch) {
const local_time = localtime(epoch); const local_time = localtime(epoch);
return replace(replace(sprintf( return replace(replace(sprintf(
@ -99,6 +91,10 @@ export function strToInt(str) {
return !isEmpty(str) ? (int(str) || null) : null; return !isEmpty(str) ? (int(str) || null) : null;
}; };
export function strToTime(str) {
return str ? (str + 's') : null;
};
export function removeBlankAttrs(res) { export function removeBlankAttrs(res) {
let content; let content;

View File

@ -8,7 +8,7 @@
'use strict'; 'use strict';
import { cursor } from 'uci'; import { cursor } from 'uci';
import { isEmpty } from 'homeproxy'; import { isEmpty, parseURL } from 'homeproxy';
const uci = cursor(); const uci = cursor();
@ -20,6 +20,7 @@ const uciinfra = 'infra',
ucimain = 'config', ucimain = 'config',
ucinode = 'node', ucinode = 'node',
ucidns = 'dns', ucidns = 'dns',
ucidnsserver = 'dns_server',
ucidnsrule = 'dns_rule', ucidnsrule = 'dns_rule',
ucirouting = 'routing', ucirouting = 'routing',
uciroutingnode = 'routing_node', uciroutingnode = 'routing_node',
@ -72,11 +73,122 @@ if (uci.get(uciconfig, ucimain, 'routing_port') === 'all')
if (uci.get(uciconfig, 'experimental')) if (uci.get(uciconfig, 'experimental'))
uci.delete(uciconfig, 'experimental'); uci.delete(uciconfig, 'experimental');
/* block-dns was removed from built-in dns servers */
const default_dns_server = uci.get(uciconfig, ucidns, 'default_server');
if (default_dns_server === 'block-dns') {
/* append a rule at last to block all DNS queries */
uci.set(uciconfig, '_migration_dns_final_block', ucidnsrule);
uci.set(uciconfig, '_migration_dns_final_block', 'label', 'migration_final_block_dns');
uci.set(uciconfig, '_migration_dns_final_block', 'enabled', '1');
uci.set(uciconfig, '_migration_dns_final_block', 'mode', 'default');
uci.set(uciconfig, '_migration_dns_final_block', 'action', 'reject');
uci.set(uciconfig, ucidns, 'default_server', 'default-dns');
}
const dns_server_migration = {};
/* DNS servers options */
uci.foreach(uciconfig, ucidnsserver, (cfg) => {
/* legacy format was deprecated in sb 1.12 */
if (cfg.address) {
const addr = parseURL((!match(cfg.address, /:\/\//) ? 'udp://' : '') + cfg.address);
/* RCode was moved into DNS rules */
if (addr.protocol === 'rcode') {
dns_server_migration[cfg['.name']] = { action: 'predefined' };
switch (addr.hostname) {
case 'success':
dns_server_migration[cfg['.name']].rcode = 'NOERROR';
break;
case 'format_error':
dns_server_migration[cfg['.name']].rcode = 'FORMERR';
break;
case 'server_failure':
dns_server_migration[cfg['.name']].rcode = 'SERVFAIL';
break;
case 'name_error':
dns_server_migration[cfg['.name']].rcode = 'NXDOMAIN';
break;
case 'not_implemented':
dns_server_migration[cfg['.name']].rcode = 'NOTIMP';
break;
case 'refused':
default:
dns_server_migration[cfg['.name']].rcode = 'REFUSED';
break;
}
uci.delete(uciconfig, cfg['.name']);
return;
}
uci.set(uciconfig, cfg['.name'], 'type', addr.protocol);
uci.set(uciconfig, cfg['.name'], 'server', addr.hostname);
uci.set(uciconfig, cfg['.name'], 'server_port', addr.port);
uci.set(uciconfig, cfg['.name'], 'path', (addr.pathname !== '/') ? addr.pathname : null);
uci.delete(uciconfig, cfg['.name'], 'address');
}
if (cfg.strategy) {
if (cfg['.name'] === default_dns_server)
uci.set(uciconfig, ucidns, 'default_strategy', cfg.strategy);
dns_server_migration[cfg['.name']] = { strategy: cfg.strategy };
uci.delete(uciconfig, cfg['.name'], 'strategy');
}
if (cfg.client_subnet) {
if (cfg['.name'] === default_dns_server)
uci.set(uciconfig, ucidns, 'client_subnet', cfg.client_subnet);
if (isEmpty(dns_server_migration[cfg['.name']]))
dns_server_migration[cfg['.name']] = {};
dns_server_migration[cfg['.name']].client_subnet = cfg.client_subnet;
uci.delete(uciconfig, cfg['.name'], 'client_subnet');
}
});
/* DNS rules options */ /* DNS rules options */
uci.foreach(uciconfig, ucidnsrule, (cfg) => { uci.foreach(uciconfig, ucidnsrule, (cfg) => {
/* outbound was removed in sb 1.12 */
if (cfg.outbound) {
uci.delete(uciconfig, cfg['.name']);
if (!cfg.enabled)
return;
map(cfg.outbound, (outbound) => {
switch (outbound) {
case 'direct-out':
case 'block-out':
break;
case 'any-out':
uci.set(uciconfig, ucirouting, 'default_outbound_dns', cfg.server);
break;
default:
uci.set(uciconfig, cfg.outbound, 'domain_resolver', cfg.server);
break;
}
});
return;
}
/* rule_set_ipcidr_match_source was renamed in sb 1.10 */ /* rule_set_ipcidr_match_source was renamed in sb 1.10 */
if (cfg.rule_set_ipcidr_match_source === '1') if (cfg.rule_set_ipcidr_match_source === '1')
uci.rename(uciconfig, cfg['.name'], 'rule_set_ipcidr_match_source', 'rule_set_ip_cidr_match_source'); uci.rename(uciconfig, cfg['.name'], 'rule_set_ipcidr_match_source', 'rule_set_ip_cidr_match_source');
/* block-dns was moved into action in sb 1.11 */
if (cfg.server === 'block-dns') {
uci.set(uciconfig, cfg['.name'], 'action', 'reject');
uci.delete(uciconfig, cfg['.name'], 'server');
} else if (!cfg.action) {
/* add missing 'action' field */
uci.set(uciconfig, cfg['.name'], 'action', 'route');
}
/* strategy and client_subnet were moved into dns rules */
if (dns_server_migration[cfg.server]) {
if (dns_server_migration[cfg.server].strategy)
uci.set(uciconfig, cfg['.name'], 'strategy', dns_server_migration[cfg.server].strategy);
if (dns_server_migration[cfg.server].client_subnet)
uci.set(uciconfig, cfg['.name'], 'client_subnet', dns_server_migration[cfg.server].client_subnet);
}
}); });
/* nodes options */ /* nodes options */
@ -95,6 +207,15 @@ uci.foreach(uciconfig, uciroutingrule, (cfg) => {
/* rule_set_ipcidr_match_source was renamed in sb 1.10 */ /* rule_set_ipcidr_match_source was renamed in sb 1.10 */
if (cfg.rule_set_ipcidr_match_source === '1') if (cfg.rule_set_ipcidr_match_source === '1')
uci.rename(uciconfig, cfg['.name'], 'rule_set_ipcidr_match_source', 'rule_set_ip_cidr_match_source'); uci.rename(uciconfig, cfg['.name'], 'rule_set_ipcidr_match_source', 'rule_set_ip_cidr_match_source');
/* block-out was moved into action in sb 1.11 */
if (cfg.outbound === 'block-out') {
uci.set(uciconfig, cfg['.name'], 'action', 'reject');
uci.delete(uciconfig, cfg['.name'], 'outbound');
} else if (!cfg.action) {
/* add missing 'action' field */
uci.set(uciconfig, cfg['.name'], 'action', 'route');
}
}); });
/* server options */ /* server options */

View File

@ -7,6 +7,7 @@
'use strict'; 'use strict';
import { md5 } from 'digest';
import { open } from 'fs'; import { open } from 'fs';
import { connect } from 'ubus'; import { connect } from 'ubus';
import { cursor } from 'uci'; import { cursor } from 'uci';
@ -15,9 +16,8 @@ import { urldecode, urlencode } from 'luci.http';
import { init_action } from 'luci.sys'; import { init_action } from 'luci.sys';
import { import {
calcStringMD5, wGET, decodeBase64Str, wGET, decodeBase64Str, getTime, isEmpty, parseURL,
getTime, isEmpty, parseURL, validation, validation, HP_DIR, RUN_DIR
HP_DIR, RUN_DIR
} from 'homeproxy'; } from 'homeproxy';
/* UCI config start */ /* UCI config start */
@ -101,6 +101,23 @@ function parse_uri(uri) {
uri = split(trim(uri), '://'); uri = split(trim(uri), '://');
switch (uri[0]) { switch (uri[0]) {
case 'anytls':
/* https://github.com/anytls/anytls-go/blob/v0.0.8/docs/uri_scheme.md */
url = parseURL('http://' + uri[1]) || {};
params = url.searchParams || {};
config = {
label: url.hash ? urldecode(url.hash) : null,
type: 'anytls',
address: url.hostname,
port: url.port,
password: urldecode(url.username),
tls: '1',
tls_sni: params.sni,
tls_insecure: (params.insecure === '1') ? '1' : '0'
};
break;
case 'http': case 'http':
case 'https': case 'https':
url = parseURL('http://' + uri[1]) || {}; url = parseURL('http://' + uri[1]) || {};
@ -464,7 +481,7 @@ function main() {
for (let url in subscription_urls) { for (let url in subscription_urls) {
url = replace(url, /#.*$/, ''); url = replace(url, /#.*$/, '');
const groupHash = calcStringMD5(url); const groupHash = md5(url);
node_cache[groupHash] = {}; node_cache[groupHash] = {};
const res = wGET(url, user_agent); const res = wGET(url, user_agent);
@ -495,8 +512,8 @@ function main() {
const label = config.label; const label = config.label;
config.label = null; config.label = null;
const confHash = calcStringMD5(sprintf('%J', config)), const confHash = md5(sprintf('%J', config)),
nameHash = calcStringMD5(label); nameHash = md5(label);
config.label = label; config.label = label;
if (filter_check(config.label)) if (filter_check(config.label))
@ -566,7 +583,7 @@ function main() {
if (node.isExisting) if (node.isExisting)
return null; return null;
const nameHash = calcStringMD5(node.label); const nameHash = md5(node.label);
uci.set(uciconfig, nameHash, 'node'); uci.set(uciconfig, nameHash, 'node');
map(keys(node), (v) => uci.set(uciconfig, nameHash, v, node[v])); map(keys(node), (v) => uci.set(uciconfig, nameHash, v, node[v]));

View File

@ -250,7 +250,7 @@ start_service() {
[ "$outbound_node" = "nil" ] || utpl -S "$HP_DIR/scripts/firewall_post.ut" > "$RUN_DIR/fw4_post.nft" [ "$outbound_node" = "nil" ] || utpl -S "$HP_DIR/scripts/firewall_post.ut" > "$RUN_DIR/fw4_post.nft"
fw4 reload >"/dev/null" 2>&1 fw4 reload >"/dev/null" 2>&1
log "$(sing-box version | awk 'NR==1{print $1,$3}') started." log "sing-box $(sing-box version -n) started."
} }
stop_service() { stop_service() {

View File

@ -16,8 +16,6 @@
"/etc/nikki/run/config.yaml": ["read"], "/etc/nikki/run/config.yaml": ["read"],
"/etc/nikki/run/providers/rule/*": ["read"], "/etc/nikki/run/providers/rule/*": ["read"],
"/etc/nikki/run/providers/proxy/*": ["read"], "/etc/nikki/run/providers/proxy/*": ["read"],
"/etc/nikki/nftables/reserved_ip.nft": ["read"],
"/etc/nikki/nftables/reserved_ip6.nft": ["read"],
"/var/log/nikki/*.log": ["read"] "/var/log/nikki/*.log": ["read"]
} }
}, },
@ -32,8 +30,6 @@
"/etc/nikki/run/config.yaml": ["write"], "/etc/nikki/run/config.yaml": ["write"],
"/etc/nikki/run/providers/rule/*": ["write"], "/etc/nikki/run/providers/rule/*": ["write"],
"/etc/nikki/run/providers/proxy/*": ["write"], "/etc/nikki/run/providers/proxy/*": ["write"],
"/etc/nikki/nftables/reserved_ip.nft": ["write"],
"/etc/nikki/nftables/reserved_ip6.nft": ["write"],
"/var/log/nikki/*.log": ["write"] "/var/log/nikki/*.log": ["write"]
} }
} }

View File

@ -448,6 +448,9 @@ function clear_all_nodes()
end) end)
uci:foreach(appname, "subscribe_list", function(t) uci:foreach(appname, "subscribe_list", function(t)
uci:delete(appname, t[".name"], "md5") uci:delete(appname, t[".name"], "md5")
uci:delete(appname, t[".name"], "chain_proxy")
uci:delete(appname, t[".name"], "preproxy_node")
uci:delete(appname, t[".name"], "to_node")
end) end)
api.uci_save(uci, appname, true, true) api.uci_save(uci, appname, true, true)
@ -518,6 +521,16 @@ function delete_select_nodes()
uci:delete(appname, t[".name"], "fallback_node") uci:delete(appname, t[".name"], "fallback_node")
end end
end) end)
uci:foreach(appname, "subscribe_list", function(t)
if t["preproxy_node"] == w then
uci:delete(appname, t[".name"], "preproxy_node")
uci:delete(appname, t[".name"], "chain_proxy")
end
if t["to_node"] == w then
uci:delete(appname, t[".name"], "to_node")
uci:delete(appname, t[".name"], "chain_proxy")
end
end)
if (uci:get(appname, w, "add_mode") or "0") == "2" then if (uci:get(appname, w, "add_mode") or "0") == "2" then
local add_from = uci:get(appname, w, "add_from") or "" local add_from = uci:get(appname, w, "add_from") or ""
if add_from ~= "" then if add_from ~= "" then
@ -633,20 +646,29 @@ function create_backup()
end end
function restore_backup() function restore_backup()
local result = { status = "error", message = "unknown error" }
local ok, err = pcall(function() local ok, err = pcall(function()
local filename = http.formvalue("filename") local filename = http.formvalue("filename")
local chunk = http.formvalue("chunk") local chunk = http.formvalue("chunk")
local chunk_index = tonumber(http.formvalue("chunk_index") or "-1") local chunk_index = tonumber(http.formvalue("chunk_index") or "-1")
local total_chunks = tonumber(http.formvalue("total_chunks") or "-1") local total_chunks = tonumber(http.formvalue("total_chunks") or "-1")
if not filename or not chunk then if not filename then
http_write_json({ status = "error", message = "Missing filename or chunk" }) result = { status = "error", message = "Missing filename" }
return
end
if not chunk then
result = { status = "error", message = "Missing chunk data" }
return return
end end
local file_path = "/tmp/" .. filename local file_path = "/tmp/" .. filename
local decoded = nixio.bin.b64decode(chunk) local decoded = nixio.bin.b64decode(chunk)
if not decoded then
result = { status = "error", message = "Base64 decode failed" }
return
end
local fp = io.open(file_path, "a+") local fp = io.open(file_path, "a+")
if not fp then if not fp then
http_write_json({ status = "error", message = "Failed to open file for writing: " .. file_path }) result = { status = "error", message = "Failed to open file: " .. file_path }
return return
end end
fp:write(decoded) fp:write(decoded)
@ -667,19 +689,21 @@ function restore_backup()
api.log(" * 重启 PassWall 服务中…\n") api.log(" * 重启 PassWall 服务中…\n")
luci.sys.call('/etc/init.d/passwall restart > /dev/null 2>&1 &') luci.sys.call('/etc/init.d/passwall restart > /dev/null 2>&1 &')
luci.sys.call('/etc/init.d/passwall_server restart > /dev/null 2>&1 &') luci.sys.call('/etc/init.d/passwall_server restart > /dev/null 2>&1 &')
result = { status = "success", message = "Upload completed", path = file_path }
else else
api.log(" * PassWall 配置文件解压失败,请重试!") api.log(" * PassWall 配置文件解压失败,请重试!")
result = { status = "error", message = "Decompression failed" }
end end
luci.sys.call("rm -rf " .. temp_dir) luci.sys.call("rm -rf " .. temp_dir)
fs.remove(file_path) fs.remove(file_path)
http_write_json({ status = "success", message = "Upload completed", path = file_path })
else else
http_write_json({ status = "success", message = "Chunk received" }) result = { status = "success", message = "Chunk received" }
end end
end) end)
if not ok then if not ok then
http_write_json({ status = "error", message = tostring(err) }) result = { status = "error", message = tostring(err) }
end end
http_write_json(result)
end end
function geo_view() function geo_view()

View File

@ -91,6 +91,16 @@ function s.remove(e, t)
m:del(s[".name"], "fallback_node") m:del(s[".name"], "fallback_node")
end end
end) end)
m.uci:foreach(appname, "subscribe_list", function(s)
if s["preproxy_node"] == t then
m:del(s[".name"], "preproxy_node")
m:del(s[".name"], "chain_proxy")
end
if s["to_node"] == t then
m:del(s[".name"], "to_node")
m:del(s[".name"], "chain_proxy")
end
end)
if (m:get(t, "add_mode") or "0") == "2" then if (m:get(t, "add_mode") or "0") == "2" then
local add_from = m:get(t, "add_from") or "" local add_from = m:get(t, "add_from") or ""
if add_from ~= "" then if add_from ~= "" then

View File

@ -56,6 +56,18 @@ if has_hysteria2 then
local s = "hysteria2" local s = "hysteria2"
table.insert(hysteria2_type, s) table.insert(hysteria2_type, s)
end end
local nodes_table = {}
for k, e in ipairs(api.get_valid_nodes()) do
if e.node_type == "normal" then
nodes_table[#nodes_table + 1] = {
id = e[".name"],
remark = e["remark"],
type = e["type"],
add_mode = e["add_mode"],
chain_proxy = e["chain_proxy"]
}
end
end
s = m:section(NamedSection, arg[1]) s = m:section(NamedSection, arg[1])
s.addremove = false s.addremove = false
@ -210,4 +222,29 @@ o:value("curl", "Curl")
o:value("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0", "Edge for Linux") o:value("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0", "Edge for Linux")
o:value("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0", "Edge for Windows") o:value("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0", "Edge for Windows")
o = s:option(ListValue, "chain_proxy", translate("Chain Proxy"))
o:value("", translate("Close(Not use)"))
o:value("1", translate("Preproxy Node"))
o:value("2", translate("Landing Node"))
local descrStr = "Chained proxy works only with Xray or Sing-box nodes.<br>"
descrStr = descrStr .. "The chained node must be the same type as your subscription node (Xray with Xray, Sing-box with Sing-box).<br>"
descrStr = descrStr .. "You can only use manual or imported nodes as chained nodes."
descrStr = translate(descrStr) .. "<br>" .. translate("Only support a layer of proxy.")
o = s:option(ListValue, "preproxy_node", translate("Preproxy Node"))
o:depends({ ["chain_proxy"] = "1" })
o.description = descrStr
o = s:option(ListValue, "to_node", translate("Landing Node"))
o:depends({ ["chain_proxy"] = "2" })
o.description = descrStr
for k, v in pairs(nodes_table) do
if (v.type == "Xray" or v.type == "sing-box") and (not v.chain_proxy or v.chain_proxy == "") and v.add_mode ~= "2" then
s.fields["preproxy_node"]:value(v.id, v.remark)
s.fields["to_node"]:value(v.id, v.remark)
end
end
return m return m

View File

@ -184,7 +184,6 @@ local api = require "luci.passwall.api"
const chunk = base64Data.substring(currentChunk * chunkSize, (currentChunk + 1) * chunkSize); const chunk = base64Data.substring(currentChunk * chunkSize, (currentChunk + 1) * chunkSize);
const xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
xhr.open("POST", '<%= api.url("restore_backup") %>', true); xhr.open("POST", '<%= api.url("restore_backup") %>', true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function () { xhr.onreadystatechange = function () {
if (xhr.readyState === 4) { if (xhr.readyState === 4) {
if (xhr.status === 200) { if (xhr.status === 200) {
@ -203,12 +202,12 @@ local api = require "luci.passwall.api"
} }
} }
}; };
xhr.send( const formData = new FormData();
"filename=" + encodeURIComponent(file.name) + formData.append("filename", file.name);
"&chunk=" + encodeURIComponent(chunk) + formData.append("chunk", chunk);
"&chunk_index=" + currentChunk + formData.append("chunk_index", currentChunk);
"&total_chunks=" + totalChunks formData.append("total_chunks", totalChunks);
); xhr.send(formData);
} else { } else {
//alert("Upload completed."); //alert("Upload completed.");
document.getElementById("upload-btn").value = "<%:UL Restore%>"; document.getElementById("upload-btn").value = "<%:UL Restore%>";

View File

@ -1795,6 +1795,15 @@ msgstr "落地节点"
msgid "Only support a layer of proxy." msgid "Only support a layer of proxy."
msgstr "仅支持一层代理。" msgstr "仅支持一层代理。"
msgid ""
"Chained proxy works only with Xray or Sing-box nodes.<br>"
"The chained node must be the same type as your subscription node (Xray with Xray, Sing-box with Sing-box).<br>"
"You can only use manual or imported nodes as chained nodes."
msgstr ""
"链式代理仅支持 Xray 与 Sing-box 节点。<br>"
"链式节点需与订阅节点类型一致Xray 对应 XraySing-box 对应 Sing-box。<br>"
"仅支持手动添加或导入的节点用作链式节点。"
msgid "Only work with using the %s node." msgid "Only work with using the %s node."
msgstr "与使用 %s 节点时生效。" msgstr "与使用 %s 节点时生效。"

View File

@ -36,6 +36,7 @@ local vless_type_default = uci:get(appname, "@global_subscribe[0]", "vless_type"
local hysteria2_type_default = uci:get(appname, "@global_subscribe[0]", "hysteria2_type") or "hysteria2" local hysteria2_type_default = uci:get(appname, "@global_subscribe[0]", "hysteria2_type") or "hysteria2"
local domain_strategy_default = uci:get(appname, "@global_subscribe[0]", "domain_strategy") or "" local domain_strategy_default = uci:get(appname, "@global_subscribe[0]", "domain_strategy") or ""
local domain_strategy_node = "" local domain_strategy_node = ""
local preproxy_node_group, to_node_group, chain_node_type = "", "", ""
-- 判断是否过滤节点关键字 -- 判断是否过滤节点关键字
local filter_keyword_mode_default = uci:get(appname, "@global_subscribe[0]", "filter_keyword_mode") or "0" local filter_keyword_mode_default = uci:get(appname, "@global_subscribe[0]", "filter_keyword_mode") or "0"
local filter_keyword_discard_list_default = uci:get(appname, "@global_subscribe[0]", "filter_discard_list") or {} local filter_keyword_discard_list_default = uci:get(appname, "@global_subscribe[0]", "filter_discard_list") or {}
@ -1714,6 +1715,16 @@ local function update_node(manual)
if kkk == "type" and vvv == "sing-box" then if kkk == "type" and vvv == "sing-box" then
uci:set(appname, cfgid, "domain_strategy", domain_strategy_node) uci:set(appname, cfgid, "domain_strategy", domain_strategy_node)
end end
-- 订阅组链式代理
if chain_node_type ~= "" and kkk == "type" and vvv == chain_node_type then
if preproxy_node_group ~="" then
uci:set(appname, cfgid, "chain_proxy", "1")
uci:set(appname, cfgid, "preproxy_node", preproxy_node_group)
elseif to_node_group ~= "" then
uci:set(appname, cfgid, "chain_proxy", "2")
uci:set(appname, cfgid, "to_node", to_node_group)
end
end
end end
end end
end end
@ -1916,6 +1927,22 @@ local execute = function()
else else
domain_strategy_node = domain_strategy_default domain_strategy_node = domain_strategy_default
end end
-- 订阅组链式代理
local function valid_chain_node(node)
if not node then return "" end
local cp = uci:get(appname, node, "chain_proxy") or ""
local am = uci:get(appname, node, "add_mode") or "0"
chain_node_type = (cp == "" and am ~= "2") and (uci:get(appname, node, "type") or "") or ""
if chain_node_type ~= "Xray" and chain_node_type ~= "sing-box" then
chain_node_type = ""
return ""
end
return node
end
preproxy_node_group = (value.chain_proxy == "1") and valid_chain_node(value.preproxy_node) or ""
to_node_group = (value.chain_proxy == "2") and valid_chain_node(value.to_node) or ""
local ua = value.user_agent local ua = value.user_agent
local access_mode = value.access_mode local access_mode = value.access_mode
local result = (not access_mode) and "自动" or (access_mode == "direct" and "直连访问" or (access_mode == "proxy" and "通过代理" or "自动")) local result = (not access_mode) and "自动" or (access_mode == "direct" and "直连访问" or (access_mode == "proxy" and "通过代理" or "自动"))

View File

@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall2 PKG_NAME:=luci-app-passwall2
PKG_VERSION:=25.8.9 PKG_VERSION:=25.8.22
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_CONFIG_DEPENDS:= \ PKG_CONFIG_DEPENDS:= \

View File

@ -30,6 +30,11 @@ o = s:option(Value, _n("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.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Value, _n("hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)")
o.placeholder = "30s"
o.default = "30s"
o.rewrite_option = o.option
o = s:option(Value, _n("obfs"), translate("Obfs Password")) o = s:option(Value, _n("obfs"), translate("Obfs Password"))
o.rewrite_option = o.option o.rewrite_option = o.option
@ -54,9 +59,6 @@ o.rewrite_option = o.option
o = s:option(Value, _n("down_mbps"), translate("Max download Mbps")) o = s:option(Value, _n("down_mbps"), translate("Max download Mbps"))
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Value, _n("hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)")
o.rewrite_option = o.option
o = s:option(Value, _n("recv_window"), translate("QUIC stream receive window")) o = s:option(Value, _n("recv_window"), translate("QUIC stream receive window"))
o.rewrite_option = o.option o.rewrite_option = o.option

View File

@ -61,7 +61,8 @@ for k, e in ipairs(api.get_valid_nodes()) do
nodes_table[#nodes_table + 1] = { nodes_table[#nodes_table + 1] = {
id = e[".name"], id = e[".name"],
remark = e["remark"], remark = e["remark"],
type = e["type"] type = e["type"],
chain_proxy = e["chain_proxy"]
} }
end end
if e.protocol == "_balancing" then if e.protocol == "_balancing" then
@ -337,6 +338,7 @@ o.default = ""
o:value("", translate("Disable")) o:value("", translate("Disable"))
o:value("xtls-rprx-vision") o:value("xtls-rprx-vision")
o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true, [_n("transport")] = "raw" }) o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true, [_n("transport")] = "raw" })
o:depends({ [_n("protocol")] = "trojan", [_n("tls")] = true, [_n("transport")] = "raw" })
o = s:option(Flag, _n("tls"), translate("TLS")) o = s:option(Flag, _n("tls"), translate("TLS"))
o.default = 0 o.default = 0
@ -392,6 +394,13 @@ o.validate = function(self, value)
return api.trim(value:gsub("[\r\n]", "")) return api.trim(value:gsub("[\r\n]", ""))
end end
o = s:option(ListValue, _n("ech_ForceQuery"), translate("ECH Query Policy"), translate("Controls the policy used when performing DNS queries for ECH configuration."))
o.default = "none"
o:value("none")
o:value("half")
o:value("full")
o:depends({ [_n("ech")] = true })
-- [[ REALITY部分 ]] -- -- [[ REALITY部分 ]] --
o = s:option(Value, _n("reality_publicKey"), translate("Public Key")) o = s:option(Value, _n("reality_publicKey"), translate("Public Key"))
o:depends({ [_n("tls")] = true, [_n("reality")] = true }) o:depends({ [_n("tls")] = true, [_n("reality")] = true })
@ -696,7 +705,7 @@ o = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Onl
o:depends({ [_n("chain_proxy")] = "2" }) o:depends({ [_n("chain_proxy")] = "2" })
for k, v in pairs(nodes_table) do for k, v in pairs(nodes_table) do
if v.type == "Xray" and v.id ~= arg[1] then if v.type == "Xray" and v.id ~= arg[1] and (not v.chain_proxy or v.chain_proxy == "") then
s.fields[_n("preproxy_node")]:value(v.id, v.remark) s.fields[_n("preproxy_node")]:value(v.id, v.remark)
s.fields[_n("to_node")]:value(v.id, v.remark) s.fields[_n("to_node")]:value(v.id, v.remark)
end end

View File

@ -81,7 +81,8 @@ for k, e in ipairs(api.get_valid_nodes()) do
nodes_table[#nodes_table + 1] = { nodes_table[#nodes_table + 1] = {
id = e[".name"], id = e[".name"],
remark = e["remark"], remark = e["remark"],
type = e["type"] type = e["type"],
chain_proxy = e["chain_proxy"]
} }
end end
if e.protocol == "_iface" then if e.protocol == "_iface" then
@ -339,12 +340,18 @@ o.default = ""
o:value("", translate("Disable")) o:value("", translate("Disable"))
o:value("xtls-rprx-vision") o:value("xtls-rprx-vision")
o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true }) o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true })
o:depends({ [_n("protocol")] = "trojan", [_n("tls")] = true })
if singbox_tags:find("with_quic") then if singbox_tags:find("with_quic") then
o = s:option(Value, _n("hysteria_hop"), translate("Port hopping range")) o = s:option(Value, _n("hysteria_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")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(Value, _n("hysteria_hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)")
o.placeholder = "30s"
o.default = "30s"
o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(Value, _n("hysteria_obfs"), translate("Obfs Password")) o = s:option(Value, _n("hysteria_obfs"), translate("Obfs Password"))
o:depends({ [_n("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
@ -425,6 +432,11 @@ if singbox_tags:find("with_quic") then
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" })
o = s:option(Value, _n("hysteria2_hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)")
o.placeholder = "30s"
o.default = "30s"
o:depends({ [_n("protocol")] = "hysteria2" })
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" })
@ -526,30 +538,30 @@ if singbox_tags:find("with_utls") then
o:value("firefox") o:value("firefox")
o:value("edge") o:value("edge")
o:value("safari") o:value("safari")
-- o:value("360") o:value("360")
o:value("qq") o:value("qq")
o:value("ios") o:value("ios")
-- o:value("android") o:value("android")
o:value("random") o:value("random")
-- o:value("randomized") o:value("randomized")
o.default = "chrome" o.default = "chrome"
o:depends({ [_n("tls")] = true, [_n("utls")] = true }) o:depends({ [_n("utls")] = true })
-- [[ REALITY部分 ]] -- -- [[ REALITY部分 ]] --
o = s:option(Flag, _n("reality"), translate("REALITY")) o = s:option(Flag, _n("reality"), translate("REALITY"))
o.default = 0 o.default = 0
o:depends({ [_n("protocol")] = "vless", [_n("utls")] = true }) o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true })
o:depends({ [_n("protocol")] = "vmess", [_n("utls")] = true }) o:depends({ [_n("protocol")] = "vmess", [_n("tls")] = true })
o:depends({ [_n("protocol")] = "shadowsocks", [_n("utls")] = true }) o:depends({ [_n("protocol")] = "shadowsocks", [_n("tls")] = true })
o:depends({ [_n("protocol")] = "socks", [_n("utls")] = true }) o:depends({ [_n("protocol")] = "socks", [_n("tls")] = true })
o:depends({ [_n("protocol")] = "trojan", [_n("utls")] = true }) o:depends({ [_n("protocol")] = "trojan", [_n("tls")] = true })
o:depends({ [_n("protocol")] = "anytls", [_n("utls")] = true }) o:depends({ [_n("protocol")] = "anytls", [_n("tls")] = true })
o = s:option(Value, _n("reality_publicKey"), translate("Public Key")) o = s:option(Value, _n("reality_publicKey"), translate("Public Key"))
o:depends({ [_n("utls")] = true, [_n("reality")] = true }) o:depends({ [_n("reality")] = true })
o = s:option(Value, _n("reality_shortId"), translate("Short Id")) o = s:option(Value, _n("reality_shortId"), translate("Short Id"))
o:depends({ [_n("utls")] = true, [_n("reality")] = true }) o:depends({ [_n("reality")] = true })
end end
o = s:option(ListValue, _n("transport"), translate("Transport")) o = s:option(ListValue, _n("transport"), translate("Transport"))
@ -801,7 +813,7 @@ o = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Onl
o:depends({ [_n("chain_proxy")] = "2" }) o:depends({ [_n("chain_proxy")] = "2" })
for k, v in pairs(nodes_table) do for k, v in pairs(nodes_table) do
if v.type == "sing-box" and v.id ~= arg[1] then if v.type == "sing-box" and v.id ~= arg[1] and (not v.chain_proxy or v.chain_proxy == "") then
s.fields[_n("preproxy_node")]:value(v.id, v.remark) s.fields[_n("preproxy_node")]:value(v.id, v.remark)
s.fields[_n("to_node")]:value(v.id, v.remark) s.fields[_n("to_node")]:value(v.id, v.remark)
end end

View File

@ -321,7 +321,11 @@ function gen_outbound(flag, node, tag, proxy_table)
end end
protocol_table = { protocol_table = {
server_ports = next(server_ports) and server_ports or nil, server_ports = next(server_ports) and server_ports or nil,
hop_interval = next(server_ports) and "30s" or nil, hop_interval = (function()
if not next(server_ports) then return nil end
local v = tonumber((node.hysteria_hop_interval or "30s"):match("^%d+"))
return (v and v >= 5) and (v .. "s") or "30s"
end)(),
up_mbps = tonumber(node.hysteria_up_mbps), up_mbps = tonumber(node.hysteria_up_mbps),
down_mbps = tonumber(node.hysteria_down_mbps), down_mbps = tonumber(node.hysteria_down_mbps),
obfs = node.hysteria_obfs, obfs = node.hysteria_obfs,
@ -397,7 +401,11 @@ function gen_outbound(flag, node, tag, proxy_table)
end end
protocol_table = { protocol_table = {
server_ports = next(server_ports) and server_ports or nil, server_ports = next(server_ports) and server_ports or nil,
hop_interval = next(server_ports) and "30s" or nil, hop_interval = (function()
if not next(server_ports) then return nil end
local v = tonumber((node.hysteria2_hop_interval or "30s"):match("^%d+"))
return (v and v >= 5) and (v .. "s") or "30s"
end)(),
up_mbps = (node.hysteria2_up_mbps and tonumber(node.hysteria2_up_mbps)) and tonumber(node.hysteria2_up_mbps) or nil, up_mbps = (node.hysteria2_up_mbps and tonumber(node.hysteria2_up_mbps)) and tonumber(node.hysteria2_up_mbps) or nil,
down_mbps = (node.hysteria2_down_mbps and tonumber(node.hysteria2_down_mbps)) and tonumber(node.hysteria2_down_mbps) or nil, down_mbps = (node.hysteria2_down_mbps and tonumber(node.hysteria2_down_mbps)) and tonumber(node.hysteria2_down_mbps) or nil,
obfs = { obfs = {

View File

@ -155,7 +155,8 @@ function gen_outbound(flag, node, tag, proxy_table)
serverName = node.tls_serverName, serverName = node.tls_serverName,
allowInsecure = (node.tls_allowInsecure == "1") and true or false, allowInsecure = (node.tls_allowInsecure == "1") and true or false,
fingerprint = (node.type == "Xray" and node.utls == "1" and node.fingerprint and node.fingerprint ~= "") and node.fingerprint or nil, fingerprint = (node.type == "Xray" and node.utls == "1" and node.fingerprint and node.fingerprint ~= "") and node.fingerprint or nil,
echConfigList = (node.ech == "1") and node.ech_config or nil echConfigList = (node.ech == "1") and node.ech_config or nil,
echForceQuery = (node.ech == "1") and (node.ech_ForceQuery or "none") 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,
@ -1060,6 +1061,7 @@ 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 if w:find("#") == 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)
end) end)
@ -1073,6 +1075,7 @@ function gen_config(var)
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 if w:find("#") == 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)
if #ip == 0 then ip = nil end if #ip == 0 then ip = nil end

View File

@ -284,10 +284,6 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin
params += opt.query("spx", dom_prefix + "reality_spiderX"); params += opt.query("spx", dom_prefix + "reality_spiderX");
params += opt.query("pqv", dom_prefix + "reality_mldsa65Verify"); params += opt.query("pqv", dom_prefix + "reality_mldsa65Verify");
} }
if (opt.get(dom_prefix + "flow") && opt.get(dom_prefix + "flow").value) {
let v_flow = opt.get(dom_prefix + "flow").value;
params += "&flow=" + v_flow;
}
params += "&security=" + v_security; params += "&security=" + v_security;
params += opt.query("alpn", dom_prefix + "alpn"); params += opt.query("alpn", dom_prefix + "alpn");
params += opt.query("sni", dom_prefix + "tls_serverName"); params += opt.query("sni", dom_prefix + "tls_serverName");
@ -960,11 +956,10 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin
if (queryParam.security == "tls") { if (queryParam.security == "tls") {
opt.set(dom_prefix + 'tls', true); opt.set(dom_prefix + 'tls', true);
opt.set(dom_prefix + 'reality', false); opt.set(dom_prefix + 'reality', false);
opt.set(dom_prefix + 'flow', queryParam.flow || '');
opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default');
opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || '');
opt.set(dom_prefix + 'tls_allowInsecure', true); opt.set(dom_prefix + 'tls_allowInsecure', true);
if (queryParam.allowinsecure === '0' || queryParam.insecure === '0') { if ((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0') {
opt.set(dom_prefix + 'tls_allowInsecure', false); opt.set(dom_prefix + 'tls_allowInsecure', false);
} }
if (queryParam.fp && queryParam.fp.trim() != "") { if (queryParam.fp && queryParam.fp.trim() != "") {
@ -978,7 +973,6 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin
if (queryParam.security == "reality") { if (queryParam.security == "reality") {
opt.set(dom_prefix + 'tls', true); opt.set(dom_prefix + 'tls', true);
opt.set(dom_prefix + 'reality', true); opt.set(dom_prefix + 'reality', true);
opt.set(dom_prefix + 'flow', queryParam.flow || '');
opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default');
opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || '');
if (queryParam.fp && queryParam.fp.trim() != "") { if (queryParam.fp && queryParam.fp.trim() != "") {
@ -1205,9 +1199,11 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin
} }
tls_serverName = tls_serverName || ""; tls_serverName = tls_serverName || "";
opt.set(dom_prefix + 'tls_serverName', tls_serverName); opt.set(dom_prefix + 'tls_serverName', tls_serverName);
opt.set(dom_prefix + 'flow', (queryParam.flow || '').replace('-udp443', ''));
opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default');
} }
opt.set(dom_prefix + 'tls_allowInsecure', true); opt.set(dom_prefix + 'tls_allowInsecure', true);
if (queryParam.allowinsecure === '0' || queryParam.insecure === '0') { if ((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0') {
opt.set(dom_prefix + 'tls_allowInsecure', false); opt.set(dom_prefix + 'tls_allowInsecure', false);
} }
@ -1342,11 +1338,11 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin
if (queryParam.security == "tls") { if (queryParam.security == "tls") {
opt.set(dom_prefix + 'tls', true); opt.set(dom_prefix + 'tls', true);
opt.set(dom_prefix + 'reality', false); opt.set(dom_prefix + 'reality', false);
opt.set(dom_prefix + 'flow', queryParam.flow || ''); opt.set(dom_prefix + 'flow', (queryParam.flow || '').replace('-udp443', ''));
opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default');
opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || '');
opt.set(dom_prefix + 'tls_allowInsecure', true); opt.set(dom_prefix + 'tls_allowInsecure', true);
if (queryParam.allowinsecure === '0' || queryParam.insecure === '0') { if ((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0') {
opt.set(dom_prefix + 'tls_allowInsecure', false); opt.set(dom_prefix + 'tls_allowInsecure', false);
} }
if (queryParam.fp && queryParam.fp.trim() != "") { if (queryParam.fp && queryParam.fp.trim() != "") {
@ -1360,7 +1356,7 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin
if (queryParam.security == "reality") { if (queryParam.security == "reality") {
opt.set(dom_prefix + 'tls', true); opt.set(dom_prefix + 'tls', true);
opt.set(dom_prefix + 'reality', true); opt.set(dom_prefix + 'reality', true);
opt.set(dom_prefix + 'flow', queryParam.flow || ''); opt.set(dom_prefix + 'flow', (queryParam.flow || '').replace('-udp443', ''));
opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default');
opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || '');
if (queryParam.fp && queryParam.fp.trim() != "") { if (queryParam.fp && queryParam.fp.trim() != "") {
@ -1539,7 +1535,7 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin
opt.set(dom_prefix + 'tuic_alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'tuic_alpn', queryParam.alpn || 'default');
opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || '');
opt.set(dom_prefix + 'tls_allowInsecure', true); opt.set(dom_prefix + 'tls_allowInsecure', true);
if (queryParam.allowinsecure === '0' || queryParam.insecure === '0') { if ((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0') {
opt.set(dom_prefix + 'tls_allowInsecure', false); opt.set(dom_prefix + 'tls_allowInsecure', false);
} }
if (hash) { if (hash) {
@ -1579,11 +1575,10 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin
if (queryParam.security == "tls") { if (queryParam.security == "tls") {
opt.set(dom_prefix + 'tls', true); opt.set(dom_prefix + 'tls', true);
opt.set(dom_prefix + 'reality', false); opt.set(dom_prefix + 'reality', false);
opt.set(dom_prefix + 'flow', queryParam.flow || '');
opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default');
opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || '');
opt.set(dom_prefix + 'tls_allowInsecure', true); opt.set(dom_prefix + 'tls_allowInsecure', true);
if (queryParam.allowinsecure === '0' || queryParam.insecure === '0') { if ((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0') {
opt.set(dom_prefix + 'tls_allowInsecure', false); opt.set(dom_prefix + 'tls_allowInsecure', false);
} }
if (queryParam.fp && queryParam.fp.trim() != "") { if (queryParam.fp && queryParam.fp.trim() != "") {
@ -1594,7 +1589,6 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin
if (queryParam.security == "reality") { if (queryParam.security == "reality") {
opt.set(dom_prefix + 'tls', true); opt.set(dom_prefix + 'tls', true);
opt.set(dom_prefix + 'reality', true); opt.set(dom_prefix + 'reality', true);
opt.set(dom_prefix + 'flow', queryParam.flow || '');
opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default');
opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || '');
if (queryParam.fp && queryParam.fp.trim() != "") { if (queryParam.fp && queryParam.fp.trim() != "") {

View File

@ -1576,6 +1576,12 @@ msgstr "后量子对等证书签名方案"
msgid "Disable adaptive sizing of TLS records" msgid "Disable adaptive sizing of TLS records"
msgstr "禁用 TLS 记录的自适应大小调整" msgstr "禁用 TLS 记录的自适应大小调整"
msgid "ECH Query Policy"
msgstr "ECH 查询策略"
msgid "Controls the policy used when performing DNS queries for ECH configuration."
msgstr "控制使用 DNS 查询 ECH 配置时的策略。"
msgid "Enable Multipath TCP, need to be enabled in both server and client configuration." msgid "Enable Multipath TCP, need to be enabled in both server and client configuration."
msgstr "启用 Multipath TCP需在服务端和客户端配置中同时启用。" msgstr "启用 Multipath TCP需在服务端和客户端配置中同时启用。"

View File

@ -336,6 +336,15 @@ eval_cache_var() {
[ -s "$TMP_PATH/var" ] && eval $(cat "$TMP_PATH/var") [ -s "$TMP_PATH/var" ] && eval $(cat "$TMP_PATH/var")
} }
has_1_65535() {
local val="$1"
val=${val//:/-}
case ",$val," in
*,1-65535,*) return 0 ;;
*) return 1 ;;
esac
}
run_xray() { run_xray() {
local flag node redir_port tcp_proxy_way socks_address socks_port socks_username socks_password http_address http_port http_username http_password local flag node redir_port tcp_proxy_way socks_address socks_port socks_username socks_password http_address http_port http_username http_password
local dns_listen_port direct_dns_query_strategy remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy dns_cache write_ipset_direct local dns_listen_port direct_dns_query_strategy remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy dns_cache write_ipset_direct
@ -1146,11 +1155,10 @@ acl_app() {
index=$(expr $index + 1) index=$(expr $index + 1)
local enabled sid remarks sources interface tcp_no_redir_ports udp_no_redir_ports node direct_dns_query_strategy write_ipset_direct remote_dns_protocol remote_dns remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy local enabled sid remarks sources interface tcp_no_redir_ports udp_no_redir_ports node direct_dns_query_strategy write_ipset_direct remote_dns_protocol remote_dns remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy
local _ip _mac _iprange _ipset _ip_or_mac source_list config_file local _ip _mac _iprange _ipset _ip_or_mac source_list config_file
sid=$(uci -q show "${CONFIG}.${item}" | grep "=acl_rule" | awk -F '=' '{print $1}' | awk -F '.' '{print $2}') local sid=$(uci -q show "${CONFIG}.${item}" | grep "=acl_rule" | awk -F '=' '{print $1}' | awk -F '.' '{print $2}')
[ "$(config_n_get $sid enabled)" = "1" ] || continue
eval $(uci -q show "${CONFIG}.${item}" | cut -d'.' -sf 3-) eval $(uci -q show "${CONFIG}.${item}" | cut -d'.' -sf 3-)
[ "$enabled" = "1" ] || continue
if [ -n "${sources}" ]; then if [ -n "${sources}" ]; then
for s in $sources; do for s in $sources; do
local s2 local s2
@ -1183,7 +1191,9 @@ acl_app() {
udp_no_redir_ports=${udp_no_redir_ports:-default} udp_no_redir_ports=${udp_no_redir_ports:-default}
[ "$tcp_no_redir_ports" = "default" ] && tcp_no_redir_ports=$TCP_NO_REDIR_PORTS [ "$tcp_no_redir_ports" = "default" ] && tcp_no_redir_ports=$TCP_NO_REDIR_PORTS
[ "$udp_no_redir_ports" = "default" ] && udp_no_redir_ports=$UDP_NO_REDIR_PORTS [ "$udp_no_redir_ports" = "default" ] && udp_no_redir_ports=$UDP_NO_REDIR_PORTS
[ "$tcp_no_redir_ports" == "1:65535" ] && [ "$udp_no_redir_ports" == "1:65535" ] && unset node if has_1_65535 "$tcp_no_redir_ports" && has_1_65535 "$udp_no_redir_ports"; then
unset node
fi
[ -n "$node" ] && { [ -n "$node" ] && {
tcp_proxy_mode="global" tcp_proxy_mode="global"

View File

@ -418,7 +418,7 @@ load_acl() {
[ -n "${is_tproxy}" ] && ipt_tmp=$ipt_m [ -n "${is_tproxy}" ] && ipt_tmp=$ipt_m
[ "$tcp_no_redir_ports" != "disable" ] && { [ "$tcp_no_redir_ports" != "disable" ] && {
if [ "$tcp_no_redir_ports" != "1:65535" ]; then if ! has_1_65535 "$tcp_no_redir_ports"; then
[ "$_ipv4" != "1" ] && add_port_rules "$ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp" $tcp_no_redir_ports "-j RETURN" 2>/dev/null [ "$_ipv4" != "1" ] && add_port_rules "$ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp" $tcp_no_redir_ports "-j RETURN" 2>/dev/null
add_port_rules "$ipt_tmp -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp" $tcp_no_redir_ports "-j RETURN" add_port_rules "$ipt_tmp -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp" $tcp_no_redir_ports "-j RETURN"
echolog " - ${msg}不代理 TCP 端口[${tcp_no_redir_ports}]" echolog " - ${msg}不代理 TCP 端口[${tcp_no_redir_ports}]"
@ -430,7 +430,7 @@ load_acl() {
} }
[ "$udp_no_redir_ports" != "disable" ] && { [ "$udp_no_redir_ports" != "disable" ] && {
if [ "$udp_no_redir_ports" != "1:65535" ]; then if ! has_1_65535 "$udp_no_redir_ports"; then
[ "$_ipv4" != "1" ] && add_port_rules "$ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp" $udp_no_redir_ports "-j RETURN" 2>/dev/null [ "$_ipv4" != "1" ] && add_port_rules "$ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp" $udp_no_redir_ports "-j RETURN" 2>/dev/null
add_port_rules "$ipt_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp" $udp_no_redir_ports "-j RETURN" add_port_rules "$ipt_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp" $udp_no_redir_ports "-j RETURN"
echolog " - ${msg}不代理 UDP 端口[${udp_no_redir_ports}]" echolog " - ${msg}不代理 UDP 端口[${udp_no_redir_ports}]"
@ -526,7 +526,7 @@ load_acl() {
[ "$TCP_NO_REDIR_PORTS" != "disable" ] && { [ "$TCP_NO_REDIR_PORTS" != "disable" ] && {
add_port_rules "$ip6t_m -A PSW2 $(comment "默认") -p tcp" $TCP_NO_REDIR_PORTS "-j RETURN" add_port_rules "$ip6t_m -A PSW2 $(comment "默认") -p tcp" $TCP_NO_REDIR_PORTS "-j RETURN"
add_port_rules "$ipt_tmp -A PSW2 $(comment "默认") -p tcp" $TCP_NO_REDIR_PORTS "-j RETURN" add_port_rules "$ipt_tmp -A PSW2 $(comment "默认") -p tcp" $TCP_NO_REDIR_PORTS "-j RETURN"
if [ "$TCP_NO_REDIR_PORTS" != "1:65535" ]; then if ! has_1_65535 "$TCP_NO_REDIR_PORTS"; then
echolog " - ${msg}不代理 TCP 端口[${TCP_NO_REDIR_PORTS}]" echolog " - ${msg}不代理 TCP 端口[${TCP_NO_REDIR_PORTS}]"
else else
TCP_PROXY_MODE="disable" TCP_PROXY_MODE="disable"
@ -537,7 +537,7 @@ load_acl() {
[ "$UDP_NO_REDIR_PORTS" != "disable" ] && { [ "$UDP_NO_REDIR_PORTS" != "disable" ] && {
add_port_rules "$ip6t_m -A PSW2 $(comment "默认") -p udp" $UDP_NO_REDIR_PORTS "-j RETURN" add_port_rules "$ip6t_m -A PSW2 $(comment "默认") -p udp" $UDP_NO_REDIR_PORTS "-j RETURN"
add_port_rules "$ipt_tmp -A PSW2 $(comment "默认") -p udp" $UDP_NO_REDIR_PORTS "-j RETURN" add_port_rules "$ipt_tmp -A PSW2 $(comment "默认") -p udp" $UDP_NO_REDIR_PORTS "-j RETURN"
if [ "$UDP_NO_REDIR_PORTS" != "1:65535" ]; then if ! has_1_65535 "$UDP_NO_REDIR_PORTS"; then
echolog " - ${msg}不代理 UDP 端口[${UDP_NO_REDIR_PORTS}]" echolog " - ${msg}不代理 UDP 端口[${UDP_NO_REDIR_PORTS}]"
else else
UDP_PROXY_MODE="disable" UDP_PROXY_MODE="disable"
@ -871,7 +871,7 @@ add_firewall_rule() {
[ "$TCP_NO_REDIR_PORTS" != "disable" ] && { [ "$TCP_NO_REDIR_PORTS" != "disable" ] && {
add_port_rules "$ipt_tmp -A PSW2_OUTPUT -p tcp" $TCP_NO_REDIR_PORTS "-j RETURN" add_port_rules "$ipt_tmp -A PSW2_OUTPUT -p tcp" $TCP_NO_REDIR_PORTS "-j RETURN"
add_port_rules "$ip6t_m -A PSW2_OUTPUT -p tcp" $TCP_NO_REDIR_PORTS "-j RETURN" add_port_rules "$ip6t_m -A PSW2_OUTPUT -p tcp" $TCP_NO_REDIR_PORTS "-j RETURN"
if [ "$TCP_NO_REDIR_PORTS" != "1:65535" ]; then if ! has_1_65535 "$TCP_NO_REDIR_PORTS"; then
echolog " - ${msg}不代理 TCP 端口[${TCP_NO_REDIR_PORTS}]" echolog " - ${msg}不代理 TCP 端口[${TCP_NO_REDIR_PORTS}]"
else else
unset TCP_LOCALHOST_PROXY unset TCP_LOCALHOST_PROXY
@ -882,7 +882,7 @@ add_firewall_rule() {
[ "$UDP_NO_REDIR_PORTS" != "disable" ] && { [ "$UDP_NO_REDIR_PORTS" != "disable" ] && {
add_port_rules "$ipt_m -A PSW2_OUTPUT -p udp" $UDP_NO_REDIR_PORTS "-j RETURN" add_port_rules "$ipt_m -A PSW2_OUTPUT -p udp" $UDP_NO_REDIR_PORTS "-j RETURN"
add_port_rules "$ip6t_m -A PSW2_OUTPUT -p udp" $UDP_NO_REDIR_PORTS "-j RETURN" add_port_rules "$ip6t_m -A PSW2_OUTPUT -p udp" $UDP_NO_REDIR_PORTS "-j RETURN"
if [ "$UDP_NO_REDIR_PORTS" != "1:65535" ]; then if ! has_1_65535 "$UDP_NO_REDIR_PORTS"; then
echolog " - ${msg}不代理 UDP 端口[${UDP_NO_REDIR_PORTS}]" echolog " - ${msg}不代理 UDP 端口[${UDP_NO_REDIR_PORTS}]"
else else
unset UDP_LOCALHOST_PROXY unset UDP_LOCALHOST_PROXY

View File

@ -432,7 +432,7 @@ load_acl() {
msg="$remarks】,${msg}" msg="$remarks】,${msg}"
[ "$tcp_no_redir_ports" != "disable" ] && { [ "$tcp_no_redir_ports" != "disable" ] && {
if [ "$tcp_no_redir_ports" != "1:65535" ]; then if ! has_1_65535 "$tcp_no_redir_ports"; then
nft "add rule $NFTABLE_NAME $nft_prerouting_chain ${_ipt_source} ip protocol tcp $(factor $tcp_no_redir_ports "tcp dport") counter return comment \"$remarks\"" nft "add rule $NFTABLE_NAME $nft_prerouting_chain ${_ipt_source} ip protocol tcp $(factor $tcp_no_redir_ports "tcp dport") counter return comment \"$remarks\""
[ "$_ipv4" != "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 ${_ipt_source} meta l4proto tcp $(factor $tcp_no_redir_ports "tcp dport") counter return comment \"$remarks\"" [ "$_ipv4" != "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 ${_ipt_source} meta l4proto tcp $(factor $tcp_no_redir_ports "tcp dport") counter return comment \"$remarks\""
echolog " - ${msg}不代理 TCP 端口[${tcp_no_redir_ports}]" echolog " - ${msg}不代理 TCP 端口[${tcp_no_redir_ports}]"
@ -444,7 +444,7 @@ load_acl() {
} }
[ "$udp_no_redir_ports" != "disable" ] && { [ "$udp_no_redir_ports" != "disable" ] && {
if [ "$udp_no_redir_ports" != "1:65535" ]; then if ! has_1_65535 "$udp_no_redir_ports"; then
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} $(factor $udp_no_redir_ports "udp dport") counter return comment \"$remarks\"" nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} $(factor $udp_no_redir_ports "udp dport") counter return comment \"$remarks\""
[ "$_ipv4" != "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ${_ipt_source} $(factor $udp_no_redir_ports "udp dport") counter return comment \"$remarks\"" 2>/dev/null [ "$_ipv4" != "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ${_ipt_source} $(factor $udp_no_redir_ports "udp dport") counter return comment \"$remarks\"" 2>/dev/null
echolog " - ${msg}不代理 UDP 端口[${udp_no_redir_ports}]" echolog " - ${msg}不代理 UDP 端口[${udp_no_redir_ports}]"
@ -544,7 +544,7 @@ load_acl() {
[ "$TCP_NO_REDIR_PORTS" != "disable" ] && { [ "$TCP_NO_REDIR_PORTS" != "disable" ] && {
nft "add rule $NFTABLE_NAME $nft_prerouting_chain ip protocol tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return comment \"默认\"" nft "add rule $NFTABLE_NAME $nft_prerouting_chain ip protocol tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return comment \"默认\""
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return comment \"默认\"" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return comment \"默认\""
if [ "$TCP_NO_REDIR_PORTS" != "1:65535" ]; then if ! has_1_65535 "$TCP_NO_REDIR_PORTS"; then
echolog " - ${msg}不代理 TCP 端口[${TCP_NO_REDIR_PORTS}]" echolog " - ${msg}不代理 TCP 端口[${TCP_NO_REDIR_PORTS}]"
else else
TCP_PROXY_MODE="disable" TCP_PROXY_MODE="disable"
@ -555,7 +555,7 @@ load_acl() {
[ "$UDP_NO_REDIR_PORTS" != "disable" ] && { [ "$UDP_NO_REDIR_PORTS" != "disable" ] && {
nft "add $NFTABLE_NAME PSW2_MANGLE ip protocol udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return comment \"默认\"" nft "add $NFTABLE_NAME PSW2_MANGLE ip protocol udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return comment \"默认\""
nft "add $NFTABLE_NAME PSW2_MANGLE_V6 counter meta l4proto udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return comment \"默认\"" nft "add $NFTABLE_NAME PSW2_MANGLE_V6 counter meta l4proto udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return comment \"默认\""
if [ "$UDP_NO_REDIR_PORTS" != "1:65535" ]; then if ! has_1_65535 "$UDP_NO_REDIR_PORTS"; then
echolog " - ${msg}不代理 UDP 端口[${UDP_NO_REDIR_PORTS}]" echolog " - ${msg}不代理 UDP 端口[${UDP_NO_REDIR_PORTS}]"
else else
UDP_PROXY_MODE="disable" UDP_PROXY_MODE="disable"
@ -893,7 +893,7 @@ add_firewall_rule() {
[ "$TCP_NO_REDIR_PORTS" != "disable" ] && { [ "$TCP_NO_REDIR_PORTS" != "disable" ] && {
nft "add rule $NFTABLE_NAME $nft_output_chain ip protocol tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return" nft "add rule $NFTABLE_NAME $nft_output_chain ip protocol tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return" nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return"
if [ "$TCP_NO_REDIR_PORTS" != "1:65535" ]; then if ! has_1_65535 "$TCP_NO_REDIR_PORTS"; then
echolog " - ${msg}不代理 TCP 端口[${TCP_NO_REDIR_PORTS}]" echolog " - ${msg}不代理 TCP 端口[${TCP_NO_REDIR_PORTS}]"
else else
unset TCP_LOCALHOST_PROXY unset TCP_LOCALHOST_PROXY
@ -904,7 +904,7 @@ add_firewall_rule() {
[ "$UDP_NO_REDIR_PORTS" != "disable" ] && { [ "$UDP_NO_REDIR_PORTS" != "disable" ] && {
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return" nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return" nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return"
if [ "$UDP_NO_REDIR_PORTS" != "1:65535" ]; then if ! has_1_65535 "$UDP_NO_REDIR_PORTS"; then
echolog " - ${msg}不代理 UDP 端口[${UDP_NO_REDIR_PORTS}]" echolog " - ${msg}不代理 UDP 端口[${UDP_NO_REDIR_PORTS}]"
else else
unset UDP_LOCALHOST_PROXY unset UDP_LOCALHOST_PROXY

View File

@ -1042,8 +1042,8 @@ local function processData(szType, content, add_mode, add_from)
end end
result.encryption = params.encryption or "none" result.encryption = params.encryption or "none"
result.flow = params.flow and params.flow:gsub("-udp443", "") or nil
result.flow = params.flow or nil result.alpn = params.alpn
if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "xhttp" or result.transport == "splithttp") then if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "xhttp" or result.transport == "splithttp") then
log("跳过节点:" .. result.remarks .."因Sing-Box不支持" .. szType .. "协议的" .. result.transport .. "传输方式需更换Xray。") log("跳过节点:" .. result.remarks .."因Sing-Box不支持" .. szType .. "协议的" .. result.transport .. "传输方式需更换Xray。")
@ -1194,7 +1194,7 @@ local function processData(szType, content, add_mode, add_from)
result.encryption = params.encryption or "none" result.encryption = params.encryption or "none"
result.flow = params.flow or nil result.flow = params.flow and params.flow:gsub("-udp443", "") or nil
result.tls = "0" result.tls = "0"
if params.security == "tls" or params.security == "reality" then if params.security == "tls" or params.security == "reality" then
@ -1272,7 +1272,6 @@ local function processData(szType, content, add_mode, add_from)
else else
result.address = host_port result.address = host_port
end end
result.protocol = params.protocol
result.hysteria_obfs = params.obfsParam result.hysteria_obfs = params.obfsParam
result.hysteria_auth_type = "string" result.hysteria_auth_type = "string"
result.hysteria_auth_password = params.auth result.hysteria_auth_password = params.auth

View File

@ -408,6 +408,7 @@ o:depends("type", "ssr")
-- [[ Hysteria2 ]]-- -- [[ Hysteria2 ]]--
o = s:option(Value, "hy2_auth", translate("Users Authentication")) o = s:option(Value, "hy2_auth", translate("Users Authentication"))
o:depends("type", "hysteria2") o:depends("type", "hysteria2")
o.password = true
o.rmempty = false o.rmempty = false
o = s:option(Flag, "flag_port_hopping", translate("Enable Port Hopping")) o = s:option(Flag, "flag_port_hopping", translate("Enable Port Hopping"))
@ -455,6 +456,7 @@ o.placeholder = "salamander"
o = s:option(Value, "salamander", translate("Obfuscation Password")) o = s:option(Value, "salamander", translate("Obfuscation Password"))
o:depends({type = "hysteria2", flag_obfs = "1"}) o:depends({type = "hysteria2", flag_obfs = "1"})
o.password = true
o.rmempty = true o.rmempty = true
o.placeholder = "cry_me_a_r1ver" o.placeholder = "cry_me_a_r1ver"
@ -575,6 +577,7 @@ o.default="auto"
-- [[ TUIC ]] -- [[ TUIC ]]
-- TuicNameId -- TuicNameId
o = s:option(Value, "tuic_uuid", translate("TUIC User UUID")) o = s:option(Value, "tuic_uuid", translate("TUIC User UUID"))
o.password = true
o.rmempty = true o.rmempty = true
o.default = uuid o.default = uuid
o:depends("type", "tuic") o:depends("type", "tuic")
@ -588,6 +591,7 @@ o:depends("type", "tuic")
-- Tuic Password -- Tuic Password
o = s:option(Value, "tuic_passwd", translate("TUIC User Password")) o = s:option(Value, "tuic_passwd", translate("TUIC User Password"))
o.password = true
o.rmempty = true o.rmempty = true
o.default = "" o.default = ""
o:depends("type", "tuic") o:depends("type", "tuic")
@ -675,6 +679,7 @@ o:depends({type = "v2ray", v2ray_protocol = "vmess"})
-- VmessId -- VmessId
o = s:option(Value, "vmess_id", translate("Vmess/VLESS ID (UUID)")) o = s:option(Value, "vmess_id", translate("Vmess/VLESS ID (UUID)"))
o.password = true
o.rmempty = true o.rmempty = true
o.default = uuid o.default = uuid
o:depends({type = "v2ray", v2ray_protocol = "vmess"}) o:depends({type = "v2ray", v2ray_protocol = "vmess"})
@ -792,7 +797,7 @@ o:depends("transport", "splithttp")
o.rmempty = true o.rmempty = true
-- [[ XHTTP部分 ]]-- -- [[ XHTTP部分 ]]--
o = s:option(ListValue, "xhttp_alpn", translate("XHTTP Alpn")) o = s:option(ListValue, "xhttp_alpn", translate("XHTTP ALPN"))
o.default = "" o.default = ""
o:value("", translate("Default")) o:value("", translate("Default"))
o:value("h3") o:value("h3")
@ -1179,10 +1184,13 @@ o:depends("xtls", true)
o:depends("reality", true) o:depends("reality", true)
o.rmempty = true o.rmempty = true
o = s:option(DynamicList, "tls_alpn", translate("TLS ALPN")) o = s:option(ListValue, "tls_alpn", translate("TLS ALPN"))
o.default = ""
o:value("", translate("Default"))
o:value("h3")
o:value("spdy/3.1")
o:value("h3,spdy/3.1")
o:depends("type", "tuic") o:depends("type", "tuic")
o.default = "h3"
o.rmempty = true
-- [[ allowInsecure ]]-- -- [[ allowInsecure ]]--
o = s:option(Flag, "insecure", translate("allowInsecure")) o = s:option(Flag, "insecure", translate("allowInsecure"))

View File

@ -480,7 +480,7 @@ function import_ssr_url(btn, urlname, sid) {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_mode')[0].value = ssm.mode; document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_mode')[0].value = ssm.mode;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_host')[0].value = ssm.host; document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_host')[0].value = ssm.host;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_path')[0].value = ssm.path; document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_path')[0].value = ssm.path;
if (params.get("extra") && params.get("extra").trim() !== "") { if (ssm.extra !== "" && ssm.extra !== undefined) {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra')[0].checked = true; // 设置 enable_xhttp_extra 为 true document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra')[0].checked = true; // 设置 enable_xhttp_extra 为 true
document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra')[0].dispatchEvent(event); // 触发事件 document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra')[0].dispatchEvent(event); // 触发事件
document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_extra')[0].value = ssm.extra; document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_extra')[0].value = ssm.extra;
@ -500,17 +500,19 @@ function import_ssr_url(btn, urlname, sid) {
if (ssm.tls == "tls") { if (ssm.tls == "tls") {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].checked = true; document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].checked = true;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].dispatchEvent(event); document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].dispatchEvent(event);
if (ssm.fq !== "" && ssm.fq !== undefined) {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.fingerprint')[0].value = ssm.fp; document.getElementsByName('cbid.shadowsocksr.' + sid + '.fingerprint')[0].value = ssm.fp;
}
if (ssm.net == "xhttp") { if (ssm.net == "xhttp") {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_alpn')[0].value = ssm.alpn; document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_alpn')[0].value = ssm.alpn;
} }
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_host')[0].value = ssm.sni || ssm.host; document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_host')[0].value = ssm.sni || ssm.host;
} if (ssm.ech !== "" && ssm.ech !== undefined) {
if (ssm.tls == "tls") { document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_ech')[0].checked = true; // 设置 enable_ech 为 true
document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_ech')[0].checked = true; document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_ech')[0].dispatchEvent(event); // 触发事件
document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_ech')[0].dispatchEvent(event);
document.getElementsByName('cbid.shadowsocksr.' + sid + '.ech_config')[0].value = ssm.ech; document.getElementsByName('cbid.shadowsocksr.' + sid + '.ech_config')[0].value = ssm.ech;
} }
}
if (ssm.mux !== undefined) { if (ssm.mux !== undefined) {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.mux')[0].checked = true; document.getElementsByName('cbid.shadowsocksr.' + sid + '.mux')[0].checked = true;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.mux')[0].dispatchEvent(event); document.getElementsByName('cbid.shadowsocksr.' + sid + '.mux')[0].dispatchEvent(event);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -212,7 +212,19 @@ end
security = (server.xtls == '1') and "xtls" or (server.tls == '1') and "tls" or (server.reality == '1') and "reality" or nil, security = (server.xtls == '1') and "xtls" or (server.tls == '1') and "tls" or (server.reality == '1') and "reality" or nil,
tlsSettings = (server.tls == '1') and { tlsSettings = (server.tls == '1') and {
-- tls -- tls
alpn = (server.transport == "xhttp" and server.xhttp_alpn ~= "") and server.xhttp_alpn or server.tls_alpn, alpn = (server.transport == "xhttp") and (function()
local alpn = {}
if server.xhttp_alpn and server.xhttp_alpn ~= "" then
string.gsub(server.xhttp_alpn, '[^,]+', function(w)
table.insert(alpn, w)
end)
end
if #alpn > 0 then
return alpn
else
return nil
end
end)() or nil,
fingerprint = server.fingerprint, fingerprint = server.fingerprint,
allowInsecure = (server.insecure == "1"), allowInsecure = (server.insecure == "1"),
serverName = server.tls_host, serverName = server.tls_host,
@ -580,7 +592,19 @@ local tuic = {
timeout = server.timeout and server.timeout .. "s" or nil, timeout = server.timeout and server.timeout .. "s" or nil,
gc_interval = server.gc_interval and server.gc_interval .. "s" or nil, gc_interval = server.gc_interval and server.gc_interval .. "s" or nil,
gc_lifetime = server.gc_lifetime and server.gc_lifetime .. "s" or nil, gc_lifetime = server.gc_lifetime and server.gc_lifetime .. "s" or nil,
alpn = server.tls_alpn, alpn = (server.type == "tuic") and (function()
local alpn = {}
if server.tls_alpn and server.tls_alpn ~= "" then
string.gsub(server.tls_alpn, '[^,]+', function(w)
table.insert(alpn, w)
end)
end
if #alpn > 0 then
return alpn
else
return nil
end
end)() or nil,
disable_sni = (server.disable_sni == "1") and true or false, disable_sni = (server.disable_sni == "1") and true or false,
zero_rtt_handshake = (server.zero_rtt_handshake == "1") and true or false, zero_rtt_handshake = (server.zero_rtt_handshake == "1") and true or false,
send_window = tonumber(server.send_window), send_window = tonumber(server.send_window),

View File

@ -3,5 +3,3 @@
/etc/nikki/mixin.yaml /etc/nikki/mixin.yaml
/etc/nikki/run/providers/rule/ /etc/nikki/run/providers/rule/
/etc/nikki/run/providers/proxy/ /etc/nikki/run/providers/proxy/
/etc/nikki/nftables/reserved_ip.nft
/etc/nikki/nftables/reserved_ip6.nft

View File

@ -70,8 +70,8 @@
push(lan_access_control, access_control); push(lan_access_control, access_control);
}); });
const reserved_ip = uci_array(uci.get('momo', 'proxy', 'reserved_ip')); const reserved_ip = uci_array(uci.get('nikki', 'proxy', 'reserved_ip'));
const reserved_ip6 = uci_array(uci.get('momo', 'proxy', 'reserved_ip6')); const reserved_ip6 = uci_array(uci.get('nikki', 'proxy', 'reserved_ip6'));
const bypass_dscp = uci_array(uci.get('nikki', 'proxy', 'bypass_dscp')); const bypass_dscp = uci_array(uci.get('nikki', 'proxy', 'bypass_dscp'));
const bypass_china_mainland_ip = uci_bool(uci.get('nikki', 'proxy', 'bypass_china_mainland_ip')); const bypass_china_mainland_ip = uci_bool(uci.get('nikki', 'proxy', 'bypass_china_mainland_ip'));
const proxy_tcp_dport = split((uci.get('nikki', 'proxy', 'proxy_tcp_dport') ?? '0-65535'), ' '); const proxy_tcp_dport = split((uci.get('nikki', 'proxy', 'proxy_tcp_dport') ?? '0-65535'), ' ');