[FREEBOX] Multiple IPv6 addresses still trigger false IP Changed events after #1273
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 48/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Ambito
- backend, networking
Direzione di ricerca
Start by tracing the scan-processing order and the three reductions described in the report: update_ipv4_ipv6(), LatestDeviceScan, and insert_events(); the issue does not name their files or tests. Compare how each handles multiple known addresses for one MAC, then inspect existing tests for scan processing and IP Changed events. Done means repeated scans with multiple known IPv6 addresses do not emit false IP Changed events, while genuine address changes still do.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
What installation are you running?
Production (netalertx) 📦
Is there an existing issue for this?
- I have searched the existing open and closed issues and I checked the docs https://docs.netalertx.com/
The issue occurs in the following browsers. Select at least 2.
- Firefox
- Chrome
- Edge
- Safari (unsupported) - PRs welcome
- N/A - This is an issue with the backend
Current Behavior
I am seeing false IP Changed events for dual-stack devices discovered by the FREEBOX plugin even after the dual-stack persistence issue reported in #1804 was fixed.
The important difference from #1804 is that devPrimaryIPv4 and devPrimaryIPv6 are now populated correctly.
The remaining issue appears when the same MAC has:
- one IPv4 address; and
- multiple legitimate IPv6 addresses.
These IPv6 addresses are already known to NetAlertX and are not newly assigned addresses.
Relation to #1804
In #1804, the original problem was that FREEBOX discovered IPv6 addresses correctly, but devPrimaryIPv6 remained empty because scan observations were reduced before update_ipv4_ipv6() could preserve both address families.
That issue was fixed and I tested the updated build successfully.
In that test:
- both
devPrimaryIPv4anddevPrimaryIPv6were populated; - dual-stack state remained stable across repeated scans; and
- the previous flood of repeated IPv6
IP Changedevents disappeared.
So I consider #1804 fixed.
This report concerns a remaining case that became visible afterwards: a device can have multiple valid IPv6 addresses at the same time, and NetAlertX can still generate IP Changed events as different already-known IPv6 addresses become selected by different parts of the scan-processing logic.
Observed IPv6 oscillation
For one affected device, I observed repeated transitions between two persistent IPv6 addresses:
IPv6-4 -> IPv6-2
IPv6-2 -> IPv6-4
IPv6-4 -> IPv6-2
IPv6-2 -> IPv6-4
Both addresses were already present in historical FREEBOX observations.
These were not newly discovered IPv6 addresses.
Different address-selection mechanisms
I investigated the current scan-processing path and found that several different reductions are applied to multiple addresses belonging to the same MAC.
1. Primary IPv4/IPv6 selection
update_ipv4_ipv6() selects the primary IPv4 and IPv6 independently from CurrentScan, ranking addresses within each address family using scanLastConnection:
ROW_NUMBER() OVER (
PARTITION BY scanMac,
CASE WHEN instr(scanLastIP, ':') > 0 THEN 'v6' ELSE 'v4' END
ORDER BY scanLastConnection DESC
)
This is the mechanism introduced as part of the #1804 fix.
It correctly allows IPv4 and IPv6 to be retained simultaneously.
However, when a device has more than one IPv6 address, whichever IPv6 currently has the newest scanLastConnection becomes the candidate for devPrimaryIPv6.
During live monitoring I observed different already-known IPv6 addresses changing rank as their scanLastConnection values changed.
2. LatestDeviceScan / devLastIP
LatestDeviceScan performs a different reduction:
ROW_NUMBER() OVER (
PARTITION BY scanMac, scanSourcePlugin
ORDER BY scanLastConnection DESC
)
This keeps one latest observation for a MAC/plugin across both IPv4 and IPv6 rows.
Therefore, the address used for the single-valued devLastIP can differ from the per-family address selected by update_ipv4_ipv6().
3. IP Changed event candidate
insert_events() uses another reduction again.
Present CurrentScan rows are grouped by MAC and reduced using:
SELECT scanMac, MIN(scanLastIP) AS scanLastIP
FROM CurrentScan
WHERE scanPresence = 1
AND scanLastIP IS NOT NULL
GROUP BY scanMac
The resulting address is then compared against:
devPrimaryIPv4devPrimaryIPv6devLastIP
Importantly, insert_events() runs before update_ipv4_ipv6() in the scan-processing cycle.
So the current scan's reduced candidate is compared against device-level values from the previous processing state.
Captured event-producing cycle
I captured an actual event-producing cycle at high polling frequency.
The addresses below are anonymized but consistently labelled.
Immediately before the event, the affected device had:
Device-6
newest IPv6 = IPv6-2
MIN(scanLastIP) = IPv6-2
devLastIP = IPv4
devPrimaryIPv4 = set
devPrimaryIPv6 = IPv6-4
The generated event was:
IP Changed
new = IPv6-2
previous = IPv4
In other words:
IPv6-2was the currentMIN(scanLastIP)candidate;- the stored primary IPv6 was still
IPv6-4; devLastIPwas IPv4.
The event conditions therefore effectively evaluated as:
IPv6-2 != devPrimaryIPv4
IPv6-2 != devPrimaryIPv6 (IPv6-4)
IPv6-2 != devLastIP (IPv4)
All three comparisons were true, so an IP Changed event was generated.
However, IPv6-2 was not a newly discovered address.
Both IPv6-2 and IPv6-4 were already-known FREEBOX IPv6 addresses for the same device.
Live CurrentScan observations
A separate live CurrentScan capture also showed that these reductions can select different addresses for the same device during the same scan.
For example, several devices had:
LatestDeviceScan candidate = IPv6
Primary IPv6 candidate = IPv6
MIN(scanLastIP) candidate = IPv4
For the affected device during the event-producing scan, the state instead reached:
newest IPv6 = IPv6-2
MIN(scanLastIP) = IPv6-2
stored primary6 = IPv6-4
This suggests that changes in which already-known IPv6 rows are currently present/reachable, together with changes in their scanLastConnection values, can cause an existing IPv6 address to be treated as an IP change.
Equal scanLastConnection values
I also observed cases where two different IPv6 addresses for the same MAC had exactly the same scanLastConnection.
The ranking currently uses:
ORDER BY scanLastConnection DESC
without a secondary ordering criterion.
I am not describing the result as random, but when timestamps are equal there is no explicit tie-breaker.
Summary
The basic dual-stack persistence problem from #1804 appears fixed.
The remaining issue is that multiple IPv6 addresses for the same MAC are still reduced differently by different parts of the scan-processing pipeline:
update_ipv4_ipv6()selects the newest IPv6 byscanLastConnection;LatestDeviceScanselects one newest address across the plugin's observations;insert_events()selectsMIN(scanLastIP)across present rows.
These different reduction rules can cause an already-known IPv6 address to be considered different from the stored device-level values and generate a false IP Changed event.
This may also interact with #1828 because temporary FREEBOX L3 reachability changes can alter which address rows are present in CurrentScan.
However, I believe the failure modes are distinct:
- #1804 concerned missing dual-stack persistence.
- #1828 concerns false
Disconnected/Connectedstate. - This report concerns false
IP Changedevents when multiple already-known IPv6 addresses exist for the same MAC.
Expected Behavior
The dual-stack fix from #1804 should continue to preserve both address families correctly:
devPrimaryIPv4 -> IPv4
devPrimaryIPv6 -> IPv6
For devices that have multiple legitimate IPv6 addresses, NetAlertX should not generate an IP Changed event merely because a different already-known IPv6 address becomes:
- the newest address by
scanLastConnection; - the current primary IPv6;
- the latest address selected for
devLastIP; or - the lexical minimum returned by
MIN(scanLastIP).
For a dual-stack device with one IPv4 address and multiple known IPv6 addresses, NetAlertX should distinguish between:
- discovery of a genuinely new address;
- disappearance/reappearance or temporary reachability changes of an already-known address;
- selection of a different existing IPv6 address as the current/primary IPv6;
- and an actual address change that should generate an
IP Changedevent.
Multiple known IPv6 addresses
For example, consider a device with these legitimate, already-known addresses:
IPv4-A
IPv6-A
IPv6-B
If subsequent scans cause the selected primary IPv6 to alternate between:
devPrimaryIPv6 = IPv6-A
and:
devPrimaryIPv6 = IPv6-B
this should not repeatedly produce:
IPv6-A -> IPv6-B
IPv6-B -> IPv6-A
IPv6-A -> IPv6-B
IP Changed events merely because reachability timestamps or current scan rows changed.
Event detection
Similarly, reducing all present addresses for a MAC to:
MIN(scanLastIP)
should not cause an IP Changed event simply because the currently present/reachable address set changes and a different already-known address becomes the lexical minimum.
An already-known/current IPv6 address for the same MAC should not be treated as a newly changed IP merely because it becomes the current event candidate.
Consistent multi-address handling
I would expect IP Changed detection to operate consistently with the multi-address model introduced by the #1804 dual-stack fix.
If NetAlertX now preserves IPv4 and IPv6 independently at the device level, event detection should also account for the fact that a device may legitimately own more than one address within the same family.
An IP Changed event should represent an actual address change according to NetAlertX's intended semantics, rather than a change in which one of several existing addresses wins a particular reduction rule.
Where ranking is required, equal scanLastConnection values should also have an explicitly defined deterministic tie-breaker.
I do not have a strong opinion on whether this requires a schema change.
The current implementation already demonstrates that multiple CurrentScan rows can be used to maintain both devPrimaryIPv4 and devPrimaryIPv6 without changing the schema.
The important expected outcome is that all parts of the scan-processing pipeline use a consistent multi-address model when deciding:
- the current IPv4 address;
- the current IPv6 address;
devLastIP; and- whether an
IP Changedevent should be generated.
A schema change may be appropriate if NetAlertX eventually wants to retain all addresses for a device as first-class persistent state, but it does not appear to be strictly required to address the false IP Changed behavior demonstrated here.
Steps To Reproduce
-
Run a current NetAlertX production release.
-
Have at least one FREEBOX client that has:
- an IPv4 address; and
- more than one IPv6 address associated with the same MAC.
-
Allow the FREEBOX plugin to complete several scheduled scans.
-
Confirm that the FREEBOX observations contain multiple addresses for the same MAC, for example:
Device A ├── IPv4-A ├── IPv6-A └── IPv6-B -
Confirm that the #1804 dual-stack fix is working and that the device has both primary address families populated:
devPrimaryIPv4 = IPv4-A devPrimaryIPv6 = IPv6-A or IPv6-BThe issue described here does not require
devPrimaryIPv6to be empty. -
Continue running FREEBOX scans while the multiple IPv6 addresses remain known for the device.
-
Observe that the per-address
scanLastConnectionvalues can change independently and that a different already-known IPv6 address can become the current IPv6 candidate. -
Check the
Eventstable or the generated NetAlertX notifications/reports. -
Observe that an
IP Changedevent can be generated for an IPv6 address that was already known for that MAC.In my captured reproduction, the pre-event state was:
newest IPv6 = IPv6-2 MIN(scanLastIP) = IPv6-2 devLastIP = IPv4 devPrimaryIPv4 = set devPrimaryIPv6 = IPv6-4NetAlertX then generated:
IP Changed new = IPv6-2 previous = IPv4Both
IPv6-2andIPv6-4were already-known FREEBOX addresses for the same device. -
Across subsequent scans, the same device can alternate between already-known IPv6 addresses, producing transitions such as:
IPv6-4 -> IPv6-2 IPv6-2 -> IPv6-4 IPv6-4 -> IPv6-2 IPv6-2 -> IPv6-4These transitions occur without the addresses being newly discovered.
Notes on reproducibility
The behavior depends on a device having multiple IPv6 observations and on which rows are present/reachable during a particular scan, so an IP Changed event may not occur on every FREEBOX cycle.
The issue is easier to observe over multiple scheduled scans.
Relevant app.conf settings
The relevant FREEBOX settings are:
FREEBOX_RUN='schedule'
FREEBOX_RUN_SCHD='*/5 * * * *'
FREEBOX_address='mafreebox.freebox.fr'
FREEBOX_api_version=6
FREEBOX_api_port=443
FREEBOX_CMD='python3 /app/server/plugins/freebox/freebox.py'
FREEBOX_RUN_TIMEOUT=30
FREEBOX_SET_ALWAYS=['devMac','devLastIP']
FREEBOX_SET_EMPTY=[]
The current FREEBOX plugin configuration also maps its per-address reachability timestamp to:
watchedValue4 -> scanLastConnection
This is the timestamp handling introduced as part of #1804.
The issue occurs with `scanLastConnection` populated.
docker-compose.yml
services:
netalertx:
image: ghcr.io/netalertx/netalertx:latest
container_name: netalertx
restart: unless-stopped
network_mode: host
volumes:
- /path/to/netalertx/data:/data
tmpfs:
- "/tmp:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
cap_drop:
- ALL
cap_add:
- NET_ADMIN
- NET_RAW
- NET_BIND_SERVICE
- CHOWN
- SETUID
- SETGID
read_only: true
security_opt:
- no-new-privileges:true
environment:
- TZ=Europe/Paris
deploy:
resources:
reservations:
memory: 1G
limits:
memory: 2G
Debug or Trace enabled
- I have read and followed the steps in the wiki link above and provided the required debug logs and the log section covers the time when the issue occurs.
Relevant app.log section
N/A
The relevant Docker log section is provided below.
Docker Logs
The following is a privacy-sanitized extract from a DEBUG scan cycle in which the FREEBOX plugin supplied multiple IPv4/IPv6 observations for the same devices.
MAC addresses, IP addresses, and device names have been replaced with placeholders. The timestamps and processing order are preserved.
00:45:32 [Scheduler] run for FREEBOX: YES
00:45:32 [Plugins] CMD: python3 /app/server/plugins/freebox/freebox.py
00:45:32 [FREEBOX] In script
00:45:33 [Plugins] SUCCESS for FREEBOX received 36 entries
00:45:33 [Plugins] Mapping objects to database table: CurrentScan
00:45:33 [Plugins] SQL query for mapping:
INSERT OR IGNORE INTO CurrentScan
("scanMac", "scanLastIP", "scanName", "scanVendor", "scanType",
"scanLastConnection", "scanSourcePlugin")
VALUES (?, ?, ?, ?, ?, ?, ?)
# The corresponding sqlParams contained multiple rows for individual
# devices, including one IPv4 address and multiple IPv6 addresses with
# independent scanLastConnection timestamps.
00:46:56 [Events] - 1a - Devices down (non-sleeping)
00:46:56 [Events] - 1b - Devices down (sleep expired)
00:46:56 [Events] - 2 - New Connections
00:46:56 [Events] - 2b - NIC-derived New Connections
00:46:56 [Events] - 3 - Disconnections
00:46:56 [Events] - 4 - IP Changes
00:46:56 [Events] - Events end
# Device updates occur after event processing.
00:46:56 [Update Devices] - (FREEBOX)
current_value: <IPv6-A> new_value: <IPv4-A> -> devLastIP
00:46:56 [Update Devices] - (FREEBOX)
scanLastIP -> devLastIP
[...]
00:46:56 [Update Devices] - (FREEBOX)
current_value: <IPv4-B> new_value: <IPv6-B> -> devLastIP
00:46:56 [Update Devices] - (FREEBOX)
scanLastIP -> devLastIP
[...]
00:46:56 [Process Scan] Updating devLastConnection from CurrentScan
00:46:56 [Process Scan] Updating Presence from CurrentScan
00:46:56 [Update Devices]
Updating devPrimaryIPv4 / devPrimaryIPv6 from CurrentScan
00:46:56 [Update Devices] Updated 17 IPv4/IPv6 entries
The relevant processing order observed in this cycle is:
- FREEBOX populates
CurrentScanwith multiple address observations. IP Changesevent processing runs.devLastIPis subsequently updated.devPrimaryIPv4/devPrimaryIPv6are subsequently updated fromCurrentScan.
The complete raw DEBUG log is not included because it contains MAC addresses, local/public IPv4/IPv6 addresses, and device names.
- Lingua principale
- Python
- Stelle
- 7.2k
- Fork
- 456
- Merge medio
- 16h 25m
- PR unite (30g)
- 30
Preparare l'ambiente
Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.
- Include un Dockerfile o un file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di netalertx/NetAlertX
-
Docker 🐋
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
bug 🐛 Contributors 🙏 help wanted 🆘
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
I maintainer di solito rispondono entro 1 giorno
-
bug 🐛 next release/in dev image 🚀 Waiting for reply⏳
Difficoltà 3/5 Mezza giornata Idoneità per principianti 57/100
netalertx/NetAlertX#1852 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Feature request ➕ please feedback 💬
Difficoltà 5/5 Più di una settimana Idoneità per principianti 45/100
netalertx/NetAlertX#1827 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Feature request ➕ please feedback 💬
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
netalertx/NetAlertX#1824 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di netalertx/NetAlertX
Issue simili
-
enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
fossasia/visdom-dev#77 ·
I maintainer di solito rispondono entro 4 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
aws-cloudformation/cfn-lint#4890 ·
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
volcengine/OpenViking#6521 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 77/100
AstrBotDevs/AstrBot#10720 ·
I maintainer di solito rispondono entro 1 giorno