BastilleBSD / bastille

Bastille is an open-source system for automating deployment and management of containerized applications on FreeBSD.
https://bastillebsd.org
BSD 3-Clause "New" or "Revised" License
848 stars 132 forks source link

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

Open itz-Jana opened 1 month ago

itz-Jana commented 1 month ago

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. https://github.com/BastilleBSD/bastille/blob/cee6f20aa5c228e7e4791bc9d0fcdc412bab71ae/usr/local/share/bastille/common.sh#L101-L107

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

tschettervictor commented 2 weeks ago

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 commented 2 weeks ago

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 commented 2 weeks ago

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 commented 2 weeks ago

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 commented 2 weeks ago

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 commented 2 weeks ago

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 commented 2 weeks ago

Looking forward to it.

tschettervictor commented 2 weeks ago

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 commented 2 weeks ago

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.

https://github.com/BastilleBSD/bastille/blob/cee6f20aa5c228e7e4791bc9d0fcdc412bab71ae/usr/local/share/bastille/common.sh#L101-L107

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 commented 2 weeks ago

@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 commented 2 weeks ago

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

tschettervictor commented 1 week ago

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 commented 1 week ago

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