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 <m...@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@lists.linuxcontainers.org >>> http://lists.linuxcontainers.org/listinfo/lxc-devel >>> >> _______________________________________________ >> lxc-devel mailing list >> lxc-devel@lists.linuxcontainers.org >> http://lists.linuxcontainers.org/listinfo/lxc-devel >> > > > _______________________________________________ > lxc-devel mailing list > lxc-devel@lists.linuxcontainers.org > http://lists.linuxcontainers.org/listinfo/lxc-devel _______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel