Tuesday, August 27, 2013

Fail2ban and RedHat/CentOS

Fail2ban is another neat intrusion detection program. It monitors log files for suspicious access attempts and, once it has enough of that, edits the firewall to block the offender. The really neat part is that it will unban the offending IP later on (you define how long); that usually will suffice to your garden variety automatic port scanner/dictionary attack but also would give hope to your user who just can't remember a password. There are other programs out there that will deal with ssh attacks, but fail2ban will handle many different services; I myself use it with Asterisk, mail, and web just to name a few.

But, you did not come here to hear me babbling; let's get busy and do some installing, shall we?

Installing fail2ban in RedHat/CentOS

For this example I will be using CentOS 6. YMMV.

  1. Get required packages. Need jwhois (for whois) from base and fail2ban from, say, epel or your favourite repository
    yum install jwhois fail2ban --enablerepo=epel

    whois is needed by /etc/fail2ban/action.d/sendmail-whois.conf, which is called
    by /etc/fail2ban/filter.d/sshd.conf.

    You will also need ssmtp or some kind of MTA so fail2ban can let you know that it caught a sneaky bastard. I briefly mentioned about ssmtp in a previous post; seek and thou shalt find.

  2. Configure fail2ban.
    1. Disable everything in /etc/fail2ban/jail.conf. We'll be using /etc/fail2ban/jail.local:
      sed -i -e 's/^enabled.*/enabled  = false/' /etc/fail2ban/jail.conf
    2. Configure /etc/fail2ban/jail.local. For now, we will just have ssh enabled
      HOSTNAME=`hostname -f`
      cat > /etc/fail2ban/jail.local << EOF
      # Fail2Ban jail.local configuration file.
      #
      
      [DEFAULT]
      actionban = iptables -I fail2ban- 1 -s  -m comment --comment "FAIL2BAN temporary ban" -j DROP
      
      # Destination email address used solely for the interpolations in
      # jail.{conf,local} configuration files.
      destemail = raub@kudria.com
      
      # This will ignore connection coming from our networks.
      # Note that local connections can come from other than just 127.0.0.1, so
      # this needs CIDR range too.
      ignoreip = 127.0.0.0/8 $(dig +short $HOSTNAME)
      
      #
      # ACTIONS
      #
      # action = %(action_mwl)s
      
      #
      # JAILS
      #
      [ssh]
      enabled = true
      port    = ssh
      filter  = sshd
      action   = iptables[name=SSH, port=ssh, protocol=tcp]
                 sendmail-whois[name=SSH, dest="%(destemail)s", sender=fail2ban@$HOSTNAME]
      logpath  = /var/log/secure
      maxretry = 5
      bantime = 28800
      EOF
      Note we are only whitelisting the host itself. You could whitelist your lan
      and other machines/networks if you want. Jail is a fail2ban term that defines a ruleset you want to check for, and ban as needed.
    3. Decide where you want fail2ban to log to. That is done in /etc/fail2ban/fail2ban.local using the logtarget variable. Some possible values could be
      cat > /etc/fail2ban/fail2ban.local << EOF
      [Definition]
      # logtarget = SYSLOG
      logtarget = /var/log/fail2ban.log
      EOF
      The file /etc/fail2ban/fail2ban.conf should provide you with examples on how to set that up.
  3. Enable fail2ban
    service fail2ban restart
    chkconfig fail2ban on
    If you now do
    chkconfig --list fail2ban
    you should then see
    fail2ban        0:off   1:off   2:on    3:on    4:on    5:on    6:off
    And then check the fail2ban log you defined just before for any funny business. If you have set it correctly, you should see an email to destemail saying fail2ban started. Now, you will get one email per jail. So, if you just did the default (ssh), you will get one email that looks like this:

    Hi,
    
    The jail SSH has been started successfully.
    
    Regards,
    
    Fail2Ban.

    When fail2ban bans someone, you will receive an email that looks like this:

    Hi,
    
    The IP 82.205.21.200 has just been banned by Fail2Ban after
    3 attempts against ASTERISK.
    
    
    Here are more information about 82.205.21.200:
    
    % This is the RIPE Database query service.
    % The objects are in RPSL format.
    %
    % The RIPE Database is subject to Terms and Conditions.
    % See http://www.ripe.net/db/support/db-terms-conditions.pdf
    
    % Note: this output has been filtered.
    %       To receive output for a database update, use the "-B" flag.
    
    % Information related to '82.205.16.0 - 82.205.31.255'
    [...]

    Note that it is not the SSH jail but the ASTERISk one; I just want to show a
    different example. Also, the stuff before the banned message is from whois.

    If you do iptables -L, you will see which rule fail2ban added to iptables:

    Chain fail2ban-SSH (1 references)
    target     prot opt source               destination
    DROP       all  --  221.178.164.251      anywhere
    RETURN     all  --  anywhere             anywhere

    Note it creates a chain for each jail.

