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

Support ipv6 for masquerade and dnat in nspawn and networkd #18007

Merged
merged 5 commits into from Feb 16, 2021

Conversation

fw-strlen
Copy link

This extends the nft backend to also support IPv6.
networkd and nspawn are extended to expose/masquerade the ipv6 address as well.
Masquerade behavior can be returned to ipv4-only mode via "IPMasquerade=ipv4".
This changes the default behaviour; ipv6 addresses are masqueraded and
ipv6 forwarding is enabled.

In the nspawn case, there is currently no way to turn off the ipv6 dnat exposure;
ideas on syntax to do that welcome.

This would close issue #10254.

Copy link
Member

@poettering poettering left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

quick!

src/shared/firewall-util-nft.c Outdated Show resolved Hide resolved
src/shared/firewall-util-nft.c Outdated Show resolved Hide resolved
src/shared/firewall-util-nft.c Outdated Show resolved Hide resolved
src/shared/firewall-util-nft.c Show resolved Hide resolved
src/shared/firewall-util-nft.c Show resolved Hide resolved
src/nspawn/nspawn-expose-ports.c Outdated Show resolved Hide resolved
src/nspawn/nspawn-expose-ports.c Outdated Show resolved Hide resolved
src/network/networkd-address.c Outdated Show resolved Hide resolved
src/network/networkd-address.c Outdated Show resolved Hide resolved
src/network/networkd-network-gperf.gperf Outdated Show resolved Hide resolved
@poettering poettering added the reviewed/needs-rework 🔨 PR has been reviewed and needs another round of reworks label Dec 17, 2020
@bluca bluca added needs-review and removed reviewed/needs-rework 🔨 PR has been reviewed and needs another round of reworks labels Dec 17, 2020
@bluca
Copy link
Member

bluca commented Dec 17, 2020

semaphore CI has a package build failure in nss which looks like a transient issue, and mkosi as well looks like some transient repository metadata issue (kicked the latter, don't have permission/see a button to kick the former)

Copy link
Member

@yuwata yuwata left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better to split out the address handling for start and end in nft_message_add_setelem_ip6range(), and add several tests for that.

src/shared/firewall-util-nft.c Outdated Show resolved Hide resolved
@@ -53,6 +53,30 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_link_local_address_family, link_local_addr
AddressFamily, "Failed to parse option");
DEFINE_STRING_TABLE_LOOKUP(dhcp_lease_server_type, sd_dhcp_lease_server_type);

int config_parse_address_family (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use DEFINE_CONFIG_PARSE_ENUM() macro.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will get rid of this completely, looks like folks don't want auto-masquerade for ipv6 after all.

src/shared/firewall-util-nft.c Show resolved Hide resolved
src/shared/firewall-util-nft.c Show resolved Hide resolved
src/shared/firewall-util-nft.c Show resolved Hide resolved
src/shared/firewall-util-nft.c Outdated Show resolved Hide resolved
src/shared/firewall-util-nft.c Show resolved Hide resolved
@yuwata yuwata added nspawn reviewed/needs-rework 🔨 PR has been reviewed and needs another round of reworks labels Dec 18, 2020
src/shared/firewall-util-nft.c Outdated Show resolved Hide resolved
src/shared/firewall-util-nft.c Show resolved Hide resolved
@andir
Copy link
Contributor

andir commented Dec 25, 2020

I am not sure defaulting to masquerade IPv6 traffic is a sensible choice when set to true. In most cases you will have plenty of addresses and no need for that on IPv6. This should be two options. One for v4 and one for v6. IPv6Masquerade must default to off.

@mweinelt
Copy link

I agree that defaulting to IPv6 NAT when coming from older versions of systemd is highly undesirable.

@poettering
Copy link
Member

I am not sure defaulting to masquerade IPv6 traffic is a sensible choice when set to true. In most cases you will have plenty of addresses and no need for that on IPv6. This should be two options. One for v4 and one for v6. IPv6Masquerade must default to off.

Hmm, I am not entirely sure I agree. ip masquerading isn't just about having too few addresses. It's also about hiding stuff behind a single IP address, i.e. abstracting the used backend routing from the frontend. I'd argue that's totally ok as a reason to have it....

That said, I see the compat problem: so far people assumed "yes" means only "ipv4" here. i.e. i figure i'd be fine if "yes" means "ipv4" here, and to get the behaviour on both ipv4 and ipv6 people should specify "both" here, or so?

Requires special mentioning in the docs, since this is different from other cases of ipv4/ipv6 bools...

@andir
Copy link
Contributor

andir commented Jan 5, 2021

I am not sure defaulting to masquerade IPv6 traffic is a sensible choice when set to true. In most cases you will have plenty of addresses and no need for that on IPv6. This should be two options. One for v4 and one for v6. IPv6Masquerade must default to off.

Hmm, I am not entirely sure I agree. ip masquerading isn't just about having too few addresses. It's also about hiding stuff behind a single IP address, i.e. abstracting the used backend routing from the frontend. I'd argue that's totally ok as a reason to have it....

I am not arguing that having the option to do so is bad. I also use S- & DNAT for some IPv6 setups. And while there are uses for this (e.g. in nspawn when you do not have a subnet available or would rather not use it)

My point is that this is absolutely unexpected to see this happen as part of the IPMasquerade option after upgrading the system.

That said, I see the compat problem: so far people assumed "yes" means only "ipv4" here. i.e. i figure i'd be fine if "yes" means "ipv4" here, and to get the behaviour on both ipv4 and ipv6 people should specify "both" here, or so?

Requires special mentioning in the docs, since this is different from other cases of ipv4/ipv6 bools...

Why not rename IPMasquerade to IPv4Masquerade and add a new option for the IPv6 equivalent? This would remove any kind of upgrade woes and also fix the terminology used within networkd.

@poettering
Copy link
Member

Why not rename IPMasquerade to IPv4Masquerade and add a new option for the IPv6 equivalent? This would remove any kind of upgrade woes and also fix the terminology used within networkd.

well, we usually avoid having two settings if they control the same stuff just for the two protos. I think we should stick to that, even if we now say that in some very exceptional cases "yes" only means "ipv4" instead of "ipv4+ipv6" like it usually does

@yuwata yuwata added needs-review and removed needs-rebase reviewed/needs-rework 🔨 PR has been reviewed and needs another round of reworks labels Jan 19, 2021
@fw-strlen
Copy link
Author

New version:

  • factor out part of ipv6 nft code to add test cases for the range element creation.
  • keep IPMasquerade=yes behavior: its same as IPMasquerade=ipv4. IPMasquerade=both will enable ipv4 and ipv6, =ipv6 just ipv6 masquerade.
  • nspawn still exposes ipv6 automatically.

src/shared/firewall-util-nft.c Outdated Show resolved Hide resolved
man/systemd.network.xml Outdated Show resolved Hide resolved
src/network/networkd-address.c Outdated Show resolved Hide resolved
src/test/test-firewall-util.c Outdated Show resolved Hide resolved
src/test/test-firewall-util.c Outdated Show resolved Hide resolved
src/test/test-firewall-util.c Outdated Show resolved Hide resolved
@poettering poettering added reviewed/needs-rework 🔨 PR has been reviewed and needs another round of reworks and removed needs-review labels Jan 19, 2021
closely mirrors the existing ipv4 ruleset:
table ip6 io.systemd.nat {
        set masq_saddr {
                type ipv6_addr
                flags interval
        }

        map map_port_ipport {
                type inet_proto . inet_service : ipv6_addr . inet_service
        }

        chain prerouting {
                type nat hook prerouting priority dstnat + 1; policy accept;
                fib daddr type local dnat ip6 addr . port to meta l4proto . th dport map @map_port_ipport
        }

        chain output {
                type nat hook output priority -99; policy accept;
                ip6 daddr != ::1 oif "lo" dnat ip6 addr . port to meta l4proto . th dport map @map_port_ipport
        }

        chain postrouting {
                type nat hook postrouting priority srcnat + 1; policy accept;
                ip6 saddr @masq_saddr masquerade
        }
}

Only difference is the use of ipv6 addresses instead of ipv4 ones.

Currently has no effect: all in-tree callers pass AF_INET exclusively.
Followup patches will make nspawn expose ipv6 too and rework
IPMasquerade option to support both/v4/v6.
Florian Westphal added 4 commits January 19, 2021 16:22
Extend nspawn so it can keep track of one ipv4 and one ipv6 address.
Extend IPMasquerade to also cover ipv6.
For compatibility reasons with earlier releases IPMasquerade=yes
is identical to IPMasquerade=ipv4.

Use IPMasquerade=both to cover ipv6 as well as ipv4.

IPForward will now also enable ipv6 forwarding if IPMasquerade for ipv6 is enabled.
In case external entity wiped the ruleset, we need to clear the
'previous' address -- its already gone.

This prevents the transaction from succeeding: the delete operation fails.
The nft set backend doesn't support network masks, it works with
ranges.  Inputs like dead::/64 thus need to be translated to two
'start' and 'end' elements.

The 'start' element is the first element in the range (i.e., dead::).
The 'stop' element is the first element *past* the range, (dead:0:0100::
in the example).

This adds a few test cases.
@yuwata yuwata added needs-review and removed reviewed/needs-rework 🔨 PR has been reviewed and needs another round of reworks labels Jan 19, 2021
Base automatically changed from master to main January 21, 2021 11:55
@poettering
Copy link
Member

lgtm

@yuwata
Copy link
Member

yuwata commented Feb 17, 2021

@fw-strlen I am sorry that I forgot to review this. I created two follow-up PRs. PTAL.

@keszybz
Copy link
Member

keszybz commented Feb 17, 2021

I know I'm late to the party, but I'm not convinced the decision to make "yes"=="ipv4" good long term. I understand backwards compat is important, but I'd expect most people want to do both if they want at least one. (Or at least in a majority of simple cases where you just turn on masquerading without any additional configuration.) I think we should start emitting a warning if "yes" is used, to move people off the option with surprising semantics.

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.

systemd-nspawn should support IPv6 too for exposing ports (currently it only does ipv4)
7 participants