diff --git a/luci-app-internet-detector/internet-detector-mod-email/files/usr/lib/lua/internet-detector/mod_email.lua b/luci-app-internet-detector/internet-detector-mod-email/files/usr/lib/lua/internet-detector/mod_email.lua index f75055ea4..963435aef 100644 --- a/luci-app-internet-detector/internet-detector-mod-email/files/usr/lib/lua/internet-detector/mod_email.lua +++ b/luci-app-internet-detector/internet-detector-mod-email/files/usr/lib/lua/internet-detector/mod_email.lua @@ -27,6 +27,9 @@ local Module = { mailSmtp = nil, mailSmtpPort = nil, mailSecurity = "tls", + msgTextPattern1 = "[%s]: %s: %s", -- Connected (host, instance, message) + msgTextPattern2 = "[%s]: %s: %s", -- Disconnected (host, instance, message) + msgSubPattern = "%s notification", -- Subject (host) status = nil, _enabled = false, _deadCounter = 0, @@ -85,8 +88,10 @@ function Module:init(t) end end -function Module:sendMessage(msg) +function Module:sendMessage(msg, textPattern) local verboseArg = "" + local emailMsg = string.format( + textPattern, self.hostAlias, self.config.serviceConfig.instance, msg) -- Debug if self.config.debug then @@ -105,8 +110,8 @@ function Module:sendMessage(msg) self.mta, verboseArg, securityArgs, self.mailSmtp, self.mailSmtpPort, self.mtaConnectTimeout, self.mtaReadTimeout, self.mailUser, self.mailPassword, self.mailSender, self.mailRecipient, - string.format("%s notification", self.hostAlias), - string.format("[%s]: %s:\n%s", self.hostAlias, self.config.serviceConfig.instance, msg)) + string.format(self.msgSubPattern, self.hostAlias), + emailMsg) -- Debug if self.config.debug then @@ -143,7 +148,7 @@ function Module:run(currentStatus, lastStatus, timeDiff) if not self._msgSentDisconnect and (self.mode == 1 or self.mode == 2) then if self._deadCounter >= self.deadPeriod then self._lastDisconnection = nil - self:sendMessage(table.concat(self._message, ", ")) + self:sendMessage(table.concat(self._message, "; "), self.msgTextPattern2) self._message = {} self._msgSentDisconnect = true else @@ -157,11 +162,10 @@ function Module:run(currentStatus, lastStatus, timeDiff) if not self._lastConnection then self._lastConnection = os.date("%Y.%m.%d %H:%M:%S", os.time()) end - if self._aliveCounter >= self.alivePeriod then self._message[#self._message + 1] = string.format( "Internet connected: %s", self._lastConnection) - self:sendMessage(table.concat(self._message, "; ")) + self:sendMessage(table.concat(self._message, "; "), self.msgTextPattern1) self._message = {} self._msgSentConnect = true else diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua index 402961035..4ebbf57ef 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua @@ -156,6 +156,23 @@ if has_xray then s_xray.anonymous = true s_xray.addremove = false + o = s_xray:option(Flag, "fragment", translate("Fragment"), translate("TCP fragments, which can deceive the censorship system in some cases, such as bypassing SNI blacklists.")) + o.default = 0 + + o = s_xray:option(ListValue, "fragment_packets", translate("Fragment Packets"), translate(" \"1-3\" is for segmentation at TCP layer, applying to the beginning 1 to 3 data writes by the client. \"tlshello\" is for TLS client hello packet fragmentation.")) + o.default = "tlshello" + o:value("1-3", "1-3") + o:value("tlshello", "tlshello") + o:depends("fragment", true) + + o = s_xray:option(Value, "fragment_length", translate("Fragment Length"), translate("Fragmented packet length (byte)")) + o.default = "10-20" + o:depends("fragment", true) + + o = s_xray:option(Value, "fragment_interval", translate("Fragment Interval"), translate("Fragmentation interval (ms)")) + o.default = "10-20" + o:depends("fragment", true) + o = s_xray:option(Flag, "sniffing", translate("Sniffing"), translate("When using the shunt, must be enabled, otherwise the shunt will invalid.")) o.default = 1 o.rmempty = false diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ray.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ray.lua index a99027b60..84096b07f 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ray.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ray.lua @@ -514,4 +514,11 @@ o = s:option(Value, option_name("xudp_concurrency"), translate("XUDP Mux concurr o.default = 8 o:depends({ [option_name("xmux")] = true }) +--[[tcpMptcp]] +o = s:option(Flag, option_name("tcpMptcp"), "tcpMptcp", translate("Enable Multipath TCP, need to be enabled in both server and client configuration.")) +o.default = 0 + +o = s:option(Flag, option_name("tcpNoDelay"), "tcpNoDelay") +o.default = 0 + api.luci_types(arg[1], m, s, type_name, option_prefix) diff --git a/luci-app-passwall/luasrc/passwall/util_xray.lua b/luci-app-passwall/luasrc/passwall/util_xray.lua index 37ee5f9d4..8514b3c12 100644 --- a/luci-app-passwall/luasrc/passwall/util_xray.lua +++ b/luci-app-passwall/luasrc/passwall/util_xray.lua @@ -42,9 +42,11 @@ function gen_outbound(flag, node, tag, proxy_table) local proxy = 0 local proxy_tag = "nil" + local fragment = nil if proxy_table ~= nil and type(proxy_table) == "table" then proxy = proxy_table.proxy or 0 proxy_tag = proxy_table.tag or "nil" + fragment = proxy_table.fragment or nil end if node.type == "Xray" then @@ -130,7 +132,10 @@ function gen_outbound(flag, node, tag, proxy_table) -- 底层传输配置 streamSettings = (node.streamSettings or node.protocol == "vmess" or node.protocol == "vless" or node.protocol == "socks" or node.protocol == "shadowsocks" or node.protocol == "trojan") and { sockopt = { - mark = 255 + mark = 255, + tcpMptcp = (node.tcpMptcp == "1") and true or nil, + tcpNoDelay = (node.tcpNoDelay == "1") and true or nil, + dialerProxy = fragment and "fragment" or nil }, network = node.transport, security = node.stream_security, @@ -644,7 +649,7 @@ function gen_config(var) end if is_new_blc_node then local blc_node = uci:get_all(appname, blc_node_id) - local outbound = gen_outbound(flag, blc_node, blc_node_tag) + local outbound = gen_outbound(flag, blc_node, blc_node_tag, { fragment = xray_settings.fragment == "1" or nil }) if outbound then table.insert(outbounds, outbound) valid_nodes[#valid_nodes + 1] = blc_node_tag @@ -716,7 +721,7 @@ function gen_config(var) preproxy_enabled = false end elseif preproxy_node and api.is_normal_node(preproxy_node) then - local preproxy_outbound = gen_outbound(flag, preproxy_node, preproxy_tag) + local preproxy_outbound = gen_outbound(flag, preproxy_node, preproxy_tag, { fragment = xray_settings.fragment == "1" or nil }) if preproxy_outbound then table.insert(outbounds, preproxy_outbound) else @@ -818,7 +823,14 @@ 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 proxy_table = { + proxy = proxy and 1 or 0, + tag = proxy and preproxy_tag or nil + } + if xray_settings.fragment == "1" and not proxy_table.tag then + proxy_table.fragment = true + end + local _outbound = gen_outbound(flag, _node, rule_name, proxy_table) if _outbound then table.insert(outbounds, _outbound) if proxy then preproxy_used = true end @@ -989,7 +1001,7 @@ function gen_config(var) sys.call("touch /tmp/etc/passwall/iface/" .. node.iface) end else - outbound = gen_outbound(flag, node) + outbound = gen_outbound(flag, node, nil, { fragment = xray_settings.fragment == "1" or nil }) end if outbound then table.insert(outbounds, outbound) end routing = { @@ -1122,7 +1134,7 @@ function gen_config(var) address = remote_dns_tcp_server, port = tonumber(remote_dns_tcp_port), network = "tcp", - nonIPQuery = "skip" + nonIPQuery = "drop" } }) @@ -1229,6 +1241,28 @@ function gen_config(var) -- } } } + + if xray_settings.fragment == "1" then + table.insert(outbounds, { + protocol = "freedom", + tag = "fragment", + settings = { + domainStrategy = (direct_dns_query_strategy and direct_dns_query_strategy ~= "") and direct_dns_query_strategy or "UseIP", + fragments = { + packets = (xray_settings.fragment_packets and xray_settings.fragment_packets ~= "") and xray_settings.fragment_packets, + length = (xray_settings.fragment_length and xray_settings.fragment_length ~= "") and xray_settings.fragment_length, + interval = (xray_settings.fragment_interval and xray_settings.fragment_interval ~= "") and xray_settings.fragment_interval + } + }, + streamSettings = { + sockopt = { + mark = 255, + tcpNoDelay = true + } + } + }) + end + table.insert(outbounds, { protocol = "freedom", tag = "direct", diff --git a/luci-app-passwall/po/zh-cn/passwall.po b/luci-app-passwall/po/zh-cn/passwall.po index 1a59200a7..09588b5d9 100644 --- a/luci-app-passwall/po/zh-cn/passwall.po +++ b/luci-app-passwall/po/zh-cn/passwall.po @@ -265,6 +265,9 @@ msgstr "默认代理模式" msgid "No Proxy" msgstr "不代理" +msgid "Proxy" +msgstr "代理" + msgid "Global Proxy" msgstr "全局代理" @@ -1536,3 +1539,30 @@ msgstr "后量子对等证书签名方案" msgid "Disable adaptive sizing of TLS records" msgstr "禁用 TLS 记录的自适应大小调整" + +msgid "Enable Multipath TCP, need to be enabled in both server and client configuration." +msgstr "启用 Multipath TCP,需在服务端和客户端配置中同时启用。" + +msgid "Fragment" +msgstr "分片" + +msgid "TCP fragments, which can deceive the censorship system in some cases, such as bypassing SNI blacklists." +msgstr "TCP 分片,在某些情况下可以欺骗审查系统,比如绕过 SNI 黑名单。" + +msgid "Fragment Packets" +msgstr "分片方式" + +msgid " \"1-3\" is for segmentation at TCP layer, applying to the beginning 1 to 3 data writes by the client. \"tlshello\" is for TLS client hello packet fragmentation." +msgstr " \"1-3\" 是 TCP 的流切片,应用于客户端第 1 至第 3 次写数据。\"tlshello\" 是 TLS 握手包切片。" + +msgid "Fragment Length" +msgstr "分片包长" + +msgid "Fragmented packet length (byte)" +msgstr "分片包长 (byte)" + +msgid "Fragment Interval" +msgstr "分片间隔" + +msgid "Fragmentation interval (ms)" +msgstr "分片间隔(ms)" diff --git a/v2ray-geodata/Makefile b/v2ray-geodata/Makefile index e05583d0a..5b8356627 100644 --- a/v2ray-geodata/Makefile +++ b/v2ray-geodata/Makefile @@ -30,13 +30,13 @@ define Download/geosite HASH:=d2ef9bd9cac2678088f5494b888bf9eecdad385dc2b5689e6c7d56e4d97173a3 endef -GEOSITE_IRAN_VER:=202402190026 +GEOSITE_IRAN_VER:=202402211435 GEOSITE_IRAN_FILE:=iran.dat.$(GEOSITE_IRAN_VER) define Download/geosite-ir URL:=https://github.com/bootmortis/iran-hosted-domains/releases/download/$(GEOSITE_IRAN_VER)/ URL_FILE:=iran.dat FILE:=$(GEOSITE_IRAN_FILE) - HASH:=564b852ddb3eef77985a7a9c0c9c4b6c9028e46b9a97d09f857c7bb7fbb1b7b7 + HASH:=7fbb773a2d1a07148c0ce8ea577eb04ff66d628b9a2d1e150e0a588c2b7657a7 endef define Package/v2ray-geodata/template