Summary

  Subject:

Create a Linux VM Template

  Updated:

2023-05-12

  Author:

Tim Hammond ([email protected])

Derek Pasnick ([email protected])

  Operating Systems:

Rocky 8

Rocky 9

Ubuntru 20.04

VMware vSphere 7.0

  Background:

This guide was written to prepare a Linux VM for VMware templateing. It is assumed that the engineer knows how to create a vSphere template.

There are several tools out there to create images for cloning. "sys-unconfig" can be run to clear basic configs and run through a new system setup wizard at the next boot. "virt-sysprep" can be programmed to perform 20+ operations. "cloud init" was complete overkill for my needs.

The vast majority of this content is a one time setup for the inital creation of the template. The next time the tempalte needs to be updated, you can start with the "Cleanup - Kernel and bits" section then proceed through the rest of the guide.

 

Table of Contents

VM Config

All Distributions

VM Specifications:

  • CPU: 1vCPU (2 cores)
  • RAM: 2 GB
  • HD: 100 GB

When creating a Rocky 8 VM with hardware version 15, VMware uses a UFEI config with secure boot by default. Keep it simple and use use BIOS.

When creating a Ubuntu 64bit VM with hardware version 15, VMware uses a BIOS config.

VM Hardware Changes

  • Use BIOS. EUFI without secure boot is silly.
  • DO NOT enable CPU hot add (disables numa rules)
  • DO NOT enable RAM hot add (disables numa rules)
  • Remove Floppy drive from hardware
  • Disable COM1
  • Disable COM2
  • Disable Parrallel
  • Disable Floppy

Change the hostname:

sudo hostnamectl set-hostname newName.domain.local

Rocky

Make sure to change "SOFTWARE SELECTION" from "server" to "minimal install."

Rocky 8 - Verify and/or Update the IP

sudo sed -i 's/192.168.30.199/192.168.30.150/g' /etc/sysconfig/network-scripts/ifcfg-ens192 sudo cat /etc/sysconfig/network-scripts/ifcfg-ens192

Rocky 9 - Verify and/or Update the IP

sudo cat /etc/NetworkManager/system-connections/ens192.nmconnection | grep -i address sudo sed -i 's/192.168.30.198/192.168.30.108/g' /etc/NetworkManager/system-connections/ens192.nmconnection

Verify DNS is setup correctly.

sudo cat /etc/resolv.conf

The output should look something like:

search domain.local nameserver 192.168.30.100 nameserver 192.168.30.101

Verify NTP is setup correctly.

sudo cat /etc/chrony.conf | grep -i "server t"

The output should look something like:

server tock.domain.local iburst server tick.domain.local iburst

Ubuntu

Verify and/or Update the IP

sudo cat /etc/netplan/00-installer-config.yaml sudo sed -i 's/192.168.30.199/192.168.30.150/g' /etc/netplan/00-installer-config.yaml

No DNS changes are required. Ubuntu uses a dynamic resolv.conf file for connecting local clients to the internal DNS stub resolver of systemd-resolved.

Verify NTP is setup correctly.

sudo cat /etc/chrony/chrony.conf | grep -i "server t"

The output should look something like:

server tock.domain.local iburst server tick.domain.local iburst

User Creation

Rocky 9.1 Only

During the install, you can only setup the root account. Creating a secondary user account was not an option. This only seemed be required for Rocky 9.1. 9.2 gave the option during the install.

So we need to:

  1. Add the localadmin user.
  2. Change the password for localadmin.
  3. Ad the localadmin to the wheel (for ssh and sudo).
adduser localadmin passwd localadmin usermod -aG wheel localadmin

LVM Expansion

Ubuntu Only

For whatever reason, Ubuntu does not use the the entire disk during the OS installation even if it is specified to use it. So we will do this before the cleanup.

Various commands to show the size of drives.

sudo lsblk sudo df -h sudo df -h /

Display the size of the volume group.

sudo vgdisplay

Extend the logical volume to use all of the remaining disk space.

sudo lvextend -l +100%FREE /dev/mapper/ubuntu--vg-ubuntu--lv

Force the OS to see the extended space.

sudo resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv

It is probably wise to do a good old reboot.

sudo reboot

!!! RUN AS ROOT !!!

In case you did not get the memo...

Run all of the proceeding commands while logged in as: root.

Optional: Ubuntu Only.
In CentOS and Rocky, a root user is enabled by default. Ubuntu disables the root user by default because it does not have a password. To enable root login, change the root password from Keepass and follow the steps below. If you would like unlock enable root login:

  1. Change the root password: sudo passwd root
  2. Unlock the root account: sudo usermod -U root
  3. Allow root to login through SSH: sudo sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/g' /etc/ssh/sshd_config
  4. Restart SSH: sudo systemctl restart sshd

Use the following command to login as root. You will be prompted for the password for the user that you are currenlty logged in as and NOT the root password.

sudo su -

Install

Rocky

Update the repo list, update the bits, install pre-reqs. With CentOS 7, install "dnf" and substitute "yum-utils" for "dnf-utils."

dnf -y update dnf -y install net-tools dnf-utils wget perl open-vm-tools rsyslog

Ubuntu

Update the repo list, update the bits, install pre-reqs.

apt-get update apt-get -y upgrade apt-get -y install net-tools byobu wget vim chrony ufw perl auditd

NTP Setup

Regardless of the operating system, the following lines are how the top of the config should appear.

server tick.domain.local iburst server tock.domain.local iburst

Rocky

You are able to set the NTP servers during setup. All you have to do is verify the settings are correct. The location of the config file is:

cat /etc/chrony.conf

Ubuntu

During the OS install, you are not prompted for the NTP servers. Chrony was installed during the install section above. You still have to change the default NTP servers. The first sed will delete any line that contains "maxsources 1." The following two lines will replace the defaults with the specified NTP servers.

sed -i '/maxsources 1/d' /etc/chrony/chrony.conf sed -i 's/pool ntp.ubuntu.com iburst maxsources 4/server tick.domain.local iburst/g' /etc/chrony/chrony.conf sed -i 's/pool 2.ubuntu.pool.ntp.org iburst maxsources 2/server tock.domain.local iburst/g' /etc/chrony/chrony.conf cat /etc/chrony/chrony.conf systemctl restart chronyd

All Distributions

Test the Chrony sources.

chronyc sources

Set the timezone.

timedatectl set-timezone America/Chicago timedatectl set-timezone America/Detroit

Verify time settings.

timedatectl

SELinux Config

This section only applies to Rocky.

Verify SELinux status:

sestatus getenforce

Change option SELINUX from disabled to enforcing and reboot after activating.

vi /etc/selinux/config selinux-activate

AppArmor Config

This section only applies to Ubuntu.

Verify AppArmor status:

systemctl status apparmor systemctl enable apparmor aa-status

IPv6 Network Config

All Distributions

This command works in all distrobutions. Verify the current state of IPV6.

  • 0 - IPv6 is currently active
  • 1 - IPv6 is currently disabled
cat /proc/sys/net/ipv6/conf/all/disable_ipv6

Verify current IPv6 status.
CentOS 7 and Rocky 8 both come back with null.
Ubuntu comes back with the following: inet6 fe80::250:56ff:fea9:2bae/64 scope link
In Ubuntu, if "ip a | grep inet6" is run, it is not persistant after a reboot.

ip a | grep inet6

Ubuntu

To disable IPv6, change yes to no.

cat /etc/default/ufw | grep -i IPV6 sed -i 's/IPV6=yes/IPV6=no/g' /etc/default/ufw

Verify if IPv6 has been disabled:

cat /etc/sysctl.conf

Rather than completely disabling IPv6 all together, the IPv6 stack can be enabled, but prevented from assigning network addresses to network interfaces. Edit the following file and append the following lines.

tee -a /etc/sysctl.conf >/dev/null <<EOF net.ipv6.conf.all.disable_ipv6 = 1 net.ipv6.conf.default.disable_ipv6 = 1 net.ipv6.conf.lo.disable_ipv6 = 1 EOF

Run the following command to apply the changes or a reboot will work too.

sysctl -p

FirewallD Config

This section only applies to Rocky.

Setup FirewallD to start during startup and run now.

systemctl status firewalld systemctl start firewalld systemctl enable firewalld

Check the service status.

firewall-cmd --state

List zones.

firewall-cmd --get-zones

List the default zones.

firewall-cmd --get-default-zone

Disable default firewall ports.

firewall-cmd --remove-service=dhcpv6-client --permanent firewall-cmd --remove-service=cockpit --permanent

Apply the firewall changes.

firewall-cmd --reload

Show the current config.

firewall-cmd --list-all

UFW Config

This section only applies to Ubuntu.

Check the status of UFW.

ufw status verbose

If UFW is disabled, enable it.

ufw enable

Create the default policy based on best practises.

ufw default deny incoming ufw default allow outgoing

Use the following command to allow SSH from any network.

ufw allow ssh comment SSH_server

Show the policies in a numbered order.

ufw status numbered

SSH Server Config

Make a backup of the sshd_config.

cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

After creating a backup of this file, this step is optional and is performed if you wish to check all the options that are currently enabled in this configuration file. You can check it out by running the following command in your terminal:

sshd -T

Make the following changes to the sshd config:

  • Protocol 2: protocl 1 is a high security risk. Since version 7.0 of OpenSSH, protocol 1 is automatically disabled during compile time. We are forceing protocol version 2 regardless.
  • HostKey /etc/ssh/ssh_host_ecdsa_key: is a less secure cipher than the others. So we are not going to use it.
  • LoginGraceTime: specifies how long after a connection request the server will wait before disconnecting. There is a STIG to set the interval to 30 seconds or less.
  • PermitRootLogin: prevents the root account from being able to SSH into the server. There are slight differances between CentOS 7, Rocky 8, and Ubuntu 20.04. That is why there are several sed commands.
  • MaxAuthTries: refers to the maximum number of authentications attempts per connection. This is not a lockout mechanism, it will not protect you from any brute force attack. When the limit is hit, the sshd stops accepting authentication attempts closing the TCP connection.
  • MaxSessions: the max number of open sessions to a server at a time. Example, if this is set to 3, you could only be SSHed into the server 2 times and one SCP session.
  • PermitEmptyPasswords: specifies whether the server allows logging in to accounts with a null passwords. If you intend to use the scp utility to make backups over the network, you must set this option to yes.
  • X11Forwarding: this is a STIG. Enabling X11 Forwarding on the host can permit a malicious user to secretly open another X11 connection to another remote client during the session and perform unobtrusive activities such as keystroke monitoring, if the X11 services are not required for the system's intended function, they should be disabled or restricted to the user's needs.
sed -i '/# default value.$/a\\nProtocol 2' /etc/ssh/sshd_config sed -i 's/#HostKey \/etc\/ssh\/ssh_host_rsa_key/HostKey \/etc\/ssh\/ssh_host_rsa_key/g' /etc/ssh/sshd_config sed -i 's/HostKey \/etc\/ssh\/ssh_host_ecdsa_key/#HostKey \/etc\/ssh\/ssh_host_ecdsa_key/g' /etc/ssh/sshd_config sed -i 's/##HostKey \/etc\/ssh\/ssh_host_ecdsa_key/#HostKey \/etc\/ssh\/ssh_host_ecdsa_key/g' /etc/ssh/sshd_config sed -i 's/#HostKey \/etc\/ssh\/ssh_host_ed25519_key/HostKey \/etc\/ssh\/ssh_host_ed25519_key/g' /etc/ssh/sshd_config sed -i 's/#LoginGraceTime 2m/LoginGraceTime 15/g' /etc/ssh/sshd_config sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/g' /etc/ssh/sshd_config sed -i 's/PermitRootLogin without-password/PermitRootLogin no/g' /etc/ssh/sshd_config sed -i 's/PermitRootLogin yes/PermitRootLogin no/g' /etc/ssh/sshd_config sed -i 's/#PermitRootLogin yes/PermitRootLogin no/g' /etc/ssh/sshd_config sed -i 's/#MaxAuthTries 6/MaxAuthTries 4/g' /etc/ssh/sshd_config sed -i 's/#MaxSessions 10/MaxSessions 4/g' /etc/ssh/sshd_config sed -i 's/#PermitEmptyPasswords no/PermitEmptyPasswords no/g' /etc/ssh/sshd_config sed -i 's/X11Forwarding yes/X11Forwarding no/g' /etc/ssh/sshd_config sed -i 's/#X11Forwarding no/X11Forwarding no/g' /etc/ssh/sshd_config

Verify the changes:

cat /etc/ssh/sshd_config | grep -i Protocol cat /etc/ssh/sshd_config | grep -i "HostKey /etc/ssh/ssh_host_rsa_key" cat /etc/ssh/sshd_config | grep -i "HostKey /etc/ssh/ssh_host_ecdsa_key" cat /etc/ssh/sshd_config | grep -i "HostKey /etc/ssh/ssh_host_ed25519_key" cat /etc/ssh/sshd_config | grep -i LoginGraceTime cat /etc/ssh/sshd_config | grep -i PermitRootLogin cat /etc/ssh/sshd_config | grep -i MaxAuthTries cat /etc/ssh/sshd_config | grep -i MaxSessions cat /etc/ssh/sshd_config | grep -i PermitEmptyPasswords cat /etc/ssh/sshd_config | grep -i X11Forwarding

Verify if the SSH ciphers have already been changed:

cat /etc/ssh/sshd_config | grep -i "KexAlgorithms " cat /etc/ssh/sshd_config | grep -i "Ciphers c" cat /etc/ssh/sshd_config | grep -i "MACs "

The lines below force better SSHD security:

  • KexAlgorithms: controls which key exchanges are allowed.
  • Ciphers: used to encrypt the data after the initial key exchange and authentication is complete.
  • Message authentication codes (MAC): Encryption provides confidentiality, message authentication code provides integrity. We need both.
tee -a /etc/ssh/sshd_config >/dev/null <<EOF # Recommended SSH ciphers KexAlgorithms [email protected],diffie-hellman-group-exchange-sha256 Ciphers [email protected],[email protected],[email protected],aes256-ctr,aes192-ctr,aes128-ctr MACs [email protected],[email protected],[email protected],hmac-sha2-512,hmac-sha2-256,[email protected] EOF

SSH Server Config - Key Login

This section is optional.

To disable users from logging in to this server using passwords, make these changes. This will require SSH keys to be created and used.

  • PasswordAuthentication: no
  • ChallengeResponseAuthentication: no (this is the default)
  • PubkeyAuthentication: yes
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config sed -i 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/g' /etc/ssh/sshd_config

SSH Server Config - Auto Logout

This section is optional:

Rocky 8 uses a older version of OpenSSH than Ubuntu 20.04. The SSH auto logout settings work in Rocky 8's version. This functionality is broken in Ubuntu 20.04's version. As a result, the workaround was to create a script. See the "Auto Logout Script" section for more information on how to install the workaround.

