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

[ENHANCEMENT] Allow for jails with static MAC addresses #716

Open
itz-Jana opened this issue Aug 27, 2024 · 13 comments
Open

[ENHANCEMENT] Allow for jails with static MAC addresses #716

itz-Jana opened this issue Aug 27, 2024 · 13 comments
Labels
enhancement New feature or request

Comments

@itz-Jana
Copy link

Is your feature request related to a problem? Please describe.
I'm trying to setup a FreeBSD host with jails that only has IPv6 and auto-configures every IP with SLAAC, so that I don't have to do any manual work on that front.

I have a mostly working configuration, the only remaining issue is that every time the jail is re-started the epair that connects it to my existing bridge (-B) is re-created and thus receives a new MAC address and thus different IPv6 addresses.

vnet.interface = "e${uniq_epair_bridge}b_${jail_name}";
exec.prestart += "ifconfig epair${uniq_epair_bridge} create";
exec.prestart += "ifconfig ${external_interface} addm epair${uniq_epair_bridge}a";
exec.prestart += "ifconfig epair${uniq_epair_bridge}a up name e${uniq_epair_bridge}a_${jail_name}";
exec.prestart += "ifconfig epair${uniq_epair_bridge}b up name e${uniq_epair_bridge}b_${jail_name}";
exec.poststop += "ifconfig ${external_interface} deletem e${uniq_epair_bridge}a_${jail_name}";
exec.poststop += "ifconfig e${uniq_epair_bridge}a_${jail_name} destroy";

Describe the solution you'd like
I would like there to be a way to have the MAC addresses of the jails be static.

I can imagine this could either be solved by only creating the epair once at jail creation time, but that would cause epairs of stopped jails to linger.