References

Installing ssmtp in RedHat/CentOS

I like ssmtp, and yes it has an extra "s" compared to smtp server. There are a lot of MTAs out there with tons of features and tweaks and so on. I myself setup and deployed postfix in quite a few organizations and never had reason to regret it. But, postfix, sendmail, and all the others are full-fledged enterprise level MTAs. Sometimes all you need is to be able to send a couple of emails from servers whenever they have something interesting to tell you ("who is banging my ssh port?" "where's my tea?"). Take CentOS, for instance. If you are not careful, it will put postfix in every single desktop you install it on. Who needs postfix in their desktop when they probably have access to a perfectly good server class mail server thingie (which could even be postfix, mind you)?

So, enter ssmtp. It is small. You can even say it is rather limited and not particularly secure. But, if all you want is to know if some machine, say, finished a batch job or added a new user and can work around its limitations, you might want to check it out.

Installing ssmtp

As I mentioned in the title, we will be installing ssmtp in some RedHat/CentOS machine. That will require to configure the box to use additional repositories. You can check if your favourite one has it; I myself like epel and know ssmtp is there. repoforge (used to be called rpmforge) might have it too. How do you add a repository? I will let you figure out.

First thing we need to do is remove postfix just in case it is there:

yum remove postfix

Then we do some ssmtp adding:

yum install ssmtp --enablerepo=epel

Now we need to configure it. To do so you need a real smtp server; all ssmtp does is forward email to a proper MTA. Let's say your mail server is mail.domain.com. If you do not need to authenticate against it (it accepts unauthenticated email only from certain machines or your LAN), you could probable get away with this:

cat > /etc/ssmtp/ssmtp.conf  << EOF
# Config file for sSMTP sendmail  
root=postmaster
mailhub=mail.domain.com
hostname=$(hostname -f)
FromLineOverride=yes
#UseTLSCert=YES
#TLSCert=/etc/pki/tls/private/ssmtp.pem
#Debug=YES
UseSTARTTLS=yes
EOF

I will be rushing over the not-so-many settings in ssmtp because they are well explained somewhere else. What I will do is stop at the ones I think you might find interesting; at least I do:

  • UseSTARTTLS: if your smtp server can do TLS, by all means use it! Or SSL! ssmtp can handle that too; check the man pages!.
  • mailhub: this is as you guessed the address for the smtp server. The nice thing about it is that you can not only define the name but also the port, in case you are not using port 25. Here are a few examples:

    • mailhub=smtp.gmail.com:587
    • mailhub=mail
    • mailhub=host363.hostmonster.com:465
    Bonus points if you recognize the ports. Here is a full example assuming you are a cox customer (I based the setup on their email setup notes) connecting using port 25 (insecure) without any auth whatsoever:
    cat > /etc/ssmtp/ssmtp.conf << EOF
    # Config file for sSMTP sendmail
    root=postmaster
    mailhub=smtp.cox.net
    hostname=$(hostname -f)
    FromLineOverride=yes
    EOF
    
  • hostname: Nothing special here, besides you probably noticed I was lazy and let the computer tell what is its own name. If you do not get the FQDN, you probably need to check your configuration somewhere.

But, what if you need to autenticate to send an email (SMTP Auth)? Well, ssmtp allows some form of authentication. No kerberos or key pairs though, just plain old username and password. If you needed that, you would add something like this

AuthUser=server1
AuthPass=secret_password
to your /etc/ssmtp/ssmtp.conf file. Password will be in plaintext, so make sure only root can read this file. Note I used server1 as the username. Reason for that is I would think either each server would have its own email account or a commom server email account would be used. You decide.

When all of that is done, it is time to do some testing. First quick test would be to send an email to you (username@somedomain.com):

echo test | ssmtp -v username@somedomain.com

The -v option is verbose, so you can see what is going on and perhaps have some clues in case it all goes boink. A fancier ssmtp test (which should give you ideas on how to use it in your own scripts) would be

victim=username@somedomain.com
ssmtp $victim << EOF
From: test@$(hostname)
To: $victim
Subject: A longer test
Hi there!

EOF

Now go check if the email arrived in your mailbox and what your spam filter thought of it. Remember, the fancier example allows you to make your email a bit more proper... just sayin'!

References