ClientAliveInterval and ClientAliveCountMax: there are two ways to configure this. There is a client alive message that can be sent in intervals. If no responce is received, after max count, the user will be logged off. The interval is in seconds. Add the m for minutes.

Example 1: ClientAliveInterval 30m * ClientAliveCountMax 2 = 60m

Example 2: ClientAliveInterval 60m * ClientAliveCountMax 0 = 60m

sed -i 's/#ClientAliveInterval 0/ClientAliveInterval 60m/g' /etc/ssh/sshd_config sed -i 's/#ClientAliveCountMax 3/ClientAliveCountMax 0/g' /etc/ssh/sshd_config

Verify the changes.

cat /etc/ssh/sshd_config | grep -i ClientAliveInterval cat /etc/ssh/sshd_config | grep -i ClientAliveCountMax

SSH Server - Moduli Generation

The /etc/ssh/moduli file contains prime numbers and generators used by the SSH server for the Diffie-Hellman key exchange. Your current /etc/ssh/moduli is probably not unique. Generating a new file will harden the server but generating this file will take a long time. This would have to be done on every server AFTER cloning.

The commands to create a new moduli are below. The -G and -T switches only work in CentOS 7 or Rocky 8. Ubuntu 20.04 is using a newer version of the Open SSH server that requires different commands. The commands for the new version are from a OpenBSD man page on ssh-keygen.

The TOTAL time to replace the moduli file is around 1.5 hours on a Linux VM that has 2 cores (1vCPU) and 2GB of RAM.

CentOS 7 and Rocky 8 - moduli keygen
Original stribika blog commands:

  • ssh-keygen -G /etc/ssh/moduli.all -b 4096
  • ssh-keygen -T /etc/ssh/moduli.safe -f /etc/ssh/moduli.all
  • mv /etc/ssh/moduli.safe /etc/ssh/moduli
  • rm /etc/ssh/moduli.all

CentOS 7 and Rocky 8 - moduli keygen
Original stribika blog and Ubuntu 12.04 man page combo:

  • ssh-keygen -G moduli-4096.candidates -b 4096
  • ssh-keygen -T moduli-4096 -f moduli-4096.candidates
  • mv moduli-4096 /etc/ssh/moduli
  • rm moduli-4096.candidates

Ubuntu 20.04 - moduli keygen
OpenBSD man page on ssh-keygen modified:

  • ssh-keygen -M generate -O bits=4096 moduli-4096.candidates
  • ssh-keygen -M screen -f moduli-4096.candidates moduli-4096
  • mv moduli-4096 /etc/ssh/moduli
  • rm moduli-4096.candidates

According to stribika's 2015 blog, if you choose to enable the "diffie-hellman-group-exchange-sha256" KexAlgorithms, delete the lines where the 5th column is less than 2000. The commands from stribika are here:

Original stribika 2001 bit truncation:

  • awk '$5 > 2000' /etc/ssh/moduli > "${HOME}/moduli"
  • wc -l "${HOME}/moduli" # make sure there is something left
  • mv "${HOME}/moduli" /etc/ssh/moduli

According to Mozilla's 2017 guide, all Diffie-Hellman moduli in use should be at least 3072-bit long. The commands below are a modifed version of stribika's. Mozilla's were giving an access denied error.

Original Mozilla's 3072 bit truncation:

  • awk '$5 >= 3071' /etc/ssh/moduli > /etc/ssh/moduli.tmp
  • mv /etc/ssh/moduli.tmp /etc/ssh/moduli

Original stribika 2001 bit truncation updated to Mozilla's 3072-bit-long truncation:

wc -l /etc/ssh/moduli awk '$5 >= 3071' /etc/ssh/moduli > /root/moduli wc -l /root/moduli mv -f /root/moduli /etc/ssh/moduli

SSH Client Config

Make a backup of the ssh_config.

cp /etc/ssh/ssh_config /etc/ssh/ssh_config.bak

After creating a backup of this file, this step is optional and is performed if you wish to check all the options that are currently enabled in this configuration file. You can check it out by running the following command in your terminal:

ssh -G localhost

Make the following changes to the ssh_config:

  • Protocol 2: protocol 1 is a high security risk. Since version 7.0 of OpenSSH, protocol 1 is automatically disabled during compile time. We are forceing protocol version 2 regardless.
  • The remainder of the changes are recommended from stribika's blog.
sed -i '/# ssh_config(5) man page.$/a\\nProtocol 2' /etc/ssh/ssh_config sed -i 's/# Host .*/Host */g' /etc/ssh/ssh_config sed -i '/# Ciphers .*.$/i\\n KexAlgorithms [email protected],diffie-hellman-group-exchange-sha256' /etc/ssh/ssh_config sed -i '/ KexAlgorithms .*$/a\ HostKeyAlgorithms [email protected],[email protected],ssh-ed25519,ssh-rsa' /etc/ssh/ssh_config sed -i "s/# Ciphers .*/ Ciphers [email protected],[email protected],[email protected],aes256-ctr,aes192-ctr,aes128-ctr/" /etc/ssh/ssh_config sed -i "s/# MACs .*/ MACs [email protected],[email protected],[email protected],hmac-sha2-512,hmac-sha2-256,[email protected]/" /etc/ssh/ssh_config sed -i '/ MACs .*$/a\ UseRoaming no\n' /etc/ssh/ssh_config