Or by generating a MAC address once at creation and saved in the config, such that it can always be re-assigned to the epair at start, something like this (though I don't know how one would generate a sufficiently random MAC):

exec.prestart += "ifconfig epair${uniq_epair_bridge}a ether 02:de:ad:be:ef:0a";
exec.prestart += "ifconfig epair${uniq_epair_bridge}b ether 02:de:ad:be:ef:0b";

I don't know if either of these options is the smartest way to solve this, so I'm very much looking for suggestions.
I am very new to BastilleBSD and FreeBSD in general, so I might be missing something obvious here.

Describe alternatives you've considered
I have considered using the -V option to have Bastille create the Bridge by itself, because from what I could tell that uses a different method to connect the jails to the bridge (?).

But that doesn't work, because then I need to have my host IP on the physical interface, instead of the bridge and thus my jails can't communicate with the host (which I need).
And it doesn't seem like a good idea for me to interfere with the Bastille generated bridge interface to move my host IP onto that.

Additional context

@itz-Jana itz-Jana added the enhancement New feature or request label Aug 27, 2024
@tschettervictor
Copy link

tschettervictor commented Oct 5, 2024

Isn’t the MAC address created by somehow randomizing it based on the jail name?

In iocage, every time I make a jail named “jail1” the MAC address is always the same using a VNET jail.

Also, the standard way of doing jails is to create a bridge on the host (bridge0 or similar) then have the host IP on the bridge, and not on the physical interface. Then in Bastille use the -B option along with bridge0 as the interface it uses.

@itz-Jana
Copy link
Author

itz-Jana commented Oct 5, 2024

Isn’t the MAC address created by somehow randomizing it based on the jail name?

In iocage, every time I make a jail named “jail1” the MAC address is always the same using a VNET jail.

No, not the case here.

Also, the standard way of doing jails is to create a bridge on the host (bridge0 or similar) then have the host IP on the bridge, and not on the physical interface. Then in Bastille use the -B option along with bridge0 as the interface it uses.

Yup, I figure that out as well by now, and it makes sense. Yet the epair that bastille creates to connect to the bridge has a different MAC every jail restart.

@tschettervictor
Copy link

Let me play with my setup. I was sure my jails started with a static MAC as I do mac filtering on our network.

@tschettervictor
Copy link

Yes you are right, and that is a bad design IMO. The jail should retain it's MAC address unless it is deleted. This can either be by setting the MAC based on the name, or doing it like you mentioned above.

BastilleBSD is unusable with the current status for me anyway.

@tschettervictor
Copy link

Will have to look into CBSD for this feature. Have you tested that?

I know iocage retains the MAC based on the jail name.

@JRGTH
Copy link
Collaborator

JRGTH commented Oct 7, 2024

Hello, I believe the randomized MAC feature was added on purpose for enhanced security, but indeed we can add an user option to opt for a static MAC instead.

@tschettervictor
Copy link

Looking forward to it.

@tschettervictor
Copy link

Would it be better to have the opt in be for the random MAC or static MAC?

I’d say having it static should be the default for identification purposes.

@tschettervictor
Copy link

tschettervictor commented Oct 8, 2024

Is your feature request related to a problem? Please describe. I'm trying to setup a FreeBSD host with jails that only has IPv6 and auto-configures every IP with SLAAC, so that I don't have to do any manual work on that front.

I have a mostly working configuration, the only remaining issue is that every time the jail is re-started the epair that connects it to my existing bridge (-B) is re-created and thus receives a new MAC address and thus different IPv6 addresses.

vnet.interface = "e${uniq_epair_bridge}b_${jail_name}";
exec.prestart += "ifconfig epair${uniq_epair_bridge} create";
exec.prestart += "ifconfig ${external_interface} addm epair${uniq_epair_bridge}a";
exec.prestart += "ifconfig epair${uniq_epair_bridge}a up name e${uniq_epair_bridge}a_${jail_name}";
exec.prestart += "ifconfig epair${uniq_epair_bridge}b up name e${uniq_epair_bridge}b_${jail_name}";
exec.poststop += "ifconfig ${external_interface} deletem e${uniq_epair_bridge}a_${jail_name}";
exec.poststop += "ifconfig e${uniq_epair_bridge}a_${jail_name} destroy";

Describe the solution you'd like I would like there to be a way to have the MAC addresses of the jails be static.

I can imagine this could either be solved by only creating the epair once at jail creation time, but that would cause epairs of stopped jails to linger.

Or by generating a MAC address once at creation and saved in the config, such that it can always be re-assigned to the epair at start, something like this (though I don't know how one would generate a sufficiently random MAC):

exec.prestart += "ifconfig epair${uniq_epair_bridge}a ether 02:de:ad:be:ef:0a";
exec.prestart += "ifconfig epair${uniq_epair_bridge}b ether 02:de:ad:be:ef:0b";

I don't know if either of these options is the smartest way to solve this, so I'm very much looking for suggestions. I am very new to BastilleBSD and FreeBSD in general, so I might be missing something obvious here.

Describe alternatives you've considered I have considered using the -V option to have Bastille create the Bridge by itself, because from what I could tell that uses a different method to connect the jails to the bridge (?).

But that doesn't work, because then I need to have my host IP on the physical interface, instead of the bridge and thus my jails can't communicate with the host (which I need). And it doesn't seem like a good idea for me to interfere with the Bastille generated bridge interface to move my host IP onto that.

Additional context

Reading through the code of iocage, it looks like it uses the first half of the host MAC (to avoid clashes on the network) then generates a random second half (HEX format) for epair(a) and simply adds +1 for epair(b)

Your solution does work, but one has to do manual work for each and every jail if you want static MACs assigned to them.

Simple Implementaion would probably be similar to

#!/bin/sh

# Get the first half of the host's MAC address
HOST_MAC=$(ifconfig bridge0 | grep ether | awk '{print $2}')
FIRST_HALF=$(echo $HOST_MAC | cut -d':' -f1-3)

# Generate a random second half and remove trailing :
RANDOM_MAC=$(hexdump -n 3 -e '/1 "%02x:"' /dev/urandom | sed 's/:$//')

# Combine the two halves
STATIC_MAC="${FIRST_HALF}:${RANDOM_MAC}"

# Output the static MAC address
echo "Generated static MAC address for jail: $STATIC_MAC"

I would hash the name or the jail, so that the mac will persist across jail destroy/rebuild commands.

@tschettervictor
Copy link

tschettervictor commented Oct 8, 2024

@JRGTH @itz-Jana

I added a PR to support this. It is 6 additional lines of code, and works great for me so far. Let me know what you think.
#723

It basically just adds an "ether" option (generated from the jail name hash) as above. This is all that iocage does. The "hwaddress" is always random, but that is not what is used by the jail to access your network.

I tested with -B and -V and got a static MAC on reboot and jail rebuild also.

@itz-Jana
Copy link
Author

itz-Jana commented Oct 9, 2024

Amazing! Didn't think a solution could be this simple. I'm going to give it a try today.

@tschettervictor
Copy link

I’m testing some more. The clone function doesn’t actually allow for cloning a bridged jail. I’ve got a working prototype that supports it. Will probably open a PR with it once I’m done.

@tschettervictor
Copy link

I've updated the PR #725
Cloning was broken for VNET bridged jails, so I fixed that.

With the code included in the two files 'common.sh' and 'clone.sh' functionality now includes

  • static mac for VNET jails
  • cloning VNET jails and properly update corresponding 'rc.conf' and 'jail.conf'
  • generate new static MAC for cloned jails

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants