mirror of
				https://github.com/kenzok8/openwrt-packages.git
				synced 2025-10-30 07:50:37 +08:00 
			
		
		
		
	update 2023-04-07 14:19:02
This commit is contained in:
		| @ -126,7 +126,7 @@ update_rules() { | ||||
| 	yhosts_rules_local=`cat /usr/share/koolproxy/data/rules/yhosts.txt  | sed -n '1p' | cut -d ":" -f2` | ||||
| 	antiad_rules_local=`cat /usr/share/koolproxy/data/rules/antiad.txt  | sed -n '2p' | cut -d "=" -f2` | ||||
| 	koolproxy_rules_local=`cat /usr/share/koolproxy/data/rules/koolproxy.txt  | sed -n '3p'|awk '{print $3,$4}'` | ||||
| 	adgk_rules_local=`cat /usr/share/koolproxy/data/rules/adgk.txt  | sed -n '1p'|awk '{print $3}'` | ||||
| 	adgk_rules_local=`cat /usr/share/koolproxy/data/rules/adgk.txt  | sed -n '2p'|awk '{print $3}'` | ||||
| 	echo $(date "+%F %T"): -------------------AdGuard规则 Version $adg_rules_local >>$LOGFILE | ||||
| 	echo $(date "+%F %T"): -------------------Steven规则 Version $steven_rules_local >>$LOGFILE | ||||
| 	echo $(date "+%F %T"): -------------------Yhosts规则 Version $yhosts_rules_local >>$LOGFILE | ||||
|  | ||||
| @ -5,11 +5,12 @@ | ||||
| include $(TOPDIR)/rules.mk | ||||
|  | ||||
| PKG_NAME:=luci-app-passwall2 | ||||
| PKG_VERSION:=1.10 | ||||
| PKG_RELEASE:=6 | ||||
| PKG_VERSION:=1.11 | ||||
| PKG_RELEASE:=1 | ||||
|  | ||||
| PKG_CONFIG_DEPENDS:= \ | ||||
| 	CONFIG_PACKAGE_$(PKG_NAME)_Transparent_Proxy \ | ||||
| 	CONFIG_PACKAGE_$(PKG_NAME)_Transparent_Proxy_Iptables-nft \ | ||||
| 	CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Brook \ | ||||
| 	CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria \ | ||||
| 	CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_IPv6_Nat \ | ||||
| @ -52,6 +53,7 @@ menu "Configuration" | ||||
| config PACKAGE_$(PKG_NAME)_Transparent_Proxy | ||||
| 	bool "Transparent Proxy" | ||||
| 	select PACKAGE_dnsmasq-full | ||||
| 	select PACKAGE_dnsmasq_full_ipset | ||||
| 	select PACKAGE_ipset | ||||
| 	select PACKAGE_iptables | ||||
| 	select PACKAGE_iptables-zz-legacy | ||||
| @ -61,7 +63,21 @@ config PACKAGE_$(PKG_NAME)_Transparent_Proxy | ||||
| 	select PACKAGE_iptables-mod-conntrack-extra | ||||
| 	select PACKAGE_kmod-ipt-nat | ||||
| 	depends on PACKAGE_$(PKG_NAME) | ||||
| 	default y | ||||
| 	default y if ! PACKAGE_firewall4 | ||||
|  | ||||
| config PACKAGE_$(PKG_NAME)_Transparent_Proxy_Iptables-nft | ||||
| 	bool "Transparent Proxy Use Iptables-nft" | ||||
| 	select PACKAGE_dnsmasq-full | ||||
| 	select PACKAGE_dnsmasq_full_ipset | ||||
| 	select PACKAGE_ipset | ||||
| 	select PACKAGE_iptables-nft | ||||
| 	select PACKAGE_iptables-mod-iprange | ||||
| 	select PACKAGE_iptables-mod-socket | ||||
| 	select PACKAGE_iptables-mod-tproxy | ||||
| 	select PACKAGE_iptables-mod-conntrack-extra | ||||
| 	select PACKAGE_kmod-ipt-nat | ||||
| 	depends on PACKAGE_$(PKG_NAME) | ||||
| 	default y if PACKAGE_firewall4 | ||||
|  | ||||
| config PACKAGE_$(PKG_NAME)_INCLUDE_Brook | ||||
| 	bool "Include Brook" | ||||
|  | ||||
| @ -129,10 +129,21 @@ for k, e in ipairs(api.get_valid_nodes()) do | ||||
| end | ||||
|  | ||||
| -- 负载均衡列表 | ||||
| balancing_node = s:option(DynamicList, "balancing_node", translate("Load balancing node list"), translate("Load balancing node list, <a target='_blank' href='https://toutyrater.github.io/routing/balance2.html'>document</a>")) | ||||
| local balancing_node = s:option(DynamicList, "balancing_node", translate("Load balancing node list"), translate("Load balancing node list, <a target='_blank' href='https://toutyrater.github.io/routing/balance2.html'>document</a>")) | ||||
| for k, v in pairs(nodes_table) do balancing_node:value(v.id, v.remarks) end | ||||
| balancing_node:depends("protocol", "_balancing") | ||||
|  | ||||
| local balancingStrategy = s:option(ListValue, "balancingStrategy", translate("Balancing Strategy")) | ||||
| balancingStrategy:depends("protocol", "_balancing") | ||||
| balancingStrategy:value("random") | ||||
| balancingStrategy:value("leastPing") | ||||
| balancingStrategy.default = "random" | ||||
|  | ||||
| local probeInterval = s:option(Value, "probeInterval", translate("Probe Interval")) | ||||
| probeInterval:depends("balancingStrategy", "leastPing") | ||||
| probeInterval.default = "1m" | ||||
| probeInterval.description = translate("The interval between initiating probes. Every time this time elapses, a server status check is performed on a server. The time format is numbers + units, such as '10s', '2h45m', and the supported time units are <code>ns</code>, <code>us</code>, <code>ms</code>, <code>s</code>, <code>m</code>, <code>h</code>, which correspond to nanoseconds, microseconds, milliseconds, seconds, minutes, and hours, respectively.") | ||||
|  | ||||
| -- 分流 | ||||
| uci:foreach(appname, "shunt_rules", function(e) | ||||
|     if e[".name"] and e.remarks then | ||||
| @ -192,13 +203,11 @@ domainStrategy.description = "<br /><ul><li>" .. translate("'AsIs': Only use dom | ||||
| .. "</li><li>" .. translate("'IPIfNonMatch': When no rule matches current domain, resolves it into IP addresses (A or AAAA records) and try all rules again.") | ||||
| .. "</li><li>" .. translate("'IPOnDemand': As long as there is a IP-based rule, resolves the domain into IP immediately.") | ||||
| .. "</li></ul>" | ||||
| domainStrategy:depends("protocol", "_balancing") | ||||
| domainStrategy:depends("protocol", "_shunt") | ||||
|  | ||||
| domainMatcher = s:option(ListValue, "domainMatcher", translate("Domain matcher")) | ||||
| domainMatcher:value("hybrid") | ||||
| domainMatcher:value("linear") | ||||
| domainMatcher:depends("protocol", "_balancing") | ||||
| domainMatcher:depends("protocol", "_shunt") | ||||
|  | ||||
|  | ||||
| @ -544,9 +553,9 @@ xray_fingerprint:value("chrome") | ||||
| xray_fingerprint:value("firefox") | ||||
| xray_fingerprint:value("safari") | ||||
| xray_fingerprint:value("ios") | ||||
| xray_fingerprint:value("android") | ||||
| --xray_fingerprint:value("android") | ||||
| xray_fingerprint:value("edge") | ||||
| xray_fingerprint:value("360") | ||||
| --xray_fingerprint:value("360") | ||||
| xray_fingerprint:value("qq") | ||||
| xray_fingerprint:value("random") | ||||
| xray_fingerprint:value("randomized") | ||||
| @ -579,9 +588,9 @@ reality_fingerprint:value("chrome") | ||||
| reality_fingerprint:value("firefox") | ||||
| reality_fingerprint:value("safari") | ||||
| reality_fingerprint:value("ios") | ||||
| reality_fingerprint:value("android") | ||||
| --reality_fingerprint:value("android") | ||||
| reality_fingerprint:value("edge") | ||||
| reality_fingerprint:value("360") | ||||
| --reality_fingerprint:value("360") | ||||
| reality_fingerprint:value("qq") | ||||
| reality_fingerprint:value("random") | ||||
| reality_fingerprint:value("randomized") | ||||
| @ -638,6 +647,11 @@ wireguard_mtu = s:option(Value, "wireguard_mtu", translate("MTU")) | ||||
| wireguard_mtu.default = "1420" | ||||
| wireguard_mtu:depends({ type = "Xray", protocol = "wireguard" }) | ||||
|  | ||||
| if api.compare_versions(api.get_app_version("xray"), ">=", "1.8.0") then | ||||
| 	wireguard_reserved = s:option(Value, "wireguard_reserved", translate("Reserved")) | ||||
| 	wireguard_reserved:depends({ type = "Xray", protocol = "wireguard" }) | ||||
| end | ||||
|  | ||||
| wireguard_keepAlive = s:option(Value, "wireguard_keepAlive", translate("Keep Alive")) | ||||
| wireguard_keepAlive.default = "0" | ||||
| wireguard_keepAlive:depends({ type = "Xray", protocol = "wireguard" }) | ||||
| @ -833,6 +847,9 @@ hysteria_hop_interval:depends("type", "Hysteria") | ||||
| hysteria_disable_mtu_discovery = s:option(Flag, "hysteria_disable_mtu_discovery", translate("Disable MTU detection")) | ||||
| hysteria_disable_mtu_discovery:depends("type", "Hysteria") | ||||
|  | ||||
| hysteria_lazy_start = s:option(Flag, "hysteria_lazy_start", translate("Lazy Start")) | ||||
| hysteria_lazy_start:depends("type", "Hysteria") | ||||
|  | ||||
| protocol.validate = function(self, value) | ||||
|     if value == "_shunt" or value == "_balancing" then | ||||
|         address.rmempty = true | ||||
|  | ||||
| @ -13,6 +13,17 @@ command_timeout = 300 | ||||
| LEDE_BOARD = nil | ||||
| DISTRIB_TARGET = nil | ||||
|  | ||||
| LOG_FILE = "/tmp/log/passwall2.log" | ||||
|  | ||||
| function log(...) | ||||
|     local result = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ") | ||||
|     local f, err = io.open(LOG_FILE, "a") | ||||
|     if f and err == nil then | ||||
|         f:write(result .. "\n") | ||||
|         f:close() | ||||
|     end | ||||
| end | ||||
|  | ||||
| function exec_call(cmd) | ||||
|     local process = io.popen(cmd .. '; echo -e "\n$?"') | ||||
|     local lines = {} | ||||
| @ -355,7 +366,7 @@ function get_customed_path(e) | ||||
| end | ||||
|  | ||||
| function is_finded(e) | ||||
|     return luci.sys.exec('type -t -p "/bin/%s" -p "%s" "%s"' % {e, get_customed_path(e), e}) ~= "" and true or false | ||||
|     return luci.sys.exec('type -t -p "/bin/%s" -p "/usr/bin/%s" -p "%s" "%s"' % {e, e, get_customed_path(e), e}) ~= "" and true or false | ||||
| end | ||||
|  | ||||
|  | ||||
|  | ||||
| @ -74,6 +74,7 @@ function gen_config(var) | ||||
|         hop_interval = (node.hysteria_hop_interval) and tonumber(node.hysteria_hop_interval) or nil, | ||||
|         disable_mtu_discovery = (node.hysteria_disable_mtu_discovery) and true or false, | ||||
|         fast_open = (node.fast_open == "1") and true or false, | ||||
|         lazy_start = (node.hysteria_lazy_start) and true or false, | ||||
|         socks5 = (local_socks_address and local_socks_port) and { | ||||
|             listen = local_socks_address .. ":" .. local_socks_port, | ||||
|             timeout = 300, | ||||
|  | ||||
| @ -106,6 +106,14 @@ function gen_outbound(flag, node, tag, proxy_table) | ||||
|             end | ||||
|         end | ||||
|  | ||||
| 		if node.protocol == "wireguard" and node.wireguard_reserved then | ||||
| 			local bytes = {} | ||||
| 			node.wireguard_reserved:gsub("[^,]+", function(b) | ||||
| 				bytes[#bytes+1] = tonumber(b) | ||||
| 			end) | ||||
| 			node.wireguard_reserved = #bytes > 0 and bytes or nil | ||||
| 		end | ||||
|  | ||||
|         result = { | ||||
|             _flag_tag = node_id, | ||||
|             _flag_proxy = proxy, | ||||
| @ -230,7 +238,8 @@ function gen_outbound(flag, node, tag, proxy_table) | ||||
|                         keepAlive = node.wireguard_keepAlive and tonumber(node.wireguard_keepAlive) or nil | ||||
|                     } | ||||
|                 } or nil, | ||||
|                 mtu = (node.protocol == "wireguard" and node.wireguard_mtu) and tonumber(node.wireguard_mtu) or nil | ||||
|                 mtu = (node.protocol == "wireguard" and node.wireguard_mtu) and tonumber(node.wireguard_mtu) or nil, | ||||
|                 reserved = (node.protocol == "wireguard" and node.wireguard_reserved) and node.wireguard_reserved or nil | ||||
|             } | ||||
|         } | ||||
|         local alpn = {} | ||||
| @ -522,6 +531,7 @@ function gen_config(var) | ||||
|     local inbounds = {} | ||||
|     local outbounds = {} | ||||
|     local routing = nil | ||||
|     local observatory = nil | ||||
|  | ||||
|     if local_socks_port then | ||||
|         local inbound = { | ||||
| @ -817,10 +827,18 @@ function gen_config(var) | ||||
|                     local outbound = gen_outbound(flag, node) | ||||
|                     if outbound then table.insert(outbounds, outbound) end | ||||
|                 end | ||||
| 				if node.balancingStrategy == "leastPing" then | ||||
| 					observatory = { | ||||
| 						subjectSelector = nodes, | ||||
| 						probeInterval = node.probeInterval or "1m" | ||||
| 					} | ||||
| 				end | ||||
|                 routing = { | ||||
|                     domainStrategy = node.domainStrategy or "AsIs", | ||||
|                     domainMatcher = node.domainMatcher or "hybrid", | ||||
|                     balancers = {{tag = "balancer", selector = nodes}}, | ||||
|                     balancers = {{ | ||||
| 						tag = "balancer", | ||||
| 						selector = nodes, | ||||
| 						strategy = {type = node.balancingStrategy or "random"} | ||||
| 					}}, | ||||
|                     rules = { | ||||
|                         {type = "field", network = "tcp,udp", balancerTag = "balancer"} | ||||
|                     } | ||||
| @ -1093,6 +1111,8 @@ function gen_config(var) | ||||
|             inbounds = inbounds, | ||||
|             -- 传出连接 | ||||
|             outbounds = outbounds, | ||||
|             -- 连接观测 | ||||
| 			observatory = observatory, | ||||
|             -- 路由 | ||||
|             routing = routing, | ||||
|             -- 本地策略 | ||||
| @ -1277,7 +1297,7 @@ function gen_dns_config(var) | ||||
|         dns = { | ||||
|             tag = "dns-in1", | ||||
|             hosts = {}, | ||||
|             disableCache = (dns_cache and dns_cache == "0") and true or false, | ||||
|             disableCache = (dns_cache == "1") and false or true, | ||||
|             disableFallback = true, | ||||
|             disableFallbackIfMatch = true, | ||||
|             servers = {}, | ||||
|  | ||||
| @ -56,26 +56,18 @@ local has_xray = api.is_finded("xray") | ||||
| 		return b64decsafe(v); | ||||
| 	} | ||||
| 	function parseNodeUrl(url) { | ||||
| 		var m = url.match(/^(([^:\/?#]+:)?(?:\/\/((?:([^\/?#:]*)([^\/?#:]*)@)?([^\/?#:]*)(?::([^\/?#:]*))?)))?([^?#]*)(\?[^#]*)?(#.*)?$/), | ||||
| 			r = { | ||||
| 				hash: m[10] || "", // #asd | ||||
| 				host: m[3] || "", // localhost:257 | ||||
| 				hostname: m[6] || "", // localhost | ||||
| 				href: m[0] || "", // http://username:password@localhost:257/deploy/?asd=asd#asd | ||||
| 				origin: m[1] || "", // http://username:password@localhost:257 | ||||
| 				pathname: m[8] || (m[1] ? "/" : ""), // /deploy/ | ||||
| 				port: m[7] || "", // 257 | ||||
| 				protocol: m[2] || "", // http: | ||||
| 				search: m[9] || "", // ?asd=asd | ||||
| 				passwd: m[4] || "", // username | ||||
| 				removed: m[5] || "" // password | ||||
| 			}; | ||||
| 		if (r.protocol.length === 2) { | ||||
| 			r.protocol = "file:///" + r.protocol.toUpperCase(); | ||||
| 			r.origin = r.protocol + "//" + r.host; | ||||
| 		} | ||||
| 		r.href = r.origin + r.pathname + r.search + r.hash; | ||||
| 		return m && r; | ||||
| 		let protocol = url.substring(0, url.indexOf("://")) + ":" | ||||
| 		let str = "http" + url.substring(url.indexOf("://")) | ||||
| 		const parsedUrl = new URL(str); | ||||
| 		var r = { | ||||
| 			hash: parsedUrl.hash, // #asd | ||||
| 			host: parsedUrl.host, // localhost:257 | ||||
| 			hostname: parsedUrl.hostname, // localhost | ||||
| 			port: parsedUrl.port, // 257 | ||||
| 			search: parsedUrl.search, // ?asd=asd | ||||
| 			passwd: parsedUrl.username || parsedUrl.password // username | ||||
| 		}; | ||||
| 		return r; | ||||
| 	} | ||||
|  | ||||
| 	function buildUrl(btn, urlname, sid) { | ||||
| @ -130,15 +122,25 @@ local has_xray = api.is_finded("xray") | ||||
| 		opt.client = urlname.indexOf("server") === -1; | ||||
| 		var v_type = opt.get("type").value; | ||||
| 		var v_alias = opt.get("remarks"); | ||||
| 		var _address = "" | ||||
| 		try { | ||||
| 			var v_server = opt.get("address"); | ||||
| 			const ipv6Regex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/; | ||||
| 			if (ipv6Regex.test(v_server.value)) { | ||||
| 				_address = "[" + v_server.value + "]" | ||||
| 			} else { | ||||
| 				_address = v_server.value | ||||
| 			} | ||||
| 		} catch(e) { | ||||
| 		} | ||||
| 		var url = null; | ||||
| 		if (v_type === "SS") { | ||||
| 			var v_server = opt.get("address"); | ||||
| 			var v_port = opt.get("port"); | ||||
| 			var v_method = opt.get("ss_encrypt_method"); | ||||
| 			var v_password = opt.get("password"); | ||||
| 			 | ||||
| 			url = b64encsafe(v_method.value + ":" + v_password.value) + "@" + | ||||
| 				v_server.value + ":" + | ||||
| 				_address + ":" + | ||||
| 				v_port.value + "/?"; | ||||
| 			 | ||||
| 			var params = ""; | ||||
| @ -160,7 +162,6 @@ local has_xray = api.is_finded("xray") | ||||
| 			} | ||||
| 			url += params; | ||||
| 		} else if (v_type === "SSR") { | ||||
| 			var v_server = opt.get("address"); | ||||
| 			var v_port = opt.get("port"); | ||||
| 			var v_protocol = opt.get("ssr_protocol"); | ||||
| 			var v_method = opt.get("ssr_encrypt_method"); | ||||
| @ -168,7 +169,7 @@ local has_xray = api.is_finded("xray") | ||||
| 			var v_password = opt.get("password"); | ||||
| 			var v_obfs_param = opt.get("obfs_param"); | ||||
| 			var v_protocol_param = opt.get("protocol_param"); | ||||
| 			var ssr_str = v_server.value + ":" + | ||||
| 			var ssr_str = _address + ":" + | ||||
| 				v_port.value + ":" + | ||||
| 				v_protocol.value + ":" + | ||||
| 				v_method.value + ":" + | ||||
| @ -184,6 +185,7 @@ local has_xray = api.is_finded("xray") | ||||
| 			info.v = "2"; | ||||
| 			info.ps = v_alias.value; | ||||
| 			info.add = opt.get("address").value; | ||||
| 			//info.add = _address; | ||||
| 			info.port = opt.get("port").value; | ||||
| 			info.id = opt.get("uuid").value; | ||||
| 			 | ||||
| @ -196,8 +198,10 @@ local has_xray = api.is_finded("xray") | ||||
| 				info.path = opt.get("h2_path").value; | ||||
| 			} else if (v_transport === "tcp") { | ||||
| 				info.type = opt.get("tcp_guise").value; | ||||
| 				info.host = opt.get("tcp_guise_http_host").value; | ||||
| 				info.path = opt.get("tcp_guise_http_path").value; | ||||
| 				if (info.type === "http") { | ||||
| 					info.host = opt.get("tcp_guise_http_host").value; | ||||
| 					info.path = opt.get("tcp_guise_http_path").value; | ||||
| 				} | ||||
| 			} else if (v_transport === "mkcp") { | ||||
| 				v_transport = "kcp"; | ||||
| 				info.type = opt.get("mkcp_guise").value; | ||||
| @ -223,10 +227,9 @@ local has_xray = api.is_finded("xray") | ||||
| 		} else if ((v_type === "V2ray" || v_type === "Xray") && opt.get("protocol").value === "vless") { | ||||
| 			v_type = "vless"; | ||||
| 			var v_password = opt.get("uuid"); | ||||
| 			var v_server = opt.get("address"); | ||||
| 			var v_port = opt.get("port"); | ||||
| 			url = encodeURIComponent(v_password.value) + | ||||
| 				"@" + v_server.value + | ||||
| 				"@" + _address + | ||||
| 				":" + v_port.value + "?"; | ||||
| 			 | ||||
| 			var params = ""; | ||||
| @ -235,6 +238,7 @@ local has_xray = api.is_finded("xray") | ||||
| 				params += opt.query("host", "ws_host"); | ||||
| 				params += opt.query("path", "ws_path"); | ||||
| 			} else if (v_transport === "h2") { | ||||
| 				v_transport = "http"; | ||||
| 				params += opt.query("host", "h2_host"); | ||||
| 				params += opt.query("path", "h2_path"); | ||||
| 			} else if (v_transport === "tcp") { | ||||
| @ -252,21 +256,32 @@ local has_xray = api.is_finded("xray") | ||||
| 				//不知道是用path还是serviceName,这里先这样吧 | ||||
| 				params += opt.query("path", "grpc_serviceName"); | ||||
| 				params += opt.query("serviceName", "grpc_serviceName"); | ||||
| 				params += opt.query("mode", "grpc_mode"); | ||||
| 			} | ||||
| 			params += "&type=" + v_transport; | ||||
| 			 | ||||
| 			params += opt.query("encryption", "encryption"); | ||||
| 			if (opt.get("tls").checked) { | ||||
| 				var v_security = "tls"; | ||||
| 				params += "&security=" + v_security; | ||||
| 				if (opt.get("tlsflow").value) { | ||||
| 				if (opt.get("xray_fingerprint") && opt.get("xray_fingerprint").value != "") { | ||||
| 					let v_fp = opt.get("xray_fingerprint").value; | ||||
| 					params += "&fp=" + v_fp; | ||||
| 				} | ||||
| 				if(opt.get("reality") && opt.get("reality").checked) { | ||||
| 					v_security = "reality"; | ||||
| 					if (opt.get("reality_fingerprint") && opt.get("reality_fingerprint").value != "") { | ||||
| 						let v_fp = opt.get("reality_fingerprint").value; | ||||
| 						params += "&fp=" + v_fp; | ||||
| 					} | ||||
| 					params += opt.query("pbk", "reality_publicKey"); | ||||
| 					params += opt.query("sid", "reality_shortId"); | ||||
| 					params += opt.query("spx", "reality_spiderX"); | ||||
| 				} | ||||
| 				if (opt.get("tlsflow") && opt.get("tlsflow").value) { | ||||
| 					let v_flow = opt.get("tlsflow").value; | ||||
| 					params += "&flow=" + v_flow; | ||||
| 				} | ||||
| 				if (opt.get("xray_fingerprint").value && opt.get("xray_fingerprint").value != "") { | ||||
| 					let v_fp = opt.get("xray_fingerprint").value | ||||
| 					params += "&fp=" + v_fp; | ||||
| 				} | ||||
| 				params += "&security=" + v_security; | ||||
| 				params += opt.query("sni", "tls_serverName"); | ||||
| 			} | ||||
|  | ||||
| @ -280,10 +295,9 @@ local has_xray = api.is_finded("xray") | ||||
| 				v_type = "trojan"; | ||||
| 			} | ||||
| 			var v_password = opt.get("password"); | ||||
| 			var v_server = opt.get("address"); | ||||
| 			var v_port = opt.get("port"); | ||||
| 			url = encodeURIComponent(v_password.value) + | ||||
| 				"@" + v_server.value + | ||||
| 				"@" + _address + | ||||
| 				":" + v_port.value + "/?"; | ||||
| 			var params = ""; | ||||
| 			if (opt.get("tls").checked) { | ||||
| @ -300,7 +314,6 @@ local has_xray = api.is_finded("xray") | ||||
| 			var url = ""; | ||||
| 			var params = "?"; | ||||
| 			var v_protocol = opt.get("brook_protocol"); | ||||
| 			var v_server = opt.get("address"); | ||||
| 			var v_port = opt.get("port"); | ||||
| 			var v_password = opt.get("password"); | ||||
| 			var b_protocol_value = v_protocol.value.split('client').join('server'); | ||||
| @ -319,14 +332,13 @@ local has_xray = api.is_finded("xray") | ||||
| 				if (v_path_value.length > 1 && v_path_value.indexOf('/') < 0) { | ||||
| 					v_path_value = '/' + v_path_value; | ||||
| 				} | ||||
| 				params += "&" + url_protocol + "=" + encodeURIComponent(prefix + v_server.value + ":" + v_port.value + v_path_value); | ||||
| 				params += "&" + url_protocol + "=" + encodeURIComponent(prefix + _address + ":" + v_port.value + v_path_value); | ||||
| 			} else { | ||||
| 				params += "&" + url_protocol + "=" + encodeURIComponent(v_server.value + ":" + v_port.value); | ||||
| 				params += "&" + url_protocol + "=" + encodeURIComponent(_address + ":" + v_port.value); | ||||
| 			} | ||||
| 			url += url_protocol; | ||||
| 			url += params; | ||||
| 		} else if (v_type === "Hysteria") { | ||||
| 			var v_server = opt.get("address"); | ||||
| 			var v_port = opt.get("port"); | ||||
| 			var params = ""; | ||||
| 			params += opt.query("protocol", "hysteria_protocol"); | ||||
| @ -338,7 +350,7 @@ local has_xray = api.is_finded("xray") | ||||
| 			params += opt.query("alpn", "hysteria_alpn"); | ||||
| 			params += opt.query("obfsParam", "hysteria_obfs"); | ||||
| 			var url = | ||||
| 				v_server.value + ":" + | ||||
| 				_address + ":" + | ||||
| 				v_port.value + "?" + | ||||
| 				params + | ||||
| 				"#" + encodeURI(v_alias.value); | ||||
| @ -677,6 +689,7 @@ local has_xray = api.is_finded("xray") | ||||
| 			if (queryParam.security) { | ||||
| 				if (queryParam.security == "tls") { | ||||
| 					opt.set('tls', true); | ||||
| 					opt.set('reality', false) | ||||
| 					opt.set('tlsflow', queryParam.flow || ''); | ||||
| 					opt.set('tls_serverName', queryParam.sni || ''); | ||||
| 					opt.set('tls_allowInsecure', true); | ||||
| @ -688,10 +701,25 @@ local has_xray = api.is_finded("xray") | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			 | ||||
|  | ||||
| 			if (queryParam.security == "reality") { | ||||
| 				opt.set('tls', true); | ||||
| 				opt.set('reality', true) | ||||
| 				opt.set('tlsflow', queryParam.flow || ''); | ||||
| 				opt.set('tls_serverName', queryParam.sni || ''); | ||||
| 				if (queryParam.fp && queryParam.fp.trim() != "") { | ||||
| 					opt.set('reality_fingerprint', queryParam.fp); | ||||
| 				} | ||||
| 				opt.set('reality_publicKey', queryParam.pbk || ''); | ||||
| 				opt.set('reality_shortId', queryParam.sid || ''); | ||||
| 				opt.set('reality_spiderX', queryParam.spx || ''); | ||||
| 			} | ||||
|  | ||||
| 			queryParam.type = queryParam.type.toLowerCase(); | ||||
| 			if (queryParam.type === "kcp" || queryParam.type === "mkcp") | ||||
| 				queryParam.type = "mkcp" | ||||
| 			if (queryParam.type === "h2" || queryParam.type === "http") | ||||
| 				queryParam.type = "h2" | ||||
| 			opt.set('transport', queryParam.type); | ||||
| 			if (queryParam.type === "tcp") { | ||||
| 				opt.set('tcp_guise', queryParam.headerType || "none"); | ||||
| @ -702,7 +730,7 @@ local has_xray = api.is_finded("xray") | ||||
| 			} else if (queryParam.type === "ws") { | ||||
| 				opt.set('ws_host', queryParam.host || ""); | ||||
| 				opt.set('ws_path', queryParam.path || ""); | ||||
| 			} else if (queryParam.type === "h2") { | ||||
| 			} else if (queryParam.type === "h2" || queryParam.type === "http") { | ||||
| 				opt.set('h2_host', queryParam.host || ""); | ||||
| 				opt.set('h2_path', queryParam.path || ""); | ||||
| 			} else if (queryParam.type === "quic") { | ||||
| @ -713,6 +741,7 @@ local has_xray = api.is_finded("xray") | ||||
| 				opt.set('mkcp_guise', queryParam.headerType || "none"); | ||||
| 			} else if (queryParam.type === "grpc") { | ||||
| 				opt.set('grpc_serviceName', (queryParam.serviceName || queryParam.path) || ""); | ||||
| 				opt.set('grpc_mode', queryParam.mode); | ||||
| 			} | ||||
| 			 | ||||
| 			if (m.hash) { | ||||
|  | ||||
| @ -274,6 +274,15 @@ msgstr "Xray 负载均衡" | ||||
| msgid "V2ray_balancing" | ||||
| msgstr "V2ray 负载均衡" | ||||
|  | ||||
| msgid "Balancing Strategy" | ||||
| msgstr "负载均衡策略" | ||||
|  | ||||
| msgid "Probe Interval" | ||||
| msgstr "探测间隔" | ||||
|  | ||||
| msgid "The interval between initiating probes. Every time this time elapses, a server status check is performed on a server. The time format is numbers + units, such as '10s', '2h45m', and the supported time units are <code>ns</code>, <code>us</code>, <code>ms</code>, <code>s</code>, <code>m</code>, <code>h</code>, which correspond to nanoseconds, microseconds, milliseconds, seconds, minutes, and hours, respectively." | ||||
| msgstr "发起探测的间隔。每经过这个时间,就会对一个服务器进行服务器状态检测。时间格式为数字+单位,比如<code>"10s"</code>, <code>"2h45m"</code>,支持的时间单位有 <code>ns</code>,<code>us</code>,<code>ms</code>,<code>s</code>,<code>m</code>,<code>h</code>,分别对应纳秒、微秒、毫秒、秒、分、时。" | ||||
|  | ||||
| msgid "Shunt" | ||||
| msgstr "分流" | ||||
|  | ||||
| @ -406,6 +415,9 @@ msgstr "QUIC 连接接收窗口" | ||||
| msgid "Disable MTU detection" | ||||
| msgstr "禁用 MTU 检测" | ||||
|  | ||||
| msgid "Lazy Start" | ||||
| msgstr "延迟启动" | ||||
|  | ||||
| msgid "Encrypt Method" | ||||
| msgstr "加密" | ||||
|  | ||||
|  | ||||
| @ -70,6 +70,7 @@ config nodes 'myshunt' | ||||
| 	option AD 'nil' | ||||
| 	option BT '_direct' | ||||
| 	option Netflix 'nil' | ||||
| 	option OpenAI 'nil' | ||||
| 	option TVB 'nil' | ||||
| 	option Proxy '_default' | ||||
| 	option China '_direct' | ||||
| @ -173,6 +174,10 @@ config shunt_rules 'Netflix' | ||||
| 	option remarks 'Netflix' | ||||
| 	option network 'tcp,udp' | ||||
| 	option domain_list 'geosite:netflix' | ||||
| 	 | ||||
| config shunt_rules 'OpenAI' | ||||
| 	option remarks 'OpenAI' | ||||
| 	option domain_list 'geosite:openai' | ||||
|  | ||||
| config shunt_rules 'TVB' | ||||
| 	option remarks 'TVB' | ||||
|  | ||||
| @ -299,12 +299,12 @@ run_v2ray() { | ||||
| 	} | ||||
| 	local buffer_size=$(config_t_get global_forwarding buffer_size) | ||||
| 	[ -n "${buffer_size}" ] && _extra_param="${_extra_param} -buffer_size ${buffer_size}" | ||||
| 	 | ||||
|  | ||||
| 	local protocol=$(config_n_get $node protocol) | ||||
| 	[ "$protocol" == "_iface" ] && { | ||||
| 		IFACES="$IFACES $(config_n_get $node iface)" | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	[ -n "$dns_listen_port" ] && { | ||||
| 		V2RAY_DNS_DIRECT_CONFIG="${TMP_PATH}/${flag}_dns_direct.json" | ||||
| 		V2RAY_DNS_DIRECT_LOG="${TMP_PATH}/${flag}_dns_direct.log" | ||||
| @ -345,10 +345,10 @@ run_v2ray() { | ||||
| 		esac | ||||
| 		[ -n "$direct_dns_query_strategy" ] && V2RAY_DNS_DIRECT_ARGS="${V2RAY_DNS_DIRECT_ARGS} -dns_query_strategy ${direct_dns_query_strategy}" | ||||
| 		[ -n "$direct_dns_client_ip" ] && V2RAY_DNS_DIRECT_ARGS="${V2RAY_DNS_DIRECT_ARGS} -dns_client_ip ${direct_dns_client_ip}" | ||||
| 		 | ||||
|  | ||||
| 		lua $UTIL_XRAY gen_dns_config ${V2RAY_DNS_DIRECT_ARGS} > $V2RAY_DNS_DIRECT_CONFIG | ||||
| 		ln_run "$(first_type $(config_t_get global_app ${type}_file) ${type})" ${type} $V2RAY_DNS_DIRECT_LOG run -c "$V2RAY_DNS_DIRECT_CONFIG" | ||||
| 		 | ||||
|  | ||||
| 		[ "$remote_dns_protocol" != "fakedns" ] && { | ||||
| 			V2RAY_DNS_REMOTE_CONFIG="${TMP_PATH}/${flag}_dns_remote.json" | ||||
| 			V2RAY_DNS_REMOTE_LOG="${TMP_PATH}/${flag}_dns_remote.log" | ||||
| @ -386,15 +386,15 @@ run_v2ray() { | ||||
| 					V2RAY_DNS_REMOTE_ARGS="${V2RAY_DNS_REMOTE_ARGS} -remote_dns_fake 1" | ||||
| 				;; | ||||
| 			esac | ||||
| 			 | ||||
|  | ||||
| 			[ -n "$remote_dns_query_strategy" ] && V2RAY_DNS_REMOTE_ARGS="${V2RAY_DNS_REMOTE_ARGS} -dns_query_strategy ${remote_dns_query_strategy}" | ||||
| 			[ -n "$remote_dns_client_ip" ] && V2RAY_DNS_REMOTE_ARGS="${V2RAY_DNS_REMOTE_ARGS} -dns_client_ip ${remote_dns_client_ip}" | ||||
| 			 | ||||
|  | ||||
| 			V2RAY_DNS_REMOTE_ARGS="${V2RAY_DNS_REMOTE_ARGS} -remote_dns_outbound_socks_address 127.0.0.1 -remote_dns_outbound_socks_port ${socks_port}" | ||||
| 			lua $UTIL_XRAY gen_dns_config ${V2RAY_DNS_REMOTE_ARGS} > $V2RAY_DNS_REMOTE_CONFIG | ||||
| 			ln_run "$(first_type $(config_t_get global_app ${type}_file) ${type})" ${type} $V2RAY_DNS_REMOTE_LOG run -c "$V2RAY_DNS_REMOTE_CONFIG" | ||||
| 		} | ||||
| 		 | ||||
|  | ||||
| 		[ -n "$dns_listen_port" ] && _extra_param="${_extra_param} -dns_listen_port ${dns_listen_port}" | ||||
| 		[ -n "$dns_cache" ] && _extra_param="${_extra_param} -dns_cache ${dns_cache}" | ||||
| 		_extra_param="${_extra_param} -dns_query_strategy UseIP" | ||||
| @ -405,7 +405,7 @@ run_v2ray() { | ||||
| 			_extra_param="${_extra_param} -remote_dns_port ${dns_remote_listen_port} -remote_dns_udp_server 127.0.0.1" | ||||
| 		fi | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	lua $UTIL_XRAY gen_config -node $node -redir_port $redir_port -tcp_proxy_way $tcp_proxy_way -loglevel $loglevel ${_extra_param} > $config_file | ||||
| 	ln_run "$(first_type $(config_t_get global_app ${type}_file) ${type})" ${type} $log_file run -c "$config_file" | ||||
| } | ||||
| @ -441,7 +441,7 @@ run_socks() { | ||||
| 	else | ||||
| 		error_msg="某种原因,此 Socks 服务的相关配置已失联,启动中止!" | ||||
| 	fi | ||||
| 	 | ||||
|  | ||||
| 	if [ "$type" == "v2ray" ] || [ "$type" == "xray" ]; then | ||||
| 		local protocol=$(config_n_get $node protocol) | ||||
| 		if [ "$protocol" == "_balancing" ] || [ "$protocol" == "_shunt" ] || [ "$protocol" == "_iface" ]; then | ||||
| @ -558,7 +558,7 @@ node_switch() { | ||||
| 			new_script_func=$(echo $script_func | sed "s#${now_node_arg}#node=${new_node}#g") | ||||
| 			${new_script_func} | ||||
| 			echo $new_node > $TMP_ID_PATH/${flag} | ||||
| 			 | ||||
|  | ||||
| 			[ "$shunt_logic" != "0" ] && [ "$(config_n_get $new_node protocol nil)" = "_shunt" ] && { | ||||
| 				echo $(config_n_get $new_node default_node nil) > $TMP_ID_PATH/${flag}_default | ||||
| 				echo $(config_n_get $new_node main_node nil) > $TMP_ID_PATH/${flag}_main | ||||
| @ -642,7 +642,7 @@ run_global() { | ||||
| 	} | ||||
| 	msg="${msg})" | ||||
| 	echolog ${msg} | ||||
| 	 | ||||
|  | ||||
| 	source $APP_PATH/helper_dnsmasq.sh stretch | ||||
| 	source $APP_PATH/helper_dnsmasq.sh add TMP_DNSMASQ_PATH=$TMP_DNSMASQ_PATH DNSMASQ_CONF_FILE=/tmp/dnsmasq.d/dnsmasq-passwall2.conf DEFAULT_DNS=$AUTO_DNS LOCAL_DNS=$LOCAL_DNS TUN_DNS=$TUN_DNS | ||||
|  | ||||
| @ -801,7 +801,7 @@ acl_app() { | ||||
| 			sid=$(uci -q show "${CONFIG}.${item}" | grep "=acl_rule" | awk -F '=' '{print $1}' | awk -F '.' '{print $2}') | ||||
| 			eval $(uci -q show "${CONFIG}.${item}" | cut -d'.' -sf 3-) | ||||
| 			[ "$enabled" = "1" ] || continue | ||||
| 			 | ||||
|  | ||||
| 			[ -z "${sources}" ] && continue | ||||
| 			for s in $sources; do | ||||
| 				is_iprange=$(lua_api "iprange(\"${s}\")") | ||||
| @ -821,7 +821,7 @@ acl_app() { | ||||
| 			[ -z "${rule_list}" ] && continue | ||||
| 			mkdir -p $TMP_ACL_PATH/$sid | ||||
| 			echo -e "${rule_list}" | sed '/^$/d' > $TMP_ACL_PATH/$sid/rule_list | ||||
| 			 | ||||
|  | ||||
| 			tcp_proxy_mode="global" | ||||
| 			udp_proxy_mode="global" | ||||
| 			node=${node:-default} | ||||
| @ -833,7 +833,7 @@ acl_app() { | ||||
| 			remote_dns=${remote_dns:-1.1.1.1} | ||||
| 			[ "$remote_dns_protocol" = "doh" ] && remote_dns=${remote_dns_doh:-https://1.1.1.1/dns-query} | ||||
| 			remote_dns_query_strategy=${remote_dns_query_strategy:-UseIPv4} | ||||
| 			 | ||||
|  | ||||
| 			[ "$node" != "nil" ] && { | ||||
| 				if [ "$node" = "default" ]; then | ||||
| 					node=$NODE | ||||
| @ -893,18 +893,18 @@ acl_app() { | ||||
|  | ||||
| start() { | ||||
| 	pgrep -f /tmp/etc/passwall2/bin > /dev/null 2>&1 && { | ||||
| 		echolog "程序已启动,无需重复启动!" | ||||
| 		return 0 | ||||
| 		echolog "程序已启动,先停止再重新启动!" | ||||
| 		stop | ||||
| 	} | ||||
|  | ||||
| 	ulimit -n 65535 | ||||
| 	start_socks | ||||
| 	 | ||||
|  | ||||
| 	local USE_TABLES="iptables" | ||||
| 	if [ -z "$(command -v iptables-legacy || command -v iptables)" ] || [ -z "$(command -v ipset)" ]; then | ||||
| 		echolog "系统未安装iptables或ipset,无法透明代理!" | ||||
| 	fi | ||||
| 	 | ||||
|  | ||||
| 	[ "$ENABLED_DEFAULT_ACL" == 1 ] && run_global | ||||
| 	source $APP_PATH/${USE_TABLES}.sh start | ||||
| 	[ "$ENABLED_DEFAULT_ACL" == 1 ] && source $APP_PATH/helper_dnsmasq.sh logic_restart | ||||
|  | ||||
| @ -21,14 +21,10 @@ local geosite_api = ucic:get_first(name, 'global_rules', "geosite_url", "https:/ | ||||
|  | ||||
| local log = function(...) | ||||
|     if arg1 then | ||||
|         local result = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ") | ||||
|         if arg1 == "log" then | ||||
|             local f, err = io.open("/tmp/log/passwall2.log", "a") | ||||
|             if f and err == nil then | ||||
|                 f:write(result .. "\n") | ||||
|                 f:close() | ||||
|             end | ||||
| 			api.log(...) | ||||
|         elseif arg1 == "print" then | ||||
| 			local result = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ") | ||||
|             print(result) | ||||
|         end | ||||
|     end | ||||
|  | ||||
| @ -80,15 +80,11 @@ local nodeResult = {} -- update result | ||||
| local debug = false | ||||
|  | ||||
| local log = function(...) | ||||
| 	local result = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ") | ||||
| 	if debug == true then | ||||
| 		local result = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ") | ||||
| 		print(result) | ||||
| 	else | ||||
| 		local f, err = io.open("/tmp/log/" .. appname .. ".log", "a") | ||||
| 		if f and err == nil then | ||||
| 			f:write(result .. "\n") | ||||
| 			f:close() | ||||
| 		end | ||||
| 		api.log(...) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| @ -328,15 +324,17 @@ local function processData(szType, content, add_mode, add_from) | ||||
| 		add_mode = add_mode, --0为手动配置,1为导入,2为订阅 | ||||
| 		add_from = add_from | ||||
| 	} | ||||
| 	--ssr://base64(host:port:protocol:method:obfs:base64pass/?obfsparam=base64param&protoparam=base64param&remarks=base64remarks&group=base64group&udpport=0&uot=0) | ||||
| 	if szType == 'ssr' then | ||||
| 		result.type = "SSR" | ||||
|  | ||||
| 		local dat = split(content, "/%?") | ||||
| 		local hostInfo = split(dat[1], ':') | ||||
| 		result.type = "SSR" | ||||
| 		result.address = "" | ||||
| 		for i=1,#hostInfo-5,1 do | ||||
| 			result.address = result.address .. hostInfo[i] .. ":" | ||||
| 		if dat[1]:match('%[(.*)%]') then | ||||
| 			result.address = dat[1]:match('%[(.*)%]') | ||||
| 		else | ||||
| 			result.address = hostInfo[#hostInfo-5] | ||||
| 		end | ||||
| 		result.address = string.sub(result.address, 0, #result.address-1)  | ||||
| 		result.port = hostInfo[#hostInfo-4] | ||||
| 		result.protocol = hostInfo[#hostInfo-3] | ||||
| 		result.method = hostInfo[#hostInfo-2] | ||||
| @ -410,6 +408,15 @@ local function processData(szType, content, add_mode, add_from) | ||||
| 			result.tls = "0" | ||||
| 		end | ||||
| 	elseif szType == "ss" then | ||||
| 		result.type = "SS" | ||||
|  | ||||
| 		--SS-URI = "ss://" userinfo "@" hostname ":" port [ "/" ] [ "?" plugin ] [ "#" tag ] | ||||
| 		--userinfo = websafe-base64-encode-utf8(method  ":" password) | ||||
| 		--ss://YWVzLTEyOC1nY206dGVzdA@192.168.100.1:8888#Example1 | ||||
| 		--ss://cmM0LW1kNTpwYXNzd2Q@192.168.100.1:8888/?plugin=obfs-local%3Bobfs%3Dhttp#Example2 | ||||
| 		--ss://2022-blake3-aes-256-gcm:YctPZ6U7xPPcU%2Bgp3u%2B0tx%2FtRizJN9K8y%2BuKlW2qjlI%3D@192.168.100.1:8888#Example3 | ||||
| 		--ss://2022-blake3-aes-256-gcm:YctPZ6U7xPPcU%2Bgp3u%2B0tx%2FtRizJN9K8y%2BuKlW2qjlI%3D@192.168.100.1:8888/?plugin=v2ray-plugin%3Bserver#Example3 | ||||
|  | ||||
| 		local idx_sp = 0 | ||||
| 		local alias = "" | ||||
| 		if content:find("#") then | ||||
| @ -418,28 +425,9 @@ local function processData(szType, content, add_mode, add_from) | ||||
| 		end | ||||
| 		result.remarks = UrlDecode(alias) | ||||
| 		local info = content:sub(1, idx_sp - 1) | ||||
| 		local hostInfo = split(base64Decode(info), "@") | ||||
| 		local hostInfoLen = #hostInfo | ||||
| 		local host = nil | ||||
| 		local userinfo = nil | ||||
| 		if hostInfoLen > 2 then | ||||
| 			host = split(hostInfo[hostInfoLen], ":") | ||||
| 			userinfo = {} | ||||
| 			for i = 1, hostInfoLen - 1 do | ||||
| 				tinsert(userinfo, hostInfo[i]) | ||||
| 			end | ||||
| 			userinfo = table.concat(userinfo, '@') | ||||
| 		else | ||||
| 			host = split(hostInfo[2], ":") | ||||
| 			userinfo = base64Decode(hostInfo[1]) | ||||
| 		end | ||||
| 		local method = userinfo:sub(1, userinfo:find(":") - 1) | ||||
| 		local password = userinfo:sub(userinfo:find(":") + 1, #userinfo) | ||||
| 		result.type = "SS" | ||||
| 		result.address = host[1] | ||||
| 		if host[2] and host[2]:find("/%?") then | ||||
| 			local query = split(host[2], "/%?") | ||||
| 			result.port = query[1] | ||||
| 		if info:find("/%?") then | ||||
| 			local find_index = info:find("/%?") | ||||
| 			local query = split(info, "/%?") | ||||
| 			local params = {} | ||||
| 			for _, v in pairs(split(query[2], '&')) do | ||||
| 				local t = split(v, '=') | ||||
| @ -459,39 +447,70 @@ local function processData(szType, content, add_mode, add_from) | ||||
| 			if result.plugin and result.plugin == "simple-obfs" then | ||||
| 				result.plugin = "obfs-local" | ||||
| 			end | ||||
| 		else | ||||
| 			result.port = host[2] | ||||
| 			info = info:sub(1, find_index - 1) | ||||
| 		end | ||||
| 		result.method = method | ||||
| 		result.password = password | ||||
|  | ||||
| 		local aead = false | ||||
| 		for k, v in ipairs({"aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305"}) do | ||||
| 			if method:lower() == v:lower() then | ||||
| 				aead = true | ||||
| 		local hostInfo = split(base64Decode(info), "@") | ||||
| 		if hostInfo and #hostInfo > 0 then | ||||
| 			local host_port = hostInfo[#hostInfo] | ||||
| 			-- [2001:4860:4860::8888]:443 | ||||
| 			-- 8.8.8.8:443 | ||||
| 			if host_port:find(":") then | ||||
| 				local sp = split(host_port, ":") | ||||
| 				result.port = sp[#sp] | ||||
| 				if api.is_ipv6addrport(host_port) then | ||||
| 					result.address = api.get_ipv6_only(host_port) | ||||
| 				else | ||||
| 					result.address = sp[1] | ||||
| 				end | ||||
| 			else | ||||
| 				result.address = host_port | ||||
| 			end | ||||
| 		end | ||||
| 		if aead then | ||||
| 			if ss_aead_type_default == "shadowsocks-libev" and has_ss then | ||||
| 				result.type = "SS" | ||||
| 			elseif ss_aead_type_default == "shadowsocks-rust" and has_ss_rust then | ||||
| 				result.type = 'SS-Rust' | ||||
| 				if method:lower() == "chacha20-poly1305" then | ||||
| 					result.method = "chacha20-ietf-poly1305" | ||||
|  | ||||
| 			local userinfo = nil | ||||
| 			if #hostInfo > 2 then | ||||
| 				userinfo = {} | ||||
| 				for i = 1, #hostInfo - 1 do | ||||
| 					tinsert(userinfo, hostInfo[i]) | ||||
| 				end | ||||
| 			elseif ss_aead_type_default == "v2ray" and has_v2ray and not result.plugin then | ||||
| 				result.type = 'V2ray' | ||||
| 				result.protocol = 'shadowsocks' | ||||
| 				result.transport = 'tcp' | ||||
| 				if method:lower() == "chacha20-ietf-poly1305" then | ||||
| 					result.method = "chacha20-poly1305" | ||||
| 				userinfo = table.concat(userinfo, '@') | ||||
| 			else | ||||
| 				userinfo = base64Decode(hostInfo[1]) | ||||
| 			end | ||||
|  | ||||
| 			local method = userinfo:sub(1, userinfo:find(":") - 1) | ||||
| 			local password = userinfo:sub(userinfo:find(":") + 1, #userinfo) | ||||
| 			result.method = method | ||||
| 			result.password = password | ||||
|  | ||||
| 			local aead = false | ||||
| 			for k, v in ipairs({"aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305"}) do | ||||
| 				if method:lower() == v:lower() then | ||||
| 					aead = true | ||||
| 				end | ||||
| 			elseif ss_aead_type_default == "xray" and has_xray and not result.plugin then | ||||
| 				result.type = 'Xray' | ||||
| 				result.protocol = 'shadowsocks' | ||||
| 				result.transport = 'tcp' | ||||
| 				if method:lower() == "chacha20-ietf-poly1305" then | ||||
| 					result.method = "chacha20-poly1305" | ||||
| 			end | ||||
| 			if aead then | ||||
| 				if ss_aead_type_default == "shadowsocks-libev" and has_ss then | ||||
| 					result.type = "SS" | ||||
| 				elseif ss_aead_type_default == "shadowsocks-rust" and has_ss_rust then | ||||
| 					result.type = 'SS-Rust' | ||||
| 					if method:lower() == "chacha20-poly1305" then | ||||
| 						result.method = "chacha20-ietf-poly1305" | ||||
| 					end | ||||
| 				elseif ss_aead_type_default == "v2ray" and has_v2ray and not result.plugin then | ||||
| 					result.type = 'V2ray' | ||||
| 					result.protocol = 'shadowsocks' | ||||
| 					result.transport = 'tcp' | ||||
| 					if method:lower() == "chacha20-ietf-poly1305" then | ||||
| 						result.method = "chacha20-poly1305" | ||||
| 					end | ||||
| 				elseif ss_aead_type_default == "xray" and has_xray and not result.plugin then | ||||
| 					result.type = 'Xray' | ||||
| 					result.protocol = 'shadowsocks' | ||||
| 					result.transport = 'tcp' | ||||
| 					if method:lower() == "chacha20-ietf-poly1305" then | ||||
| 						result.method = "chacha20-poly1305" | ||||
| 					end | ||||
| 				end | ||||
| 			end | ||||
| 		end | ||||
| @ -513,33 +532,28 @@ local function processData(szType, content, add_mode, add_from) | ||||
| 			result.password = UrlDecode(Info[1]) | ||||
| 			local port = "443" | ||||
| 			Info[2] = (Info[2] or ""):gsub("/%?", "?") | ||||
| 			local hostInfo = nil | ||||
| 			if Info[2]:find(":") then | ||||
| 				hostInfo = split(Info[2], ":") | ||||
| 				result.address = hostInfo[1] | ||||
| 				local idx_port = 2 | ||||
| 				if hostInfo[2]:find("?") then | ||||
| 					hostInfo = split(hostInfo[2], "?") | ||||
| 					idx_port = 1 | ||||
| 				end | ||||
| 				if hostInfo[idx_port] ~= "" then port = hostInfo[idx_port] end | ||||
| 			else | ||||
| 				if Info[2]:find("?") then | ||||
| 					hostInfo = split(Info[2], "?") | ||||
| 				end | ||||
| 				result.address = hostInfo and hostInfo[1] or Info[2] | ||||
| 			end | ||||
| 			local peer, sni = nil, "" | ||||
| 			local allowInsecure = allowInsecure_default | ||||
| 			local query = split(Info[2], "?") | ||||
| 			local host_port = query[1] | ||||
| 			local params = {} | ||||
| 			for _, v in pairs(split(query[2], '&')) do | ||||
| 				local t = split(v, '=') | ||||
| 				params[string.lower(t[1])] = UrlDecode(t[2]) | ||||
| 			end | ||||
| 			if params.allowinsecure then | ||||
| 				allowInsecure = params.allowinsecure | ||||
| 			-- [2001:4860:4860::8888]:443 | ||||
| 			-- 8.8.8.8:443 | ||||
| 			if host_port:find(":") then | ||||
| 				local sp = split(host_port, ":") | ||||
| 				port = sp[#sp] | ||||
| 				if api.is_ipv6addrport(host_port) then | ||||
| 					result.address = api.get_ipv6_only(host_port) | ||||
| 				else | ||||
| 					result.address = sp[1] | ||||
| 				end | ||||
| 			else | ||||
| 				result.address = host_port | ||||
| 			end | ||||
|  | ||||
| 			local peer, sni = nil, "" | ||||
| 			if params.peer then peer = params.peer end | ||||
| 			sni = params.sni and params.sni or "" | ||||
| 			if params.ws and params.ws == "1" then | ||||
| @ -551,7 +565,16 @@ local function processData(szType, content, add_mode, add_from) | ||||
| 			result.port = port | ||||
| 			result.tls = '1' | ||||
| 			result.tls_serverName = peer and peer or sni | ||||
| 			result.tls_allowInsecure = allowInsecure and "1" or "0" | ||||
| 			if params.allowinsecure then | ||||
| 				if params.allowinsecure == "1" or params.allowinsecure == "0" then | ||||
| 					result.tls_allowInsecure = params.allowinsecure | ||||
| 				else | ||||
| 					result.tls_allowInsecure = string.lower(params.allowinsecure) == "true" and "1" or "0" | ||||
| 				end | ||||
| 				--log(result.remarks .. ' 使用节点AllowInsecure设定: '.. result.tls_allowInsecure) | ||||
| 			else | ||||
| 				result.tls_allowInsecure = allowInsecure_default and "1" or "0" | ||||
| 			end | ||||
| 		end | ||||
| 	elseif szType == "ssd" then | ||||
| 		result.type = "SS" | ||||
| @ -581,36 +604,34 @@ local function processData(szType, content, add_mode, add_from) | ||||
| 			result.uuid = UrlDecode(Info[1]) | ||||
| 			local port = "443" | ||||
| 			Info[2] = (Info[2] or ""):gsub("/%?", "?") | ||||
| 			local hostInfo = nil | ||||
| 			if Info[2]:find(":") then | ||||
| 				hostInfo = split(Info[2], ":") | ||||
| 				result.address = hostInfo[1] | ||||
| 				local idx_port = 2 | ||||
| 				if hostInfo[2]:find("?") then | ||||
| 					hostInfo = split(hostInfo[2], "?") | ||||
| 					idx_port = 1 | ||||
| 				end | ||||
| 				if hostInfo[idx_port] ~= "" then port = hostInfo[idx_port] end | ||||
| 			else | ||||
| 				if Info[2]:find("?") then | ||||
| 					hostInfo = split(Info[2], "?") | ||||
| 				end | ||||
| 				result.address = hostInfo and hostInfo[1] or Info[2] | ||||
| 			end | ||||
| 			 | ||||
| 			local query = split(Info[2], "?") | ||||
| 			local host_port = query[1] | ||||
| 			local params = {} | ||||
| 			for _, v in pairs(split(query[2], '&')) do | ||||
| 				local t = split(v, '=') | ||||
| 				params[t[1]] = UrlDecode(t[2]) | ||||
| 			end | ||||
| 			-- [2001:4860:4860::8888]:443 | ||||
| 			-- 8.8.8.8:443 | ||||
| 			if host_port:find(":") then | ||||
| 				local sp = split(host_port, ":") | ||||
| 				port = sp[#sp] | ||||
| 				if api.is_ipv6addrport(host_port) then | ||||
| 					result.address = api.get_ipv6_only(host_port) | ||||
| 				else | ||||
| 					result.address = sp[1] | ||||
| 				end | ||||
| 			else | ||||
| 				result.address = host_port | ||||
| 			end | ||||
|  | ||||
| 			params.type = string.lower(params.type) | ||||
| 			if params.type == 'ws' then | ||||
| 				result.ws_host = params.host | ||||
| 				result.ws_path = params.path | ||||
| 			end | ||||
| 			if params.type == 'h2' then | ||||
| 			if params.type == 'h2' or params.type == 'http' then | ||||
| 				params.type = "h2" | ||||
| 				result.h2_host = params.host | ||||
| 				result.h2_path = params.path | ||||
| 			end | ||||
| @ -637,17 +658,24 @@ local function processData(szType, content, add_mode, add_from) | ||||
| 			if params.type == 'grpc' then | ||||
| 				if params.path then result.grpc_serviceName = params.path end | ||||
| 				if params.serviceName then result.grpc_serviceName = params.serviceName end | ||||
| 				result.grpc_mode = params.mode | ||||
| 			end | ||||
| 			result.transport = params.type | ||||
| 			 | ||||
| 			result.encryption = params.encryption or "none" | ||||
|  | ||||
| 			result.tls = "0" | ||||
| 			if params.security == "tls" then | ||||
| 			if params.security == "tls" or params.security == "reality" then | ||||
| 				result.tls = "1" | ||||
| 				result.tlsflow = params.flow or nil | ||||
| 				result.tls_serverName = (params.sni and params.sni ~= "") and params.sni or params.host | ||||
| 				result.fingerprint = (params.fp and params.fp ~= "") and params.fp or "chrome" | ||||
| 				if params.security == "reality" then | ||||
| 					result.reality = "1" | ||||
| 					result.reality_publicKey = params.pbk or nil | ||||
| 					result.reality_shortId = params.sid or nil | ||||
| 					result.reality_spiderX = params.spx or nil | ||||
| 				end | ||||
| 			end | ||||
|  | ||||
| 			result.port = port | ||||
| @ -664,9 +692,7 @@ local function processData(szType, content, add_mode, add_from) | ||||
| 		result.type = "Hysteria" | ||||
| 		 | ||||
| 		local dat = split(content, '%?') | ||||
| 		local hostInfo = split(dat[1], ':') | ||||
| 		result.address = hostInfo[1] | ||||
| 		result.port = hostInfo[2] | ||||
| 		local host_port = dat[1] | ||||
| 		local params = {} | ||||
| 		for _, v in pairs(split(dat[2], '&')) do | ||||
| 			local t = split(v, '=') | ||||
| @ -674,6 +700,19 @@ local function processData(szType, content, add_mode, add_from) | ||||
| 				params[t[1]] = t[2] | ||||
| 			end | ||||
| 		end | ||||
| 		-- [2001:4860:4860::8888]:443 | ||||
| 		-- 8.8.8.8:443 | ||||
| 		if host_port:find(":") then | ||||
| 			local sp = split(host_port, ":") | ||||
| 			result.port = sp[#sp] | ||||
| 			if api.is_ipv6addrport(host_port) then | ||||
| 				result.address = api.get_ipv6_only(host_port) | ||||
| 			else | ||||
| 				result.address = sp[1] | ||||
| 			end | ||||
| 		else | ||||
| 			result.address = host_port | ||||
| 		end | ||||
| 		result.protocol = params.protocol | ||||
| 		result.hysteria_obfs = params.obfsParam | ||||
| 		result.hysteria_auth_type = "string" | ||||
| @ -990,8 +1029,8 @@ local function parse_link(raw, add_mode, add_from) | ||||
| 				if result then | ||||
| 					if not result.type then | ||||
| 						log('丢弃节点:' .. result.remarks .. ",找不到可使用二进制.") | ||||
| 					elseif (add_mode == "2" and is_filter_keyword(result.remarks)) or not result.address or result.remarks == "NULL" or result.address=="127.0.0.1" or | ||||
| 							(not datatypes.hostname(result.address) and not (datatypes.ipmask4(result.address) or datatypes.ipmask6(result.address))) then | ||||
| 					elseif (add_mode == "2" and is_filter_keyword(result.remarks)) or not result.address or result.remarks == "NULL" or result.address == "127.0.0.1" or | ||||
| 							(not datatypes.hostname(result.address) and not (api.is_ip(result.address))) then | ||||
| 						log('丢弃过滤节点: ' .. result.type .. ' 节点, ' .. result.remarks) | ||||
| 					else | ||||
| 						tinsert(node_list, result) | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	![41898282+github-actions[bot]@users.noreply.github.com](/assets/img/avatar_default.png) github-actions[bot]
					github-actions[bot]