Verify the changes. I did not want to use grep in the verification because I wanted to see check to make sure the spacing looked appropriate.

cat /etc/ssh/ssh_config

The following part is optional.

To disable users from logging in to other systems using passwords, make these changes. This will require SSH keys to be created and used.

  • sed -i 's/# PasswordAuthentication yes/\n PasswordAuthentication no/g' /etc/ssh/ssh_config
  • sed -i '/ PasswordAuthentication no/a\ ChallengeResponseAuthentication no\n' /etc/ssh/ssh_config
  • sed -i '/ ChallengeResponseAuthentication no/a\ PubkeyAuthentication yes' /etc/ssh/ssh_config

Debian 10 Extras

The following pieces were notes from a Debian 10 minimal install project that was aborted.

Add "AllowUsers localadmin" to the bottom of sshd_config:

  • echo "AllowUsers localadmin" | tee -a /etc/ssh/sshd_config

Run the following command to modify the "visudo" config. Do NOT edit this in vi/vim/nano etc. Append user group to the end of the file.

  • /usr/sbin/visudo
  • localadmin ALL=(ALL:ALL) ALL
  • tail /etc/sudoers | grep localadmin

Customize the VIM config by creating the file in the respective users home dir (vi ~/.vimrc). Then paste the following.

  • " highlight search
  • :set hlsearch
  • " when searching, ignore text case
  • :set ignorecase
  • " change the line number color
  • :highlight LineNr ctermfg=grey
  • " show line numbers all of the time
  • :set number
  • " enable pasteing with right mouse click
  • :set mouse=r

Ubuntu - Disable Message Of The Day (MOTD)

This section is optional.

This was only tested with Ubuntu 20.04.

The default Ubuntu MOTD is tacky. We created our own.

If you like the default Ubuntu login, but want to cut down on some of the noise at login, you can disable specific items such as the dynamic MOTD news. An example of the news would be: "Super-optimized for small spaces - read how we shrank the memory footprint of MicroK8s to make it the smallest full K8s around."

Verify the motd-news setting. Disable the motd-news setting with a sed command.

  • cat /etc/default/motd-news | grep -i ENABLED
  • sed -i 's/ENABLED=1/ENABLED=0/g' /etc/default/motd-news

Remove the executable permission from the specific files that you want to turn off.

  • chmod -x /etc/update-motd.d/10-help-text
  • chmod -x /etc/update-motd.d/50-motd-news
  • chmod -x /etc/update-motd.d/90-updates-available

For a list of what is disabled:

  • find /etc/update-motd.d/ -name "*" -perm 644

To disable all Ubuntu MOTD content, follow these steps:

  1. Verify the motd-news setting.
  2. Disable the motd-news setting with a sed command.
  3. Remove the executable permission from all files.
  4. For a list of what is disabled:
cat /etc/default/motd-news | grep -i ENABLED sed -i 's/ENABLED=1/ENABLED=0/g' /etc/default/motd-news cat /etc/default/motd-news | grep -i ENABLED chmod -x /etc/update-motd.d/* find /etc/update-motd.d/ -name "*" -perm 644

Message Of The Day (MOTD) Setup

This section is optional.

This was not tested with CentOS 7.

This was setup and tested on Rocky 8 and Ubuntu 20.04.

Banner: a message that displays when a SSH session is started and BEFORE the login.

MOTD: a message that displays AFTER a user has logged in to a SSH session.

Make the following changes to the sshd config:

  • PrintMotd: if this is enabled, the user will get a MOTD displayed AFTER login. The contents of the /etc/motd file is printed to the screen. This is NOT a bash script. It is only a flat file.
  • PrintLastLog: after succesful login, a message shows the date/time and the IP address of the last login.
  • Banner: this is a message that is printed to the screen BEFORE login.
cat /etc/ssh/sshd_config | grep -i Banner cat /etc/ssh/sshd_config | grep -i PrintLastLog cat /etc/ssh/sshd_config | grep -i PrintMotd

If you do need to make changes to the sshd_config, the commands are here:

  • sed -i 's/.*PrintMotd.*/PrintMotd no/g' /etc/ssh/sshd_config
  • sed -i 's/.*Banner.*/#Banner none/g' /etc/ssh/sshd_config

The commands above here are defaults, so no changes should be required. PrintLastLog does need to be changed from the default.

sed -i 's/.*PrintLastLog.*/PrintLastLog no/g' /etc/ssh/sshd_config

If any changes were made to sshd_config, restart sshd.

systemctl restart sshd
Filename: tmp_-_script_-_motd.sh
#!/bin/bash ########################################################### # Summary ########################################################### # # Updated: # 2021-08-18 # # Authors: # Tim Hammond [email protected] # Derek Pasnick [email protected] # # Supported Operating Systems: # Rocky 8, Ubuntu 20.04 # # Description: # Just havin' meself soMe fun. One important thing to note # is that there is a slight differance between the tabs in # Rocky 8 and Ubuntu. By adding an extra space in front of # each variable output line, this centers everything # reasonably well and keeps the spacing consistent in both # distributions. # # ########################################################### # Referances ########################################################### # # http://mewbies.com/how_to_customize_your_console_login_message_tutorial.htm # https://fishi.devtail.io/weblog/2015/02/06/dyamic-login-messages-update-motd/ # https://landoflinux.com/linux_ssh_login_banner.html # https://nebulab.com/blog/awesome-motds-with-ubuntu # https://serversforhackers.com/c/customize-your-login-screen-via-linuxs-message-of-the-day-ubuntucentos # # ########################################################### # Variables ########################################################### cpu_current=$(cat /proc/loadavg | awk '{print $1*100 "%"}') cpu_load_all=$(cat /proc/loadavg | awk '{print $1 ", " $2 ", " $3}') cpu_load_1=$(cat /proc/loadavg | awk {'print $1'}) cpu_load_5=$(cat /proc/loadavg | awk {'print $2'}) cpu_load_10=$(cat /proc/loadavg | awk {'print $3'}) distro_name=$(. /etc/os-release; echo "$NAME") distro_version=$(. /etc/os-release; echo "$VERSION_ID") distro_all=$(echo $distro_name $distro_version) hostname=$(hostname -s) ip=$(hostname -i) hd_total=$(df -h | awk '{if($(NF) == "/") {print $(NF-4); exit;}}') hd_used_gb=$(df -h | awk '{if($(NF) == "/") {print $(NF-3); exit;}}') hd_used_per=$(df -h | awk '{if($(NF) == "/") {print $(NF-1); exit;}}') ll_user=$(last -i -n 2 | tail -3 | awk '!/^wtmp*/ {print $1 }') ll_ip=$(last -i -n 2 | tail -3 | awk '!/^wtmp*/ {print $3 }') ll_weekday=$(last -i -n 2 | tail -3 | awk '!/^wtmp*/ {print $4 }') ll_month=$(last -i -n 2 | tail -3 | awk '!/^wtmp*/ {print $5 }') ll_day=$(last -i -n 2 | tail -3 | awk '!/^wtmp*/ {print $6 }') ll_loginTime=$(last -i -n 2 | tail -3 | awk '!/^wtmp*/ {print $7 }') processes=$(ps aux | wc -l) ram_total_kb=$(awk '/MemTotal/ {print $2}' /proc/meminfo) ram_total_mb=$((ram_total_kb / 1000)) ram_free_kb=$(awk '/MemFree/ {print $2}' /proc/meminfo) ram_free_mb=$((ram_free_kb / 1000)) ram_used_mb=$((ram_total_mb - ram_free_mb)) ram_used_percent=$((ram_used_mb * 100 / ram_total_mb)) ram_used_all=$(echo ${ram_used_percent}'% ('${ram_used_mb}M')') uptime_days=$(expr `cat /proc/uptime | cut -d '.' -f1` % 31556926 / 86400) uptime_hours=$(expr `cat /proc/uptime | cut -d '.' -f1` % 31556926 % 86400 / 3600) uptime_minutes=$(expr `cat /proc/uptime | cut -d '.' -f1` % 31556926 % 86400 % 3600 / 60) uptime_total="${uptime_days} days, ${uptime_hours} hours" user_sessions=$(users | wc -l) ########################################################### # Show Me da Money ########################################################### cat << EOF ███████╗██╗██████╗ ███████╗██████╗ ██╗ ██╗███╗ ██╗██╗ ██╗ ██╔════╝██║██╔══██╗██╔════╝██╔══██╗██║ ██║████╗ ██║██║ ██╔╝ █████╗ ██║██████╔╝█████╗ ██████╔╝██║ ██║██╔██╗ ██║█████╔╝ ██╔══╝ ██║██╔══██╗██╔══╝ ██╔═══╝ ██║ ██║██║╚██╗██║██╔═██╗ ███████╗██║██║ ██║███████╗██║ ╚██████╔╝██║ ╚████║██║ ██╗ ╚══════╝╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═╝ Happy computing Mr. Gopher! Hostname:...$hostname IP Addy:....$ip Uptime:.....$uptime_total Distro:.....$distro_all CPU:........$cpu_current User Count:.$user_sessions CPU Load:...$cpu_load_all Processes:..$processes RAM-Total:..${ram_total_mb}M HD-Total:...$hd_total RAM-Used:...$ram_used_all HD-Used:....$hd_used_per ($hd_used_gb) Last login: $ll_user on $ll_weekday $ll_day $ll_month at $ll_loginTime from $ll_ip. EOF

MOTD Setup

Upload bash script to:

/tmp

For Rocky 8, put the bash script in: /etc/profile.d/. For Ubuntu, most of the documenation said to put the bash script in: /etc/update-motd.d/. I put the bash script for BOTH distros in: /etc/profile.d/ and the scripts worked as expected. Lastly, make the MOTD bash script executable (regardless of the distro/location).

mv -f /tmp/tmp_-_script_-_motd.sh /etc/profile.d/motd.sh chmod +x /etc/profile.d/motd.sh chown root /etc/profile.d/motd.sh chgrp root /etc/profile.d/motd.sh /etc/profile.d/motd.sh

Auto Logout Script

This section is optional.

I tested this bash script for Rocky 8 and Ubuntu 20.04. I put it in: /etc/profile.d/ and the script worked as expected in both distros. Lastly, make the bash script executable (regardless of the distro/location).

This script works for both console and SSH sessions.

This will log you out of your current session. It will not log you out if you have a dialog or vi open.

Filename: tmp_-_script_-_autologout.sh
#!/bin/bash ########################################################### # Summary ########################################################### # # Updated: # 2021-08-18 # # Authors: # Tim Hammond [email protected] # Derek Pasnick [email protected] # # Supported Operating Systems: # Rocky 8, Ubuntu 20.04 # # Description: # # This script will auto logout all the users in XXXX # seconds except specific users. The a good example of an # account to exclude would be protonmail. Otherwise, the # "Basic Example" below would meet all other needs. We are # just being a little fancy with some flexibility. # # ########################################################### # Referances ########################################################### # # https://www.stigviewer.com/stig/red_hat_enterprise_linux_7/2020-05-15/finding/V-72223 # https://access.redhat.com/solutions/664483 # # ########################################################### # Setup ########################################################### # # Refer to the "tmp_-_vm_-_sanitize_vXX.txt" runbook for # distro specific instructions. # # ########################################################### # Notes ########################################################### # # The TMOUT option sets the amount of time (in seconds) # that an idle connection will be allowed. # # The readonly command is used to make variables and # functions readonly. In other words, your user cannot # change the value of the variable called TMOUT. Consider # this as a security feature. # # If you need to add more users, use the following example. # # if [ "$USER" = "username" ] || [ "$USER" = "username" ] || [ "$USER" = "username" ]; then # echo "NO TIMEOUT For $USER, Enjoy!!!" # else # TMOUT=60 # readonly TMOUT # export TMOUT # fi # # Basic Example of script: # TMOUT=900 # readonly TMOUT # export TMOUT # # Cheat Sheet (seconds * minutes): # 60*60=3600 # 60*30=1800 # 60*15=900 # 60*10=600 # 60*5=300 # # ########################################################### if [ "$USER" = "protonmail" ]; then echo "You are special $USER. Happy computing!" else TMOUT=900 readonly TMOUT export TMOUT fi

Autologout.sh Setup

Upload bash script to:

/tmp mv -f /tmp/tmp_-_script_-_autologout.sh /etc/profile.d/autologout.sh chmod +x /etc/profile.d/autologout.sh chown root /etc/profile.d/autologout.sh chgrp root /etc/profile.d/autologout.sh

Cleanup - Kernel and bits

All Distributions

Reboot the system to apply all of the changes above.

reboot

Use the following command to login as root. You will be prompted for the password for the user that you are currenlty logged in as and NOT the root password.

sudo su -

Stop logging. Ubuntu might bark that another service is dependant on rsyslog. Run: systemctl stop syslog.socket rsyslog.service

service rsyslog stop service auditd stop

CentOS and Rocky

CentOS 7
Remove any old kernels and packages:

package-cleanup -y --oldkernels --count=1 dnf -y clean all

Rocky 8+
Remove any old kernels and packages:

dnf remove --oldinstallonly --setopt installonly_limit=2 kernel -y dnf -y clean all

Ubuntu

Remove any old kernels. The "purge-old-kernels" command will keep the current kernel and one previous kernel version. The "apt-get -y autoremove --purge" command does the same thing without errors. The --purge removes old kernels. Without the purge, it only cleans old packages. purge-old-kernels -y --keep 1.

apt-get -y autoremove --purge

Clean out old apt-get packages:

