NAME

rascals - find and blacklist rascally twerps


SYNOPSIS

  rascals --exclude=231.58.192.122 --period=1h --limit=30 --expire=1d auth.log


DESCRIPTION

rascals reads auth.log looking for ssh dictionary attackers (``rascals'') and adds the offending host to a blacklist. This list may be used by the ``tcp wrappers'' subsystem (via /etc/hosts.allow) to block or tarpit attacking hosts.

rascals automatically removes older entries in the rascals blacklist each time it runs, based on the expiration date when the entries were added.

rascals is designed to run with no maintenance: install and forget.

rascals may be run from the command-line as root, or from a root crontab (see INSTALLATION and EXAMPLES, especially the Author's usage below).

Nearly all of the default behavior of rascals can be changed (see OPTIONS below).

To make use of the rascals blacklist using tcp wrappers, add the following line to the top of your /etc/hosts.allow file:

  sshd : /var/log/rascals : deny

See EXAMPLES below for some other interesting /etc/hosts.allow options.


INSTALLATION

For the impatient, here is the checklist of things that must be done for rascals to maintain its blacklist automatically:

That's it--no fuss, no muss.


OPTIONS

In a nutshell, rascals works like this:

Rascals goes through the last 5 minutes (``period'') of the given log looking for 5 entries (``limit'') matching sshd (``service'') requests for ``Illegal user'' (``pattern'') and adds the offending IP to the rascals log (``rascals'') for a period of 2 hours (``expire'').

All options are configurable: you can change the period (how much of the log to examine), the limit (how many times an offense must occur before they're blacklisted), the service (defaults to sshd, but could be any service, such as 'sm-mta' or 'ipop3d'), the pattern (what an offense looks like in the log), and the expiration (how long the offending IP will be on the blacklist).

This section describes in some detail your options.

General Options

help
Shows a brief help message and exits.

report=[new|old|all]
Writes a brief report to STDERR when done. This options is useful if you want to get a little reporting from cron or just want to see what happened.

If 'new' is specified, new rascals added to the blacklist will be returned (if no output appears, no new entries were added to the blacklist at this time).

If 'old' is specified, expiring rascals will be listed (if no output appears, no expiring rascals were removed from the blacklist at this time).

'all' prints both new additions and expirations.

If no report type is specified, rascals runs silently.

version
Shows the current version of rascals and exits.

Selection Options

These options determine how rascals finds hosts that are attacking your server.

Please be aware that rascals only understands log files in standard syslog format:

  Jan 10 12:02:38 myhostname someservice[8888]: message from someservice

This includes auth.log, maillog, messages, and other common logs written to by syslog.

exclude
Which hosts to exclude when looking for rascals. This option may be specified multiple times for each host to exclude. E.g.,:
  rascals --exclude=123.45.67.89 --exclude=132.41.33.12

The exclude option is a safety valve: put your own IP address here, as well as any addresses from valid clients who might regularly mistype their own password.

Default: (empty)

service
Which service to look for in the specified log file when looking for rascals. Examples of 'services' include sshd, sendmail, proftpd, telnet, ipop3d, popper, sm-mta, etc. rascals can find attacks from any type of service (as long as it can be found in a log file), but tcp wrappers does not wrap all services. Check your host configuration to determine which services can be protected by tcp wrappers.

Only exact string matches will work here. To match multiple services you'll need to run rascals multiple times. This may change in a future release.

Default: sshd

period
How far back in auth.log to look for rascals (i.e., entries older than this will be skipped). See Time Specifications below for valid time specifications.

Default: 5m

limit
How many log entries matching pattern (see next item) necessary before we decide that this host is a rascal.

Default: 5

pattern
The message to look for in auth.log. Changing this should only be done if you know what you're doing. See CAVEATS for more information.

Default: '^(?:Failed password for root|(?:Invalid|Illegal) user \S+) from (\S+)'

A pattern that might work for some ipop3d dictionary attacks:

  'Login failed .*\[(\S+)\]$'

See also <Log Message Patterns> in the CAVEATS section below for more pattern help.

Action Options

These options determine how rascals behaves once it has found rascally hosts.

expire
How long the rascals we find during this run should remain on the blacklist. See Time Specifications below for valid time specifications. See also Expiration Time in the CAVEATS section below for help on setting this to increase expiration precision.

Default: 2h

rascals
The location of the rascals blacklist. (Also determines the name of the temporary file used when creating a new rascals blacklist.)

Default: /var/log/rascals

Time Specifications

Times specified in the period and expire options follow this format:

  (integer)(unit)

'integer' may be any positive whole number (e.g., 1, 2, 3, 4, etc.).

'unit' may be one of the following:

d
days

h
hours

m
minutes

s
seconds

For example, to specify an expiration of 2 weeks:

  --expire=14d

To specify an expiration of 8 minutes:

  --expire=8m

To find entries in the past 12 hours:

  --period=12h


EXAMPLES

Here are some examples of how to run rascals. Further below are examples on how to configure /etc/hosts.allow, and a sample crontab entry.

rascals Examples

Basic usage:

  rascals /var/log/auth.log

This will scan /var/log/auth.log for failed sshd attempts. When it find 5 entries in the last 5 minutes, it will add the attacking host to /var/log/rascals for 2 hours (these are all defaults).

Author's usage:

Here is how your author uses rascals on one of his servers:

    */5 * * * *   root   rascals --exclude=12.34.56.78 --report=all /var/log/auth.log

with the following entry in /etc/hosts.allow:

  ALL : /var/log/rascals : spawn /bin/sleep 60
  ALL : ALL : allow

We scan every 5 minutes for attackers. Some attacks can do several login attempts per second, but for this server 5 minutes is often enough. I add my own IP address via the --exclude option to make sure I don't lock myself out of the server.

On another server, the author runs rascals every two minutes, and sets the --period to '2m' also so there are no gaps in the log processing (no chance for an attacker to guess the scanning pattern and bypass detection).

The --report option will cause rascals to write output, which in turn causes cron to send an email, effectively notifying the system administrator that this server is under attack.

Processing compressed logs:

If your auth.log rotates frequently, you can use zcat and a pipe to rascals:

    zcat -f /var/log/auth.log.[012].gz /var/log/auth.log | rascals

which will process these logs:

    /var/log/auth.log
    /var/log/auth.log.0.gz
    /var/log/auth.log.1.gz
    /var/log/auth.log.2.gz

/etc/hosts.allow examples

You might want to try some of these interesting options in your /etc/hosts.allow file. Here's how to just block sshd attacks using rascals:

  sshd : /var/log/rascals : deny

Here's one way to make a tarpit that allows a login attempt but only after waiting 30 seconds:

  sshd : /var/log/rascals : spawn /bin/sleep 30

Here's another tarpit, but which closes the connection after the tarpit:

  sshd : /var/log/rascals : spawn /bin/sleep 30 : deny

You can replace 'sshd' with any service to block that service, or try 'ALL' to disallow any connection attempts to any service that tcp wrappers protects.

Crontab examples

You can easily automate the maintenance of rascals' log file using cron. An entry like this in your /etc/crontab file will check for attacks every half-hour:

  */30 * * * * root /usr/local/sbin/rascals /var/log/auth.log --report=all


FAQ

Q. The attacks keep coming! What can I do?

A. You probably need a stronger disincentive. Try:

    sshd : /var/log/rascals : spawn /bin/sleep 600
  The trade-off here is that I'm assuming you have plenty of sockets
  to handle the incoming connection attempts. You may find that an
  attack with many simultaneous connections from the attacking IP can
  quickly overwhelm you. If that's the case, just start closing them
  down immediately:
    sshd : /var/log/rascals : deny
  Yes, you'll still get connection attempts, but this will shut them
  down fast enough that the following will likely occur:
    1) you'll have enough sockets for legitimate connections
    2) the attacker will probably give up after a while anyway--you
       have no control over the attackers response.

Q. I watch my logs and notice that an attack will go on for several minutes before rascals detects it and shuts it down. How can I make rascals scan more frequently?

A. Change the cron entry to scan more frequently. rascals is light enough to run every minute, even on very large logs:

     * * * * * root /usr/local/sbin/rascals /var/log/auth.log
  (Note that this is BSD-Vixie /etc/crontab syntax, with a username
  specified in the 6th field.)


CAVEATS

rascals will likely do what you want without any command-line options set or changes. However, due to the myriad configurations and services running on various flavors of Unix out there, these defaults may not all work for you.

For example, your sshd agent may register itself with syslog as 'sshd2' or some other such name, in which case you'll need to specify the service option to override the default. Luckily, rascals is highly configurable.

Below are some of the things you'll want to consider if you need to set any command-line options for one reason or another.

Temporary Files

rascals creates a temporary file to which the new rascals are written and the old rascals are appended. This temporary file is based on the --rascals option (default: /var/log/rascals).

This file should be written to a safe location (i.e., a location where normal users do not have write privileges) as should all log files.

This temporary file is renamed when it is complete, and overwrites the old rascals file. A race condition exists when multiple instances of rascals are running, so try not to do that.

Log Rotation

If your auth.log is rotated between rascals runs, you won't see those last entries in the rotated log, unless you figure out some way to include those compressed logs. You might try this:

  zcat -f /var/log/auth.log.0.gz /var/log/auth.log | rascals

