mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-07-27 10:31:38 +08:00
🍉 Sync 2026-05-26 21:02:29
This commit is contained in:
parent
755c7e3679
commit
8ab0ff5223
2
ipv6-neigh/Cargo.lock
generated
2
ipv6-neigh/Cargo.lock
generated
@ -395,7 +395,7 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
[[package]]
|
||||
name = "hickory-proto"
|
||||
version = "0.27.0-alpha.1"
|
||||
source = "git+https://github.com/hickory-dns/hickory-dns.git?rev=c5e29b9da8334a14961a6326ad04e25397205430#c5e29b9da8334a14961a6326ad04e25397205430"
|
||||
source = "git+https://github.com/hickory-dns/hickory-dns.git?rev=ee7ba64757eca61d86f323ef992eba482605d7c3#ee7ba64757eca61d86f323ef992eba482605d7c3"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"data-encoding",
|
||||
|
||||
@ -13,7 +13,7 @@ futures = "0.3.32"
|
||||
netlink-packet-route = {version = "0.30" }
|
||||
netlink-packet-core= {version ="0.8"}
|
||||
clap = { version = "4.6", default-features = false, features = ["cargo", "derive", "help", "std", "suggestions"] }
|
||||
hickory-proto = { git = "https://github.com/hickory-dns/hickory-dns.git", rev = "c5e29b9da8334a14961a6326ad04e25397205430", features = ["dnssec-ring"] }
|
||||
hickory-proto = { git = "https://github.com/hickory-dns/hickory-dns.git", rev = "ee7ba64757eca61d86f323ef992eba482605d7c3", features = ["dnssec-ring"] }
|
||||
ubus = "0.1.7"
|
||||
serde_json = "1.0.149"
|
||||
log = "0.4"
|
||||
|
||||
@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ipv6-neigh
|
||||
PKG_VERSION:=0.1.0
|
||||
PKG_RELEASE:=13
|
||||
PKG_RELEASE:=14
|
||||
|
||||
PKG_BUILD_DEPENDS:=rust/host
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
||||
@ -518,6 +518,133 @@ async fn main() -> Result<(), ()> {
|
||||
private_subnet_v6,
|
||||
)
|
||||
.await;
|
||||
// Recover kernel orphans: neighbours that are REACHABLE in the kernel
|
||||
// but absent from `registered` and DNS. This happens when a netlink
|
||||
// NewNeighbour event is lost (receive-buffer overflow) or when a device
|
||||
// transitions to REACHABLE during the startup race window.
|
||||
// reconcile_dns's AXFR pass cannot catch these because the record is
|
||||
// also absent from DNS, so no probe is ever triggered for them.
|
||||
if let Ok(neighbours) = dump_neighbours(handle.clone(), private_subnet_v4).await {
|
||||
// Build a set of IPs that are currently REACHABLE in the kernel,
|
||||
// used below to detect registered entries the kernel has marked FAILED.
|
||||
let reachable_ips: std::collections::HashSet<String> = neighbours
|
||||
.iter()
|
||||
.filter(|n| n.state == NeighbourState::Reachable)
|
||||
.map(|n| inet_to_string(&n.inet))
|
||||
.collect();
|
||||
|
||||
for neigh in &neighbours {
|
||||
if should_skip_neigh(neigh) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if is_failed_state(neigh.state) {
|
||||
// Kernel confirms FAILED — remove from registered + DNS if present.
|
||||
// Mirrors the real-time NewNeighbour(FAILED) handler but catches
|
||||
// cases where that event was lost.
|
||||
let ip_str = inet_to_string(&neigh.inet);
|
||||
let key_opt: Option<(String, String)> = leases
|
||||
.get(&neigh.mac)
|
||||
.map(|h| (h.clone(), ip_str.clone()))
|
||||
.or_else(|| {
|
||||
registered
|
||||
.keys()
|
||||
.find(|(_, ip)| ip == &ip_str)
|
||||
.cloned()
|
||||
});
|
||||
if let Some(key) = key_opt {
|
||||
if let Some(entry) = registered.remove(&key) {
|
||||
debug!("reconcile neigh: kernel FAILED {} -> {:?}", entry.hostname, neigh.inet);
|
||||
if !do_delete_dns(&entry.hostname, &neigh.inet, &updater).await {
|
||||
registered.insert(key, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if neigh.state != NeighbourState::Reachable {
|
||||
continue;
|
||||
}
|
||||
if let NeighbourAddress::Inet6(addr) = &neigh.inet {
|
||||
if !active_prefixes.is_empty()
|
||||
&& !active_prefixes.iter().any(|p| ipv6_in_prefix(*addr, p))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if is_gua_ipv6(addr) && private_subnet_v6 {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let ip_str = inet_to_string(&neigh.inet);
|
||||
let Some(hostname) = leases.get(&neigh.mac) else {
|
||||
continue;
|
||||
};
|
||||
let key = (hostname.clone(), ip_str);
|
||||
if let Some(entry) = registered.get_mut(&key) {
|
||||
// Already tracked — refresh to suppress spurious probes.
|
||||
entry.last_confirmed = Instant::now();
|
||||
entry.ifindex = neigh.ifindex;
|
||||
} else {
|
||||
debug!("reconcile neigh: kernel orphan {} -> {:?}", hostname, neigh.inet);
|
||||
if let NeighbourAddress::Inet6(addr) = &neigh.inet {
|
||||
if if_ipv6_in_private_subnet(addr) {
|
||||
prune_ula_for_host(
|
||||
hostname,
|
||||
max_ula_per_host,
|
||||
&mut registered,
|
||||
&updater,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
if process_new_neigh(neigh, &updater, &leases, private_subnet_v6).await {
|
||||
registered.insert(
|
||||
key,
|
||||
RegisteredEntry {
|
||||
hostname: hostname.clone(),
|
||||
last_confirmed: Instant::now(),
|
||||
ifindex: neigh.ifindex,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sweep registered entries whose IP the kernel has evicted entirely
|
||||
// (not present in the dump at all, not even as FAILED) AND that haven't
|
||||
// been confirmed recently. These are devices whose FAILED event was
|
||||
// lost and which the kernel has since garbage-collected from its table.
|
||||
// Only act if the entry is old enough (> 2× probe interval) to avoid
|
||||
// racing with normal STALE→REACHABLE transitions.
|
||||
let stale_cutoff = Duration::from_secs(probe_interval.saturating_mul(2));
|
||||
let now = Instant::now();
|
||||
let to_remove: Vec<(String, String)> = registered
|
||||
.iter()
|
||||
.filter(|((_hostname, ip_str), entry)| {
|
||||
!reachable_ips.contains(ip_str.as_str())
|
||||
&& now.duration_since(entry.last_confirmed) > stale_cutoff
|
||||
})
|
||||
.map(|(k, _)| k.clone())
|
||||
.collect();
|
||||
for key in to_remove {
|
||||
if let Some(entry) = registered.remove(&key) {
|
||||
let ip_str = &key.1;
|
||||
let inet = if let Ok(addr) = ip_str.parse::<std::net::Ipv6Addr>() {
|
||||
NeighbourAddress::Inet6(addr)
|
||||
} else if let Ok(addr) = ip_str.parse::<std::net::Ipv4Addr>() {
|
||||
NeighbourAddress::Inet(addr)
|
||||
} else {
|
||||
registered.insert(key, entry);
|
||||
continue;
|
||||
};
|
||||
debug!("reconcile neigh: evicted {} -> {}", entry.hostname, ip_str);
|
||||
if !do_delete_dns(&entry.hostname, &inet, &updater).await {
|
||||
registered.insert(key, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = gua_keepalive_timer.tick() => {
|
||||
if !keepalive_gua || keepalive_gua_interval == 0 {
|
||||
|
||||
@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall
|
||||
PKG_VERSION:=26.5.20
|
||||
PKG_RELEASE:=137
|
||||
PKG_RELEASE:=138
|
||||
PKG_PO_VERSION:=$(PKG_VERSION)
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
|
||||
@ -947,6 +947,7 @@ function restore_backup()
|
||||
fp:write(decoded)
|
||||
fp:close()
|
||||
if chunk_index + 1 == total_chunks then
|
||||
uci:revert(appname)
|
||||
luci.sys.call("echo '' > /tmp/log/passwall.log")
|
||||
api.log(" * PassWall 配置文件上传成功…")
|
||||
local temp_dir = '/tmp/passwall_bak'
|
||||
|
||||
@ -132,12 +132,14 @@ function base64Encode(text)
|
||||
end
|
||||
|
||||
function UrlEncode(szText)
|
||||
if type(szText) ~= "string" then return "" end
|
||||
return szText:gsub("([^%w%-_%.%~])", function(c)
|
||||
return string.format("%%%02X", string.byte(c))
|
||||
end)
|
||||
end
|
||||
|
||||
function UrlDecode(szText)
|
||||
if type(szText) ~= "string" then return "" end
|
||||
return szText and szText:gsub("%+", " "):gsub("%%(%x%x)", function(h)
|
||||
return string.char(tonumber(h, 16))
|
||||
end) or nil
|
||||
|
||||
@ -66,10 +66,10 @@ local function build_common(node)
|
||||
|
||||
local ech_opts = node["ech-opts"]
|
||||
if ech_opts and ech_opts.enable == true then
|
||||
if ech_opts.config then
|
||||
o.tls.ech = ech_opts.config
|
||||
elseif ech_opts["query-server-name"] then
|
||||
if ech_opts["query-server-name"] then
|
||||
o.tls.ech = ech_opts["query-server-name"] .. "+https://223.5.5.5/dns-query"
|
||||
elseif ech_opts.config then
|
||||
o.tls.ech = ech_opts.config
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -683,6 +683,11 @@ local function processData(szType, content, add_mode, group, sub_cfg)
|
||||
result.tls = "0"
|
||||
end
|
||||
|
||||
if info.ech and info.ech ~= "" then
|
||||
result.ech = "1"
|
||||
result.ech_config = info.ech
|
||||
end
|
||||
|
||||
result.tcp_fast_open = info.tfo
|
||||
|
||||
info.fm = (info.fm and info.fm ~= "") and UrlDecode(info.fm) or nil
|
||||
|
||||
Loading…
Reference in New Issue
Block a user