opnsense / core

OPNsense GUI, API and systems backend
https://opnsense.org/
BSD 2-Clause "Simplified" License
3.24k stars 723 forks source link

Automatic IPv6 link-local address can break DHCPv6 for spoofed MAC address on WAN connection #4430

Open tlschroe opened 3 years ago

tlschroe commented 3 years ago

Important notices

Before you add a new report, we ask you kindly to acknowledge the following:

[X] I have read the contributing guide lines at https://github.com/opnsense/core/blob/master/CONTRIBUTING.md

[X] I have searched the existing issues and I'm convinced that mine is new.

Describe the bug

IPv6 had never worked under OPNsense with my ISP on my WAN interface with a spoofed MAC address, but a connected PC could get an IPv6 address.

As configured, the kernel will automatically generate an IPv6 link-local address for an interface when it is brought up.

For the Realtek re driver and likely others, the generated link-local address is derived from the permanent burned-in MAC address of the card.

The DHCPv6 server at my ISP (Comcast) appears to check to see if the MAC address from a DHCPv6 packet matches the link-local address of the IPv6 message within the packet.

If they don't match, the DHCPv6 server won't reply.

For a spoofed/cloned MAC address, they will never match.

To Reproduce

Observed behavior is very likely to be ISP dependent.

ifconfig of an interface with a spoofed MAC will show the spoofed MAC and automatically-generated link-local address. RFC 4682 (or multiple online calculators) will convert between MAC address and link-local address and demonstrate the mismatch.

Expected behavior

The link-local address of the interface should match the spoofed MAC address of the interface to prevent a failure of DHCPv6. Alternately and ideally, a randomized RFC 4941 link-local address should be used to prevent the leakage of MAC addresses and bypass this type of checking.

Screenshots

Relevant log files

Additional context

Performed a packet capture on a live WAN connection with a spoofed MAC address. It was actively sending DHCPv6 solicit messages, but not seeing any responses. Used ifconfig to manually delete the automatically-generated link-local address and added a new link-local address that was generated from the spoofed MAC address per RFC 4682. Received a response almost instantly.

For a workaround:

System -> Settings -> Tunables: net.inet6.ip6.auto_linklocal = 0

Interfaces -> Virtual IPs -> Settings: The link-local address that was calculated from my spoofed MAC address was added to the WAN interface with a /64 mask.

Rebooted and everything worked.

Environment

Testing was performed on 20.7.3-amd64, but issue with DHCPv6, spoofed MAC, and my ISP has existed since I started using OPNsense several years ago.

AdSchellevis commented 3 years ago

At a first glance I expect this to be more a subject for the docs, usually we trust the kernel to add the correct link-local, which obviously doesn't change anymore after setting a new mac.

Just for reference, the spoofed-mac addresses are added here:

https://github.com/opnsense/core/blob/a4bcbd5a92fa381c0f5e4f26990dabd21606c084/src/etc/inc/interfaces.inc#L2412-L2423

I'm just a bit worried for races when trying to reconfigure the link-local, which is correctly why I suspect documentation would be better..

tlschroe commented 3 years ago

If I understand correctly, auto_linklocal can also be enabled/disabled on a per interface basis.

The link-local address that matches the spoofed MAC could then be specified when bringing the interface up.

At the very least, it should be noted in the help text that a spoofed MAC might break DHCPv6.

tlschroe commented 3 years ago

I lied above about my workaround. Everything didn't work. After globally disabling auto_linklocal, my link-local address on my LAN interface also disappeared. I had to add a 2nd Virtual IP with a link-local address for my LAN interface. Otherwise, LAN side machines couldn't get IPv6 addresses.

fichtner commented 3 years ago

This is interesting. Thank you for looking into the details! This has some implications from the ISP but in general we need to assess how the link local is calculated in case we really need to take over generation or provide an override. A few people asked for such things and I think bridges already have a link local toggle for different reason so integration for configure time is not impossible.

I will take a closer look and report back.

Cheers, Franco

AdSchellevis commented 3 years ago

Initially I expected the link-local to be assigned on the physical interfaces at creation, but that doesn't seem to be the case. looking at the bridge configure I think it would have been better to add this generic to interfaces, so move https://github.com/opnsense/core/blob/a4bcbd5a92fa381c0f5e4f26990dabd21606c084/src/etc/inc/interfaces.inc#L380

to somewhere around

https://github.com/opnsense/core/blob/a4bcbd5a92fa381c0f5e4f26990dabd21606c084/src/etc/inc/interfaces.inc#L2399

