Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

network: don't forget old RAs when a new one arrives #24898

Merged
merged 1 commit into from
Oct 3, 2022

Conversation

tchebb
Copy link
Contributor

@tchebb tchebb commented Oct 2, 2022

IPv6 Neighbor Discovery lets us autoconfigure a link's IPv6 addresses, routes, DNS servers, and DNS search domains by listening for Router Advertisement (RA) packets broadcast by one or more routers on the link. Each RA can contain zero or more "options," each describing one piece of configuration (e.g. a single route).

Currently, when we receive an RA from a router, we delete any addresses, routes, etc. that originated from that router's previous RAs unless they're also present as options in the new RA.

That behavior is a violation of RFC 4861. In Section 9, the RFC states that

Senders MAY send a subset of options in different packets. ... Thus, a receiver MUST NOT associate any action with the absence of an option in a particular packet. This protocol specifies that receivers should only act on the expiration of timers and on the information that is received in the packets.

Several other passages in the RFC reiterate this. Section 6.2.3:

A router MAY choose not to include some or all options when sending unsolicited Router Advertisements.

Section 6.3.4:

Hosts accept the union of all received information; the receipt of a Router Advertisement MUST NOT invalidate all information received in a previous advertisement or from another source.

At least one consumer router in production today, the Google Nest Wifi, often sends RAs that omit its global IPv6 prefix. When current versions of systemd-networkd receive those RAs, they immediately delete the interface's global IPv6 address, which breaks IPv6 connectivity.

Fix the issue by removing the invalidation logic entirely. It's not needed at all, since we already invalidate addresses, routes, and DNS configuration when the interface goes down or their lifetimes expire.

This fix does have the side effect of preventing changes to the .network file (e.g. denylisted prefixes, whether to add routes from RAs) from taking effect as soon as a new RA arrives. Instead, a full interface reconfiguration is needed. But triggering those changes on RA receipt was already rather arbitrary and out of the administrator's control, so I think this change is fine.

commit 69203fb ("network: ndisc: remove old addresses and routes after at least one SLAAC address becomes ready") introduced this behavior. commit 5055072 fixed it partially, by preventing one router's RAs from invalidating another router's configuration.

IPv6 Neighbor Discovery lets us autoconfigure a link's IPv6 addresses,
routes, DNS servers, and DNS search domains by listening for Router
Advertisement (RA) packets broadcast by one or more routers on the link.
Each RA can contain zero or more "options," each describing one piece of
configuration (e.g. a single route).

Currently, when we receive an RA from a router, we delete any addresses,
routes, etc. that originated from that router's previous RAs unless
they're also present as options in the new RA.

That behavior is a violation of RFC 4861[1]. In Section 9, the RFC
states that

    Senders MAY send a subset of options in different packets. ... Thus,
    a receiver MUST NOT associate any action with the absence of an
    option in a particular packet. This protocol specifies that
    receivers should only act on the expiration of timers and on the
    information that is received in the packets.

Several other passages in the RFC reiterate this. Section 6.2.3:

    A router MAY choose not to include some or all options when sending
    unsolicited Router Advertisements.

Section 6.3.4:

    Hosts accept the union of all received information; the receipt of a
    Router Advertisement MUST NOT invalidate all information received in
    a previous advertisement or from another source.

At least one consumer router in production today, the Google Nest Wifi,
often sends RAs that omit its global IPv6 prefix. When current versions
of systemd-networkd receive those RAs, they immediately delete the
interface's global IPv6 address, which breaks IPv6 connectivity.

Fix the issue by removing the invalidation logic entirely. It's not
needed at all, since we already invalidate addresses, routes, and DNS
configuration when the interface goes down or their lifetimes expire.

This fix does have the side effect of preventing changes to the .network
file (e.g. denylisted prefixes, whether to add routes from RAs) from
taking effect as soon as a new RA arrives. Instead, a full interface
reconfiguration is needed. But triggering those changes on RA receipt
was already rather arbitrary and out of the administrator's control, so
I think this change is fine.

commit 69203fb ("network: ndisc: remove old addresses and routes
after at least one SLAAC address becomes ready") introduced this
behavior. commit 5055072 fixed it partially, by preventing one
router's RAs from invalidating another router's configuration.

[1] https://www.rfc-editor.org/rfc/rfc4861

Fixes: 69203fb ("network: ndisc: remove old addresses and routes after at least one SLAAC address becomes ready")
@yuwata
Copy link
Member

yuwata commented Oct 3, 2022

Hm, I see, the current implement violates RFC. Thanks.

But, how should networkd revoke outdated announcement from a router? Addresses or routes assigned based on a RA will never removed with this change. It may break connectivity when a setting in a router is changed.

@yuwata
Copy link
Member

yuwata commented Oct 3, 2022

But, how should networkd revoke outdated announcement from a router? Addresses or routes assigned based on a RA will never removed with this change. It may break connectivity when a setting in a router is changed.

I re-read the RFC, and I found that in such case the router needs to send outdated prefix with zero lifetime.
E.g. https://www.rfc-editor.org/rfc/rfc4861#section-12

@yuwata yuwata merged commit 2ccada8 into systemd:main Oct 3, 2022
@tchebb tchebb deleted the fix-ndisc-invalidation branch October 3, 2022 02:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

None yet

2 participants