update 2023-03-17 23:37:01
This commit is contained in:
parent
4b29bcffc4
commit
bf0101179b
|
@ -5,7 +5,7 @@
|
|||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-homeproxy
|
||||
PKG_VERSION:=usertesting-0337
|
||||
PKG_VERSION:=usertesting-0311
|
||||
|
||||
LUCI_TITLE:=The modern ImmortalWrt proxy platform for ARM64/AMD64
|
||||
LUCI_PKGARCH:=all
|
||||
|
|
|
@ -293,6 +293,7 @@ return view.extend({
|
|||
var m, s, o, ss, so;
|
||||
var main_node = uci.get(data[0], 'config', 'main_node');
|
||||
var routing_mode = uci.get(data[0], 'config', 'routing_mode');
|
||||
var features = data[1];
|
||||
|
||||
m = new form.Map('homeproxy', _('Edit nodes'));
|
||||
|
||||
|
@ -334,7 +335,7 @@ return view.extend({
|
|||
var packet_encoding = uci.get(data[0], 'subscription', 'packet_encoding');
|
||||
var imported_node = 0;
|
||||
input_links.forEach((l) => {
|
||||
var config = parseShareLink(l, data[1]);
|
||||
var config = parseShareLink(l, features);
|
||||
if (config) {
|
||||
if (config.tls === '1' && allow_insecure === '1')
|
||||
config.tls_insecure = '1'
|
||||
|
@ -428,15 +429,15 @@ return view.extend({
|
|||
so = ss.option(form.ListValue, 'type', _('Type'));
|
||||
so.value('direct', _('Direct'));
|
||||
so.value('http', _('HTTP'));
|
||||
if (data[1].with_quic)
|
||||
if (features.with_quic)
|
||||
so.value('hysteria', _('Hysteria'));
|
||||
so.value('shadowsocks', _('Shadowsocks'));
|
||||
if (data[1].with_shadowsocksr)
|
||||
if (features.with_shadowsocksr)
|
||||
so.value('shadowsocksr', _('ShadowsocksR'));
|
||||
so.value('shadowtls', _('ShadowTLS'));
|
||||
so.value('socks', _('Socks'));
|
||||
so.value('trojan', _('Trojan'));
|
||||
if (data[1].with_wireguard)
|
||||
if (features.with_wireguard)
|
||||
so.value('wireguard', _('WireGuard'));
|
||||
so.value('vless', _('VLESS'));
|
||||
so.value('vmess', _('VMess'));
|
||||
|
@ -751,14 +752,40 @@ return view.extend({
|
|||
desc.innerHTML = _('No additional encryption support: It\'s basically duplicate encryption.');
|
||||
else
|
||||
desc.innerHTML = _('No TCP transport, plain HTTP is merged into the HTTP transport.');
|
||||
|
||||
var tls_element = this.map.findElement('id', 'cbid.homeproxy.%s.tls'.format(section_id)).firstElementChild;
|
||||
if ((value === 'http' && tls_element.checked) || (value === 'grpc' && !features.with_grpc)) {
|
||||
this.map.findElement('id', 'cbid.homeproxy.%s.http_idle_timeout'.format(section_id)).nextElementSibling.innerHTML =
|
||||
_('Specifies the period of time after which a health check will be performed using a ping frame if no frames have been received on the connection.<br/>' +
|
||||
'Please note that a ping response is considered a received frame, so if there is no other traffic on the connection, the health check will be executed every interval.');
|
||||
|
||||
this.map.findElement('id', 'cbid.homeproxy.%s.http_ping_timeout'.format(section_id)).nextElementSibling.innerHTML =
|
||||
_('Specifies the timeout duration after sending a PING frame, within which a response must be received.<br/>' +
|
||||
'If a response to the PING frame is not received within the specified timeout duration, the connection will be closed.');
|
||||
} else if (value === 'grpc' && features.with_grpc) {
|
||||
this.map.findElement('id', 'cbid.homeproxy.%s.http_idle_timeout'.format(section_id)).nextElementSibling.innerHTML =
|
||||
_('If the transport doesn\'t see any activity after a duration of this time, it pings the client to check if the connection is still active.');
|
||||
|
||||
this.map.findElement('id', 'cbid.homeproxy.%s.http_ping_timeout'.format(section_id)).nextElementSibling.innerHTML =
|
||||
_('The timeout that after performing a keepalive check, the client will wait for activity. If no activity is detected, the connection will be closed.');
|
||||
}
|
||||
}
|
||||
so.modalonly = true;
|
||||
|
||||
/* gRPC config */
|
||||
/* gRPC config start */
|
||||
so = ss.option(form.Value, 'grpc_servicename', _('gRPC service name'));
|
||||
so.depends('transport', 'grpc');
|
||||
so.modalonly = true;
|
||||
|
||||
if (features.with_grpc) {
|
||||
so = ss.option(form.Flag, 'grpc_permit_without_stream', _('gRPC permit without stream'),
|
||||
_('If enabled, the client transport sends keepalive pings even with no active connections.'));
|
||||
so.default = so.disabled;
|
||||
so.depends('transport', 'grpc');
|
||||
so.modalonly = true;
|
||||
}
|
||||
/* gRPC config end */
|
||||
|
||||
/* HTTP config start */
|
||||
so = ss.option(form.DynamicList, 'http_host', _('Host'));
|
||||
so.datatype = 'hostname';
|
||||
|
@ -774,6 +801,22 @@ return view.extend({
|
|||
so.value('put', _('PUT'));
|
||||
so.depends('transport', 'http');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.option(form.Value, 'http_idle_timeout', _('Idle timeout'),
|
||||
_('Specifies the period of time after which a health check will be performed using a ping frame if no frames have been received on the connection.<br/>' +
|
||||
'Please note that a ping response is considered a received frame, so if there is no other traffic on the connection, the health check will be executed every interval.'));
|
||||
so.datatype = 'uinteger';
|
||||
so.depends('transport', 'grpc');
|
||||
so.depends({'transport': 'http', 'tls': '1'});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.option(form.Value, 'http_ping_timeout', _('Ping timeout'),
|
||||
_('Specifies the timeout duration after sending a PING frame, within which a response must be received.<br/>' +
|
||||
'If a response to the PING frame is not received within the specified timeout duration, the connection will be closed.'));
|
||||
so.datatype = 'uinteger';
|
||||
so.depends('transport', 'grpc');
|
||||
so.depends({'transport': 'http', 'tls': '1'});
|
||||
so.modalonly = true;
|
||||
/* HTTP config end */
|
||||
|
||||
/* WebSocket config start */
|
||||
|
@ -960,7 +1003,7 @@ return view.extend({
|
|||
so.onclick = L.bind(hp.uploadCertificate, this, _('certificate'), 'client_ca');
|
||||
so.modalonly = true;
|
||||
|
||||
if (data[1].with_ech) {
|
||||
if (features.with_ech) {
|
||||
so = ss.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.'));
|
||||
so.depends('tls', '1');
|
||||
|
@ -982,7 +1025,7 @@ return view.extend({
|
|||
so.modalonly = true;
|
||||
}
|
||||
|
||||
if (data[1].with_utls) {
|
||||
if (features.with_utls) {
|
||||
so = ss.option(form.ListValue, 'tls_utls', _('uTLS fingerprint'),
|
||||
_('uTLS is a fork of "crypto/tls", which provides ClientHello fingerprinting resistance.'));
|
||||
so.value('', _('Disable'));
|
||||
|
@ -997,6 +1040,15 @@ return view.extend({
|
|||
so.value('randomized', _('Randomized'));
|
||||
so.value('safari', _('Safari'));
|
||||
so.depends('tls', '1');
|
||||
so.validate = function(section_id, value) {
|
||||
if (section_id) {
|
||||
let tls_reality = this.map.lookupOption('tls_reality', section_id)[0].formvalue(section_id);
|
||||
if (tls_reality && !value)
|
||||
return _('Expecting: %s').format(_('non-empty value'));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.option(form.Flag, 'tls_reality', _('REALITY'));
|
||||
|
|
|
@ -21,6 +21,7 @@ return view.extend({
|
|||
|
||||
render: function(data) {
|
||||
var m, s, o;
|
||||
var features = data[1];
|
||||
|
||||
m = new form.Map('homeproxy', _('Edit servers'));
|
||||
|
||||
|
@ -54,7 +55,7 @@ return view.extend({
|
|||
|
||||
o = s.option(form.ListValue, 'type', _('Type'));
|
||||
o.value('http', _('HTTP'));
|
||||
if (data[1].with_quic) {
|
||||
if (features.with_quic) {
|
||||
o.value('hysteria', _('Hysteria'));
|
||||
o.value('naive', _('NaïveProxy'));
|
||||
}
|
||||
|
@ -231,17 +232,27 @@ return view.extend({
|
|||
desc.innerHTML = _('No additional encryption support: It\'s basically duplicate encryption.');
|
||||
else
|
||||
desc.innerHTML = _('No TCP transport, plain HTTP is merged into the HTTP transport.');
|
||||
|
||||
var tls_element = this.map.findElement('id', 'cbid.homeproxy.%s.tls'.format(section_id)).firstElementChild;
|
||||
if ((value === 'http' && tls_element.checked) || (value === 'grpc' && !features.with_grpc))
|
||||
this.map.findElement('id', 'cbid.homeproxy.%s.http_idle_timeout'.format(section_id)).nextElementSibling.innerHTML =
|
||||
_('Specifies the time until idle clients should be closed with a GOAWAY frame. PING frames are not considered as activity.');
|
||||
else if (value === 'grpc' && features.with_grpc)
|
||||
this.map.findElement('id', 'cbid.homeproxy.%s.http_idle_timeout'.format(section_id)).nextElementSibling.innerHTML =
|
||||
_('If the transport doesn\'t see any activity after a duration of this time, it pings the client to check if the connection is still active.');
|
||||
}
|
||||
o.depends('type', 'trojan');
|
||||
o.depends('type', 'vless');
|
||||
o.depends('type', 'vmess');
|
||||
o.modalonly = true;
|
||||
|
||||
/* gRPC config */
|
||||
/* gRPC config start */
|
||||
o = s.option(form.Value, 'grpc_servicename', _('gRPC service name'));
|
||||
o.depends('transport', 'grpc');
|
||||
o.modalonly = true;
|
||||
|
||||
/* gRPC config end */
|
||||
|
||||
/* HTTP config start */
|
||||
o = s.option(form.DynamicList, 'http_host', _('Host'));
|
||||
o.datatype = 'hostname';
|
||||
|
@ -255,6 +266,21 @@ return view.extend({
|
|||
o = s.option(form.Value, 'http_method', _('Method'));
|
||||
o.depends('transport', 'http');
|
||||
o.modalonly = true;
|
||||
|
||||
o = s.option(form.Value, 'http_idle_timeout', _('Idle timeout'),
|
||||
_('Specifies the time until idle clients should be closed with a GOAWAY frame. PING frames are not considered as activity.'));
|
||||
o.datatype = 'uinteger';
|
||||
o.depends('transport', 'grpc');
|
||||
o.depends({'transport': 'http', 'tls': '1'});
|
||||
o.modalonly = true;
|
||||
|
||||
if (features.with_grpc) {
|
||||
o = s.option(form.Value, 'http_ping_timeout', _('Ping timeout'),
|
||||
_('The timeout that after performing a keepalive check, the client will wait for activity. If no activity is detected, the connection will be closed.'));
|
||||
o.datatype = 'uinteger';
|
||||
o.depends('transport', 'grpc');
|
||||
o.modalonly = true;
|
||||
}
|
||||
/* HTTP config end */
|
||||
|
||||
/* WebSocket config start */
|
||||
|
@ -330,7 +356,7 @@ return view.extend({
|
|||
o.optional = true;
|
||||
o.modalonly = true;
|
||||
|
||||
if (data[1].with_acme) {
|
||||
if (features.with_acme) {
|
||||
o = s.option(form.Flag, 'tls_acme', _('Enable ACME'),
|
||||
_('Use ACME TLS certificate issuer.'));
|
||||
o.default = o.disabled;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -10,8 +10,11 @@
|
|||
import { readfile, writefile } from 'fs';
|
||||
import { cursor } from 'uci';
|
||||
|
||||
import { executeCommand, isEmpty, strToInt, removeBlankAttrs, validateHostname, validation } from 'homeproxy';
|
||||
import { HP_DIR, RUN_DIR } from 'homeproxy';
|
||||
import {
|
||||
executeCommand, isEmpty, strToInt,
|
||||
removeBlankAttrs, validateHostname, validation,
|
||||
HP_DIR, RUN_DIR
|
||||
} from 'homeproxy';
|
||||
|
||||
/* UCI config start */
|
||||
const uci = cursor();
|
||||
|
@ -215,7 +218,10 @@ function generate_outbound(node) {
|
|||
method: node.http_method,
|
||||
max_early_data: strToInt(node.websocket_early_data),
|
||||
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,
|
||||
ping_timeout: node.http_ping_timeout ? (node.http_ping_timeout + 's') : null,
|
||||
permit_without_stream: (node.grpc_permit_without_stream === '1') || null
|
||||
} : null,
|
||||
udp_over_tcp: (node.udp_over_tcp === '1') || null,
|
||||
tcp_fast_open: (node.tcp_fast_open === '1') || null,
|
||||
|
@ -325,7 +331,7 @@ if (!isEmpty(main_node)) {
|
|||
if (dns_server !== wan_dns) {
|
||||
push(config.dns.servers, {
|
||||
tag: 'main-dns',
|
||||
address: 'tcp://' + ((validation('ip6addr', dns_server) === 0) ? `[${dns_server}]` : dns_server),
|
||||
address: 'tcp://' + (validation('ip6addr', dns_server) ? `[${dns_server}]` : dns_server),
|
||||
strategy: (ipv6_support !== '1') ? 'ipv4_only' : null,
|
||||
detour: 'main-out'
|
||||
});
|
||||
|
@ -524,7 +530,9 @@ if (server_enabled === '1')
|
|||
method: cfg.http_method,
|
||||
max_early_data: strToInt(cfg.websocket_early_data),
|
||||
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,
|
||||
ping_timeout: cfg.http_ping_timeout ? (cfg.http_ping_timeout + 's') : null
|
||||
} : null
|
||||
});
|
||||
});
|
||||
|
|
|
@ -114,7 +114,7 @@ export function validation(datatype, data) {
|
|||
return null;
|
||||
|
||||
const ret = system(`/sbin/validate_data ${shellQuote(datatype)} ${shellQuote(data)} 2>/dev/null`);
|
||||
return ret;
|
||||
return (ret === 0);
|
||||
};
|
||||
/* String helper end */
|
||||
|
||||
|
@ -174,9 +174,9 @@ export function parseURL(url) {
|
|||
return '';
|
||||
});
|
||||
|
||||
if (validation('ip4addr', val) === 0 ||
|
||||
validation('ip6addr', replace(val, /\[|\]/g, '')) === 0 ||
|
||||
validation('hostname', val) === 0)
|
||||
if (validation('ip4addr', val) ||
|
||||
validation('ip6addr', replace(val, /\[|\]/g, '')) ||
|
||||
validation('hostname', val))
|
||||
objurl.hostname = val;
|
||||
|
||||
return '';
|
||||
|
|
|
@ -360,11 +360,11 @@ function parse_uri(uri) {
|
|||
if (config.address)
|
||||
config.address = replace(config.address, /\[|\]/g, '');
|
||||
|
||||
if (validation('host', config.address) !== 0 || validation('port', config.port) !== 0) {
|
||||
if (!validation('host', config.address) || !validation('port', config.port)) {
|
||||
log(sprintf('Skipping invalid %s node: %s.', config.type, config.label || 'NULL'));
|
||||
return null;
|
||||
} else if (!config.label)
|
||||
config.label = (validation('ip6addr', config.address) === 0 ?
|
||||
config.label = (validation('ip6addr', config.address) ?
|
||||
`[${config.address}]` : config.address) + ':' + config.port;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue