mirror of
https://github.com/caiwx86/small-packages.git
synced 2026-10-29 20:05:13 +08:00
update 2026-06-21 21:58:17
This commit is contained in:
1 parent
1a2f3e74c1
commit
dc85f71cc1
12 files changed
+1227
-936
No files matched your search
@@ -10,14 +10,12 @@ npu_usage="$(grep '%' "$NSS_PATH"/cpu_load_ubi | awk -F ' ' '{print $2}')"
|
||||
|
||||
if [ -e "$ATH11K_NSS_OFFLOAD" ]; then
|
||||
if [ "$(cat "$ATH11K_NSS_OFFLOAD" 2>/dev/null)" = "1" ]; then
|
||||
wifi_nss=", WiFi NSS: ON"
|
||||
else
|
||||
wifi_nss=", WiFi NSS: OFF"
|
||||
wifi="with WiFi"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -d "$NSS_PATH" ]; then
|
||||
echo -n "CPU: ${cpu_usage}, NPU: ${npu_usage}${wifi_nss}"
|
||||
echo -n "CPU: ${cpu_usage}, NPU${wifi}: ${npu_usage}"
|
||||
else
|
||||
echo -n "CPU: ${cpu_usage}${wifi_nss}"
|
||||
echo -n "CPU: ${cpu_usage}"
|
||||
fi
|
||||
@@ -107,6 +107,7 @@ choice
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_Xray
|
||||
bool "Xray-core"
|
||||
select PACKAGE_xray-core
|
||||
select PACKAGE_coreutils-timeout
|
||||
endchoice
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_ChinaDNS_NG
|
||||
|
||||
@@ -661,6 +661,8 @@ function index()
|
||||
entry({"admin", "services", "shadowsocksr", "clash_client_policies"}, call("clash_client_policies")).leaf = true
|
||||
entry({"admin", "services", "shadowsocksr", "clash_client_rule_save"}, call("clash_client_rule_save")).leaf = true
|
||||
entry({"admin", "services", "shadowsocksr", "clash_client_rule_clear"}, call("clash_client_rule_clear")).leaf = true
|
||||
entry({"admin", "services", "shadowsocksr", "fetch_certsha256"}, call("fetch_certsha256")).leaf = true
|
||||
entry({"admin", "services", "shadowsocksr", "fetch_certbyname"}, call("fetch_certbyname")).leaf = true
|
||||
--[[Backup]]
|
||||
entry({"admin", "services", "shadowsocksr", "backup"}, call("create_backup")).leaf = true
|
||||
end
|
||||
@@ -1271,6 +1273,84 @@ function clash_client_rule_clear()
|
||||
})
|
||||
end
|
||||
|
||||
function fetch_certsha256()
|
||||
local function fetch_cert_sha256(host, port, sni, timeout)
|
||||
if not host then return "" end
|
||||
port = tonumber(port) or 443
|
||||
sni = sni or host
|
||||
timeout = tonumber(timeout) or 5
|
||||
|
||||
local cmd = string.format(
|
||||
"timeout %d openssl s_client -connect %s:%d -servername %s -showcerts </dev/null 2>/dev/null " ..
|
||||
"| awk 'BEGIN{c=0}/BEGIN CERT/{c++} c==1{print} /END CERT/{if(c==1)exit}' " ..
|
||||
"| openssl x509 -outform der 2>/dev/null " ..
|
||||
"| sha256sum 2>/dev/null",
|
||||
timeout, host, port, sni
|
||||
)
|
||||
|
||||
local out = trim(luci.sys.exec(cmd))
|
||||
|
||||
local fp = out:match("^([0-9a-fA-F]+)")
|
||||
if not fp or fp:lower():match("^e3b0c44298fc1c149afbf4c8996fb924") then
|
||||
return ""
|
||||
end
|
||||
return fp:upper()
|
||||
end
|
||||
|
||||
local sid = luci.http.formvalue("sid") or ""
|
||||
local address = (sid ~= "") and uci:get("shadowsocksr", sid, "server") or ""
|
||||
local port_raw = (sid ~= "") and uci:get("shadowsocksr", sid, "server_port") or ""
|
||||
local port = tonumber(port_raw) or 0
|
||||
local sni = (id ~= "") and uci:get("shadowsocksr", sid, "tls_host") or ""
|
||||
sni = (sni and sni ~= "") and sni or address
|
||||
if address == "" or port == 0 then
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({ code = 0, msg = "Address or Port is invalid" })
|
||||
return
|
||||
end
|
||||
local data = fetch_cert_sha256(address, port, sni, 5)
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(data ~= "" and { code = 1, data = data } or { code = 0 })
|
||||
end
|
||||
|
||||
function fetch_certbyname()
|
||||
local function fetch_cert_byname(host, port, sni, timeout)
|
||||
if not host then return "" end
|
||||
port = tonumber(port) or 443
|
||||
sni = sni or host
|
||||
timeout = tonumber(timeout) or 5
|
||||
|
||||
local cmd = string.format(
|
||||
"timeout %d openssl s_client -connect %s:%d -servername %s -showcerts </dev/null 2>/dev/null " ..
|
||||
"| openssl x509 -noout -subject 2>/dev/null " ..
|
||||
"| awk '{gsub(/^.*=[[:space:]]*/, \"\"); gsub(/,.*$/, \"\"); print}'",
|
||||
timeout, host, port, sni
|
||||
)
|
||||
|
||||
local out = trim(luci.sys.exec(cmd))
|
||||
|
||||
if out == "" then
|
||||
return ""
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
local sid = luci.http.formvalue("sid") or ""
|
||||
local address = (sid ~= "") and uci:get("shadowsocksr", sid, "server") or ""
|
||||
local port_raw = (sid ~= "") and uci:get("shadowsocksr", sid, "server_port") or ""
|
||||
local port = tonumber(port_raw) or 0
|
||||
local sni = (id ~= "") and uci:get("shadowsocksr", sid, "tls_host") or ""
|
||||
sni = (sni and sni ~= "") and sni or address
|
||||
if address == "" or port == 0 then
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({ code = 0, msg = "Address or Port is invalid" })
|
||||
return
|
||||
end
|
||||
local data = fetch_cert_byname(address, port, sni, 5)
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(data ~= "" and { code = 1, data = data } or { code = 0 })
|
||||
end
|
||||
|
||||
function act_ping()
|
||||
local e = {}
|
||||
local domain = luci.http.formvalue("domain")
|
||||
|
||||
@@ -321,6 +321,10 @@ m.on_after_save = function(self)
|
||||
end
|
||||
end
|
||||
|
||||
local server_header = Template("/shadowsocksr/server_header")
|
||||
server_header.section = sid
|
||||
m:append(server_header)
|
||||
|
||||
-- [[ Servers Setting ]]--
|
||||
s = m:section(NamedSection, sid, "servers")
|
||||
s.anonymous = true
|
||||
@@ -1542,14 +1546,18 @@ end
|
||||
if xray_version_val >= 260131 then
|
||||
-- Xray 版本大于等于 26.1.31
|
||||
-- [[ Xray TLS pinSHA256 ]] --
|
||||
o = s:option(Value, "tls_CertSha", translate("TLS Chain Fingerprint (SHA256)"), translate("Once set, connects only when the server’s chain fingerprint matches."))
|
||||
o = s:option(Value, "tls_CertSha", translate("TLS Chain Fingerprint (SHA256)"))
|
||||
o.rmempty = true
|
||||
o:depends({type = "v2ray", tls = true})
|
||||
o.description = translate("Once set, connects only when the server’s chain fingerprint matches.") ..
|
||||
string.format("<a href='javascript:void(0)' onclick='javascript:fetchCertSha256(this)'>%s</a>", "→ " .. translate("Fetch Manually"))
|
||||
|
||||
-- [[ Xray TLS verify leaf certificate name ]] --
|
||||
o = s:option(Value, "tls_CertByName", translate("TLS Certificate Name (CertName)"), translate("TLS is used to verify the leaf certificate name."))
|
||||
o = s:option(Value, "tls_CertByName", translate("TLS Certificate Name (CertName)"))
|
||||
o.rmempty = true
|
||||
o:depends({type = "v2ray", tls = true})
|
||||
o.description = translate("TLS is used to verify the leaf certificate name.") ..
|
||||
string.format("<a href='javascript:void(0)' onclick='javascript:fetchCertByName(this)'>%s</a>", "→ " .. translate("Fetch Manually"))
|
||||
end
|
||||
|
||||
-- [[ Hysteria2 TLS pinSHA256 ]] --
|
||||
|
||||
@@ -4,7 +4,7 @@ local dsp = require "luci.dispatcher"
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
function clearlog(btn) {
|
||||
XHR.get('<%=dsp.build_url("admin/services/shadowsocksr/clear_log")%>', null,
|
||||
XHR.get('<%=dsp.build_url("admin", "services", "shadowsocksr", "clear_log")%>', null,
|
||||
function(x, data) {
|
||||
if (x && x.status == 200) {
|
||||
var log_textarea = document.getElementById('log_textarea');
|
||||
@@ -15,7 +15,7 @@ local dsp = require "luci.dispatcher"
|
||||
);
|
||||
}
|
||||
|
||||
XHR.poll(5, '<%=dsp.build_url("admin/services/shadowsocksr/get_log")%>', null,
|
||||
XHR.poll(5, '<%=dsp.build_url("admin", "services", "shadowsocksr", "get_log")%>', null,
|
||||
function(x, data) {
|
||||
if (x && x.status == 200) {
|
||||
var log_textarea = document.getElementById('log_textarea');
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
let sid = "<%=self.section%>";
|
||||
|
||||
function fetchCertSha256(el) {
|
||||
if (el.getAttribute("data-loading") === "1") return;
|
||||
el.setAttribute("data-loading", "1");
|
||||
el.style.pointerEvents = "none";
|
||||
el.style.color = "red";
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "shadowsocksr", "fetch_certsha256")%>',
|
||||
{ sid: sid },
|
||||
function(x, res) {
|
||||
el.setAttribute("data-loading", "0");
|
||||
el.style.pointerEvents = "";
|
||||
el.style.color = "";
|
||||
if (!x || x.status !== 200) {
|
||||
alert("<%:Error%>");
|
||||
return;
|
||||
}
|
||||
if (!res || res.code !== 1 || !res.data) {
|
||||
alert(res && res.msg ? res.msg : "<%:Fetch Failed%> !");
|
||||
return;
|
||||
}
|
||||
const inputs = document.querySelectorAll('input[id$=".tls_CertSha"]');
|
||||
if (inputs.length > 0) {
|
||||
inputs.forEach(function(input) {
|
||||
input.value = res.data;
|
||||
// 触发 change 事件,让 LuCI 检测到字段已修改
|
||||
const event = new Event('change', { bubbles: true });
|
||||
input.dispatchEvent(event);
|
||||
});
|
||||
// 成功提示(只有找到输入框时才提示)
|
||||
alert(res && res.msg ? res.msg : "<%:Successfully retrieved certificate fingerprint:%> " + res.data);
|
||||
} else {
|
||||
// 未找到输入框时提示
|
||||
alert("<%:Certificate fingerprint retrieved successfully, but no input field found!%>");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function fetchCertByName(el) {
|
||||
if (el.getAttribute("data-loading") === "1") return;
|
||||
el.setAttribute("data-loading", "1");
|
||||
el.style.pointerEvents = "none";
|
||||
el.style.color = "red";
|
||||
XHR.get
|
||||
('<%=luci.dispatcher.build_url("admin", "services", "shadowsocksr", "fetch_certbyname")%>',
|
||||
{ sid: sid },
|
||||
function(x, res) {
|
||||
el.setAttribute("data-loading", "0");
|
||||
el.style.pointerEvents = "";
|
||||
el.style.color = "";
|
||||
if (!x || x.status !== 200) {
|
||||
alert("<%:Error%>");
|
||||
return;
|
||||
}
|
||||
if (!res || res.code !== 1 || !res.data) {
|
||||
alert(res && res.msg ? res.msg : "<%:Fetch Failed%> !");
|
||||
return;
|
||||
}
|
||||
const inputs = document.querySelectorAll('input[id$=".tls_CertByName"]');
|
||||
if (inputs.length > 0) {
|
||||
inputs.forEach(function(input) {
|
||||
input.value = res.data;
|
||||
// 触发 change 事件,让 LuCI 检测到字段已修改
|
||||
const event = new Event('change', { bubbles: true });
|
||||
input.dispatchEvent(event);
|
||||
});
|
||||
// 成功提示(只有找到输入框时才提示)
|
||||
alert(res && res.msg ? res.msg : "<%:Successfully retrieved certificate name:%> " + res.data);
|
||||
} else {
|
||||
// 未找到输入框时提示
|
||||
alert("<%:Certificate name retrieved successfully, but no input field found!%>");
|
||||
}
|
||||
});
|
||||
}
|
||||
//]]>
|
||||
</script>
|
||||
@@ -165,7 +165,7 @@ end
|
||||
return;
|
||||
}
|
||||
port.innerHTML = '<font style=\"color:#0072c3\">connect</font>';
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin/services/shadowsocksr/ping")%>', {
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "shadowsocksr", "ping")%>', {
|
||||
index,
|
||||
sid: dom.getAttribute("data-sid"),
|
||||
domain: dom.getAttribute("hint"),
|
||||
@@ -280,7 +280,7 @@ end
|
||||
var server_page = pageElem ? pageElem.value : '<%=self.server_page or 1%>';
|
||||
var server_page_size = pageSizeElem ? pageSizeElem.value : '<%=self.server_page_size or 0%>';
|
||||
if (input) input.value = order;
|
||||
XHR.post('<%=luci.dispatcher.build_url("admin/services/shadowsocksr/save_order")%>', {
|
||||
XHR.post('<%=luci.dispatcher.build_url("admin", "services", "shadowsocksr", "save_order")%>', {
|
||||
order: order,
|
||||
page: server_page,
|
||||
page_size: server_page_size
|
||||
|
||||
@@ -248,7 +248,7 @@ end
|
||||
<input class="btn cbi-button cbi-button-remove" type="button" value="<%:Delete%>"
|
||||
onclick="
|
||||
var sid = '<%=k%>';
|
||||
XHR.post('<%=luci.dispatcher.build_url("admin/services/shadowsocksr/delete_node")%>', {
|
||||
XHR.post('<%=luci.dispatcher.build_url("admin", "services", "shadowsocksr", "delete_node")%>', {
|
||||
sid: sid
|
||||
}, function(x, result) {
|
||||
result = result || {};
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -50,32 +50,28 @@ local b64encode = nixio.bin.b64encode
|
||||
local effective_node_local_port = tonumber(server.local_port) or tonumber(default_node_local_port) or 1234
|
||||
|
||||
if server.type == "ss-rust" then
|
||||
server.type = "ss"
|
||||
server.type = "ss"
|
||||
end
|
||||
|
||||
local function parse_realm_uri(uri)
|
||||
if type(uri) ~= "string" then return nil end
|
||||
-- realm://token@server/realm_id?query
|
||||
local token, server_url, realm_id, query = trim(uri):match("^realm://([^@]+)@([^/]+)/([^?]*)%??(.*)$")
|
||||
if not token or not server_url or not realm_id then return nil end
|
||||
-- realm[+http]://token@server/realm_id?query
|
||||
local scheme, token, server_url, realm_id, query = trim(uri):match("^(realm%+http|realm)://([^@]+)@([^/]+)/([^?]*)%??(.*)$")
|
||||
if not scheme or not token or not server_url or not realm_id then return nil end
|
||||
realm_id = realm_id:gsub("/+$", "")
|
||||
local realm = {
|
||||
scheme = scheme,
|
||||
token = token,
|
||||
server_url = server_url,
|
||||
realm_id = realm_id
|
||||
}
|
||||
-- 解析 query 中的 stun=
|
||||
if query and query ~= "" then
|
||||
local stun_servers = {}
|
||||
for key, value in query:gmatch("([^&=?]+)=([^&]+)") do
|
||||
if key == "stun" and value ~= "" then
|
||||
stun_servers[#stun_servers + 1] = value
|
||||
end
|
||||
end
|
||||
if #stun_servers > 0 then
|
||||
realm.stun_servers = stun_servers
|
||||
end
|
||||
local stun_servers
|
||||
for value in (query or ""):gmatch("[?&]?[Ss][Tt][Uu][Nn]=([^&]+)") do
|
||||
if not stun_servers then stun_servers = {} end
|
||||
stun_servers[#stun_servers + 1] = value
|
||||
end
|
||||
realm.stun_servers = stun_servers
|
||||
return realm
|
||||
end
|
||||
|
||||
@@ -428,22 +424,24 @@ end
|
||||
-- 开启 socks 代理
|
||||
-- 检查是否启用 socks 代理
|
||||
if proto and proto:find("tcp") and socks_port ~= "0" then
|
||||
table.insert(Xray.inbounds, {
|
||||
-- socks
|
||||
protocol = "socks",
|
||||
port = tonumber(socks_port),
|
||||
local auth = (socks_server.socks5_auth and socks_server.socks5_auth ~= "noauth")
|
||||
and {{
|
||||
user = socks_server.socks5_user,
|
||||
pass = socks_server.socks5_pass
|
||||
}} or nil
|
||||
|
||||
table.insert(Xray.inbounds, {
|
||||
-- socks
|
||||
protocol = "socks",
|
||||
port = tonumber(socks_port),
|
||||
settings = {
|
||||
auth = socks_server.socks5_auth or "noauth",
|
||||
udp = true,
|
||||
mixed = ((socks_server.socks5_mixed == '1') and true or false) or nil,
|
||||
accounts = (socks_server.socks5_auth and socks_server.socks5_auth ~= "noauth") and {
|
||||
{
|
||||
user = socks_server.socks5_user,
|
||||
pass = socks_server.socks5_pass
|
||||
}
|
||||
} or nil
|
||||
} or nil
|
||||
})
|
||||
mixed = socks_server.socks5_mixed == "1" or nil,
|
||||
accounts = (xray_version_val <= 260503) and auth or nil,
|
||||
users = (xray_version_val > 260503) and auth or nil
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
-- 传出连接
|
||||
@@ -648,9 +646,7 @@ Xray.outbounds = {
|
||||
local realm = parse_realm_uri(server.hysteria2_realm_url)
|
||||
local url, stun
|
||||
if realm then
|
||||
if realm.token and realm.server_url and realm.realm_id then
|
||||
url = "realm://" .. realm.token .. "@" .. realm.server_url .. "/" .. realm.realm_id
|
||||
end
|
||||
url = realm.scheme .. "://" .. realm.token .. "@" .. realm.server_url .. "/" .. realm.realm_id
|
||||
stun = realm.stun_servers or server.hysteria2_realm_stun
|
||||
end
|
||||
local r = {
|
||||
|
||||
@@ -21,13 +21,13 @@ define Download/geoip
|
||||
HASH:=a322dfb6bfd8987c83453c39582a07771c9deddf9f8f7d2d19c7927ebd5e76c8
|
||||
endef
|
||||
|
||||
GEOSITE_VER:=20260621035818
|
||||
GEOSITE_VER:=20260621074522
|
||||
GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER)
|
||||
define Download/geosite
|
||||
URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/
|
||||
URL_FILE:=dlc.dat
|
||||
FILE:=$(GEOSITE_FILE)
|
||||
HASH:=3aa6a23a6f4bd89cf5b22348fd6527b5b53881cdeece3147ee3ac3381fe61ec2
|
||||
HASH:=680b8a378b94b69e6398cd05d5b5b016cb0809fad30f385211ce91a5a0f74815
|
||||
endef
|
||||
|
||||
GEOSITE_IRAN_VER:=202606150209
|
||||
|
||||
Reference in new issue
Block a user