Linux server security by a newbie
based on:
imthenachoman: how to secure linux
blunix ultimate guide linux security
also read:
securing debian manual
plesk secure linux
The basics
you should try to have as less stuff on your server as possible (running services, installed software, etc) to reduce the attack surface
try to keep your server as up to date as possible, sometimes, mainteinance may require downtime, you should plan beforehand when is the server going to be down so that users don’t notice it as much
Umask and Skel
modifying umask permissions on the skel should be the first step
the skel is a template of what files, directories and permissions a user’s home dir gets on creation
you may be used to octal file permissions on files and folder, but an umask might confuse you by believing it replaces the previous octal; instead, an umask “subtracts” a digit of the octal (sets it to 0) from the default octal (666 or 777)
by using 027, the owner user receives no changes, the owner group is denied write permissions, and the rest of users are denied all permissions
the first command sets the umask permissions for any new non-root users on creation and the second one changes umask permissions on the current existing users
some may also recommend setting root umask to 077, but that may break some stuff, like being able to access files in /etc as a non-root user
echo umask 027 | tee -a /etc/skel/.bashrc
echo umask 027 | tee -a ~/.bashrc
Creating accounts
here are some examples on how to create accounts, for example, for a service account you would use:
adduser \
--comment "www.example.com PHP website" \
--uid 5000 \
--system \
--group www-example-com \
--home /var/www/www.example.com \
--shell /bin/false \
--disabled-passwordand for an user account:
adduser \
--comment "john.doe@example.com" \
--uid 1010 \
--home /home/john.doe-example-com \
--shell /bin/bash \
--disabled-password \
john-doe-example-comas you can see, accounts for services don’t get a shell
Sudo and Su
by default sudo and su are available to all users, you may want to change sudo and su behavior to allow only desired users
check if there is already a group (sudo on debian and wheel on redhat)
cat /etc/group | grep "sudo"
cat /etc/group | grep "wheel"if not, then add it yourself
sudo groupadd sudousers
sudo usermod -a -G sudousers user1
sudo usermod -a -G sudousers user2
sudo usermod -a -G sudousers ...open the /etc/sudoers file
sudo visudoand add/edit this line
%sudousers ALL=(ALL:ALL) ALLdo the same with su
sudo groupadd suusers
sudo usermod -a -G suusers user1
sudo usermod -a -G suusers user2
sudo usermod -a -G suusers ...
sudo dpkg-statoverride --update --add root suusers 4750 /bin/suSsh settings
keep a 2nd terminal open to not lock yourself if the other users didn’t have a password before changing the config, they may get locked out
first you want to create a group for ssh users and add users to it
sudo groupadd sshusers
sudo usermod -a -G sshusers user1
sudo usermod -a -G sshusers user2
sudo usermod -a -G sshusers ...
sudo cp --archive /etc/ssh/sshd_config /etc/ssh/sshd_config-COPY-$(date +"%Y%m%d%H%M%S")
sudo sed -i -r -e '/^#|^$/ d' /etc/ssh/sshd_configthen you may want to edit the ssh config with settings that make more sense
i’ve commented/modified some key related lines, check the comments
nano /etc/ssh/sshd_config########################################################################################################
# start settings from https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67 as of 2019-01-01
########################################################################################################
# Supported HostKey algorithms by order of preference.
#HostKey /etc/ssh/ssh_host_ed25519_key #uncomment for keys
#HostKey /etc/ssh/ssh_host_rsa_key #uncomment for keys
#HostKey /etc/ssh/ssh_host_ecdsa_key #uncomment for keys
#KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256 #uncomment for keys
#Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr #uncomment for keys
#MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com #uncomment for keys
# LogLevel VERBOSE logs user's key fingerprint on login. Needed to have a clear audit track of which key was using to log in.
LogLevel VERBOSE
# Use kernel sandbox mechanisms where possible in unprivileged processes
# Systrace on OpenBSD, Seccomp on Linux, seatbelt on MacOSX/Darwin, rlimit elsewhere.
# Note: This setting is deprecated in OpenSSH 7.5 (https://www.openssh.com/txt/release-7.5)
# UsePrivilegeSeparation sandbox
########################################################################################################
# end settings from https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67 as of 2019-01-01
########################################################################################################
# don't let users set environment variables
PermitUserEnvironment no
# Log sftp level file access (read/write/etc.) that would not be easily logged otherwise.
Subsystem sftp internal-sftp -f AUTHPRIV -l INFO
# only use the newer, more secure protocol
Protocol 2
# disable X11 forwarding as X11 is very insecure
# you really shouldn't be running X on a server anyway
X11Forwarding no
# disable port forwarding
AllowTcpForwarding no
AllowStreamLocalForwarding no
GatewayPorts no
PermitTunnel no
# don't allow login if the account has an empty password
PermitEmptyPasswords no
# ignore .rhosts and .shosts
#IgnoreRhosts yes #uncomment for keys
# verify hostname matches IP
UseDNS yes
Compression no
TCPKeepAlive no
AllowAgentForwarding no
PermitRootLogin no
# don't allow .rhosts or /etc/hosts.equiv
HostbasedAuthentication no
# https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/115
#HashKnownHosts yes
AllowGroups sshusers
ClientAliveCountMax 0 #recommended was 3
ClientAliveInterval 300 #recommended was 15
#ListenAddress 0.0.0.0
#ListenAddress 192.168.1.100
LoginGraceTime 30
MaxAuthTries 2
MaxSessions 2
MaxStartups 2 #recommended was 10:30:60
#PasswordAuthentication no #uncomment if you don't want to use passwords and use keys instead
Port 22check for duplicated settings (empty = good)
awk 'NF && $1!~/^(#|HostKey)/{print $1}' /etc/ssh/sshd_config | sort | uniq -c | grep -v ' 1 'restart the service
sudo service sshd restart
sudo sshd -TFail2ban
fail2ban works by blocking ips that fail multiple connections in a short time, if you want to set it up, here’s how to
sudo apt install fail2bancreate a new file in /etc/fail2ban/jail.local and replace the brackets accordingly
[DEFAULT]
# the IP address range we want to ignore
ignoreip = 127.0.0.1/8 [LAN SEGMENT]
# who to send e-mail to
destemail = [your e-mail]
# who is the email from
sender = [your e-mail]
# since we're using exim4 to send emails
mta = mail
# get email alerts
action = %(action_mwl)sand another one for ssh on /etc/fail2ban/jail.d/ssh.local
[sshd]
enabled = true
banaction = ufw
port = ssh
filter = sshd
logpath = %(sshd_log)s
maxretry = 5and enable it
sudo fail2ban-client start
sudo fail2ban-client reload
sudo fail2ban-client add sshdFirejail
firejail allows you to force selected programs to run sandboxed, if you want to use it here’s an example
sudo apt install firejail firejail-profiles
sudo ln -s /usr/bin/firejail /usr/local/bin/google-chrome-stable
firejail --listand for turning a program back to normal
sudo rm /usr/local/bin/google-chrome-stableTime
time must be correctly synchronized so that connections work, you have to set up an ntp client to global servers
sudo apt install ntp
sudo sed -i -r -e "s/^((server|pool).*)/# \1 # commented by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")/" /etc/ntp.conf
echo -e "\npool pool.ntp.org iburst # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | sudo tee -a /etc/ntp.confSecuring proc (may break on some systemd systems)
by default, the proc directory allows users to view info of all proccesses, we want to change that so that users can only view info about their proccesses
sudo cp --archive /etc/fstab /etc/fstab-COPY-$(date +"%Y%m%d%H%M%S")
echo -e "\nproc /proc proc defaults,hidepid=2 0 0 # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | sudo tee -a /etc/fstab
sudo reboot nowthis change sets hidepid to 2,
Enforcing strong passwords (optional)
you may want your users’s passwords to meet certain requirements, this config sets the typical (but outated) alphanumeric requirements (upper lower number non-alpha)
sudo apt install libpam-pwqualityon file etc/pam.d/common-password
change
password requisite pam_pwquality.soto
password requisite pam_pwquality.so retry=3 minlen=10 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1 maxrepeat=3 gecoschecFirewall
firewall configuration (ufw/iptables) changes case by case, you may want to deny traffic by default and allow only some ports
on ufw the difference between allow and limit is that limit blocks IPs that try more than 5 connections whithin 30 seconds
if your are renting from a provider instead of running on bare metal, you may use the web gui instead
sudo apt install ufw
sudo ufw default deny outgoing comment 'deny all outgoing traffic'
sudo ufw default deny incoming comment 'deny all incoming traffic'
SSH_PORT="$(sudo sshd -T | awk '/^port / { print $2; exit }')"
sudo ufw limit in "${SSH_PORT}/tcp" comment 'allow SSH connections in'
sudo ufw allow out 53 comment 'allow DNS calls out'
sudo ufw enableMalware scanning
clamav is an scanner designed for linux, you may install and configure it if you want to
Info leaking
you may want to check if you’re leaking info on the response headers, like version numbers that may let attacker know your server is vulnerable to certain attacks, for example, if you were using php, checking your site with curl -I -L returns the text “x-powered-by: PHP/8.2.1”