Server Hardening

To make use of it, add this at the bottom of your iptables script:

#create iptables blocklist rule and ipset hash
ipset create blocklist hash:net
iptables -I INPUT 1 -m set --match-set blocklist 
 ↪src -j DROP

Then put this somewhere executable and run it out of cron once a day:


list="chinese nigerian russian lacnic exploited-servers"
"" # Project
 ↪Honey Pot Directory of Dictionary Attacker IPs
 ↪# TOR Exit Nodes
"" # MaxMind GeoIP 
 ↪Anonymous Proxies
 ↪# BruteForceBlocker IP List
 ↪# Emerging Threats - Russian Business Networks List
"" # Spamhaus Dont Route 
 ↪Or Peer List (DROP)
"" # C.I. Army Malicious 
 ↪IP List
""  # 30 day List
"" # Autoshun Shun List
"" # attackers

cd  $TMP_DIR
# This gets the various lists
for i in "${BLOCKLISTS[@]}"
    curl "$i" > $IP_TMP
    grep -Po '(?:\d{1,3}\.){3}\d{1,3}(?:/\d{1,2})?' $IP_TMP >>
for i in `echo $list`; do
    # This section gets wizcrafts lists
    wget --quiet$i-iptables-blocklist.html
    # Grep out all but ip blocks
    cat $i-iptables-blocklist.html | grep -v \< | grep -v \: |
     ↪grep -v \; | grep -v \# | grep [0-9] > $i.txt
    # Consolidate blocks into master list
    cat $i.txt >> $IP_BLOCKLIST_TMP


ipset flush blocklist
egrep -v "^#|^$" $IP_BLOCKLIST | while IFS= read -r ip
        ipset add blocklist $ip

rm -fR $TMP_DIR/*

exit 0

It's possible you don't want all these blocked. I usually leave tor exit nodes open to enable anonymity, or if you do business in China, you certainly can't block every IP range coming from there. Remove unwanted items from the URLs to be downloaded. When I turned this on, within 24 hours, the number of banned IPs triggered by brute-force crack attempts on SSH dropped from hundreds to less than ten.

Although there are many more areas to be hardened, since according to principle three we assume all measures will be defeated, I will have to leave things like locking down cron and bash as well as automating standard security configurations across environments for another day. There are a few more packages I consider security musts, including multiple methods to check for intrusion (I run both chkrootkit and rkhunter to update signatures and scan my systems at least daily). I want to conclude with one last must-use tool: Fail2ban.

Fail2ban is available in virtually every distribution's repositories now, and it has become my go-to. Not only is it an extensible Swiss-army knife of brute-force authentication prevention, it comes with an additional bevy of filters to detect other attempts to do bad things to your system. If you do nothing but install it, run it, keep it updated and turn on its filters for any services you run, especially SSH, you will be far better off than you were otherwise. As for me, I have other higher-level software like WordPress log to auth.log for filtering and banning of malefactors with Fail2ban. You can custom-configure how long to ban based on how many filter matches (like failed login attempts of various kinds) and specify longer bans for "recidivist" abusers that keep coming back.

Here's one example of the extensibility of the tool. During log review (another important component of a holistic security approach), I noticed many thousands of the following kinds of probes, coming especially from China:

sshd[***]: Received disconnect from **.**.**.**: 11: Bye Bye [preauth]
sshd[***]: Received disconnect from **.**.**.**: 11: Bye Bye [preauth]
sshd[***]: Received disconnect from **.**.**.**: 11: Bye Bye [preauth]

There were two forms of this, and I could not find any explanation of a known exploit that matched this pattern, but there had to be a reason I was getting so many so quickly. It wasn't enough to be a denial of service, but it was a steady flow. Either it was a zero-day exploit or some algorithm sending malformed requests of various kinds hoping to trigger a memory problem in hopes of uncovering an exploit—in any case, there was no reason to allow them to continue.

I added this line to the failregex = section of /etc/fail2ban/filter.d/sshd.local:

^%(__prefix_line)sReceived disconnect from <HOST>: 
 ↪11: (Bye Bye)? \[preauth\]$

Within minutes, I had banned 20 new IP addresses, and my logs were almost completely clear of these lines going forward.

By now, you've seen my three primary principles of server hardening in action enough to know that systematically applying them to your systems will have you churning out reasonably hardened systems in no time. But, just to reiterate one more time:

  1. Minimize attack surface.

  2. Secure whatever remains and must be exposed.

  3. Assume all security measures will be defeated.

Feel free to give me a shout and let me know what you thought about the article. Let me know your thoughts on what I decided to include, any major omissions I cut for the sake of space you thought should have been included, and things you'd like to see in the future!


-- I was cloud before cloud was cool. Not in the sense of being an amorphous collection of loosely related molecules with indeterminate borders -- or maybe I am. Holla @geek_king,