First let's define with the help of Wikipedia what a dictionary attack is:
In cryptanalysis and computer security, a dictionary attack is a technique for defeating a cipher or authentication mechanism by trying to determine its decryption key or passphrase by searching likely possibilities.
A dictionary attack uses a brute-force technique of successively trying all the words in an exhaustive list called a dictionary (from a pre-arranged list of values). In contrast with a normal brute force attack, where a large proportion key space is searched systematically, a dictionary attack tries only those possibilities which are most likely to succeed, typically derived from a list of words for example a dictionary (hence the phase dictionary attack) or a bible etc. Generally, dictionary attacks succeed because many people have a tendency to choose passwords which are short (7 characters or fewer), single words found in dictionaries or simple, easily-predicted variations on words, such as appending a digit.
So as you can see, we have two "types of brute force attacks" those which use dictionary and those that does not. With this technique we will be protected from both of them.
This technique, uses iptables to block a particular IP, that has passed the threshold of a certain number of connections in a given period of time.
I will show here, some basic IPtables rules to protect a web server from brute force attacks, but this example can be adapted to other scenarios.
Basic rules, only open port 80 (http) and 22 (ssh)
This is written as a script that may be run each time your server start, or can configured to run iptables as daemon, as I will show you later.
iptables -F
iptables -A INPUT -i lo -p all -j ACCEPT
iptables -A OUTPUT -o lo -p all -j ACCEPT
iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp ! --tcp-option 2 -j REJECT --reject-with tcp-reset
iptables -A INPUT -p tcp --dport ssh -j ACCEPT
iptables -A INPUT -p tcp --dport www -j ACCEPT
iptables -P INPUT DROP
This IPtables script example, will close all port but ssh and www ports, but our server is still open to brute force attacks, so let's close this by adding two more rules that will only permit a certain number of connections to our server from a given IP.
Stop brute force attacks
Here is the example that will stop the brute force attacks.
iptables -F
iptables -A INPUT -i lo -p all -j ACCEPT
iptables -A OUTPUT -o lo -p all -j ACCEPT
iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp ! --tcp-option 2 -j REJECT --reject-with tcp-reset
iptables -A INPUT -p tcp --dport ssh -j ACCEPT
iptables -A INPUT -p tcp --dport www -j ACCEPT
iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --set
iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --update --seconds 600 \
--hitcount 2 -j DROP
iptables -P INPUT DROP
If we now run
sudo iptables -L
This is the output
Chain INPUT (policy DROP)
target prot opt source destination
DROP tcp -- anywhere anywhere tcp dpt:ssh state NEW recent: UPDATE seconds: 600 hit_count: 2 name: DEFAULT side: source
tcp -- anywhere anywhere tcp dpt:ssh state NEW recent: SET name: DEFAULT side: source
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
REJECT tcp -- anywhere anywhere tcp option=!2 reject-with tcp-reset
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
ACCEPT tcp -- anywhere anywhere tcp dpt:www
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere
The last two lines do the trick. Here is a simple explanation of what they do:
This line:
iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --set
Starts a table with each IP that starts a connection to ssh port.
And this one:
iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --update --seconds 600 \
--hitcount 2 -j DROP
Counts the number of connections that IP makes to our server in time frame of 600 seconds, if the number of connectios passed 2 (hitcount). The server will not accept any more connections from that IP for 600 seconds.
You can adjust those values to better fit your needs.
Make it automatic
If you are running Debian or Ubuntu you may run:
sudo /etc/init.d/iptables save
If you are running Arch Linux run:
sudo /etc/rc.d/iptables save
And add iptable to the daemons part in the /etc/rc.conf file.
Logging the connections
If you want to keep a log of the failed connections write something like this:
iptables -F
iptables -A INPUT -i lo -p all -j ACCEPT
iptables -A OUTPUT -o lo -p all -j ACCEPT
iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp ! --tcp-option 2 -j REJECT --reject-with tcp-reset
iptables -A INPUT -p tcp --dport ssh -j ACCEPT
iptables -A INPUT -p tcp --dport www -j ACCEPT
iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --set
iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --update --seconds 600 \
--hitcount 2 -j LOG
iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --update --seconds 600 \
--hitcount 3 -j DROP
iptables -P INPUT DROP
Look that the LOG line has a hitcount number minor that the DROP line, this will make iptables to write a line like this:
Apr 26 20:44:44 arch kernel: IN=eth0 OUT= MAC=00:19:d1:ea:e6:3f:00:11:2f:8f:f8:f8:08:00 SRC=97.107.x.x DST=200.87.x.x LEN=60 TOS=0x00 PREC=0x00 TTL=52 ID=37839 DF PROTO=TCP SPT=50094 DPT=22 WINDOW=5840 RES=0x00 SYN URGP=0
No comments:
Post a Comment