maybe even after the spoofed mac address, in which case the generation might be correct (initially).

It would require a new toggle on the interface ideally we would phase-out the bridge option in the future (since it's generic), @fichtner what do you think?

fichtner commented 3 years ago

Sure, although a reverse toggle isn’t so helpful. It would be nicer to have a link local override as well then.

Biggest question is if toggle after MAC spoof produces the correct link local. If it does we can split this into a fix and a feature (the feature not being too urgent).

On 24. Oct 2020, at 14:58, Ad Schellevis notifications@github.com wrote:

 Initially I expected the link-local to be assigned on the physical interfaces at creation, but that doesn't seem to be the case. looking at the bridge configure I think it would have been better to add this generic to interfaces, so move https://github.com/opnsense/core/blob/a4bcbd5a92fa381c0f5e4f26990dabd21606c084/src/etc/inc/interfaces.inc#L380

to somewhere around

https://github.com/opnsense/core/blob/a4bcbd5a92fa381c0f5e4f26990dabd21606c084/src/etc/inc/interfaces.inc#L2399

maybe even after the spoofed mac address, in which case the generation might be correct (initially).

It would require a new toggle on the interface ideally we would phase-out the bridge option in the future (since it's generic), @fichtner what do you think?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

fichtner commented 3 years ago

PS: the only thing we should avoid is calculating a valid link local in our code. Slippery slope...

On 24. Oct 2020, at 16:04, Franco Fichtner franco@lastsummer.de wrote:

 Sure, although a reverse toggle isn’t so helpful. It would be nicer to have a link local override as well then.

Biggest question is if toggle after MAC spoof produces the correct link local. If it does we can split this into a fix and a feature (the feature not being too urgent).

On 24. Oct 2020, at 14:58, Ad Schellevis notifications@github.com wrote:

 Initially I expected the link-local to be assigned on the physical interfaces at creation, but that doesn't seem to be the case. looking at the bridge configure I think it would have been better to add this generic to interfaces, so move https://github.com/opnsense/core/blob/a4bcbd5a92fa381c0f5e4f26990dabd21606c084/src/etc/inc/interfaces.inc#L380

to somewhere around

https://github.com/opnsense/core/blob/a4bcbd5a92fa381c0f5e4f26990dabd21606c084/src/etc/inc/interfaces.inc#L2399

maybe even after the spoofed mac address, in which case the generation might be correct (initially).

It would require a new toggle on the interface ideally we would phase-out the bridge option in the future (since it's generic), @fichtner what do you think?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

tlschroe commented 3 years ago

With the Realtek driver and a spoofed MAC, I toggled the interface through the GUI (uncheck enable, save, apply, check enable, save, apply). This did not generate the correct link-local address.

I did not check the interface with ifconfig while it was in the down state to see if it retained the spoofed MAC address.

An override would work for me.

fichtner commented 3 years ago

I meant toggling the ifconfig option. We currently don’t do this and it might be problematic here. If it works that would be nice if it doesn’t this is harder to fix.

On 25. Oct 2020, at 05:26, tlschroe notifications@github.com wrote:

 With the Realtek driver and a spoofed MAC, I toggled the interface through the GUI (uncheck enable, save, apply, check enable, save, apply). This did not generate the correct link-local address.

I did not check the interface with ifconfig while it was in the down state to see if it retained the spoofed MAC address.

An override would work for me.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

tlschroe commented 3 years ago

Thanks for the clarification.

I missed some of the context.

OPNsense-bot commented 3 years ago

This issue has been automatically timed-out (after 180 days of inactivity).

For more information about the policies for this repository, please read https://github.com/opnsense/core/blob/master/CONTRIBUTING.md for further details.

If someone wants to step up and work on this issue, just let us know, so we can reopen the issue and assign an owner to it.

fichtner commented 3 months ago

From https://github.com/opnsense/core/issues/5630:

[...] the kernel says if auto_linklocal is set and the link-local is removed and the interface brought down and up again it will assign a new link-local automatically. I tested this with a faked ether MAC address and it does indeed use faked one rather than the original hwaddr MAC address. So addressing this loophole in the configuration code should be easy enough when a new MAC address needs to be set. I don't see a big need for removing auto_linklocal. It's just not going to end well. The bridge is a special case where it't not on by default so the option was added there to enable a defined use case.

fichtner commented 3 months ago

@kevinchalet experiment at 20e8126d94

# opnsense-patch 20e8126d94
kevinchalet commented 3 months ago

@kevinchalet experiment at 20e8126

It seems to be working fine on a VLAN interface using a spoofed MAC address (the parent, physical interface is not configured or attached) 👏🏻

(amusingly, I had to wait a bit because Orange ignores ICMP router solicitations if you don't use the same IPv6 LL address as the one used during the previous DHCP dance... 😅)

fichtner commented 3 months ago

@AdSchellevis what‘s your opinion on this?

AdSchellevis commented 3 months ago

@fichtner the down flag in some cases can be a bit annoying, but since it's only set when a manual mac address is provided and changed, I don't expect much issues. It might be good to add a small note about the automatic link-local addition on interface up for future reference.

fichtner commented 3 months ago

@AdSchellevis ok I’ll improve some issues with the code as it is (realhwif vs. realifv6 must ideally be the same and how ifconfig commands can be batched correctly to avoid down in cases where it won’t help) and add that comment next week.

fichtner commented 3 months ago

@kevinchalet a2ac1999f37e should do the trick for you

@AdSchellevis the change that landed also now resets the MAC address when the spoofmac field is cleared. I thought that would probably make sense... :)

kevinchalet commented 3 months ago

Seems to be working fine, @fichtner! 👍🏻

AdSchellevis commented 3 months ago

@fichtner it looks consistent, thanks

kevinchalet commented 1 month ago

Hey,

Looks like https://github.com/opnsense/core/commit/afe9c107665b3fb6a5f9167bf60e7399b0f06957 reverted this change in 24.7 (don't ask me how I discovered it 🤣).

Do you plan on revisiting it in the next version?

Cheers.

fichtner commented 1 month ago

Yes, revert was the safer option for initial 24.7 as it was overzealous with LAGG interfaces zeroing their MAC address. Don’t ask me how I know either 😉

Master has a different fix to retain the new behaviour for eventual 24.7.x release.

kevinchalet commented 1 month ago

Master has a different fix to retain the new behaviour for eventual 24.7.x release.

Ah, nice, thanks! I can indeed see you added a $mac_next !== '00:00:00:00:00:00' in master. Is that the only change?

If it's too fragile, maybe it could be a dedicated option, something like a "link-local IPv6 override address setting" that is separate from the spoofed MAC address field?

fichtner commented 1 month ago

It should be good now. I don’t see why LAGGs wants everyone to think their original address is all zeroes. Technically makes sense, practically not so much. This should be a one off case.

fichtner commented 1 month ago

And yes that conditional is the only change.

kevinchalet commented 1 month ago

And yes that conditional is the only change.

Great. I'll update my local copy and see how it goes 😃

Cheers.

kevinchalet commented 2 weeks ago

Hey,

Hope you're doing well, @fichtner 🫡

Master has a different fix to retain the new behaviour for eventual 24.7.x release.

Any idea when that fix could land in a 24.7.x branch? 😃 Patching isn't painful in itself, but every time an OPNsense update requires a reboot (like the last 2 patches), a DHCP request with the non-spoofed address is sent to my ISP once the box comes back to life and my ISP ends up - temporarily - ignoring all requests due to that mismatch (even if you re-apply the patch immediately and send a DHCP request with the old, spoofed address).

All the best.

fichtner commented 2 weeks ago

Hey Kevin,

sorry, @AdSchellevis and me agreed to test this once more before shipping but I think the testing part was not done. It’s been too busy lately.

cheers, Franco

kevinchalet commented 2 weeks ago

No worries, @fichtner! Thanks for letting me know 👍🏻

AdSchellevis commented 1 week ago

@fichtner doublechecked the lagg on my end it this seems to work fine now, patched the following on top of 24.7.3:

opnsense-patch afe9c10 7669567
kevinchalet commented 1 week ago

Don't you think it would be safer to introduce a separate "link-local address override" option for that? Just in case someone wouldn't want the link-local address to match the MAC or would prefer a specific address.

fichtner commented 1 week ago

People can just use a specific LL VIP if they want. :)

kevinchalet commented 1 week ago

Makes sense, but I'm fairly sure I tried that a while ago and it didn't work as I was expecting (maybe because the DHCP request was made before the VIP had a chance to be set?)

fichtner commented 1 week ago

First VIP wins worst case perhaps. A toggle for disabling AUTO_LINKLOCAL may be useful, but I'd like to see someone explain this use case first before doing random solutions to problems nobody has.

Cheers, Franco

kevinchalet commented 1 week ago

Sounds reasonable 😄