(
See baseline also)
Below is a quick must-do (or baseline if you will) list I have compiled that should be applied to any server running linux:
1. Remove all unnecessary services - the smaller attack surface you have the better! If you can help it try to install 'minimal' or 'core' versions of the OS - both CentOS and Debian provide them!
2. Harden SSH configuration in /etc/ssh/sshd_config:
- Disable root logins
PermitRootLogin no
- Disable plain-text logins (i.e. private key auth only)
PasswordAuthentication no
- Only listen on necessary interfaces
ListenAddress 10.11.12.13
- Ensure only SSH v2 is enabled (enabled by default on most modern versions of OpenSSH)
Protocol 2
- Ensure UsePrivilegeSeparation is set to 'sandbox' mode
UsePrivilegeSeparation sandbox
- Ensure logging is enabled
SyslogFacility AUTHPRIV
LogLevel INFO
- Set login grace time (can help mitigate DDoS attacks)
LoginGraceTime 1m
- Ensure strict mode is enabled (ensures SSH keys etc. are setup correctly for users)
StrictMode yes
- Public key authentication:
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
- Ensure user can't login with empty passwords:
PermitEmptyPasswords no
- Enable / disable challenge response if needed (e.g. Google Authenticator, two-factor auth etc.):
ChallengeResponseAuthentication no
- Disable weak ciphers (source: https://calomel.org/openssh.html)
Ciphers aes256-ctr,aes192-ctr,aes128-ctr
- Unless absolutley needed - disable X11 forwarding:
X11Forwarding no
and in /etc/ssh/ssh_config:
- Unless absolutely needed - disable X11 forwarding:
ForwardAgent no
ForwardX11 no
ForwardX11Trusted no
3. Kernel tweaks
# Disable IPv6 if not needed
echo 1 > /proc/sys/net/ipv6/conf/<interface-name>/disable_ipv6
Reboot and verify - if all OK make the changes permanent with:
echo 'net.ipv6.conf.all.disable_ipv6 = 1' > /etc/sysctl.conf
# Disable IP forwarding (i.e. if not using anything that requires routing e.g. vpn server etc.)
net.ipv4.ip_forward = 0
# log any malformed packets
net.ipv4.conf.all.log_martians = 1
# disable source routing
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.all.accept_source_route = 0
# disable icmp re-directs / icmp dos mitigation
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
# enable syn cookies for synflood protection
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 1280
# enable reverse-path forwarding filter
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# disable tcp timstamping
net.ipv4.tcp_timestamps = 0
Now make the changes permanent with:
sysctl -p
4. Ensure selinux is enabled:
sestatus
If it is not turned on we modify:
/etc/sysconfig/selinux
and ensure 'SELINUXTYPE=targeted'
5. Setup IPTables properly
Ensure that a default-accept rule is in place on all of the default chains:
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT
and then flush the chains as well as any non-standard chains:
sudo iptables -t nat -F
sudo iptables -t mangle -F
sudo iptables -F
sudo iptables -X
Now we will start by allowing traffic to freely flow out and in from our loopback interface:
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A OUTPUT -o lo -j ACCEPT
We will also want to ensure that already established connections can get back to the server - i.e. allow stateful connections.
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
We will likely also want to allow all outbound traffic from connections that are currently established:
sudo iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT
We will also likely wish to allow SSH access from a specific host network:
sudo iptables -A INPUT -p tcp -s 10.11.12.13/32 --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
and allow the incoming SSH connection outbound back to the SSH initiator:
sudo iptables -A OUTPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT
We might also wish to accept ICMP echo requests:
sudo iptables -A INPUT -p icmp -j ACCEPT
Allow outbound requests for DNS and HTTP/S:
sudo iptables -A OUTPUT -p udp --dport 53 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A OUTPUT -p tcp --dport 53 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A OUTPUT -p tcp --dport 80 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A OUTPUT -p tcp --dport 443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
And also log and then drop any other packets:
sudo iptables -N LOGGING
sudo iptables -A INPUT -j LOGGING
sudo iptables -A FORWARD -j LOGGING
sudo iptables -A LOGGING -m limit --limit 2/min -j LOG --log-prefix "IPTables-Dropped: " --log-level 4
sudo iptables -A LOGGING -j DROP
Finally we should remove our default-allow rules we inserted prior:
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT DROP
I also wrote an article here: http://blog.manton.im/2016/06/securing-iptables-in-centos-7-attack.html that might be of interest.
6. Ensure ntp / datetime information is configured correctly.
7. Ensure you have brute-force detection / prevention system in place e.g. fail2ban or sshguard.
8. Utilize tcpwrappers
9. Setup syslog forwarding to a centralized server.
10. Harden other services - dependent on intended usage e.g. web server (apache, nginx etc.)