[lxc-devel] [PATCH] CentOS and Fedora Templates: Harden root passwords and add static MAC network addresses.
lxc at zitta.fr
lxc at zitta.fr
Mon Jan 13 19:24:10 UTC 2014
Le 13/01/2014 20:09, Michael H. Warfield a écrit :
> On Mon, 2014-01-13 at 18:13 +0200, Marian Marinov wrote:
>> On 12/27/2013 01:08 AM, Michael H. Warfield wrote:
>>> CentOS and Fedora Templates: Harden root passwords and add static MAC network addresses.
>>>
>>> 1) Add logic to root password setting. Root password is now set to
>>> "Root-${name}-${RANDOM} to defeat common brute force scans.
>>> 2) Enhance exit messages to explain root password and password changing.
>>> 3) Add random generated hwaddr (MAC) entires for any network interfaces
>>> in default config copied to container.
>> I'm using both the fedora and centos templates and having a static MAC is a problem.
>> I have replaced static MAC with $(gen_mac) shell function.
>> function gen_mac() {
>> mac_vars=(0 1 2 3 4 5 6 7 8 9 a b c d e f)
>> mac_base='52:53:54:'
> Forgot to mention... I don't know where you got the 52:53:54 prefix
> from (02: bit is set so it's a "locally managed" address and it doesn't
> matter all that much) but we seem to have settled in on MAC addresses
> with the upper octet of fe: (which is also locally managed). That's
> what I've been coding into my generation routines and that's what's been
> added to some of the C code by others.
>
>> ret=''
>> for i in {1..6}; do
>> n=$RANDOM
>> let 'n %= 16'
>> ret="${ret}${mac_vars[$n]}"
>> if [ $i -eq 2 ] || [ $i -eq 4 ]; then
>> ret="${ret}:"
>> fi
>> done
>> echo "${mac_base}${ret}"
>> }
>>
>> There is also another variant of this function:
>> function gen_mac() {
>> echo "52:53:54:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')"
>> }
Hi,
There is a recent (today) patch to manage this natively in lxc-create.
https://github.com/lxc/lxc/commit/508c263ee6ed2fac73f6979af287caba38963b4b
I think templates should drop this kind of tricky feature and let
lxc-create do it.
Or at least, it should warn if a NIC don't have an hwaddr and route user to
the lxc.network.hwaddr entry in lxc.conf man page
>>
>>> 4) Add shell variable expansion of default config.
>>> 5) Cross patch templates to bring them more into coherence with each other.
>>>
>>> Signed-off-by: Michael H. Warfield <mhw at WittsEnd.com>
>>> ---
>>> templates/lxc-centos.in | 114 +++++++++++++++++++++++++++++++++++++-----------
>>> templates/lxc-fedora.in | 99 +++++++++++++++++++++++++++++++++++++----
>>> 2 files changed, 180 insertions(+), 33 deletions(-)
>>>
>>> diff --git a/templates/lxc-centos.in b/templates/lxc-centos.in
>>> index 7d47715..5bb5349 100644
>>> --- a/templates/lxc-centos.in
>>> +++ b/templates/lxc-centos.in
>>> @@ -33,6 +33,7 @@ default_path=@LXCPATH@
>>> # We really need something better here!
>>> root_password=root
>>>
>>> +# These are only going into comments in the resulting config...
>>> lxc_network_type=veth
>>> lxc_network_link=lxcbr0
>>>
>>> @@ -256,8 +257,10 @@ EOF
>>> mknod -m 600 ${dev_path}/initctl p
>>> mknod -m 666 ${dev_path}/ptmx c 5 2
>>>
>>> - echo "setting root passwd to $root_password"
>>> + echo "Setting root passwd to '$root_password'"
>>> echo "root:$root_password" | chroot $rootfs_path chpasswd
>>> + # Also set this password as expired to force the user to change it!
>>> + chroot $rootfs_path passwd -e root
>>>
>>> # This will need to be enhanced for CentOS 7 when systemd
>>> # comes into play... /\/\|=mhw=|\/\/
>>> @@ -374,6 +377,7 @@ copy_centos()
>>> # i prefer rsync (no reason really)
>>> mkdir -p $rootfs_path
>>> rsync -a $cache/rootfs/ $rootfs_path/
>>> + echo
>>> return 0
>>> }
>>>
>>> @@ -428,28 +432,71 @@ install_centos()
>>> return $?
>>> }
>>>
>>> -copy_configuration()
>>> +create_hwaddr()
>>> {
>>> + echo $(dd if=/dev/urandom bs=8 count=1 2>/dev/null | md5sum
>>> + | sed -e 's/\(..\)\(..\)\(..\)\(..\)\(..\).*/fe:\1:\2:\3:\4:\5/')
>>> +}
>>>
>>> +copy_configuration()
>>> +{
>>> mkdir -p $config_path
>>> +
>>> + grep -q "^lxc.rootfs" $config_path/config 2>/dev/null || echo "
>>> +lxc.rootfs = $rootfs_path
>>> +" >> $config_path/config
>>> +
>>> + # The following code is to create static MAC addresses for each
>>> + # interface in the container. This code will work for multiple
>>> + # interfaces in the default config.
>>> + mv $config_path/config $config_path/config.def
>>> + while read LINE
>>> + do
>>> + # This should catch variable expansions from the default config...
>>> + if expr "${LINE}" : '.*\$' > /dev/null 2>&1
>>> + then
>>> + LINE=$(eval "echo \"${LINE}\"")
>>> + fi
>>> +
>>> + # There is a tab and a space in the regex bracket below!
>>> + # Seems that \s doesn't work in brackets.
>>> + KEY=$(expr $LINE : '\s*\([^ ]*\)\s*=')
>>> +
>>> + if [[ "${KEY}" != "lxc.network.hwaddr" ]]
>>> + then
>>> + echo ${LINE} >> $config_path/config
>>> +
>>> + if [[ "${KEY}" == "lxc.network.link" ]]
>>> + then
>>> + echo "lxc.network.hwaddr = $(create_hwaddr)" >> $config_path/config
>>> + fi
>>> + fi
>>> + done < $config_path/config.def
>>> +
>>> + rm -f $config_path/config.def
>>> +
>>> cat <<EOF >> $config_path/config
>>> lxc.utsname = $utsname
>>> lxc.tty = 4
>>> lxc.pts = 1024
>>> -lxc.rootfs = $rootfs_path
>>> -lxc.mount = $config_path/fstab
>>> +lxc.mount = $config_path/fstab
>>> lxc.cap.drop = sys_module mac_admin mac_override sys_time
>>>
>>> lxc.autodev = $auto_dev
>>>
>>> +# When using LXC with apparmor, uncomment the next line to run unconfined:
>>> +#lxc.aa_profile = unconfined
>>> +
>>> # example simple networking setup, uncomment to enable
>>> #lxc.network.type = $lxc_network_type
>>> #lxc.network.flags = up
>>> #lxc.network.link = $lxc_network_link
>>> #lxc.network.name = eth0
>>> -# additional example for veth network type, static MAC address,
>>> -# and persistent veth device name on host side
>>> +# Additional example for veth network type
>>> +# static MAC address,
>>> #lxc.network.hwaddr = 00:16:3e:77:52:20
>>> +# persistent veth device name on host side
>>> +# Note: This may potentially collide with other containers of same name!
>>> #lxc.network.veth.pair = v-$name-e0
>>>
>>> #cgroups
>>> @@ -460,8 +507,6 @@ lxc.cgroup.devices.allow = c 1:5 rwm
>>> # consoles
>>> lxc.cgroup.devices.allow = c 5:1 rwm
>>> lxc.cgroup.devices.allow = c 5:0 rwm
>>> -lxc.cgroup.devices.allow = c 4:0 rwm
>>> -lxc.cgroup.devices.allow = c 4:1 rwm
>>> # /dev/{,u}random
>>> lxc.cgroup.devices.allow = c 1:9 rwm
>>> lxc.cgroup.devices.allow = c 1:8 rwm
>>> @@ -473,13 +518,12 @@ EOF
>>>
>>> cat <<EOF > $config_path/fstab
>>> proc proc proc nodev,noexec,nosuid 0 0
>>> -devpts dev/pts devpts defaults 0 0
>>> sysfs sys sysfs defaults 0 0
>>> EOF
>>>
>>> if [ $? -ne 0 ]; then
>>> - echo "Failed to add configuration"
>>> - return 1
>>> + echo "Failed to add configuration"
>>> + return 1
>>> fi
>>>
>>> return 0
>>> @@ -489,22 +533,21 @@ clean()
>>> {
>>>
>>> if [ ! -e $cache ]; then
>>> - exit 0
>>> + exit 0
>>> fi
>>>
>>> # lock, so we won't purge while someone is creating a repository
>>> (
>>> - flock -x 200
>>> - if [ $? != 0 ]; then
>>> - echo "Cache repository is busy."
>>> - exit 1
>>> - fi
>>> -
>>> - echo -n "Purging the download cache for centos-$release..."
>>> - rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
>>> - exit 0
>>> + flock -x 200
>>> + if [ $? != 0 ]; then
>>> + echo "Cache repository is busy."
>>> + exit 1
>>> + fi
>>>
>>> - ) 200>/var/lock/subsys/lxc-centos
>>> + echo -n "Purging the download cache for centos-$release..."
>>> + rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
>>> + exit 0
>>> + ) 200>@LOCALSTATEDIR@/lock/subsys/lxc-centos
>>> }
>>>
>>> usage()
>>> @@ -554,6 +597,12 @@ if [ ! -z "$clean" -a -z "$path" ]; then
>>> exit 0
>>> fi
>>>
>>> +# Let's do something better for the initial root password.
>>> +# It's not perfect but it will defeat common scanning brute force
>>> +# attacks in the case where ssh is exposed. It will also be set to
>>> +# expired, forcing the user to change it at first login.
>>> +root_password=Root-${name}-${RANDOM}
>>> +
>>> if [ -z "${utsname}" ]; then
>>> utsname=${name}
>>> fi
>>> @@ -572,7 +621,7 @@ fi
>>> # utsname and hostname = Container_Name.Domain_Name
>>>
>>> if [ $(expr "$utsname" : '.*\..*\.') = 0 ]; then
>>> - if [ -n "$(dnsdomainname)" ]; then
>>> + if [[ "$(dnsdomainname)" != "" && "$(dnsdomainname)" != "localdomain" ]]; then
>>> utsname=${utsname}.$(dnsdomainname)
>>> fi
>>> fi
>>> @@ -666,5 +715,20 @@ if [ ! -z $clean ]; then
>>> clean || exit 1
>>> exit 0
>>> fi
>>> -echo "container rootfs and config created, default root password is '$root_password'"
>>> -echo "edit the config file to check/enable networking setup"
>>> +echo "
>>> +Container rootfs and config have been created.
>>> +Edit the config file to check/enable networking setup.
>>> +"
>>> +
>>> +echo "The temporary password for root is: '$root_password'
>>> +
>>> +You may want to note that password down before starting the container.
>>> +
>>> +The password set up as "expired" and will require it to be changed it at
>>> +first login, which you should do as soon as possible. If you lose the
>>> +root password or wish to change it without starting the container, you
>>> +can change it from the host by running the following command (which will
>>> +also reset the expired flag):
>>> +
>>> + chroot ${rootfs_path} passwd
>>> +"
>>> diff --git a/templates/lxc-fedora.in b/templates/lxc-fedora.in
>>> index 5f66ff1..b0c214a 100644
>>> --- a/templates/lxc-fedora.in
>>> +++ b/templates/lxc-fedora.in
>>> @@ -33,6 +33,10 @@ default_path=@LXCPATH@
>>> # We really need something better here!
>>> root_password=root
>>>
>>> +# These are only going into comments in the resulting config...
>>> +lxc_network_type=veth
>>> +lxc_network_link=lxcbr0
>>> +
>>> # is this fedora?
>>> # Alow for weird remixes like the Raspberry Pi
>>> #
>>> @@ -194,8 +198,10 @@ EOF
>>> mknod -m 600 ${dev_path}/initctl p
>>> mknod -m 666 ${dev_path}/ptmx c 5 2
>>>
>>> - echo "setting root passwd to $root_password"
>>> + echo "Setting root passwd to '$root_password'"
>>> echo "root:$root_password" | chroot $rootfs_path chpasswd
>>> + # Also set this password as expired to force the user to change it!
>>> + chroot $rootfs_path passwd -e root
>>>
>>> # specifying this in the initial packages doesn't always work.
>>> # Even though it should have...
>>> @@ -243,7 +249,7 @@ configure_fedora_init()
>>>
>>> configure_fedora_systemd()
>>> {
>>> - unlink ${rootfs_path}/etc/systemd/system/default.target
>>> + rm -f ${rootfs_path}/etc/systemd/system/default.target
>>> touch ${rootfs_path}/etc/fstab
>>> chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/udev.service
>>> chroot ${rootfs_path} ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target
>>> @@ -837,6 +843,7 @@ copy_fedora()
>>> # i prefer rsync (no reason really)
>>> mkdir -p $rootfs_path
>>> rsync -Ha $cache/rootfs/ $rootfs_path/
>>> + echo
>>> return 0
>>> }
>>>
>>> @@ -891,11 +898,53 @@ install_fedora()
>>> return $?
>>> }
>>>
>>> -copy_configuration()
>>> +# Generate a random hardware (MAC) address composed of FE followed by
>>> +# 5 random bytes...
>>> +create_hwaddr()
>>> {
>>> + echo $(dd if=/dev/urandom bs=8 count=1 2>/dev/null | md5sum |
>>> + sed -e 's/\(..\)\(..\)\(..\)\(..\)\(..\).*/fe:\1:\2:\3:\4:\5/')
>>> +}
>>>
>>> +copy_configuration()
>>> +{
>>> mkdir -p $config_path
>>> - grep -q "^lxc.rootfs" $config_path/config 2>/dev/null || echo "lxc.rootfs = $rootfs_path" >> $config_path/config
>>> +
>>> + grep -q "^lxc.rootfs" $config_path/config 2>/dev/null || echo "
>>> +lxc.rootfs = $rootfs_path
>>> +" >> $config_path/config
>>> +
>>> + # The following code is to create static MAC addresses for each
>>> + # interface in the container. This code will work for multiple
>>> + # interfaces in the default config. It will also strip any
>>> + # hwaddr stanzas out of the default config since we can not share
>>> + # MAC addresses between containers.
>>> + mv $config_path/config $config_path/config.def
>>> + while read LINE
>>> + do
>>> + # This should catch variable expansions from the default config...
>>> + if expr "${LINE}" : '.*\$' > /dev/null 2>&1
>>> + then
>>> + LINE=$(eval "echo \"${LINE}\"")
>>> + fi
>>> +
>>> + # There is a tab and a space in the regex bracket below!
>>> + # Seems that \s doesn't work in brackets.
>>> + KEY=$(expr "${LINE}" : '\s*\([^ ]*\)\s*=')
>>> +
>>> + if [[ "${KEY}" != "lxc.network.hwaddr" ]]
>>> + then
>>> + echo "${LINE}" >> $config_path/config
>>> +
>>> + if [[ "${KEY}" == "lxc.network.link" ]]
>>> + then
>>> + echo "lxc.network.hwaddr = $(create_hwaddr)" >> $config_path/config
>>> + fi
>>> + fi
>>> + done < $config_path/config.def
>>> +
>>> + rm -f $config_path/config.def
>>> +
>>> cat <<EOF >> $config_path/config
>>> lxc.utsname = $utsname
>>> lxc.tty = 4
>>> @@ -908,6 +957,18 @@ lxc.autodev = $auto_dev
>>> # When using LXC with apparmor, uncomment the next line to run unconfined:
>>> #lxc.aa_profile = unconfined
>>>
>>> +# example simple networking setup, uncomment to enable
>>> +#lxc.network.type = $lxc_network_type
>>> +#lxc.network.flags = up
>>> +#lxc.network.link = $lxc_network_link
>>> +#lxc.network.name = eth0
>>> +# Additional example for veth network type
>>> +# static MAC address,
>>> +#lxc.network.hwaddr = 00:16:3e:77:52:20
>>> +# persistent veth device name on host side
>>> +# Note: This may potentially collide with other containers of same name!
>>> +#lxc.network.veth.pair = v-$name-e0
>>> +
>>> #cgroups
>>> lxc.cgroup.devices.deny = a
>>> # /dev/null and zero
>>> @@ -929,6 +990,7 @@ EOF
>>> proc proc proc nodev,noexec,nosuid 0 0
>>> sysfs sys sysfs defaults 0 0
>>> EOF
>>> +
>>> if [ $? -ne 0 ]; then
>>> echo "Failed to add configuration"
>>> return 1
>>> @@ -1006,6 +1068,12 @@ if [ ! -z "$clean" -a -z "$path" ]; then
>>> exit 0
>>> fi
>>>
>>> +# Let's do something better for the initial root password.
>>> +# It's not perfect but it will defeat common scanning brute force
>>> +# attacks in the case where ssh is exposed. It will also be set to
>>> +# expired, forcing the user to change it at first login.
>>> +root_password=Root-${name}-${RANDOM}
>>> +
>>> if [ -z "${utsname}" ]; then
>>> utsname=${name}
>>> fi
>>> @@ -1024,7 +1092,7 @@ fi
>>> # utsname and hostname = Container_Name.Domain_Name
>>>
>>> if [ $(expr "$utsname" : '.*\..*\.') = 0 ]; then
>>> - if [ -n "$(dnsdomainname)" ]; then
>>> + if [[ "$(dnsdomainname)" != "" && "$(dnsdomainname)" != "localdomain" ]]; then
>>> utsname=${utsname}.$(dnsdomainname)
>>> fi
>>> fi
>>> @@ -1128,12 +1196,14 @@ if [ ! -z $clean ]; then
>>> clean || exit 1
>>> exit 0
>>> fi
>>> -echo "container rootfs and config created"
>>> +echo "
>>> +Container rootfs and config have been created.
>>> +Edit the config file to check/enable networking setup.
>>> +"
>>>
>>> if [[ -d ${cache_base}/bootstrap ]]
>>> then
>>> - echo "
>>> -You have successfully built a Fedora container and cache. This cache may
>>> + echo "You have successfully built a Fedora container and cache. This cache may
>>> be used to create future containers of various revisions. The directory
>>> ${cache_base}/bootstrap contains a bootstrap
>>> which may no longer needed and can be removed.
>>> @@ -1147,3 +1217,16 @@ This is only used in the creation of the bootstrap run-time-environment
>>> and may be removed.
>>> "
>>> fi
>>> +
>>> +echo "The temporary password for root is: '$root_password'
>>> +
>>> +You may want to note that password down before starting the container.
>>> +
>>> +The password set up as "expired" and will require it to be changed it at
>>> +first login, which you should do as soon as possible. If you lose the
>>> +root password or wish to change it without starting the container, you
>>> +can change it from the host by running the following command (which will
>>> +also reset the expired flag):
>>> +
>>> + chroot ${rootfs_path} passwd
>>> +"
>>>
>>>
>>>
>>> _______________________________________________
>>> lxc-devel mailing list
>>> lxc-devel at lists.linuxcontainers.org
>>> http://lists.linuxcontainers.org/listinfo/lxc-devel
>>>
>> _______________________________________________
>> lxc-devel mailing list
>> lxc-devel at lists.linuxcontainers.org
>> http://lists.linuxcontainers.org/listinfo/lxc-devel
>>
>
>
> _______________________________________________
> lxc-devel mailing list
> lxc-devel at lists.linuxcontainers.org
> http://lists.linuxcontainers.org/listinfo/lxc-devel
More information about the lxc-devel
mailing list