mirror of
https://github.com/kenzok8/small-package
synced 2025-01-05 11:36:47 +08:00
update 2024-11-16 20:36:29
This commit is contained in:
parent
cb401e1147
commit
c1836cab65
@ -10,12 +10,12 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=haproxy
|
||||
PKG_VERSION:=3.0.5
|
||||
PKG_VERSION:=3.0.6
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://www.haproxy.org/download/3.0/src
|
||||
PKG_HASH:=ae38221e85aeba038a725efbef5bfe5e76671ba7959e5eb74c39fd079e5d002e
|
||||
PKG_HASH:=cf1bf58b5bc79c48db7b01667596ffd98343adb29a41096f075f00a8f90a7335
|
||||
|
||||
PKG_MAINTAINER:=Thomas Heil <heil@terminal-consulting.de>, \
|
||||
Christian Lachner <gladiac@gmail.com>
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
CLONEURL=https://git.haproxy.org/git/haproxy-3.0.git
|
||||
BASE_TAG=v3.0.5
|
||||
BASE_TAG=v3.0.6
|
||||
TMP_REPODIR=tmprepo
|
||||
PATCHESDIR=patches
|
||||
|
||||
|
@ -81,6 +81,7 @@ return baseclass.extend({
|
||||
],
|
||||
|
||||
outbound_type: [
|
||||
['direct', _('DIRECT')],
|
||||
['http', _('HTTP')],
|
||||
['socks5', _('SOCKS5')],
|
||||
['ss', _('Shadowsocks')],
|
||||
@ -89,7 +90,7 @@ return baseclass.extend({
|
||||
['vmess', _('VMess')],
|
||||
['vless', _('VLESS')],
|
||||
['trojan', _('Trojan')],
|
||||
['hysteria', _('Hysteria')],
|
||||
//['hysteria', _('Hysteria')],
|
||||
['hysteria2', _('Hysteria2')],
|
||||
['tuic', _('TUIC')],
|
||||
['wireguard', _('WireGuard')],
|
||||
@ -652,6 +653,8 @@ return baseclass.extend({
|
||||
return true;
|
||||
},
|
||||
validateAuthPassword: function(section_id, value) {
|
||||
if (!value)
|
||||
return true;
|
||||
if (!value.match(/^[^:]+$/))
|
||||
return _('Expecting: %s').format('[^:]+');
|
||||
|
||||
@ -703,6 +706,25 @@ return baseclass.extend({
|
||||
return true;
|
||||
},
|
||||
|
||||
validateShadowsocksPassword: function(self, encmode, section_id, value) {
|
||||
var length = self.shadowsocks_cipher_length[encmode];
|
||||
if (typeof length !== 'undefined') {
|
||||
length = Math.ceil(length/3)*4;
|
||||
if (encmode.match(/^2022-/)) {
|
||||
if (value.length !== length || !value.match(/^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/) || value[length-1] !== '=')
|
||||
return _('Expecting: %s').format(_('valid base64 key with %d characters').format(length));
|
||||
} else {
|
||||
if (length === 0 && !value)
|
||||
return _('Expecting: %s').format(_('non-empty value'));
|
||||
if (length !== 0 && value.length !== length)
|
||||
return _('Expecting: %s').format(_('valid key length with %d characters').format(length));
|
||||
}
|
||||
} else
|
||||
return true;
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
validateTimeDuration: function(section_id, value) {
|
||||
if (!value)
|
||||
return true;
|
||||
|
@ -37,20 +37,672 @@ return view.extend({
|
||||
ss.renderSectionAdd = L.bind(hm.renderSectionAdd, ss, prefmt, true);
|
||||
ss.handleAdd = L.bind(hm.handleAdd, ss, prefmt);
|
||||
|
||||
so = ss.option(form.Value, 'label', _('Label'));
|
||||
ss.tab('field_general', _('General fields'));
|
||||
ss.tab('field_tls', _('TLS fields'));
|
||||
ss.tab('field_transport', _('Transport fields'));
|
||||
ss.tab('field_multiplex', _('Multiplex fields'));
|
||||
ss.tab('field_dial', _('Dial fields'));
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'label', _('Label'));
|
||||
so.load = L.bind(hm.loadDefaultLabel, so);
|
||||
so.validate = L.bind(hm.validateUniqueValue, so);
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.option(form.Flag, 'enabled', _('Enable'));
|
||||
so = ss.taboption('field_general', form.Flag, 'enabled', _('Enable'));
|
||||
so.default = so.enabled;
|
||||
so.editable = true;
|
||||
|
||||
so = ss.option(form.ListValue, 'type', _('Type'));
|
||||
so = ss.taboption('field_general', form.ListValue, 'type', _('Type'));
|
||||
so.default = hm.outbound_type[0][0];
|
||||
hm.outbound_type.forEach((res) => {
|
||||
so.value.apply(so, res);
|
||||
})
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'server', _('Server address'));
|
||||
so.datatype = 'host';
|
||||
so.rmempty = false;
|
||||
so.depends({type: 'direct', '!reverse': true});
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'port', _('Port'));
|
||||
so.datatype = 'port';
|
||||
so.rmempty = false;
|
||||
so.depends({type: 'direct', '!reverse': true});
|
||||
|
||||
/* HTTP / SOCKS fields */
|
||||
/* hm.validateAuth */
|
||||
so = ss.taboption('field_general', form.Value, 'username', _('Username'));
|
||||
so.validate = L.bind(hm.validateAuthUsername, so);
|
||||
so.depends({type: /^(http|socks5|ssh)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'password', _('Password'));
|
||||
so.password = true;
|
||||
so.validate = L.bind(hm.validateAuthPassword, so);
|
||||
so.depends({type: /^(http|socks5|trojan|hysteria2|tuic|ssh)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.TextValue, 'headers', _('HTTP header'));
|
||||
so.renderWidget = function(/* ... */) {
|
||||
var frameEl = form.TextValue.prototype.renderWidget.apply(this, arguments);
|
||||
|
||||
frameEl.firstChild.style.fontFamily = hm.monospacefonts.join(',');
|
||||
|
||||
return frameEl;
|
||||
}
|
||||
so.placeholder = '{\n "User-Agent": [\n "Clash/v1.18.0",\n "mihomo/1.18.3"\n ],\n "Authorization": [\n //"token 1231231"\n ]\n}';
|
||||
so.validate = L.bind(hm.validateJson, so);
|
||||
so.depends('type', 'http');
|
||||
so.modalonly = true;
|
||||
|
||||
/* Hysteria / Hysteria2 fields */
|
||||
so = ss.taboption('field_general', form.DynamicList, 'hysteria_ports', _('Ports pool'));
|
||||
so.datatype = 'or(port, portrange)';
|
||||
so.depends({type: /^(hysteria|hysteria2)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'hysteria_up_mbps', _('Max upload speed'),
|
||||
_('In Mbps.'));
|
||||
so.datatype = 'uinteger';
|
||||
so.depends({type: /^(hysteria|hysteria2)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'hysteria_down_mbps', _('Max download speed'),
|
||||
_('In Mbps.'));
|
||||
so.datatype = 'uinteger';
|
||||
so.depends({type: /^(hysteria|hysteria2)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.ListValue, 'hysteria_obfs_type', _('Obfuscate type'));
|
||||
so.value('', _('Disable'));
|
||||
so.value('salamander', _('Salamander'));
|
||||
so.depends('type', 'hysteria2');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'hysteria_obfs_password', _('Obfuscate password'),
|
||||
_('Enabling obfuscation will make the server incompatible with standard QUIC connections, losing the ability to masquerade with HTTP/3.'));
|
||||
so.password = true;
|
||||
so.rmempty = false;
|
||||
so.depends('type', 'hysteria');
|
||||
so.depends({type: 'hysteria2', hysteria_obfs_type: /.+/});
|
||||
so.modalonly = true;
|
||||
|
||||
/* SSH fields */
|
||||
so = ss.taboption('field_general', form.TextValue, 'ssh_priv_key', _('Priv-key'));
|
||||
so.depends('type', 'ssh');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'ssh_priv_key_passphrase', _('Priv-key passphrase'));
|
||||
so.password = true;
|
||||
so.depends({type: 'ssh', ssh_priv_key: /.+/});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.DynamicList, 'ssh_host_key_algorithms', _('Host-key algorithms'));
|
||||
so.placeholder = 'rsa';
|
||||
so.depends('type', 'ssh');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.DynamicList, 'ssh_host_key', _('Host-key'));
|
||||
so.placeholder = 'ssh-rsa AAAAB3NzaC1yc2EAA...';
|
||||
so.depends({type: 'ssh', ssh_host_key_algorithms: /.+/});
|
||||
so.modalonly = true;
|
||||
|
||||
/* Shadowsocks fields */
|
||||
so = ss.taboption('field_general', form.ListValue, 'shadowsocks_chipher', _('Chipher'));
|
||||
so.default = hm.shadowsocks_cipher_methods[1][0];
|
||||
hm.shadowsocks_cipher_methods.forEach((res) => {
|
||||
so.value.apply(so, res);
|
||||
})
|
||||
so.depends('type', 'ss');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'shadowsocks_password', _('Password'));
|
||||
so.password = true;
|
||||
so.validate = function(section_id, value) {
|
||||
var encmode = this.section.getOption('shadowsocks_chipher').formvalue(section_id);
|
||||
return hm.validateShadowsocksPassword.call(this, hm, encmode, section_id, value);
|
||||
}
|
||||
so.depends({type: 'ss', shadowsocks_chipher: /.+/});
|
||||
so.modalonly = true;
|
||||
|
||||
/* Snell fields */
|
||||
so = ss.taboption('field_general', form.Value, 'snell_psk', _('Pre-shared key'));
|
||||
so.password = true;
|
||||
so.rmempty = false;
|
||||
so.validate = L.bind(hm.validateAuthPassword, so);
|
||||
so.depends('type', 'snell');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.ListValue, 'snell_version', _('Version'));
|
||||
so.value('1', _('v1'));
|
||||
so.value('2', _('v2'));
|
||||
so.value('3', _('v3'));
|
||||
so.default = '3';
|
||||
so.depends('type', 'snell');
|
||||
so.modalonly = true;
|
||||
|
||||
/* TUIC fields */
|
||||
so = ss.taboption('field_general', form.Value, 'uuid', _('UUID'));
|
||||
so.rmempty = false;
|
||||
so.validate = L.bind(hm.validateUUID, so);
|
||||
so.depends('type', 'tuic');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'tuic_ip', _('IP override'),
|
||||
_('Override the IP address of the server that DNS response.'));
|
||||
so.datatype = 'ipaddr(1)';
|
||||
so.depends('type', 'tuic');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.ListValue, 'tuic_congestion_controller', _('Congestion controller'),
|
||||
_('QUIC congestion controller.'));
|
||||
so.default = 'cubic';
|
||||
so.value('cubic', _('cubic'));
|
||||
so.value('new_reno', _('new_reno'));
|
||||
so.value('bbr', _('bbr'));
|
||||
so.depends('type', 'tuic');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.ListValue, 'tuic_udp_relay_mode', _('UDP relay mode'),
|
||||
_('UDP packet relay mode.'));
|
||||
so.value('', _('Default'));
|
||||
so.value('native', _('Native'));
|
||||
so.value('quic', _('QUIC'));
|
||||
so.depends({type: 'tuic', tuic_udp_over_stream: '0'});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Flag, 'tuic_udp_over_stream', _('UDP over stream'),
|
||||
_('This is the TUIC port of the SUoT protocol, designed to provide a QUIC stream based UDP relay mode that TUIC does not provide.'));
|
||||
so.default = so.disabled;
|
||||
so.depends('type', 'tuic');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.ListValue, 'tuic_udp_over_stream_version', _('UDP over stream version'));
|
||||
so.value('1', _('v1'));
|
||||
so.depends({type: 'tuic', tuic_udp_over_stream: '1'});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'tuic_max_udp_relay_packet_size', _('Max UDP relay packet size'));
|
||||
so.datatype = 'uinteger';
|
||||
so.placeholder = '1500';
|
||||
so.depends('type', 'tuic');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Flag, 'tuic_reduce_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/>' +
|
||||
'Disabling this is highly recommended, as it is vulnerable to replay attacks.'));
|
||||
so.default = so.disabled;
|
||||
so.depends('type', 'tuic');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'tuic_heartbeat', _('Heartbeat interval'),
|
||||
_('In millisecond.'));
|
||||
so.datatype = 'uinteger';
|
||||
so.placeholder = '10000';
|
||||
so.depends('type', 'tuic');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'tuic_request_timeout', _('Request timeout'),
|
||||
_('In millisecond.'));
|
||||
so.datatype = 'uinteger';
|
||||
so.placeholder = '8000';
|
||||
so.depends('type', 'tuic');
|
||||
so.modalonly = true;
|
||||
|
||||
/* Trojan fields */
|
||||
so = ss.taboption('field_general', form.Flag, 'trojan_ss_enabled', _('Shadowsocks encrypt'));
|
||||
so.default = so.disabled;
|
||||
so.depends('type', 'trojan');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.ListValue, 'trojan_ss_chipher', _('Shadowsocks chipher'));
|
||||
so.value('aes-128-gcm', _('aes-128-gcm'));
|
||||
so.value('aes-256-gcm', _('aes-256-gcm'));
|
||||
so.value('chacha20-ietf-poly1305', _('chacha20-ietf-poly1305'));
|
||||
so.depends({type: 'trojan', trojan_ss_enabled: '1'});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'trojan_ss_password', _('Shadowsocks password'));
|
||||
so.password = true;
|
||||
so.validate = function(section_id, value) {
|
||||
var encmode = this.section.getOption('trojan_ss_chipher').formvalue(section_id);
|
||||
return hm.validateShadowsocksPassword.call(this, hm, encmode, section_id, value);
|
||||
}
|
||||
so.depends({type: 'trojan', trojan_ss_enabled: '1'});
|
||||
so.modalonly = true;
|
||||
|
||||
/* VMess / VLESS fields */
|
||||
so = ss.taboption('field_general', form.Value, 'vmess_uuid', _('UUID'));
|
||||
so.rmempty = false;
|
||||
so.validate = L.bind(hm.validateUUID, so);
|
||||
so.depends({type: /^(vmess|vless)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.ListValue, 'vless_flow', _('Flow'));
|
||||
so.value('', _('None'));
|
||||
so.value('xtls-rprx-vision');
|
||||
so.depends('type', 'vless');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'vmess_alterid', _('Alter ID'));
|
||||
so.datatype = 'uinteger';
|
||||
so.default = '0';
|
||||
so.depends('type', 'vmess');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.ListValue, 'vmess_chipher', _('Chipher'));
|
||||
so.default = 'auto';
|
||||
so.value('auto', _('auto'));
|
||||
so.value('none', _('none'));
|
||||
so.value('zero', _('zero'));
|
||||
so.value('aes-128-gcm', _('aes-128-gcm'));
|
||||
so.value('chacha20-poly1305', _('chacha20-poly1305'));
|
||||
so.depends('type', 'vmess');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Flag, 'vmess_global_padding', _('Global padding'),
|
||||
_('Protocol parameter. Will waste traffic randomly if enabled (enabled by default in v2ray and cannot be disabled).'));
|
||||
so.default = so.enabled;
|
||||
so.depends('type', 'vmess');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Flag, 'vmess_authenticated_length', _('Authenticated length'),
|
||||
_('Protocol parameter. Enable length block encryption.'));
|
||||
so.default = so.disabled;
|
||||
so.depends('type', 'vmess');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.ListValue, 'vmess_packet_encoding', _('Packet encoding'));
|
||||
so.value('', _('none'));
|
||||
so.value('packetaddr', _('packet addr (v2ray-core v5+)'));
|
||||
so.value('xudp', _('Xudp (Xray-core)'));
|
||||
so.depends({type: /^(vmess|vless)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
/* Plugin fields */
|
||||
so = ss.taboption('field_general', form.ListValue, 'plugin', _('Plugin'));
|
||||
so.value('', _('none'));
|
||||
so.value('obfs', _('obfs-simple'));
|
||||
//so.value('v2ray-plugin', _('v2ray-plugin'));
|
||||
so.value('shadow-tls', _('shadow-tls'));
|
||||
so.value('restls', _('restls'));
|
||||
so.depends('type', 'ss');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.ListValue, 'plugin_opts_obfsmode', _('Plugin: ') + _('Obfs Mode'));
|
||||
so.value('http', _('HTTP'));
|
||||
so.value('tls', _('TLS'));
|
||||
so.depends('plugin', 'obfs');
|
||||
so.depends('type', 'snell');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'plugin_opts_host', _('Plugin: ') + _('Host that supports TLS 1.3'));
|
||||
so.placeholder = 'cloud.tencent.com';
|
||||
so.rmempty = false;
|
||||
so.depends({plugin: /^(obfs|v2ray-plugin|shadow-tls|restls)$/});
|
||||
so.depends('type', 'snell');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'plugin_opts_thetlspassword', _('Plugin: ') + _('Password'));
|
||||
so.password = true;
|
||||
so.rmempty = false;
|
||||
so.depends({plugin: /^(shadow-tls|restls)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.ListValue, 'plugin_opts_shadowtls_version', _('Plugin: ') + _('Version'));
|
||||
so.value('1', _('v1'));
|
||||
so.value('2', _('v2'));
|
||||
so.value('3', _('v3'));
|
||||
so.default = '2';
|
||||
so.depends({plugin: 'shadow-tls'});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'plugin_opts_restls_versionhint', _('Plugin: ') + _('Version hint'));
|
||||
so.default = 'tls13';
|
||||
so.rmempty = false;
|
||||
so.depends({plugin: 'restls'});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'plugin_opts_restls_script', _('Plugin: ') + _('Restls script'));
|
||||
so.default = '300?100<1,400~100,350~100,600~100,300~200,300~100';
|
||||
so.rmempty = false;
|
||||
so.depends({plugin: 'restls'});
|
||||
so.modalonly = true;
|
||||
|
||||
/* Extra fields */
|
||||
so = ss.taboption('field_general', form.Flag, 'udp', _('UDP'));
|
||||
so.default = so.disabled;
|
||||
so.depends({type: /^(direct|socks5|ss|vmess|vless|trojan|wireguard)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Flag, 'uot', _('UoT'),
|
||||
_('Enable the SUoT protocol, requires server support. Conflict with Multiplex.'));
|
||||
so.default = so.disabled;
|
||||
so.depends('type', 'ss');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.ListValue, 'uot_version', _('SUoT version'));
|
||||
so.value('1', _('v1'));
|
||||
so.value('2', _('v2'));
|
||||
so.default = '2';
|
||||
so.depends('uot', '1');
|
||||
so.modalonly = true;
|
||||
|
||||
/* TLS fields */
|
||||
so = ss.taboption('field_general', form.Flag, 'tls', _('TLS'));
|
||||
so.default = so.disabled;
|
||||
so.validate = function(section_id, value) {
|
||||
var type = this.section.getOption('type').formvalue(section_id);
|
||||
var tls = this.section.getUIElement(section_id, 'tls').node.querySelector('input');
|
||||
var tls_alpn = this.section.getUIElement(section_id, 'tls_alpn');
|
||||
|
||||
// Force enabled
|
||||
if (['trojan', 'hysteria', 'hysteria2', 'tuic'].includes(type)) {
|
||||
tls.checked = true;
|
||||
tls.disabled = true;
|
||||
} else {
|
||||
tls.disabled = null;
|
||||
}
|
||||
|
||||
// Default alpn
|
||||
if (!`${tls_alpn.getValue()}`) {
|
||||
let def_alpn;
|
||||
|
||||
switch (type) {
|
||||
case 'hysteria':
|
||||
case 'hysteria2':
|
||||
case 'tuic':
|
||||
def_alpn = ['h3'];
|
||||
break;
|
||||
case 'vmess':
|
||||
case 'vless':
|
||||
case 'trojan':
|
||||
def_alpn = ['h2', 'http/1.1'];
|
||||
break;
|
||||
default:
|
||||
def_alpn = [];
|
||||
}
|
||||
|
||||
tls_alpn.setValue(def_alpn);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
so.depends({type: /^(http|socks5|vmess|vless|trojan|hysteria|hysteria2|tuic)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_tls', form.Flag, 'tls_disable_sni', _('Disable SNI'),
|
||||
_('Donot send server name in ClientHello.'));
|
||||
so.default = so.disabled;
|
||||
so.depends({tls: '1', type: /^(tuic)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_tls', form.Value, 'tls_sni', _('TLS SNI'),
|
||||
_('Used to verify the hostname on the returned certificates.'));
|
||||
so.depends({tls: '1', type: /^(http|vmess|vless|trojan|hysteria|hysteria2)$/});
|
||||
so.depends({tls: '1', tls_disable_sni: '0', type: /^(tuic)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_tls', form.DynamicList, 'tls_alpn', _('TLS ALPN'),
|
||||
_('List of supported application level protocols, in order of preference.'));
|
||||
so.depends({tls: '1', type: /^(vmess|vless|trojan|hysteria|hysteria2|tuic)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_tls', form.Value, 'tls_fingerprint', _('Cert fingerprint'),
|
||||
_('Certificate fingerprint. Used to implement SSL Pinning and prevent MitM.'));
|
||||
so.validate = function(section_id, value) {
|
||||
if (!value)
|
||||
return true;
|
||||
if (!((value.length === 64) && (value.match(/^[0-9a-fA-F]+$/))))
|
||||
return _('Expecting: %s').format(_('valid SHA256 string with %d characters').format(64));
|
||||
|
||||
return true;
|
||||
}
|
||||
so.depends({tls: '1', type: /^(http|socks5|vmess|vless|trojan|hysteria|hysteria2)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_tls', form.Flag, 'tls_skip_cert_verify', _('Skip cert verify'),
|
||||
_('Donot verifying server certificate.') +
|
||||
'<br/>' +
|
||||
_('This is <strong>DANGEROUS</strong>, your traffic is almost like <strong>PLAIN TEXT</strong>! Use at your own risk!'));
|
||||
so.default = so.disabled;
|
||||
so.depends({tls: '1', type: /^(http|socks5|vmess|vless|trojan|hysteria|hysteria2|tuic)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
// uTLS fields
|
||||
so = ss.taboption('field_tls', form.ListValue, 'tls_client_fingerprint', _('Client fingerprint'));
|
||||
so.default = hm.tls_client_fingerprints[0][0];
|
||||
hm.tls_client_fingerprints.forEach((res) => {
|
||||
so.value.apply(so, res);
|
||||
})
|
||||
so.depends({tls: '1', type: /^(vmess|vless|trojan)$/});
|
||||
so.depends({type: 'ss', plugin: /^(shadow-tls|restls)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_tls', form.Flag, 'tls_reality', _('REALITY'));
|
||||
so.default = so.disabled;
|
||||
so.depends({tls: '1', type: /^(vmess|vless|trojan)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_tls', form.Value, 'tls_reality_public_key', _('REALITY public key'));
|
||||
so.rmempty = false;
|
||||
so.depends('tls_reality', '1');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_tls', form.Value, 'tls_reality_short_id', _('REALITY short ID'));
|
||||
so.rmempty = false;
|
||||
so.depends('tls_reality', '1');
|
||||
so.modalonly = true;
|
||||
|
||||
/* Transport fields */
|
||||
so = ss.taboption('field_general', form.Flag, 'transport_enabled', _('Transport'));
|
||||
so.default = so.disabled;
|
||||
so.depends({type: /^(vmess|vless|trojan)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_transport', form.ListValue, 'transport_type', _('Transport type'));
|
||||
so.default = 'http';
|
||||
so.value('http', _('HTTP'));
|
||||
so.value('h2', _('HTTPUpgrade'));
|
||||
so.value('grpc', _('gRPC'));
|
||||
so.value('ws', _('WebSocket'));
|
||||
so.validate = function(section_id, value) {
|
||||
var type = this.section.getOption('type').formvalue(section_id);
|
||||
|
||||
switch (type) {
|
||||
case 'vmess':
|
||||
case 'vless':
|
||||
if (!['http', 'h2', 'grpc', 'ws'].includes(value))
|
||||
return _('Expecting: only support %s.').format(_('HTTP') +
|
||||
' / ' + _('HTTPUpgrade') +
|
||||
' / ' + _('gRPC') +
|
||||
' / ' + _('WebSocket'));
|
||||
break;
|
||||
case 'trojan':
|
||||
if (!['grpc', 'ws'].includes(value))
|
||||
return _('Expecting: only support %s.').format(_('gRPC') +
|
||||
' / ' + _('WebSocket'));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
so.depends('transport_enabled', '1');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_transport', form.DynamicList, 'transport_hosts', _('Server hostname'));
|
||||
so.datatype = 'list(hostname)';
|
||||
so.placeholder = 'example.com';
|
||||
so.depends({transport_enabled: '1', transport_type: 'h2'});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_transport', form.Value, 'transport_http_method', _('HTTP request method'));
|
||||
so.value('GET', _('GET'));
|
||||
so.value('POST', _('POST'));
|
||||
so.value('PUT', _('PUT'));
|
||||
so.default = 'GET';
|
||||
so.rmempty = false;
|
||||
so.depends({transport_enabled: '1', transport_type: 'http'});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_transport', form.DynamicList, 'transport_paths', _('Request path'));
|
||||
so.placeholder = '/video';
|
||||
so.default = '/';
|
||||
so.rmempty = false;
|
||||
so.depends({transport_enabled: '1', transport_type: 'http'});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_transport', form.Value, 'transport_path', _('Request path'));
|
||||
so.placeholder = '/';
|
||||
so.default = '/';
|
||||
so.rmempty = false;
|
||||
so.depends({transport_enabled: '1', transport_type: /^(h2|ws)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_transport', form.TextValue, 'transport_http_headers', _('HTTP header'));
|
||||
so.renderWidget = function(/* ... */) {
|
||||
var frameEl = form.TextValue.prototype.renderWidget.apply(this, arguments);
|
||||
|
||||
frameEl.firstChild.style.fontFamily = hm.monospacefonts.join(',');
|
||||
|
||||
return frameEl;
|
||||
}
|
||||
so.placeholder = '{\n "Host": "example.com",\n "Connection": [\n "keep-alive"\n ]\n}';
|
||||
so.validate = L.bind(hm.validateJson, so);
|
||||
so.depends({transport_enabled: '1', transport_type: /^(http|ws)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_transport', form.Value, 'transport_grpc_servicename', _('gRPC service name'));
|
||||
so.depends({transport_enabled: '1', transport_type: 'grpc'});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_transport', form.Value, 'transport_ws_max_early_data', _('Max Early Data'),
|
||||
_('Early Data first packet length limit.'));
|
||||
so.datatype = 'uinteger';
|
||||
so.value('2048');
|
||||
so.depends({transport_enabled: '1', transport_type: 'ws'});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_transport', form.Value, 'transport_ws_early_data_header', _('Early Data header name'));
|
||||
so.value('Sec-WebSocket-Protocol');
|
||||
so.depends({transport_enabled: '1', transport_type: 'ws'});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_transport', form.Flag, 'transport_ws_v2ray_http_upgrade', _('V2ray HTTPUpgrade'));
|
||||
so.default = so.disabled;
|
||||
so.depends({transport_enabled: '1', transport_type: 'ws'});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_transport', form.Flag, 'transport_ws_v2ray_http_upgrade_fast_open', _('V2ray HTTPUpgrade fast open'));
|
||||
so.default = so.disabled;
|
||||
so.depends({transport_enabled: '1', transport_type: 'ws', transport_ws_v2ray_http_upgrade: '1'});
|
||||
so.modalonly = true;
|
||||
|
||||
/* Multiplex fields */ // TCP protocol only
|
||||
so = ss.taboption('field_general', form.Flag, 'smux_enabled', _('Multiplex'));
|
||||
so.default = so.disabled;
|
||||
so.depends({type: /^(vmess|vless|trojan)$/});
|
||||
so.depends({type: 'ss', uot: '0'});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_multiplex', form.ListValue, 'smux_protocol', _('Protocol'));
|
||||
so.default = 'h2mux';
|
||||
so.value('smux', _('smux'));
|
||||
so.value('yamux', _('yamux'));
|
||||
so.value('h2mux', _('h2mux'));
|
||||
so.depends('smux_enabled', '1');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_multiplex', form.Value, 'smux_max_connections', _('Maximum connections'));
|
||||
so.datatype = 'uinteger';
|
||||
so.placeholder = '4';
|
||||
so.depends('smux_enabled', '1');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_multiplex', form.Value, 'smux_min_streams', _('Minimum streams'),
|
||||
_('Minimum multiplexed streams in a connection before opening a new connection.'));
|
||||
so.datatype = 'uinteger';
|
||||
so.placeholder = '4';
|
||||
so.depends('smux_enabled', '1');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_multiplex', form.Value, 'smux_max_streams', _('Maximum streams'),
|
||||
_('Maximum multiplexed streams in a connection before opening a new connection.<br/>' +
|
||||
'Conflict with <code>%s</code> and <code>%s</code>.')
|
||||
.format(_('Maximum connections'), _('Minimum streams')));
|
||||
so.datatype = 'uinteger';
|
||||
so.placeholder = '0';
|
||||
so.depends({smux_enabled: '1', smux_max_connections: '', smux_min_streams: ''});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_multiplex', form.Flag, 'smux_padding', _('Enable padding'));
|
||||
so.default = so.disabled;
|
||||
so.depends('smux_enabled', '1');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_multiplex', form.Flag, 'smux_only_tcp', _('TCP only'),
|
||||
_('Enable multiplexing only for TCP.'));
|
||||
so.default = so.disabled;
|
||||
so.depends('smux_enabled', '1');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_multiplex', form.Flag, 'smux_statistic', _('Enable statistic'),
|
||||
_('Show connections in the dashboard for breaking connections easier.'));
|
||||
so.default = so.disabled;
|
||||
so.depends('smux_enabled', '1');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_multiplex', form.Flag, 'smux_brutal', _('Enable TCP Brutal'),
|
||||
_('Enable TCP Brutal congestion control algorithm'));
|
||||
so.default = so.disabled;
|
||||
so.depends('smux_enabled', '1');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_multiplex', form.Value, 'smux_brutal_up', _('Upload bandwidth'),
|
||||
_('Upload bandwidth in Mbps.'));
|
||||
so.datatype = 'uinteger';
|
||||
so.depends('smux_brutal', '1');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_multiplex', form.Value, 'smux_brutal_down', _('Download bandwidth'),
|
||||
_('Download bandwidth in Mbps.'));
|
||||
so.datatype = 'uinteger';
|
||||
so.depends('smux_brutal', '1');
|
||||
so.modalonly = true;
|
||||
|
||||
/* Dial fields */
|
||||
so = ss.taboption('field_dial', form.Flag, 'tfo', _('TFO'));
|
||||
so.default = so.disabled;
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_dial', form.Flag, 'mptcp', _('mpTCP'));
|
||||
so.default = so.disabled;
|
||||
so.modalonly = true;
|
||||
|
||||
// dev: Features under development
|
||||
so = ss.taboption('field_dial', form.Value, 'dialer_proxy', _('dialer-proxy'));
|
||||
so.readonly = true;
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_dial', widgets.DeviceSelect, 'interface_name', _('Bind interface'),
|
||||
_('Bind outbound interface.</br>') +
|
||||
_('Priority: Proxy Node > Proxy Group > Global.'));
|
||||
so.multiple = false;
|
||||
so.noaliases = true;
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_dial', form.Value, 'routing_mark', _('Routing mark'),
|
||||
_('Priority: Proxy Node > Proxy Group > Global.'));
|
||||
so.datatype = 'uinteger';
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_dial', form.ListValue, 'ip_version', _('IP version'));
|
||||
so.default = hm.ip_version[0][0];
|
||||
hm.ip_version.forEach((res) => {
|
||||
so.value.apply(so, res);
|
||||
})
|
||||
so.modalonly = true;
|
||||
/* Proxy Node END */
|
||||
|
||||
/* Provider START */
|
||||
@ -210,7 +862,8 @@ return view.extend({
|
||||
so.default = so.enabled;
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_override', form.Flag, 'override_uot', _('UoT'));
|
||||
so = ss.taboption('field_override', form.Flag, 'override_uot', _('UoT'),
|
||||
_('Enable the SUoT protocol, requires server support. Conflict with Multiplex.'));
|
||||
so.default = so.disabled;
|
||||
so.modalonly = true;
|
||||
|
||||
@ -224,7 +877,10 @@ return view.extend({
|
||||
so.datatype = 'uinteger';
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_override', form.Flag, 'override_skip_cert_verify', _('skip-cert-verify'));
|
||||
so = ss.taboption('field_override', form.Flag, 'override_skip_cert_verify', _('Skip cert verify'),
|
||||
_('Donot verifying server certificate.') +
|
||||
'<br/>' +
|
||||
_('This is <strong>DANGEROUS</strong>, your traffic is almost like <strong>PLAIN TEXT</strong>! Use at your own risk!'));
|
||||
so.default = so.disabled;
|
||||
so.modalonly = true;
|
||||
|
||||
@ -245,7 +901,7 @@ return view.extend({
|
||||
so.datatype = 'uinteger';
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_override', form.ListValue, 'override_ip_version', _('ip-version'));
|
||||
so = ss.taboption('field_override', form.ListValue, 'override_ip_version', _('IP version'));
|
||||
so.default = hm.ip_version[0][0];
|
||||
hm.ip_version.forEach((res) => {
|
||||
so.value.apply(so, res);
|
||||
|
@ -148,8 +148,6 @@ return view.extend({
|
||||
|
||||
return node;
|
||||
}
|
||||
o.validate = function(section_id, value) {
|
||||
}
|
||||
o.validate = L.bind(hm.validateAuthPassword, o);
|
||||
o.rmempty = false;
|
||||
o.depends({type: /^(http|socks|mixed|hysteria2)$/, username: /.+/});
|
||||
@ -229,21 +227,8 @@ return view.extend({
|
||||
return node;
|
||||
}
|
||||
o.validate = function(section_id, value) {
|
||||
var encmode = this.section.getOption('shadowsocks_chipher').formvalue(section_id);
|
||||
var length = hm.shadowsocks_cipher_length[encmode];
|
||||
if (length) {
|
||||
length = Math.ceil(length/3)*4;
|
||||
if (encmode.match(/^2022-/)) {
|
||||
if (value.length !== length || !value.match(/^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/) || value[length-1] !== '=')
|
||||
return _('Expecting: %s').format(_('valid base64 key with %d characters').format(length));
|
||||
} else {
|
||||
if (length !== 0 && value.length !== length)
|
||||
return _('Expecting: %s').format(_('valid key length with %d characters').format(length));
|
||||
}
|
||||
} else
|
||||
return true;
|
||||
|
||||
return true;
|
||||
var encmode = this.section.getOption('shadowsocks_chipher').formvalue(section_id);
|
||||
return hm.validateShadowsocksPassword.call(this, hm, encmode, section_id, value);
|
||||
}
|
||||
o.depends({type: 'shadowsocks', shadowsocks_chipher: /.+/});
|
||||
o.modalonly = true;
|
||||
@ -275,6 +260,12 @@ return view.extend({
|
||||
o.depends('type', 'tuic');
|
||||
o.modalonly = true;
|
||||
|
||||
o = s.option(form.Value, 'tuic_max_udp_relay_packet_size', _('Max UDP relay packet size'));
|
||||
o.datatype = 'uinteger';
|
||||
o.default = '1500';
|
||||
o.depends('type', 'tuic');
|
||||
o.modalonly = true;
|
||||
|
||||
o = s.option(form.Value, 'tuic_max_idle_time', _('Idle timeout'),
|
||||
_('In seconds.'));
|
||||
o.default = '15000';
|
||||
@ -289,12 +280,6 @@ return view.extend({
|
||||
o.depends('type', 'tuic');
|
||||
o.modalonly = true;
|
||||
|
||||
o = s.option(form.Value, 'tuic_max_udp_relay_packet_size', _('Max UDP relay packet size'));
|
||||
o.datatype = 'uinteger';
|
||||
o.default = '1500';
|
||||
o.depends('type', 'tuic');
|
||||
o.modalonly = true;
|
||||
|
||||
/* VMess fields */
|
||||
o = s.option(form.Value, 'vmess_uuid', _('UUID'));
|
||||
o.renderWidget = function() {
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -10,7 +10,7 @@ import { urldecode, urlencode } from 'luci.http';
|
||||
|
||||
import {
|
||||
isEmpty, strToBool, strToInt, durationToSecond,
|
||||
removeBlankAttrs,
|
||||
arrToObj, removeBlankAttrs,
|
||||
HM_DIR, RUN_DIR, PRESET_OUTBOUND
|
||||
} from 'fchomo';
|
||||
|
||||
@ -38,6 +38,7 @@ const ucisniff = 'sniff',
|
||||
ucidnser = 'dns_server',
|
||||
ucidnspoli = 'dns_policy',
|
||||
ucipgrp = 'proxy_group',
|
||||
ucinode = 'node',
|
||||
uciprov = 'provider',
|
||||
ucirule = 'ruleset',
|
||||
ucirout = 'rules',
|
||||
@ -419,6 +420,156 @@ config.proxies = [
|
||||
type: 'dns'
|
||||
}
|
||||
];
|
||||
uci.foreach(uciconf, ucinode, (cfg) => {
|
||||
if (cfg.enabled === '0')
|
||||
return null;
|
||||
|
||||
push(config.proxies, {
|
||||
name: cfg.label,
|
||||
type: cfg.type,
|
||||
|
||||
server: cfg.server,
|
||||
port: strToInt(cfg.port),
|
||||
|
||||
/* Dial fields */
|
||||
tfo: strToBool(cfg.tfo),
|
||||
mptcp: strToBool(cfg.mptcp),
|
||||
// dev: Features under development
|
||||
["dialer-proxy"]: null, //cfg.dialer_proxy,
|
||||
["interface-name"]: cfg.interface_name,
|
||||
["routing-mark"]: strToInt(cfg.routing_mark),
|
||||
["ip-version"]: cfg.ip_version,
|
||||
|
||||
/* HTTP / SOCKS / Shadowsocks / VMess / VLESS / Trojan / hysteria2 / TUIC / SSH */
|
||||
username: cfg.username,
|
||||
uuid: cfg.vmess_uuid || cfg.uuid,
|
||||
cipher: cfg.vmess_chipher || cfg.shadowsocks_chipher,
|
||||
password: cfg.shadowsocks_password || cfg.password,
|
||||
headers: cfg.headers ? json(cfg.headers) : null,
|
||||
|
||||
/* Hysteria / Hysteria2 */
|
||||
ports: isEmpty(cfg.hysteria_ports) ? null : join(',', cfg.hysteria_ports),
|
||||
up: cfg.hysteria_up_mbps ? cfg.hysteria_up_mbps + ' Mbps' : null,
|
||||
down: cfg.hysteria_down_mbps ? cfg.hysteria_down_mbps + ' Mbps' : null,
|
||||
obfs: cfg.hysteria_obfs_type,
|
||||
["obfs-password"]: cfg.hysteria_obfs_password,
|
||||
|
||||
/* SSH */
|
||||
["private-key"]: cfg.ssh_priv_key,
|
||||
["private-key-passphrase"]: cfg.ssh_priv_key_passphrase,
|
||||
["host-key-algorithms"]: cfg.ssh_host_key_algorithms,
|
||||
["host-key"]: cfg.ssh_host_key,
|
||||
|
||||
/* Shadowsocks */
|
||||
|
||||
/* Snell */
|
||||
psk: cfg.snell_psk,
|
||||
version: cfg.snell_version,
|
||||
["obfs-opts"]: cfg.type === 'snell' ? {
|
||||
mode: cfg.plugin_opts_obfsmode,
|
||||
host: cfg.plugin_opts_host,
|
||||
} : null,
|
||||
|
||||
/* TUIC */
|
||||
ip: cfg.tuic_ip,
|
||||
["congestion-controller"]: cfg.tuic_congestion_controller,
|
||||
["udp-relay-mode"]: cfg.tuic_udp_relay_mode,
|
||||
["udp-over-stream"]: strToBool(cfg.tuic_udp_over_stream),
|
||||
["udp-over-stream-version"]: cfg.tuic_udp_over_stream_version,
|
||||
["max-udp-relay-packet-size"]: strToInt(cfg.tuic_max_udp_relay_packet_size),
|
||||
["reduce-rtt"]: strToBool(cfg.tuic_reduce_rtt),
|
||||
["heartbeat-interval"]: strToInt(cfg.tuic_heartbeat),
|
||||
["request-timeout"]: strToInt(cfg.tuic_request_timeout),
|
||||
// fast-open: true
|
||||
// max-open-streams: 20
|
||||
|
||||
/* Trojan */
|
||||
["ss-opts"]: cfg.trojan_ss_enabled === '1' ? {
|
||||
enabled: true,
|
||||
method: cfg.trojan_ss_chipher,
|
||||
password: cfg.trojan_ss_password
|
||||
}: null,
|
||||
|
||||
/* VMess / VLESS */
|
||||
flow: cfg.vless_flow,
|
||||
alterId: strToInt(cfg.vmess_alterid),
|
||||
["global-padding"]: cfg.type === 'vmess' ? (cfg.vmess_global_padding === '0' ? false : true) : null,
|
||||
["authenticated-length"]: strToBool(cfg.vmess_authenticated_length),
|
||||
["packet-encoding"]: cfg.vmess_packet_encoding,
|
||||
|
||||
/* Plugin fields */
|
||||
plugin: cfg.plugin,
|
||||
["plugin-opts"]: cfg.plugin ? {
|
||||
mode: cfg.plugin_opts_obfsmode,
|
||||
host: cfg.plugin_opts_host,
|
||||
password: cfg.plugin_opts_thetlspassword,
|
||||
version: cfg.plugin_opts_shadowtls_version,
|
||||
["version-hint"]: cfg.plugin_opts_restls_versionhint,
|
||||
["restls-script"]: cfg.plugin_opts_restls_script
|
||||
} : null,
|
||||
|
||||
/* Extra fields */
|
||||
udp: strToBool(cfg.udp),
|
||||
["udp-over-tcp"]: strToBool(cfg.uot),
|
||||
["udp-over-tcp-version"]: cfg.uot_version,
|
||||
|
||||
/* TLS fields */
|
||||
tls: (cfg.type in ['trojan', 'hysteria', 'hysteria2', 'tuic']) ? null : strToBool(cfg.tls),
|
||||
["disable-sni"]: strToBool(cfg.tls_disable_sni),
|
||||
...arrToObj([[(cfg.type in ['vmess', 'vless']) ? 'servername' : 'sni', cfg.tls_sni]]),
|
||||
fingerprint: cfg.tls_fingerprint,
|
||||
alpn: cfg.tls_alpn, // Array
|
||||
["skip-cert-verify"]: strToBool(cfg.tls_skip_cert_verify),
|
||||
["client-fingerprint"]: cfg.tls_client_fingerprint,
|
||||
["reality-opts"]: cfg.tls_reality === '1' ? {
|
||||
["public-key"]: cfg.tls_reality_public_key,
|
||||
["short-id"]: cfg.tls_reality_short_id
|
||||
} : null,
|
||||
|
||||
/* Transport fields */
|
||||
// https://github.com/muink/mihomo/blob/3e966e82c793ca99e3badc84bf3f2907b100edae/adapter/outbound/vmess.go#L74
|
||||
...(cfg.transport_enabled === '1' ? {
|
||||
network: cfg.transport_type,
|
||||
["http-opts"]: cfg.transport_type === 'http' ? {
|
||||
method: cfg.transport_http_method,
|
||||
path: isEmpty(cfg.transport_paths) ? ['/'] : cfg.transport_paths, // Array
|
||||
headers: cfg.transport_http_headers ? json(cfg.transport_http_headers) : null,
|
||||
} : null,
|
||||
["h2-opts"]: cfg.transport_type === 'h2' ? {
|
||||
host: cfg.transport_hosts, // Array
|
||||
path: cfg.transport_path || '/',
|
||||
} : null,
|
||||
["grpc-opts"]: cfg.transport_type === 'grpc' ? {
|
||||
["grpc-service-name"]: cfg.transport_grpc_servicename
|
||||
} : null,
|
||||
["ws-opts"]: cfg.transport_type === 'ws' ? {
|
||||
path: cfg.transport_path || '/',
|
||||
headers: cfg.transport_http_headers ? json(cfg.transport_http_headers) : null,
|
||||
["max-early-data"]: strToInt(cfg.transport_ws_max_early_data),
|
||||
["early-data-header-name"]: cfg.transport_ws_early_data_header,
|
||||
["v2ray-http-upgrade"]: strToBool(cfg.transport_ws_v2ray_http_upgrade),
|
||||
["v2ray-http-upgrade-fast-open"]: strToBool(cfg.transport_ws_v2ray_http_upgrade_fast_open)
|
||||
} : null
|
||||
} : {}),
|
||||
|
||||
/* Multiplex fields */
|
||||
smux: cfg.smux_enabled === '1' ? {
|
||||
enabled: true,
|
||||
protocol: cfg.smux_protocol,
|
||||
["max-connections"]: strToInt(cfg.smux_max_connections),
|
||||
["min-streams"]: strToInt(cfg.smux_min_streams),
|
||||
["max-streams"]: strToInt(cfg.smux_max_streams),
|
||||
statistic: strToBool(cfg.smux_statistic),
|
||||
["only-tcp"]: strToBool(cfg.smux_only_tcp),
|
||||
padding: strToBool(cfg.smux_padding),
|
||||
["brutal-opts"]: cfg.smux_brutal === '1' ? {
|
||||
enabled: true,
|
||||
up: strToInt(cfg.smux_brutal_up), // Mbps
|
||||
down: strToInt(cfg.smux_brutal_down) // Mbps
|
||||
} : null
|
||||
} : null
|
||||
});
|
||||
});
|
||||
/* Proxy Node END */
|
||||
|
||||
/* Proxy Group START */
|
||||
|
@ -22,30 +22,23 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
local result = nil
|
||||
if node and node ~= "nil" then
|
||||
local node_id = node[".name"]
|
||||
if tag == nil then
|
||||
tag = node_id
|
||||
end
|
||||
local node_remarks = node.remarks
|
||||
|
||||
local proxy = 0
|
||||
local proxy_tag = "nil"
|
||||
local proxy_tag = nil
|
||||
if proxy_table ~= nil and type(proxy_table) == "table" then
|
||||
proxy = proxy_table.proxy or 0
|
||||
proxy_tag = proxy_table.tag or "nil"
|
||||
end
|
||||
|
||||
if node.type == "sing-box" then
|
||||
proxy = 0
|
||||
if proxy_tag ~= "nil" then
|
||||
node.detour = proxy_tag
|
||||
end
|
||||
proxy_tag = proxy_table.tag or nil
|
||||
end
|
||||
|
||||
if node.type ~= "sing-box" then
|
||||
local config_tag = tag
|
||||
if config_tag == nil then
|
||||
config_tag = node_id
|
||||
end
|
||||
local relay_port = node.port
|
||||
new_port = get_new_port()
|
||||
local config_file = string.format("%s_%s_%s.json", flag, tag, new_port)
|
||||
if tag and node_id and tag ~= node_id then
|
||||
config_file = string.format("%s_%s_%s_%s.json", flag, tag, node_id, new_port)
|
||||
local config_file = string.format("%s_%s_%s.json", flag, config_tag, new_port)
|
||||
if config_tag and node_id and config_tag ~= node_id then
|
||||
config_file = string.format("%s_%s_%s_%s.json", flag, config_tag, node_id, new_port)
|
||||
end
|
||||
sys.call(string.format('/usr/share/%s/app.sh run_socks "%s"> /dev/null',
|
||||
appname,
|
||||
@ -55,7 +48,7 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
"127.0.0.1", --bind
|
||||
new_port, --socks port
|
||||
config_file, --config file
|
||||
(proxy == 1 and relay_port) and tostring(relay_port) or "" --relay port
|
||||
(proxy_tag and proxy_tag ~= "nil" and relay_port) and tostring(relay_port) or "" --relay port
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -64,11 +57,19 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
address = "127.0.0.1",
|
||||
port = new_port
|
||||
}
|
||||
else
|
||||
if proxy_tag and proxy_tag ~= "nil" then
|
||||
node.detour = proxy_tag
|
||||
end
|
||||
end
|
||||
|
||||
if tag == nil then
|
||||
tag = node_id .. "_" .. node_remarks
|
||||
end
|
||||
|
||||
result = {
|
||||
_flag_tag = node_id,
|
||||
_flag_proxy = proxy,
|
||||
_id = node_id,
|
||||
_flag = flag,
|
||||
_flag_proxy_tag = proxy_tag,
|
||||
tag = tag,
|
||||
type = node.protocol,
|
||||
@ -778,6 +779,7 @@ function gen_config(var)
|
||||
local dns = nil
|
||||
local inbounds = {}
|
||||
local outbounds = {}
|
||||
local COMMON = {}
|
||||
|
||||
local singbox_settings = uci:get_all(appname, "@global_singbox[0]") or {}
|
||||
|
||||
@ -797,7 +799,6 @@ function gen_config(var)
|
||||
|
||||
local experimental = nil
|
||||
|
||||
local default_outTag = nil
|
||||
if node_id then
|
||||
local node = uci:get_all(appname, node_id)
|
||||
if node then
|
||||
@ -1000,7 +1001,7 @@ function gen_config(var)
|
||||
local proxy = preproxy_enabled and node[rule_name .. "_proxy_tag"] == preproxy_tag and _node_id ~= preproxy_node_id
|
||||
local copied_outbound
|
||||
for index, value in ipairs(outbounds) do
|
||||
if value["_flag_tag"] == _node_id and value["_flag_proxy_tag"] == preproxy_tag then
|
||||
if value["_id"] == _node_id and value["_flag_proxy_tag"] == preproxy_tag then
|
||||
copied_outbound = api.clone(value)
|
||||
break
|
||||
end
|
||||
@ -1036,23 +1037,23 @@ function gen_config(var)
|
||||
})
|
||||
end
|
||||
end
|
||||
local _outbound = gen_outbound(flag, _node, rule_name, { proxy = proxy and 1 or 0, tag = proxy and preproxy_tag or nil })
|
||||
local outbound_tag = rule_name .. ":" .. _node.remarks
|
||||
local _outbound = gen_outbound(flag, _node, outbound_tag, { tag = proxy and preproxy_tag or nil })
|
||||
if _outbound then
|
||||
set_outbound_detour(_node, _outbound, outbounds, rule_name)
|
||||
rule_outboundTag = set_outbound_detour(_node, _outbound, outbounds, outbound_tag)
|
||||
table.insert(outbounds, _outbound)
|
||||
rule_outboundTag = rule_name
|
||||
end
|
||||
end
|
||||
elseif _node.protocol == "_iface" then
|
||||
if _node.iface then
|
||||
local _outbound = {
|
||||
type = "direct",
|
||||
tag = rule_name,
|
||||
tag = rule_name .. ":" .. _node.remarks,
|
||||
bind_interface = _node.iface,
|
||||
routing_mark = 255,
|
||||
}
|
||||
table.insert(outbounds, _outbound)
|
||||
rule_outboundTag = rule_name
|
||||
rule_outboundTag = _outbound.tag
|
||||
sys.call("touch /tmp/etc/passwall/iface/" .. _node.iface)
|
||||
end
|
||||
end
|
||||
@ -1211,8 +1212,7 @@ function gen_config(var)
|
||||
end)
|
||||
|
||||
if default_outboundTag then
|
||||
route.final = default_outboundTag
|
||||
default_outTag = default_outboundTag
|
||||
COMMON.default_outbound_tag = default_outboundTag
|
||||
end
|
||||
|
||||
for index, value in ipairs(rules) do
|
||||
@ -1222,25 +1222,27 @@ function gen_config(var)
|
||||
if node.iface then
|
||||
local outbound = {
|
||||
type = "direct",
|
||||
tag = node_id,
|
||||
tag = node.remarks or node_id,
|
||||
bind_interface = node.iface,
|
||||
routing_mark = 255,
|
||||
}
|
||||
table.insert(outbounds, outbound)
|
||||
default_outTag = outbound.tag
|
||||
route.final = default_outTag
|
||||
COMMON.default_outbound_tag = outbound.tag
|
||||
sys.call("touch /tmp/etc/passwall/iface/" .. node.iface)
|
||||
end
|
||||
else
|
||||
local outbound = gen_outbound(flag, node)
|
||||
if outbound then
|
||||
default_outTag = set_outbound_detour(node, outbound, outbounds)
|
||||
COMMON.default_outbound_tag = set_outbound_detour(node, outbound, outbounds)
|
||||
table.insert(outbounds, outbound)
|
||||
route.final = default_outTag
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if COMMON.default_outbound_tag then
|
||||
route.final = COMMON.default_outbound_tag
|
||||
end
|
||||
|
||||
if dns_listen_port then
|
||||
dns = {
|
||||
servers = {},
|
||||
@ -1265,6 +1267,8 @@ function gen_config(var)
|
||||
server = dns_socks_address,
|
||||
server_port = tonumber(dns_socks_port)
|
||||
})
|
||||
else
|
||||
default_outTag = COMMON.default_outbound_tag
|
||||
end
|
||||
|
||||
local remote_strategy = "prefer_ipv6"
|
||||
@ -1406,7 +1410,7 @@ function gen_config(var)
|
||||
}
|
||||
if value.outboundTag ~= "block" and value.outboundTag ~= "direct" then
|
||||
dns_rule.server = "remote"
|
||||
if value.outboundTag ~= "default" and remote_server.address then
|
||||
if value.outboundTag ~= COMMON.default_outbound_tag and remote_server.address then
|
||||
local remote_dns_server = api.clone(remote_server)
|
||||
remote_dns_server.tag = value.outboundTag
|
||||
remote_dns_server.detour = value.outboundTag
|
||||
|
@ -50,44 +50,31 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
local result = nil
|
||||
if node and node ~= "nil" then
|
||||
local node_id = node[".name"]
|
||||
if tag == nil then
|
||||
tag = node_id
|
||||
end
|
||||
local node_remarks = node.remarks
|
||||
|
||||
local proxy = 0
|
||||
local proxy_tag = "nil"
|
||||
local proxy_tag = nil
|
||||
local fragment = nil
|
||||
local noise = nil
|
||||
if proxy_table ~= nil and type(proxy_table) == "table" then
|
||||
proxy = proxy_table.proxy or 0
|
||||
proxy_tag = proxy_table.tag or "nil"
|
||||
proxy_tag = proxy_table.tag or nil
|
||||
fragment = proxy_table.fragment or nil
|
||||
noise = proxy_table.noise or nil
|
||||
end
|
||||
|
||||
if node.type == "Xray" then
|
||||
if node.flow == "xtls-rprx-vision" then
|
||||
else
|
||||
proxy = 0
|
||||
if proxy_tag ~= "nil" then
|
||||
node.proxySettings = {
|
||||
tag = proxy_tag,
|
||||
transportLayer = true
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if node.type ~= "Xray" then
|
||||
if node.type == "Socks" then
|
||||
node.protocol = "socks"
|
||||
node.transport = "tcp"
|
||||
else
|
||||
local config_tag = tag
|
||||
if config_tag == nil then
|
||||
config_tag = node_id
|
||||
end
|
||||
local relay_port = node.port
|
||||
new_port = get_new_port()
|
||||
local config_file = string.format("%s_%s_%s.json", flag, tag, new_port)
|
||||
if tag and node_id and tag ~= node_id then
|
||||
config_file = string.format("%s_%s_%s_%s.json", flag, tag, node_id, new_port)
|
||||
local config_file = string.format("%s_%s_%s.json", flag, config_tag, new_port)
|
||||
if config_tag and node_id and config_tag ~= node_id then
|
||||
config_file = string.format("%s_%s_%s_%s.json", flag, config_tag, node_id, new_port)
|
||||
end
|
||||
sys.call(string.format('/usr/share/%s/app.sh run_socks "%s"> /dev/null',
|
||||
appname,
|
||||
@ -97,7 +84,7 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
"127.0.0.1", --bind
|
||||
new_port, --socks port
|
||||
config_file, --config file
|
||||
(proxy == 1 and relay_port) and tostring(relay_port) or "" --relay port
|
||||
(proxy_tag and proxy_tag ~= "nil" and relay_port) and tostring(relay_port) or "" --relay port
|
||||
)
|
||||
))
|
||||
node = {}
|
||||
@ -107,6 +94,16 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
node.port = new_port
|
||||
end
|
||||
node.stream_security = "none"
|
||||
else
|
||||
if node.flow == "xtls-rprx-vision" then
|
||||
else
|
||||
if proxy_tag and proxy_tag ~= "nil" then
|
||||
node.proxySettings = {
|
||||
tag = proxy_tag,
|
||||
transportLayer = true
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if node.type == "Xray" then
|
||||
@ -142,9 +139,13 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
node.wireguard_reserved = #bytes > 0 and bytes or nil
|
||||
end
|
||||
|
||||
if tag == nil then
|
||||
tag = node_id .. "_" .. node_remarks
|
||||
end
|
||||
|
||||
result = {
|
||||
_flag_tag = node_id,
|
||||
_flag_proxy = proxy,
|
||||
_id = node_id,
|
||||
_flag = flag,
|
||||
_flag_proxy_tag = proxy_tag,
|
||||
tag = tag,
|
||||
proxySettings = node.proxySettings or nil,
|
||||
@ -450,7 +451,6 @@ function gen_config_server(node)
|
||||
domainStrategy = "IPOnDemand",
|
||||
rules = {
|
||||
{
|
||||
type = "field",
|
||||
ip = {"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"},
|
||||
outboundTag = (node.accept_lan == nil or node.accept_lan == "0") and "blocked" or "direct"
|
||||
}
|
||||
@ -641,6 +641,7 @@ function gen_config(var)
|
||||
local observatory = nil
|
||||
local inbounds = {}
|
||||
local outbounds = {}
|
||||
local COMMON = {}
|
||||
|
||||
local xray_settings = uci:get_all(appname, "@global_xray[0]") or {}
|
||||
|
||||
@ -817,7 +818,7 @@ function gen_config(var)
|
||||
end
|
||||
end
|
||||
local inbound_tag = gen_loopback(loopback_tag, loopback_dst)
|
||||
table.insert(rules, { type = "field", inboundTag = { inbound_tag }, balancerTag = balancer_tag })
|
||||
table.insert(rules, { inboundTag = { inbound_tag }, balancerTag = balancer_tag })
|
||||
return balancer_tag
|
||||
end
|
||||
|
||||
@ -897,7 +898,7 @@ function gen_config(var)
|
||||
if use_proxy and proxy_balancer_tag and proxy_nodes[_node_id] then use_proxy = false end
|
||||
local copied_outbound
|
||||
for index, value in ipairs(outbounds) do
|
||||
if value["_flag_tag"] == _node_id and value["_flag_proxy_tag"] == (use_proxy and proxy_tag or "nil") then
|
||||
if value["_id"] == _node_id and value["_flag_proxy_tag"] == (use_proxy and proxy_tag or nil) then
|
||||
copied_outbound = api.clone(value)
|
||||
break
|
||||
end
|
||||
@ -923,23 +924,23 @@ function gen_config(var)
|
||||
_node.address = "127.0.0.1"
|
||||
_node.port = new_port
|
||||
table.insert(rules, 1, {
|
||||
type = "field",
|
||||
inboundTag = {"proxy_" .. rule_name},
|
||||
outboundTag = not proxy_balancer_tag and proxy_tag or nil,
|
||||
balancerTag = proxy_balancer_tag
|
||||
})
|
||||
end
|
||||
local proxy_table = {
|
||||
proxy = use_proxy and 1 or 0,
|
||||
tag = use_proxy and proxy_tag or nil
|
||||
}
|
||||
if xray_settings.fragment == "1" and not proxy_table.tag then
|
||||
proxy_table.fragment = true
|
||||
if not proxy_table.tag then
|
||||
if xray_settings.fragment == "1" then
|
||||
proxy_table.fragment = true
|
||||
end
|
||||
if xray_settings.noise == "1" then
|
||||
proxy_table.noise = true
|
||||
end
|
||||
end
|
||||
if xray_settings.noise == "1" and not proxy_table.tag then
|
||||
proxy_table.noise = true
|
||||
end
|
||||
local outbound = gen_outbound(flag, _node, rule_name, proxy_table)
|
||||
local outbound = gen_outbound(flag, _node, rule_name .. ":" .. _node.remarks, proxy_table)
|
||||
local outbound_tag
|
||||
if outbound then
|
||||
set_outbound_detour(_node, outbound, outbounds, rule_name)
|
||||
@ -997,6 +998,8 @@ function gen_config(var)
|
||||
--default_node
|
||||
local default_node_id = node.default_node or "_direct"
|
||||
local default_outbound_tag, default_balancer_tag = gen_shunt_node("default", default_node_id)
|
||||
COMMON.default_outbound_tag = default_outbound_tag
|
||||
COMMON.default_balancer_tag = default_balancer_tag
|
||||
--shunt rule
|
||||
uci:foreach(appname, "shunt_rules", function(e)
|
||||
local outbound_tag, balancer_tag = gen_shunt_node(e[".name"])
|
||||
@ -1055,8 +1058,7 @@ function gen_config(var)
|
||||
end)
|
||||
end
|
||||
local rule = {
|
||||
_flag = e.remarks,
|
||||
type = "field",
|
||||
ruleTag = e.remarks,
|
||||
inboundTag = inbound_tag,
|
||||
outboundTag = outbound_tag,
|
||||
balancerTag = balancer_tag,
|
||||
@ -1068,13 +1070,13 @@ function gen_config(var)
|
||||
}
|
||||
if domains then
|
||||
local _rule = api.clone(rule)
|
||||
_rule["_flag"] = _rule["_flag"] .. "_domains"
|
||||
_rule.ruleTag = _rule.ruleTag .. " Domains"
|
||||
_rule.domains = domains
|
||||
table.insert(rules, _rule)
|
||||
end
|
||||
if ip then
|
||||
local _rule = api.clone(rule)
|
||||
_rule["_flag"] = _rule["_flag"] .. "_ip"
|
||||
_rule.ruleTag = _rule.ruleTag .. " IP"
|
||||
_rule.ip = ip
|
||||
table.insert(rules, _rule)
|
||||
end
|
||||
@ -1087,7 +1089,6 @@ function gen_config(var)
|
||||
--[[
|
||||
if default_outbound_tag or default_balancer_tag then
|
||||
table.insert(rules, {
|
||||
type = "field",
|
||||
outboundTag = default_outbound_tag,
|
||||
balancerTag = default_balancer_tag,
|
||||
network = "tcp,udp"
|
||||
@ -1105,18 +1106,19 @@ function gen_config(var)
|
||||
if node.balancing_node then
|
||||
local balancer_tag = gen_balancer(node)
|
||||
if balancer_tag then
|
||||
table.insert(rules, { type = "field", network = "tcp,udp", balancerTag = balancer_tag })
|
||||
table.insert(rules, { network = "tcp,udp", balancerTag = balancer_tag })
|
||||
end
|
||||
routing = {
|
||||
balancers = balancers,
|
||||
rules = rules
|
||||
}
|
||||
COMMON.default_balancer_tag = balancer_tag
|
||||
end
|
||||
elseif node.protocol == "_iface" then
|
||||
if node.iface then
|
||||
local outbound = {
|
||||
protocol = "freedom",
|
||||
tag = "outbound",
|
||||
tag = node.remarks or node_id,
|
||||
streamSettings = {
|
||||
sockopt = {
|
||||
mark = 255,
|
||||
@ -1125,12 +1127,13 @@ function gen_config(var)
|
||||
}
|
||||
}
|
||||
table.insert(outbounds, outbound)
|
||||
COMMON.default_outbound_tag = outbound.tag
|
||||
sys.call("touch /tmp/etc/passwall/iface/" .. node.iface)
|
||||
end
|
||||
else
|
||||
local outbound = gen_outbound(flag, node, nil, { fragment = xray_settings.fragment == "1" or nil, noise = xray_settings.fragment == "1" or nil })
|
||||
if outbound then
|
||||
set_outbound_detour(node, outbound, outbounds)
|
||||
COMMON.default_outbound_tag = set_outbound_detour(node, outbound, outbounds)
|
||||
table.insert(outbounds, outbound)
|
||||
end
|
||||
routing = {
|
||||
@ -1231,12 +1234,8 @@ function gen_config(var)
|
||||
}
|
||||
})
|
||||
else
|
||||
if node_id and tcp_redir_port then
|
||||
dns_outbound_tag = node_id
|
||||
local node = uci:get_all(appname, node_id)
|
||||
if node.protocol == "_shunt" then
|
||||
dns_outbound_tag = "default"
|
||||
end
|
||||
if COMMON.default_outbound_tag then
|
||||
dns_outbound_tag = COMMON.default_outbound_tag
|
||||
end
|
||||
end
|
||||
|
||||
@ -1268,7 +1267,6 @@ function gen_config(var)
|
||||
})
|
||||
|
||||
table.insert(routing.rules, 1, {
|
||||
type = "field",
|
||||
inboundTag = {
|
||||
"dns-in"
|
||||
},
|
||||
@ -1276,7 +1274,6 @@ function gen_config(var)
|
||||
})
|
||||
end
|
||||
table.insert(rules, {
|
||||
type = "field",
|
||||
inboundTag = {
|
||||
"dns-in1"
|
||||
},
|
||||
@ -1288,7 +1285,6 @@ function gen_config(var)
|
||||
})
|
||||
if _remote_dns_host then
|
||||
table.insert(rules, {
|
||||
type = "field",
|
||||
inboundTag = {
|
||||
"dns-in1"
|
||||
},
|
||||
@ -1301,7 +1297,6 @@ function gen_config(var)
|
||||
end
|
||||
if remote_dns_doh_ip then
|
||||
table.insert(rules, {
|
||||
type = "field",
|
||||
inboundTag = {
|
||||
"dns-in1"
|
||||
},
|
||||
@ -1409,6 +1404,13 @@ function gen_config(var)
|
||||
protocol = "blackhole",
|
||||
tag = "blackhole"
|
||||
})
|
||||
for index, value in ipairs(config.outbounds) do
|
||||
for k, v in pairs(config.outbounds[index]) do
|
||||
if k:find("_") == 1 then
|
||||
config.outbounds[index][k] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
return jsonc.stringify(config, 1)
|
||||
end
|
||||
end
|
||||
|
@ -1,16 +1,13 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=njit8021xclient
|
||||
PKG_BASE_VERSION:=2.0
|
||||
PKG_RELEASE:=1
|
||||
PKG_RELEASE:=2
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/bitdust/njit8021xclient.git
|
||||
PKG_SOURCE_DATE:=2018-11-24
|
||||
PKG_SOURCE_VERSION:=dd28c17f24275bbbf4c44504b832c0f1e6b9ae40
|
||||
PKG_MIRROR_HASH:=ceab49b57f397ec608788ae92d25f13651e808aa4156c4c4049698dac405cb0a
|
||||
|
||||
PKG_VERSION:=$(PKG_BASE_VERSION)-$(PKG_SOURCE_DATE)-$(call version_abbrev,$(PKG_SOURCE_VERSION))
|
||||
PKG_MIRROR_HASH:=f82c2e4459fadb36466af24b0edd6c96f3cb6f3f2f425ea170a5cc91749dd8a6
|
||||
|
||||
PKG_FIXUP:=autoreconf
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
@ -8,24 +8,18 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=scutclient
|
||||
PKG_BASE_VERSION:=3.1.3
|
||||
PKG_VERSION:=3.1.3
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/scutclient/scutclient.git
|
||||
PKG_SOURCE_DATE:=2021-11-26
|
||||
PKG_SOURCE_VERSION:=b265ca8ffea204bd1788b0addd42184496b8a118
|
||||
PKG_MIRROR_HASH:=10da818f0a8a892d98d5ab5ca1f9ecbb3022bf2cd4ee04132ee5f1f0e52a740e
|
||||
|
||||
PKG_VERSION:=$(PKG_BASE_VERSION)-$(PKG_SOURCE_DATE)-$(call version_abbrev,$(PKG_SOURCE_VERSION))
|
||||
PKG_SOURCE_VERSION:=v$(PKG_VERSION)
|
||||
PKG_MIRROR_HASH:=3b98fb51956c0de8c25432c22c56477b245c5949be2b5ec7574ad10c83274668
|
||||
|
||||
PKG_MAINTAINER:=Scutclient Project
|
||||
PKG_LICENSE:=AGPL-3.0
|
||||
PKG_LICENSE_FILES:=COPYING
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
CMAKE_INSTALL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user