Preventing Brute Force Attacks

From DD-WRT Wiki

Revision as of 13:53, 2 October 2008 by Jbarbieri (Talk | contribs)
Jump to: navigation, search

Contents

Preventing Brute Force Attacks

Please, corrections, and improvements to this WIKI article are welcomed and requested, as this WIKI article is currently a work in progress.......

The First Method: Basic Protection

Introduction

Thanks to the suggestion by JoFa, and the legwork, testing and code from jbarbieri, you can now rest easy in having SSH, as well as other service ports open on the WAN portion of your router for ease of use, while severely hampering the attempts of a brute force hack attempt. Remember, always use unique and long passwords!

Prerequisites

  • 'Version': theoretically any DD-WRT; tested on v24sp1+
  • 'Builds':
    • Works on: Standard, Mega
    • Doesn't work on: Micro, Micro+
    • Untested on: VoIP, VPN, custom builds

Implementing the protection for SSH

Note that this protection example is designed to prevent connections on port 22 (SSH). It will not cover telnet (it's better to disable that anyway), nor VPN (PPTP/OpenVPN). It will not work on Micro(+) builds (as of SVN 10431).

Go to the Administration -> Commands page of your router's GUI. Paste the following code in the script box the click Save Firewall:

iptables -I INPUT -p tcp --dport 22 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -I INPUT 2 -p tcp --dport 22 -m state --state NEW -m limit --limit 3/min --limit-burst 3 -j ACCEPT
iptables -I INPUT 3 -p tcp --dport 22 -j logreject

This code shown here was made for limiting connection attempts to port 22 (SSH) to only 3 per minute. You can adapt this code to implement other ports, change the amount of attempts before timeout, change the length of the timeout, etc.

Protecting TELNET in addition to SSH

The above code can be extended to protect against multiple connections on various other ports. For instance, assuming you want to protect your SSH and TELNET enabled router, you could use the following code:

iptables -I INPUT -p tcp --dport 22 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -I INPUT 2 -p tcp --dport 23 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -I INPUT 3 -p tcp --dport 22 -m state --state NEW -m limit --limit 3/min --limit-burst 3 -j ACCEPT
iptables -I INPUT 4 -p tcp --dport 23 -m state --state NEW -m limit --limit 3/min --limit-burst 3 -j ACCEPT
iptables -I INPUT 5 -p tcp --dport 22 -j logreject 
iptables -I INPUT 6 -p tcp --dport 23 -j logreject

As you can see, extending the script is not difficult; all that you must do is make sure the lines containing RELATED are first, then the ones containing NEW then the logreject lines.

Applying the concept to forwarded ports

Say your SSH server is running on a LAN machine (instead of the router). You can forward port 22 to the internal server, protecting it using the above concept.

iptables -t nat -I PREROUTING -p tcp -d $(nvram get wan_ipaddr) --dport 22 -j DNAT --to 192.168.1.101:22
iptables -I FORWARD -p tcp -d 192.168.1.101 --dport 22 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -I FORWARD 2 -p tcp -d 192.168.1.101 --dport 22 -m state --state NEW -m limit --limit 3/min --limit-burst 3 -j ACCEPT
iptables -I FORWARD 3 -p tcp --dport 22 -j logreject

Note: In this example, 192.168.1.101 is the IP of the LAN machine that is running the SSH server. It's probably best to change the external port number (dport) in the nat rule to something other than 22 if you actually intend to use these techniques yourself (using standard port for SSH is sure to get some attention by hackers, bots, etc.).

The Advanced Method: Protection For Any Open Port

Under Construction

This method, when filled in, will make use of a new chain, greatly simplifying the process of protecting other ports from brute-force attacks.


First, the rate_limit chain has to be created, and the rules entered into it:

iptables -N rate_limit
iptables -F rate_limit
iptables-A rate_limit -p tcp --dport 22 -m limit --limit 3/min --limit-burst 3 -j ACCEPT
iptables -A rate_limit -p ICMP --icmp-type echo-request -m limit --limit 3/sec -j ACCEPT
iptables -A rate_limit -p <protocol> --dport <port> -m limit --limit <x/sec/min/hr> --limit-burst X -j ACCEPT
iptables -A rate_limit -p ! ICMP -j LOG --log-prefix " Connection dropped!! "
iptables-A rate_limit -p tcp -j REJECT --reject-with tcp-reset
iptables-A rate_limit -p udp -j REJECT --reject-with icmp-port-unreachable
iptables-A rate_limit -j DROP 


To actually make use of this chain, you just need to add the rules in the INPUT chain, which makes any new connection goto the rate limit chain:

iptables -I INPUT -p ICMP --icmp-type echo-request -j rate_limit
iptables -I INPUT -p tcp --dport 22 -m state --state NEW -j rate_limit
iptables -I INPUT -p udp --dport 1194 -m state --state NEW -j rate_limit
iptables -I INPUT -p <protocol> --dport <port> -m state --state NEW -j rate_limit

This sends any new connection for SSH or OpenVPN to the rate limit chain. You can substitute any protocol and port number to have it go through the rate_limit as well. This also rate_limits ICMP pings, to 3 per second...any faster and it blocks them. Since ping floods are common, the LOG statement was changed so that if the protocol is ICMP, it will NOT log, which won't cause your router to bog down.