apt-get -y autoremove apt-get -y autoclean apt-get -y clean rm -rf /var/cache/apt/archives/*

Cleanup - NICS

Remove the udev persistent device rules.

rm -f /etc/udev/rules.d/70*

CentOS 7 and Rocky 8
Remove traces of the MAC address and UUIDs.

cat /etc/sysconfig/network-scripts/ifcfg-e* | grep -i HWADDR cat /etc/sysconfig/network-scripts/ifcfg-e* | grep -i UUID sed -i '/HWADDR/d' /etc/sysconfig/network-scripts/ifcfg-e* sed -i '/UUID/d' /etc/sysconfig/network-scripts/ifcfg-e*

Rocky 9
Remove traces of the MAC address and UUIDs.

cat /etc/NetworkManager/system-connections/*.nmconnection | grep -i hwaddr cat /etc/NetworkManager/system-connections/*.nmconnection | grep -i uuid sed -i '/hwaddr/d' /etc/NetworkManager/system-connections/*.nmconnection sed -i '/uuid/d' /etc/NetworkManager/system-connections/*.nmconnection

Ubuntu 20.04
Remove traces of the MAC address. UUID does not seem to exist in netplan.

cat /etc/netplan/00-installer-config.yaml | grep -i mac sed -i '/macaddress/d' /etc/netplan/00-installer-config.yaml

Mrs. Clean - Script

The SSH server host keys must be recreated with each new VM. Otherwise, the same host keys would be on every VM and that would be a huge problem. So, we delete them. Each distribution handles this a differently.

CentOS and Rocky will recreate the SSH keys after the next reboot or the next time the SSH service restarts.

Ubuntu will NOT recreate the ssh keys. Additional commands are required.

The idea of the following script is the same as a Windows "run once" startup shortcut. After the script has run once, it will delete itself.

The /etc/machine-id file contains the unique machine ID of the local system that is set during installation. The machine ID is a single newline-terminated, hexadecimal, ID string. This was added to RHEL 7.1 to identify the machine in the network. Ubuntu used this parameter as well. This parameter must be unique. When engineers clone a VM, the machine-id is not changed, and the VM may have the same machine-id. The engineer should change the machine-id of the cloned VM for the server to be uniquely identifiable over the network.

Only /etc/machine-id needs to be regenorated as /var/lib/dbus/machine-id is a symbolic link to /etc/machine-id.

systemd-random-seed.service is a service that restores the random seed of the system at early-boot and saves it at shutdown. Saving/restoring the random seed across boots increases the amount of available entropy early at boot. On disk, the random seed is stored in: /var/lib/systemd/random-seed.

tee -a /usr/local/bin/mrs-clean.sh >/dev/null <<EOF #!/bin/bash # # Remove the current machine-id. /bin/rm -vf /etc/machine-id # # Create a new machine-id from a random generator. /usr/bin/systemd-machine-id-setup # # Remove the current urandom seed. The seed will be # regenerated at the next system startup. /bin/rm -vf /var/lib/systemd/random-seed # # Remove all existing SSH host keys. /bin/rm -vf /etc/ssh/ssh_host_* # # This is a Ubuntu specific command that did not seem to # work consistantly with cloneing/templating. # dpkg-reconfigure openssh-server # # This is a distro agnostic way to regenerate any keys if # they do not already exist. # /usr/bin/ssh-keygen -A # # These commands create high level security SSH host keys. # These commands are based on stribika's blog post with the # addition of specifying the paths. /usr/bin/ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N "" < /dev/null /usr/bin/ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N "" < /dev/null # # Restart the SSH server service so that it uses the # newly created host keys. systemctl restart sshd # # Caution, this command will clear all existing crontab # jobs. We are assuming there were no scheduled jobs. crontab -r # # Delete yourself. Sorry to see you go Mrs. Clean. TaTa. /bin/rm "\$0" EOF

Make the script executable.

chmod 770 /usr/local/bin/mrs-clean.sh

Mrs. Clean - Cron Job

To add new crontab jobs, use the command below. This will use the default editor. In most cases, the default editor is vi/vim. You cannot use vi/vim on its own. You have to use the crontab command.

By using "sudo" in the command, this will add the jobs to the root accounts cronjob. As a result, using "sudo" in the actual commands is not necessary. After the text editor is open, paste the following line.

  • crontab -e
  • @reboot /usr/local/bin/mrs-clean.sh
(crontab -l; echo "@reboot /usr/local/bin/mrs-clean.sh";) | crontab -

Verify the crontab job is scheduled for root.

crontab -l -u root

Cleanup - Files and history

Force the logs to rotate and purge old logs.

logrotate -f /etc/logrotate.conf rm -rf /var/log/anaconda/* rm -rf /var/log/apt/* rm -rf /var/log/journal/* rm -f /var/log/btmp* rm -f /var/log/dmesg* rm -f /var/log/faillog rm -f /var/log/lastlog rm -f /var/log/syslog rm -f /var/log/*.gz rm -f /var/log/*.log

Issue the following commands to truncate the logs.

cat /dev/null > /var/log/audit/audit.log cat /dev/null > /var/log/wtmp cat /dev/null > /var/log/lastlog cat /dev/null > /var/log/grubby

Clean all mail.

rm -rf /var/mail/*

Clean /tmp out.

rm -rf /tmp/* rm -rf /var/tmp/*

Clean various goodies and bash histories.

unset HISTFILE rm -f /root/.bash_history rm -f /root/anaconda-ks.cfg rm -rf /root/.ssh/ rm -rf /root/.gnupg/ rm -f /home/localadmin/.bash_history rm -f /home/localadmin/anaconda-ks.cfg rm -rf /home/localadmin/.ssh/ rm -rf /home/localadmin/.gnupg/ history -c

Ready to rock?

Shutdown the system.

shutdown -h now

Perform the following tasks:

  1. Verify that the NIC is on the correct network.
  2. Change the CD drive to "client device."
  3. Remove any VMware snapshots.
  4. Convert the VM to a VMware template.

References

General Template Notes

VMware Customization Requirments

SSHD Config, hardening, and moduli key ssh-keygen

Increasing the drive size

random-seed Info

machine-id Info

Cronjob creation

Info on creating a service

We did not create a systemd service. We ended up creating a crontab job.