exim-blue-ldFollowing on from last week’s w00tw00t block, here’s another quick fail2ban rule, this time to handle some Exim DOS/mail bombing problems.

I already use Fail2Ban to block unauthorised users who attempt to use my mail server as a relay to send spam, and this works very well. Recently, I’ve started seeing messages like this one start to appear in my exim logs:

2013-05-21 01:01:52 Connection from [2.38.90.63] refused: too many connections: 1 Time(s)
2013-05-21 01:01:53 Connection from [2.38.90.63] refused: too many connections: 1 Time(s)
2013-05-21 01:01:58 Connection from [2.38.90.63] refused: too many connections: 2 Time(s)
2013-05-21 01:01:59 Connection from [2.38.90.63] refused: too many connections: 1 Time(s)
2013-05-21 01:02:00 Connection from [2.38.90.63] refused: too many connections: 1 Time(s)
2013-05-21 01:02:11 Connection from [2.38.90.63] refused: too many connections: 1 Time(s)

In each case, the IP address originates from somewhere I’d not expect to receive email from, so it looks like some spammers are trying to mail bomb/DOS me.

In jail.local

[exim-dos]
enabled = true
filter = exim-dos
port = all
logpath = /var/log/exim*/mainlog
maxretry = 1
bantime = 3600

In filter.d/exim-dos.conf

# Fail2Ban Exim DOS configuration file.
# Checks for DOS/Flooding attempts.
#
# Author: Marcus Povey
#

[Definition]

# Option: failregex
# Notes.: regex to match the password failures messages in the logfile. The
# host must be matched by a group named "host". The tag "" can
# be used for standard IP/hostname matching and is only an alias for
# (?:::f{4,6}:)?(?P[\w\-.^_]+)
# Values: TEXT
#
failregex = \[\] .*refused: too many connections

# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex =

Some potential gotchas

You may notice that I’ve set the bantime to quite a low value, this is because this rule has the potential of some false positives or collateral damage in certain situations.

Most likely you’ll get the too many connections error when some naughty fellow starts mailbombing you, but sometimes connections will be refused for legitimate users while an attack is in progress, which would result in the good guys being banned as well as the bad.

Setting bantime to something relatively short (one hour in my example) should limit fallout, since legitimate email servers will retry later, while most script kiddies will have moved on.

» Visit the project on Github…

If you run a web server and you take a look at the logs, you will likely have seen something like this appearing:

xxx.xxx.xxx.xxx - - [01/May/2013:18:32:36 +0100] "GET /w00tw00t.at.ISC.SANS.DFind:)
HTTP/1.1" 400 320 "-" "-"

This is the product of a tool called w00tw00t, which is used by nefarious script kiddies to probe and attempt to compromise your server. If your server is up-to-date, there is probably not too much to worry about (without wanting to jinx it), however since a strength in depth approach is always the best plan when it comes to security, it is probably a good idea if we could deploy some additional countermeasures.

A common tactic is to use a tool like fail2ban to monitor your logs and then firewall off the offenders IP address, and there are filters out there to do this.

However, like a lot of people, I use the caching proxy Squid, in reverse proxy mode, to help handle high load on a web server. Since, in this configuration, Apache (and therefore fail2ban’s standard w00tw00t rules) will see these requests as coming from the cache machine, we need to take another approach.

One option is to modify the Apache log format to use the X-Forwarded-For variable instead (details of how can be found here), and thus preserving the original IP address in the logs. However, this would require me to modify a number of vhosts, and it seemed simpler to monitor the one squid access log.

So, I wrote a quick fail2ban filter to catch w00tw00t scans and block the offending IP address.

In jail.local

[squid-w00tw00t]
enabled = true
filter = squid-w00tw00t
port = all
logpath = /var/log/squid/access.log
maxretry = 1

In filter.d/squid-w00tw00t.conf

# Fail2Ban configuration file to catch w00tw00t scans on squid reverse proxy settings
#
# Author: Marcus Povey
#

[INCLUDES]

# Read common prefixes. If any customizations available -- read them from
# common.local
before = common.conf

[Definition]

_daemon = squid

# Option: failregex
# Notes.: regex to match the password failures messages in the logfile. The
# host must be matched by a group named "host". The tag "" can
# be used for standard IP/hostname matching and is only an alias for
# (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
# Values: TEXT
#
failregex = <HOST> TCP_.*http.*/(w00tw00t|wootwoot|WootWoot|WooTWooT).*$

# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex =

» Visit the project on Github…

DNS is the system which converts a human readable address, like www.google.com, into the IP address that the computer actually uses to route your connection through the internet, e.g. 173.194.34.179.

This works very well, however, it is a clear text protocol. So, even if all other traffic from your computer is encrypted (for example, by routing your outbound traffic through a VPN – more on that later), you may still be “leaking” your browsing activity to others on your network.

Since I intend to do my best to stamp out cleartext wherever it may be, this is a problem for me.

Encrypting DNS

Unfortunately, DNS is still very much a legacy technology as far as modern security practices are concerned, and does not natively support encryption. Fortunately, OpenDNS, a distributed DNS alternative, have provided DNSCrypt, which is open source, and will encrypt dns connections between your computer and their servers.

DNSCrypt will help protect your browsing from being snooped on, however, you should be aware it’s not foolproof; while people on the same WIFI hotspot / your ISP will not be able especially if you see a lot of error (broken trust chain) resolving ... messages in your system log and your connection stops working when forwarding upstream.to see the clear text of the DNS resolution flash by, once it’s resolved into an IP address, they will still see the outbound connection. So, while they won’t see www.google.com in their capture logs, they will still see that you made a connection to 173.194.34.179, which an attacker can resolve back into www.google.com if they have the motivation. To protect against this, you must deploy this technology along side a VPN of some sort, which will encrypt the whole communication, at least until the VPN outputs onto the internet proper.

All that said, I’ve got it turned on on my home network (since there’s no sense in making an attacker’s life easy), and I’ve got it running on my laptop to give me extra protection against snooping while surfing on public wifi, and in the case of my laptop, I also surf over a VPN.

Setting it up

By far and away the easiest thing to do is use DNSCrypt-proxy, which serves as a drop in replacement for your normal DNS server provided by your ISP. Run it on your local machine, configure your network settings to talk to 127.0.0.1, and you’re done.

In my home network, I had an additional complication, in that I run my own DNS server, which provides DNS names for various human readable names for computers and devices around the home (my computers, the NAS, the printers and so on). I wanted to preserve these, and then configure the DNS server to relay anything that wasn’t local (or cached) via the encrypted link. To accomplish this, I needed to run DNSProxy on the network DNS machine along side BIND (the traditional DNS server software), but listening on a different port.

dnscrypt-proxy --local-address=127.0.0.1:5553 --daemonize

Over on github, my fork of the project contains a Debian /etc/init.d startup script which starts the proxy up in this configuration. You may find this useful.

Then, all I’d need to do is configure BIND to use the dns proxy as a forwarder, and I should be done.

In /etc/bind/named.conf.options:

forwarders {
    127.0.0.1 port 5553;
};

You can use pretty much any port that you like, but don’t be tempted to use something obvious like 5353, since this will cause problems with any Avahi/Bonjour services you may have running.

You may also want to put a blank forwarders section in the zone file for your local domain (which is strictly speaking “correct”, but many examples don’t), e.g.:

zone "example.local" {
    type master;
    notify no;
    file "/etc/bind/db.example.local";
    forwarders { };
};

Some gotchas

First, OpenDNS by default provide “helpful” content filtering, typo correction and a search page for bad domains. This last means that any bad domain will resolve to their web servers on 67.215.65.132, which can break your resolv.conf search domain. This can cause problems in certain situations if, for example, you have subdomains or wildcards in your zone file for your local domain, and will make them only accessible by the fully qualified domain name.

A workaround for this is to create a free account on OpenDNS, register your network, and then disable their web content filtering and typo correction, although my feeling is that I may have made a mistake in the configuration.

Second, OpenDNS’ servers do not support DNSSEC despite promises to the contrary. Not sure why, probably because it would break the DNS hijacking which makes the above unrecognised domain redirection possible. Since their business is security, OpenDNS should be doing DNSSEC validation on your behalf, how much of an issue this is an open question.

Still, it’s worth noting, since you will at least see a lot of error (broken trust chain) resolving ... messages in your system log and in all probability your connection will stop working when forwarding upstream.

Happy encrypting!

Update: CloudNS, an Australian based name service, now offer DNSCrypt together with no logging. There are also a number of OpenNIC servers which are starting to support DNS Encryption, so it’s worth keeping an eye on the Tier2 server page.