which will make sure you always have the last auth.log rotation period being processed.

Expiration Time

The expiration time (set via --expire) will only be precise when it is a multiple of the frequency of how often you run rascals.

That is, if you run rascals every hour, and your expiration is set to 90 minutes, the expired rascals will be removed on the next rascals run after the 90 minutes has gone by, which could add half an hour to the actual expiration time.

It's best to make the expire time a multiple of the run frequency (e.g., if rascals runs every half hour, set the expire time to a multiple of a half hour: 30m, 60m, 90m, 120m, etc.) if you want to make sure that the blacklist expires precisely (more or less) when you intend it to.

Most people run rascals at a very short frequency (e.g., 2-5 minutes) in which case the worst expiration lag would be 2-5 minutes, which probably isn't very important anyway.

Blacklist Size

The author is not aware of a size limit on the blacklist, but assumes that tcp wrapper performace would begin to degrade after a few hundred hosts. Setting a reasonable expiration time will ensure that your blacklist doesn't become too large for too long.

Blacklist Not Working

If the /etc/hosts.allow doesn't seem to be blocking, you might want to make sure it's actually installed (beyond the scope of this document). Try adding yourself to it:

  ALL : my.hostname.tld : deny

Always keep a shell open so you can remove this entry!

Always keep a shell open so you can remove this entry!

Always keep a shell open so you can remove this entry!

(What I tell you three times is true).

If this works, make sure that your rascals entry is above the first 'ALL : ALL : allow' line in /etc/hosts.allow. Remember: tcp wrappers uses a simple 'first-match' algorithm to decide whether to allow or deny a host.

Log Message Patterns

If you specify a pattern, it must have at least one ``capture'', and the first capture must capture the hostname or IP address of the rascal. For example, to look for dictionary attacks via ftp, you might do something like this:

  rascal --service=proftpd --pattern='USER \S+: no such user found from (\S+)'

Scanning Frequency

If your scanning frequency is more often than the period specification you have set, you will possibly get duplicate entries from one scan to the next. To illustrate:

  +------ start of auth.log
  |1
  |2
  |3  <--- scanning starts here, based on 'period' setting
  |4
  |5
  |6
  |7
  |8
  |9
  +------  end of log

If we scan again before 'period' time has elapsed, this will occur:

  +------ start of auth.log
  |1
  |2
  |3
  |4
  |5
  |6  <--- scanning starts here, based on 'period' setting
  |7  * duplicated
  |8  * duplicated
  |9  * duplicated
  |10
  |11
  |12
  |13
  |14
  +------  end of log

This isn't necessarily bad, but is something to be aware of.

Lockout

You can lock yourself out of your server! Don't do this. And don't call me if you do--I can't help you. Messing with /etc/hosts.allow can be tricky business if you don't know what you're doing (so read the manpages listed below and experiement, but always leave a shell open to your server).

The following brief list are good practices for newbies (and everyone else):


TODO


AUTHOR

Scott Wiersdorf, <scott@perlcode.org>


COPYRIGHT

Copyright (c) 2005 Scott Wiersdorf. All rights reserved.


LICENSE

rascals is released under the the same terms as Perl itself.


SEE ALSO

hosts_options(5), hosts_access(5), /etc/hosts.allow