mirror of
https://github.com/caiwx86/small-packages.git
synced 2026-11-01 05:43:56 +08:00
update 2026-07-19 00:51:28
This commit is contained in:
1 parent
c43863be38
commit
270f321458
11 files changed
+1859
-1123
No files matched your search
@@ -24,9 +24,10 @@ local SUPPORTED_COMPONENTS = {
|
||||
naiveproxy = true
|
||||
}
|
||||
local SUPPORTED_GEO_COMPONENTS = {
|
||||
country_mmdb = true,
|
||||
geosite = true,
|
||||
v2ray_geo = true
|
||||
{ name = "country_mmdb", require = nil },
|
||||
{ name = "geosite", require = "/etc/openclash" },
|
||||
{ name = "v2ray_geoip", require = nil },
|
||||
{ name = "v2ray_geosite", require = nil }
|
||||
}
|
||||
|
||||
local function trim(value)
|
||||
@@ -576,7 +577,15 @@ local function read_component_state(component, action)
|
||||
end
|
||||
|
||||
local function read_geo_state(component, action)
|
||||
if not SUPPORTED_GEO_COMPONENTS[component] then
|
||||
local is_supported = false
|
||||
for _, item in ipairs(SUPPORTED_GEO_COMPONENTS) do
|
||||
if item.name == component then
|
||||
is_supported = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not is_supported then
|
||||
return nil, 400, "unsupported_component"
|
||||
end
|
||||
|
||||
@@ -649,6 +658,7 @@ function index()
|
||||
entry({"admin", "services", "shadowsocksr", "component_set_mirror"}, call("component_set_mirror")).leaf = true
|
||||
entry({"admin", "services", "shadowsocksr", "component_status"}, call("component_status")).leaf = true
|
||||
entry({"admin", "services", "shadowsocksr", "component_upgrade"}, call("component_upgrade")).leaf = true
|
||||
entry({"admin", "services", "shadowsocksr", "geo_component"}, call("geo_component")).leaf = true
|
||||
entry({"admin", "services", "shadowsocksr", "geo_local_status"}, call("geo_local_status")).leaf = true
|
||||
entry({"admin", "services", "shadowsocksr", "geo_status"}, call("geo_status")).leaf = true
|
||||
entry({"admin", "services", "shadowsocksr", "geo_upgrade"}, call("geo_upgrade")).leaf = true
|
||||
@@ -1016,6 +1026,20 @@ function geo_status()
|
||||
write_geo_json(data)
|
||||
end
|
||||
|
||||
function geo_component()
|
||||
local component = {}
|
||||
for _, item in ipairs(SUPPORTED_GEO_COMPONENTS) do
|
||||
local available = true
|
||||
if item.require then
|
||||
available = nixio.fs.access(item.require)
|
||||
end
|
||||
if available then
|
||||
table.insert(component, item.name)
|
||||
end
|
||||
end
|
||||
write_geo_json({ component = component })
|
||||
end
|
||||
|
||||
function geo_local_status()
|
||||
local component = luci.http.formvalue("component")
|
||||
local data, status, err = read_geo_state(component, "local_info")
|
||||
@@ -1035,6 +1059,19 @@ function geo_upgrade()
|
||||
write_geo_json({component = component, error = err or "bad_request", success = "0"})
|
||||
return
|
||||
end
|
||||
|
||||
local info = read_geo_state(component, "info")
|
||||
if info then
|
||||
for key, value in pairs(info) do
|
||||
if data[key] == nil or data[key] == "" then
|
||||
data[key] = value
|
||||
end
|
||||
end
|
||||
if data.success == "1" then
|
||||
data.can_upgrade = info.can_upgrade
|
||||
end
|
||||
end
|
||||
|
||||
write_geo_json(data)
|
||||
end
|
||||
|
||||
@@ -1287,22 +1324,30 @@ function clash_client_rule_clear()
|
||||
end
|
||||
|
||||
function fetch_certsha256()
|
||||
local function fetch_cert_sha256(host, port, sni, timeout)
|
||||
local function fetch_cert_sha256(host, port, sni, timeout, http3)
|
||||
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 cmd
|
||||
if http3 then
|
||||
cmd = string.format(
|
||||
"timeout %d curl --http3 -k -w '%%{certs}' -o /dev/null https://%s:%d 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
|
||||
)
|
||||
else
|
||||
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
|
||||
)
|
||||
end
|
||||
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 ""
|
||||
@@ -1316,12 +1361,22 @@ function fetch_certsha256()
|
||||
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
|
||||
local protocol = uci:get("shadowsocksr", id, "v2ray_protocol") or ""
|
||||
local h3, timeout = false, 10
|
||||
if protocol == "hysteria2" then
|
||||
h3 = true
|
||||
timeout = 60
|
||||
if port == 0 then
|
||||
local hop = uci:get("shadowsocksr", id, "port_range") or "0"
|
||||
port = tonumber(hop:match("^%s*(%d+)"))
|
||||
end
|
||||
end
|
||||
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)
|
||||
local data = fetch_cert_sha256(address, port, sni, timeout, h3)
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(data ~= "" and { code = 1, data = data } or { code = 0 })
|
||||
end
|
||||
|
||||
@@ -22,15 +22,20 @@
|
||||
var geoMeta = {
|
||||
country_mmdb: {
|
||||
label: '<%:Country MMDB%>',
|
||||
help: '<%:Update the Country.mmdb database used by Mihomo/Clash runtime when available.%>'
|
||||
help: '<%:Update the Country.mmdb database used by Xray/V2Ray runtime when available.%>'
|
||||
},
|
||||
geosite: {
|
||||
label: '<%:GeoSite Database%>',
|
||||
help: '<%:Update the GeoSite.dat database used by Mihomo/Clash runtime when available.%>'
|
||||
label: '<%:OpenClash GeoSite Database%>',
|
||||
help: '<%:Update the GeoSite.dat database used by Mihomo/Clash runtime when available.%>',
|
||||
require: '/etc/openclash'
|
||||
},
|
||||
v2ray_geo: {
|
||||
label: '<%:V2Ray GEO Databases%>',
|
||||
help: '<%:Update geoip.dat and geosite.dat used by Xray/V2Ray runtime when available.%>'
|
||||
v2ray_geoip: {
|
||||
label: '<%:V2Ray GeoIP Databases%>',
|
||||
help: '<%:Update the geoip.dat used by Xray/V2Ray runtime when available.%>'
|
||||
},
|
||||
v2ray_geosite: {
|
||||
label: '<%:V2Ray GeoSite Databases%>',
|
||||
help: '<%:Update the geosite.dat used by Xray/V2Ray runtime when available.%>'
|
||||
}
|
||||
};
|
||||
|
||||
@@ -91,6 +96,7 @@
|
||||
}
|
||||
|
||||
function renderComponentInfo(data, checkedRemote) {
|
||||
// console.log('Geo data:', data);
|
||||
var panel = document.getElementById('component-status');
|
||||
var upgradeButton = document.getElementById('component-upgrade');
|
||||
var action = document.getElementById('component-action');
|
||||
@@ -192,6 +198,7 @@
|
||||
mirror: mirror
|
||||
}, function() {
|
||||
queryLocalComponentInfo();
|
||||
queryLocalGeoInfo();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -204,7 +211,41 @@
|
||||
return geoMeta[component] ? geoMeta[component].help : '';
|
||||
}
|
||||
|
||||
function renderGeoInfo(data) {
|
||||
function loadGeoComponent() {
|
||||
var url = '<%=luci.dispatcher.build_url("admin", "services", "shadowsocksr", "geo_component")%>';
|
||||
var selector = document.getElementById('geo-selector');
|
||||
if (!selector)
|
||||
return;
|
||||
|
||||
XHR.get(url, {}, function(x, rv) {
|
||||
if (!rv || !Array.isArray(rv.component))
|
||||
return;
|
||||
|
||||
var fragment = document.createDocumentFragment();
|
||||
for (var i = 0; i < rv.component.length; i++) {
|
||||
var comp = rv.component[i];
|
||||
var meta = geoMeta[comp];
|
||||
if (!meta)
|
||||
continue;
|
||||
|
||||
var option = document.createElement('option');
|
||||
option.value = comp;
|
||||
option.textContent = meta.label;
|
||||
fragment.appendChild(option);
|
||||
}
|
||||
|
||||
selector.innerHTML = '';
|
||||
selector.appendChild(fragment);
|
||||
|
||||
if (selector.options.length > 0) {
|
||||
selector.selectedIndex = 0;
|
||||
onGeoChange();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function renderGeoInfo(data, checkedRemote) {
|
||||
// console.log('Geo data:', data);
|
||||
var panel = document.getElementById('geo-status');
|
||||
var upgradeButton = document.getElementById('geo-upgrade');
|
||||
var action = document.getElementById('geo-action');
|
||||
@@ -227,11 +268,23 @@
|
||||
}
|
||||
|
||||
html.push('<div><strong><%:Current Version%>:</strong> ' + (data.current_version || '<%:File Not Exist%>') + '</div>');
|
||||
if (data.component !== 'v2ray_geo' && data.current_version_extra) {
|
||||
html.push('<div><strong><%:Latest Version%>:</strong> ' + (data.latest_version || '<%:Unknown%>') + '</div>');
|
||||
var installed = data.installed !== undefined ? data.installed : (data.current_version ? true : false);
|
||||
html.push('<div><strong><%:Installed%>:</strong> ' + (installed ? '<%:Yes%>' : '<%:No%>') + '</div>');
|
||||
if (data.component !== 'v2ray_geoip' && data.current_version_extra) {
|
||||
html.push('<div><strong><%:Additional Version%>:</strong> ' + data.current_version_extra + '</div>');
|
||||
}
|
||||
if (data.component !== 'v2ray_geosite' && data.current_version_extra) {
|
||||
html.push('<div><strong><%:Additional Version%>:</strong> ' + data.current_version_extra + '</div>');
|
||||
}
|
||||
if (data.error) {
|
||||
html.push('<div style="color:red"><%:Status%>: ' + displayError(data.error) + '</div>');
|
||||
} else if (!checkedRemote) {
|
||||
html.push('<div style="color:#666"><%:Status%>: <%:No Check%></div>');
|
||||
} else if (data.can_upgrade) {
|
||||
html.push('<div style="color:#d48806"><%:Status%>: <%:Upgrade available%></div>');
|
||||
} else if (data.latest_version) {
|
||||
html.push('<div style="color:green"><%:Status%>: <%:Already up to date%></div>');
|
||||
} else if (data.message) {
|
||||
html.push('<div style="color:green"><%:Status%>: ' + (data.success ? displayMessage(data.message) : (data.message || '<%:Unknown%>')) + '</div>');
|
||||
} else {
|
||||
@@ -240,7 +293,7 @@
|
||||
|
||||
panel.innerHTML = html.join('');
|
||||
if (upgradeButton) {
|
||||
upgradeButton.disabled = false;
|
||||
upgradeButton.disabled = !!data.error || !checkedRemote || !data.latest_version || !data.can_upgrade;
|
||||
}
|
||||
if (action) {
|
||||
action.innerHTML = data.message
|
||||
@@ -249,26 +302,28 @@
|
||||
}
|
||||
}
|
||||
|
||||
function queryGeoInfo(button) {
|
||||
function queryGeoInfo(button, doUpgrade) {
|
||||
var component = selectedGeoComponent();
|
||||
var mirror = selectedMirror();
|
||||
var action = document.getElementById('geo-action');
|
||||
var url = '<%=luci.dispatcher.build_url("admin", "services", "shadowsocksr", "geo_upgrade")%>';
|
||||
var url = doUpgrade
|
||||
? '<%=luci.dispatcher.build_url("admin", "services", "shadowsocksr", "geo_upgrade")%>'
|
||||
: '<%=luci.dispatcher.build_url("admin", "services", "shadowsocksr", "geo_status")%>';
|
||||
|
||||
if (button) {
|
||||
button.disabled = true;
|
||||
button.value = '<%:Checking...%>';
|
||||
button.value = doUpgrade ? '<%:Upgrading...%>' : '<%:Checking...%>';
|
||||
}
|
||||
|
||||
if (action) {
|
||||
action.innerHTML = '<%:Processing...%>';
|
||||
action.innerHTML = doUpgrade ? '<%:Processing...%>' : '';
|
||||
}
|
||||
|
||||
XHR.get(url, { component: component, mirror: mirror }, function(x, rv) {
|
||||
renderGeoInfo(rv);
|
||||
renderGeoInfo(rv, true);
|
||||
if (button) {
|
||||
button.disabled = false;
|
||||
button.value = '<%:CHECK AND UPDATE%>';
|
||||
button.value = doUpgrade ? '<%:Upgrade%>' : '<%:Check Update%>';
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -282,7 +337,7 @@
|
||||
component: selectedGeoComponent(),
|
||||
mirror: selectedMirror()
|
||||
}, function(x, rv) {
|
||||
renderGeoInfo(rv);
|
||||
renderGeoInfo(rv, false);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -290,9 +345,18 @@
|
||||
queryLocalGeoInfo();
|
||||
}
|
||||
|
||||
function selectedGeoComponent() {
|
||||
var selector = document.getElementById('geo-selector');
|
||||
return selector ? selector.value : 'country_mmdb';
|
||||
}
|
||||
|
||||
function geoHelp(component) {
|
||||
return geoMeta[component] ? geoMeta[component].help : '';
|
||||
}
|
||||
|
||||
window.setTimeout(function() {
|
||||
onComponentChange();
|
||||
onGeoChange();
|
||||
loadGeoComponent()
|
||||
}, 0);
|
||||
//]]>
|
||||
</script>
|
||||
@@ -437,8 +501,9 @@
|
||||
</div>
|
||||
<select id="geo-selector" class="cbi-input-select component-selector" onchange="onGeoChange()">
|
||||
<option value="country_mmdb"><%:Country MMDB%></option>
|
||||
<option value="geosite"><%:GeoSite Database%></option>
|
||||
<option value="v2ray_geo"><%:V2Ray GEO Databases%></option>
|
||||
<option value="geosite"><%:OpenClash GeoSite Database%></option>
|
||||
<option value="v2ray_geoip"><%:V2Ray GeoIP Databases%></option>
|
||||
<option value="v2ray_geosite"><%:V2Ray GeoSite Databases%></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@@ -447,7 +512,8 @@
|
||||
<div id="geo-status"><em><%:Collecting data...%></em></div>
|
||||
<div class="component-upgrade-help" id="geo-help"></div>
|
||||
<div class="component-upgrade-actions">
|
||||
<input type="button" class="btn cbi-button cbi-button-apply" id="geo-upgrade" value="<%:CHECK AND UPDATE%>" onclick="queryGeoInfo(this)" />
|
||||
<input type="button" class="btn cbi-button cbi-button-reload" value="<%:Check Update%>" onclick="queryGeoInfo(this, false)" />
|
||||
<input type="button" class="btn cbi-button cbi-button-apply" id="geo-upgrade" value="<%:Upgrade%>" onclick="queryGeoInfo(this, true)" />
|
||||
</div>
|
||||
<div class="component-upgrade-result" id="geo-action"></div>
|
||||
</div>
|
||||
|
||||
@@ -18,7 +18,10 @@
|
||||
return;
|
||||
}
|
||||
if (!res || res.code !== 1 || !res.data) {
|
||||
alert(res && res.msg ? res.msg : "<%:Fetch Failed%> !");
|
||||
alert(res && res.msg ? res.msg : "<%:Fetch Failed%> !\n" +
|
||||
"<%:Requires OpenSSL to retrieve the TLS certificate chain fingerprint.%>\n" +
|
||||
"<%:QUIC protocols such as HY2 also require curl with http3 support.%>"
|
||||
);
|
||||
return;
|
||||
}
|
||||
const inputs = document.querySelectorAll('input[id$=".tls_CertSha"]');
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user