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/.$//')" > } > > > > 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 > -- Michael H. Warfield (AI4NB) | (770) 978-7061 | m...@wittsend.com /\/\|=mhw=|\/\/ | (678) 463-0932 | http://www.wittsend.com/mhw/ NIC whois: MHW9 | An optimist believes we live in the best of all PGP Key: 0x674627FF | possible worlds. A pessimist is sure of it!
signature.asc
Description: This is a digitally signed message part
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel