Skip to content

Instantly share code, notes, and snippets.

@ahmadsoe
Forked from lrobert/hardenUbuntu.sh
Last active April 11, 2020 20:00
Show Gist options
  • Save ahmadsoe/bfc923595b183a7fe91f to your computer and use it in GitHub Desktop.
Save ahmadsoe/bfc923595b183a7fe91f to your computer and use it in GitHub Desktop.
Ubuntu Installation script
#!/bin/bash
#
# Lee Robert's Base Ubuntu Installation script for use on Digital Ocean (Or any other ubuntu install really.)
# Made and tested with Ubuntu 13.04 64bit
#
# USAGE: bash hardenUbuntu.sh
#
# Steps:
# 01. Secure Root User
# 02. Make .bashrc print out pretty colors (and root's prompt will be red)
# 03. Create a local user
# 04. Update sudoers file so only root + local user can use sudo
# 05. Harden ssh. If root has authorized_keys we'll make our local user use that and disable password auth for ssh
# 06. Upgrade the system
# 07. Install fail2ban
# 08. Enable unattended security updates
# 09. Configure logwatch (emails log summaries)
# 10. Setup time syncronization
# 11. Setup localtime (hard-coded Canada/Eastern)
# 12. Turn on firewall with SSH access allowed
# 13. Install New Relic daemon if we have an api key.
# 14. Install Postfix
#
# TODO:
# - Better timezone selection
# - Better firewall rules (such as specifying an ip address to allow ssh from.
# - Investigate RBAC
# - Investigate Roles
# - Investigate what kernel parameters need to be set in /etc/sysctl.conf
# - Configure the OOM
# - Uninstall unneeded software
#
# Written by Lee Robert (https://github.com/lrobert)
#
# Detect if we are running as root (or using sudo)
if [ `id -u` != 0 ]; then
echo -e "\nScript must be run as root. Please use sudo to run this script or login as root.\n";
exit 1;
fi
TIMEZONE="/usr/share/zoneinfo/Asia/Jakarta"
NEW_USER_NAME=""
SYS_ADMIN_EMAIL=""
echo -e "Timezone: $TIMEZONE"
echo -e "If you want a different timezone you must edit the script.\n"
while [ -z "$NEW_USER_NAME" ]; do
echo -e -n "Please enter the name of your new user: "
read NEW_USER_NAME
done
while [ -z "$SYS_ADMIN_EMAIL" ]; do
echo -e -n "Please enter the email of your system admin (for email logs):"
read SYS_ADMIN_EMAIL
done
# http://plusbryan.com/my-first-5-minutes-on-a-server-or-essential-security-for-linux-servers
# Update Root Password
# -----------------------
#echo -e "Please change the password for ROOT."
#passwd root
# Enable color prompt and change color code from 32 to 31 for root
# and just enable color prompt for all new users
# -----------------------
echo -e "\nUpdating .bashrc to enable fancy colors.\n"
sed -i -e 's/#force_color_prompt/force_color_prompt/g' /root/.bashrc
sed -i -e 's/32m/31m/g' /root/.bashrc
sed -i -e 's/#force_color_prompt/force_color_prompt/g' /etc/skel/.bashrc
# Create new user (voziv)
echo -e "Creating new user: $NEW_USER_NAME\n"
useradd -m -s /bin/bash $NEW_USER_NAME
echo -e "Please change the password for $NEW_USER_NAME\n"
passwd $NEW_USER_NAME
# Update sudoers file
sed -i -e "s/%admin/#%admin/g" /etc/sudoers
sed -i -e "s/%sudo/#%sudo/g" /etc/sudoers
sed -i -e "s/root\tALL=(ALL:ALL) ALL/root\tALL=(ALL:ALL) ALL\n$NEW_USER_NAME\tALL=(ALL:ALL) ALL/g" /etc/sudoers
# Disable Password Auth in ssh (MAKE SURE YOU HAVE authorized_keys SET UP BEFORE DOING THIS!!!!)
sed -i -e 's/PermitRootLogin Yes/PermitRootLogin no/g' /etc/ssh/sshd_config
echo -e "\nAllowUsers $NEW_USER_NAME\n" >> /etc/ssh/sshd_config
# If we have authorized_keys set up in root we'll copy them over
# to our new user and disable password auth
if [ -a "/root/.ssh/authorized_keys" ]; then
if [[ $(stat -c%s "/root/.ssh/authorized_keys") -gt 10 ]]; then
echo -e "Detected authorized_keys file. Copying to $NEW_USER_NAME and disabled password authentication via SSH.\n"
mkdir /home/$NEW_USER_NAME/.ssh
cp /root/.ssh/authorized_keys /home/$NEW_USER_NAME/.ssh/authorized_keys
chown -R $NEW_USER_NAME:$NEW_USER_NAME /home/$NEW_USER_NAME/
chmod 700 /home/$NEW_USER_NAME/.ssh
chmod 400 /home/$NEW_USER_NAME/.ssh/authorized_keys
sed -i -e 's/#PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config
fi
fi
# Listen address for ssh
LISTEN_ADDRESS=""
echo -e -n "Input address to listen SSH (blank to skip): "
read LISTEN_ADDRESS
if [[ ! -z "$LISTEN_ADDRESS" ]]; then
sed -i -e "s/#ListenAddress 0.0.0.0/ListenAddress $LISTEN_ADDRESS/g" /etc/ssh/sshd_config
else
echo -e "\n Skipping listen address.\n"
fi
echo -e "\nRestarting SSH service.\n"
service ssh restart
# Update and Upgrade the system
echo -e "\nRunning Update and Upgrade on the system.\n"
echo -e "\n When prompted about grub's menu.lst please keep the original!\n"
echo -e "\n When prompted about grub's menu.lst please keep the original!\n"
echo -e "\n When prompted about grub's menu.lst please keep the original!\n"
apt-get update -qq
apt-get upgrade -y -qq
# NOTE: Don't update the grub menu.lst just to be safe.
# Install fail2ban
echo -e "\n Installing fail2ban.\n"
apt-get install fail2ban -y -qq
sed -i -e "s/destemail = root@localhost/destemail = $SYS_ADMIN_EMAIL/g" /etc/fail2ban/jail.conf
sed -e "s/\[recidive\]\\n/lols/g" /etc/fail2ban/jail.conf
# Allow unattended updates
# -----------------------
echo -e "\n Setting up unattended upgrades!\n"
apt-get install unattended-upgrades -y -qq
echo -e "APT::Periodic::Update-Package-Lists \"1\";" >> /etc/apt/apt.conf.d/10periodic
echo -e "APT::Periodic::Download-Upgradeable-Packages \"1\";" >> /etc/apt/apt.conf.d/10periodic
echo -e "APT::Periodic::AutocleanInterval \"7\";" >> /etc/apt/apt.conf.d/10periodic
echo -e "APT::Periodic::Unattended-Upgrade \"1\";" >> /etc/apt/apt.conf.d/10periodic
# This already allows what we need
# nano /etc/apt/apt.conf.d/50unattended-upgrades
# Unattended-Upgrade::Allowed-Origins {
# "Ubuntu lucid-security";
# // "Ubuntu lucid-updates";
# };
# Install logwatch
echo -e "\n Setting up logwatch.\n"
apt-get install logwatch -y -qq
sed -i -e 's/\/usr\/sbin\/logwatch/#\/usr\/sbin\/logwatch/g' /etc/cron.daily/00logwatch
echo -e "\n/usr/sbin/logwatch --mailto $SYS_ADMIN_EMAIL --detail high --format html\n" >> /etc/cron.daily/00logwatch
# Install additional packages
echo -e "\n Installing htop, git, and sysstat.\n"
apt-get install htop git sysstat -y -qq
# Set up Daily Time Syncro
echo -e "\n Setting up ntpdate.\n"
echo -e "ntpdate us.pool.ntp.org ntp.ubuntu.com" > /etc/cron.daily/ntpdate && chmod +x /etc/cron.daily/ntpdate
# Set up localtime
echo -e "\n Setting Timezone to $TIMEZONE.\n"
cp $TIMEZONE /etc/localtime
echo -e "\n Setup ufw firewall..\n"
ufw default deny incoming
ufw default allow outgoing
# disable PING
read -p "Disable PING <y/N>? " DISABLE_PING
if [[ $DISABLE_PING == "y" || $DISABLE_PING == "Y" || $DISABLE_PING == "yes" || $DISABLE_PING == "Yes" ]]
then
sed -i 's/-A ufw-before-input -p icmp --icmp-type destination-unreachable -j ACCEPT/-A ufw-before-input -p icmp --icmp-type destination-unreachable -j DROP/g' "/etc/ufw/before.rules"
sed -i 's/-A ufw-before-input -p icmp --icmp-type source-quench -j ACCEPT/-A ufw-before-input -p icmp --icmp-type source-quench -j DROP/g' "/etc/ufw/before.rules"
sed -i 's/-A ufw-before-input -p icmp --icmp-type time-exceeded -j ACCEPT/-A ufw-before-input -p icmp --icmp-type time-exceeded -j DROP/g' "/etc/ufw/before.rules"
sed -i 's/-A ufw-before-input -p icmp --icmp-type parameter-problem -j ACCEPT/-A ufw-before-input -p icmp --icmp-type parameter-problem -j DROP/g' "/etc/ufw/before.rules"
sed -i 's/-A ufw-before-input -p icmp --icmp-type echo-request -j ACCEPT/-A ufw-before-input -p icmp --icmp-type echo-request -j DROP/g' "/etc/ufw/before.rules"
else
echo -e "\n PING enabled..\n"
fi
# allow port
while true; do
read -p "Add additional port to be allowed <Y/n>? " ADD_PORT
if [[ $ADD_PORT == "y" || $ADD_PORT == "Y" || $ADD_PORT == "yes" || $ADD_PORT == "Yes" ]]
then
read -p "Input port number: " PORT_NUMBER
read -p "Input IP/subnet access to port $PORT_NUMBER <blank to allow from Anywhere>: " ALLOW_HOST
if [[ ! -z "$ALLOW_HOST" ]]; then
echo -e "\n allow port $PORT_NUMBER from $ALLOW_HOST.\n"
ufw allow from $ALLOW_HOST to any port $PORT_NUMBER
else
echo -e "\n allow port $PORT_NUMBER from Anywhere.\n"
ufw allow $PORT_NUMBER
fi
## continue add other port
continue
else
echo -e "\n end of configuration port.\n"
break
fi
done
echo -e "\n Enable ufw firewall..\n"
ufw enable
ufw status verbose
#echo -e -n "Confirm ufw setting.."
# Install New Relic
NEW_RELIC_KEY=""
echo -e -n "Enter New Relic license key (blank to skip): "
read NEW_RELIC_KEY
if [[ ! -z "$NEW_RELIC_KEY" ]]; then
echo -e "\n Installing New Relic.\n"
echo -e "deb http://apt.newrelic.com/debian/ newrelic non-free" > /etc/apt/sources.list.d/newrelic.list
wget -O- https://download.newrelic.com/548C16BF.gpg | apt-key add -
apt-get update -y -qq
apt-get install newrelic-sysmond -y -qq
nrsysmond-config --set license_key=$NEW_RELIC_KEY
/etc/init.d/newrelic-sysmond start
else
echo -e "\n Skipping New Relic.\n"
fi
# PHP Lets use onedrej's repository to get the latest version
# apt-get install software-properties-common python-software-properties python3-software-properties
# sudo apt-add-repository ppa:ondrej/php5
# Install postfix
echo -e "\n Setting host relay for postfix.\n"
# posfix configuration
DEFAULT_SMTP_HOST="smtp.sendgrid.net"
DEFAULT_SMTP_PORT=587
SMTP_USERNAME=""
SMTP_PASSWORD=""
read -p "Enter SMTP host [$DEFAULT_SMTP_HOST]: " SMTP_HOST
SMTP_HOST=${SMTP_HOST:-$DEFAULT_SMTP_HOST}
read -p "Enter SMTP port [$DEFAULT_SMTP_PORT]: " SMTP_PORT
SMTP_PORT=${SMTP_PORT:-$DEFAULT_SMTP_PORT}
echo -e -n "\n Enter SMTP username: "
read SMTP_USERNAME
echo -e -n "\n Enter SMTP password: "
read SMTP_PASSWORD
postconf -e 'smtp_sasl_auth_enable = yes'
postconf -e "smtp_sasl_password_maps = static:$SMTP_USERNAME:$SMTP_PASSWORD"
postconf -e 'smtp_sasl_security_options = noanonymous'
postconf -e 'smtp_tls_security_level = encrypt'
postconf -e 'header_size_limit = 4096000'
postconf -e "relayhost = [$SMTP_HOST]:$SMTP_PORT"
/etc/init.d/postfix restart
echo -e "\n DONE.. \n"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment