After deploying a new Ubuntu Linux server on Digital Ocean or Linode, there are a few customization steps I take to improve usability and security of the server. These instructions are assuming you’ve install Ubuntu Linux 18.04 LTS or 20.04 LTS.
Install Strong Entropy
apt update apt -y install haveged pollinate
Schedule re-seeding random number generator at boot
(crontab -l ; echo "@reboot sleep 60 ; /usr/bin/pollinate -r" )| crontab -
SSH Server Hardening
Backup SSH Server Config files
cp /etc/ssh/sshd_config /etc/ssh/backup.sshd_config cp /etc/ssh/moduli /etc/ssh/backup.moduli
Security Changes to sshd_conf
sed -i '/X11Forwarding/c\X11Forwarding no' /etc/ssh/sshd_config sed -i 's/^#HostKey \/etc\/ssh\/ssh_host_\(rsa\|ed25519\)_key$/\HostKey \/etc\/ssh\/ssh_host_\1_key/g' /etc/ssh/sshd_config sed -i 's/^HostKey \/etc\/ssh\/ssh_host_\(dsa\|ecdsa\)_key$/\#HostKey \/etc\/ssh\/ssh_host_\1_key/g' /etc/ssh/sshd_config echo -e "\n# Restrict key exchange, cipher, and MAC algorithms\nKexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256\nCiphers aes128-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr\nMACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256,hmac-sha2-512" >> /etc/ssh/sshd_config
Remove small Diffie-Hellman moduli
awk '$5 >= 3071' /etc/ssh/moduli > /etc/ssh/moduli.safe mv /etc/ssh/moduli.safe /etc/ssh/moduli
Regenerate SSH Server Keys
rm /etc/ssh/ssh_host_* ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N "" ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""
Restart OpenSSH server
service ssh restart
Generate New Root SSH Keys
ssh-keygen -t rsa -b 4096 ; ssh-keygen -t ed25519
Replace Authorized SSH Public Keys
The keys you just created will be used as an emergency fail-safe in case you lose your password and/or your own ssh keys and cannot access the system. To make sure no other unknown keys are authorized to login as root, we will create a new authorized_keys file and add our fail-safe keys to it.
cd /root/.ssh cp id_rsa.pub authorized_keys cat id_ed25519.pub >> authorized_keys
Download the private key files and store someplace safe (offline). DO NOT DELETE THEM FROM THE SERVER.
- /root/.ssh/id_rsa
- /root/.ssh/id_ed25519
Edit the authorized_keys file and paste your own keys to the bottom of the file
vi /root/.ssh/authorized_keys
Swap File
If on Azure, see the instruction below for Swap File on Azure.
If a swap partition was not created by the deployment, create one based on the amount of RAM installed.
Installed RAM (GB) | Swap File (GB) |
---|---|
2 or less | 1 |
3 – 6 | 2 |
7 – 12 | 3 |
13 – 20 | 4 |
Create swap file (example for 1GB swap file)
fallocate -l 1G /swapfile chmod 600 /swapfile mkswap /swapfile swapon /swapfile echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Swap File on Azure
The Azure WALinuxAgent will automatically create a swap file on the resource (temporary) drive.
cp /etc/waagent.conf /etc/waagent.conf.save sed -i '/ResourceDisk.Format/c\ResourceDisk.Format=y' /etc/waagent.conf sed -i '/ResourceDisk.EnableSwap/c\ResourceDisk.EnableSwap=y' /etc/waagent.conf sed -i '/ResourceDisk.SwapSizeMB/c\ResourceDisk.SwapSizeMB=4096' /etc/waagent.conf service walinuxagent restart
Create Linux Update Scripts
cat > /usr/local/bin/linux-update << EOF apt-get -y autoremove --purge sync apt-get clean apt-get autoclean apt update apt -y full-upgrade sync update-grub echo "Press Enter to reboot or Ctrl-C to abort..." read aa sync reboot EOF cat > /usr/local/bin/linux-cleanup << EOF apt-get -y autoremove --purge sync update-grub EOF chmod +rx /usr/local/bin/linux-update /usr/local/bin/linux-cleanup
Install Updates and reboot when prompted
linux-update
Install Various Useful Packages
apt -y install apport apt-transport-https aptitude at build-essential byobu command-not-found curl dnsutils ethtool git htop man ntpdate patch psmisc screen software-properties-common sosreport update-motd update-notifier-common vim zip unzip
Set Hostname
hostnamectl set-hostname domain.tld
Rebuild Hosts File
cat > /etc/hosts <<EOF 127.0.0.1 localhost `hostname -i` `hostname -f` `hostname -s` EOF cat /etc/hosts
Check the output at the end of the command to make sure the hosts file looks similar to this
127.0.0.1 localhost 192.168.1.100 domain.tld domain
Harden IPv4 Network
cat > /etc/sysctl.conf <<EOF # IP Spoofing protection net.ipv4.conf.all.rp_filter = 1 net.ipv4.conf.default.rp_filter = 1 # Ignore ICMP broadcast requests net.ipv4.icmp_echo_ignore_broadcasts = 1 # Disable source packet routing net.ipv4.conf.all.accept_source_route = 0 net.ipv4.conf.default.accept_source_route = 0 # Ignore send redirects net.ipv4.conf.all.send_redirects = 0 net.ipv4.conf.default.send_redirects = 0 # Block SYN attacks net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_max_syn_backlog = 2048 net.ipv4.tcp_synack_retries = 2 net.ipv4.tcp_syn_retries = 5 # Log Martians net.ipv4.conf.all.log_martians = 1 net.ipv4.icmp_ignore_bogus_error_responses = 1 # Ignore ICMP redirects net.ipv4.conf.all.accept_redirects = 0 net.ipv4.conf.default.accept_redirects = 0 net.ipv4.conf.all.secure_redirects = 0 net.ipv4.conf.default.secure_redirects = 0 EOF
If you are not using IPv6, disable it
cat >> /etc/sysctl.conf <<EOF # Disable IPv6 net.ipv6.conf.all.disable_ipv6 = 1 net.ipv6.conf.default.disable_ipv6 = 1 net.ipv6.conf.lo.disable_ipv6 = 1 EOF
Restrict Root Login to Console
cp /etc/securetty /etc/securetty.old cat > /etc/securetty <<EOF console tty1 tty2 tty3 tty4 tty5 tty6 EOF
Configure Time Services
Set Local Time Zone
dpkg-reconfigure tzdata
Define Time Servers
sed -i '/^#NTP=/c\NTP=time.google.com' /etc/systemd/timesyncd.conf
Restart Time Sync
systemctl restart systemd-timesyncd ntpdate -u time.google.com
Journal Log Cleanup
(crontab -l ; echo "@daily journalctl --vacuum-time=30d --vacuum-size=1G" )| crontab -
Unattended Security Updates
Install unattended-upgrades package
apt install unattended-upgrades
Enable automatic upgrades
dpkg-reconfigure unattended-upgrades
Configure apt options
cat > /etc/apt/apt.conf.d/10periodic <<EOF APT::Periodic::Download-Upgradeable-Packages "1"; APT::Periodic::AutocleanInterval "1"; EOF
Configure only security updates and reboot time (2:00am)
cat > /etc/apt/apt.conf.d/50unattended-upgrades <<EOF Unattended-Upgrade::Allowed-Origins { "\${distro_id}:\${distro_codename}"; "\${distro_id}:\${distro_codename}-security"; "\${distro_id}ESM:\${distro_codename}"; }; Unattended-Upgrade::Package-Blacklist { }; Unattended-Upgrade::Automatic-Reboot "true"; Unattended-Upgrade::Automatic-Reboot-Time "02:00"; EOF
Configure Download Timer Service
rm -rf /etc/systemd/system/apt-daily.timer* systemctl --full edit apt-daily.timer
modify the following for random download time between 6am – noon and 6pm – midnight
RandomizedDelaySec=6h
Configure Upgrade Timer Service
rm -rf /etc/systemd/system/apt-daily-upgrade.timer* systemctl --full edit apt-daily-upgrade.timer
modify the following for random upgrade time between 12:25am and 12:55am
OnCalendar=*-*-* 0:25 RandomizedDelaySec=30m
Update to Latest Linux Kernel
Install new Kernel
apt -y install --install-recommends linux-virtual-hwe-18.04
reboot and reconnect with putty as root user
reboot
Remove old kernel packages and dependencies
apt-get -y autoremove ; apt -y purge linux-generic linux-headers-generic linux-image-generic linux-virtual linux-headers-virtual linux-image-virtual ; apt -y purge linux*4.15.*
Make sure all Linux packages are up-to-date
linux-update
Suggested Next Steps
- Emerging Threats and Geo-Protection (Ubuntu)
- Virtualmin LAMP Server or Virtualmin LEMP Server
- Webmin System Administration Console