I have a FreeBSD system behind a Linux-based router (using DD-WRT firmware). The FreeBSD system is running sshd and is regularly probed by various script-kiddies.

It currently runs a script, that, upon seeing more than 3 failed attempts to login from the same IP-address, blocks the address completely. The block used to be local (using FreeBSD's ipfw), but I'd like to cover the entire LAN -- by asking the router to do the blocking. Which brings me to using Linux' means of firewalling -- the iptables.

If I use:

iptables -I INPUT -s $IP -j DROP

then the router will reject the IP trying to contact the router itself -- but will happily forward the connection to the LAN.

If I use

iptables -I FORWARD -s $IP -j DROP

it will stop attackers from reaching my LAN, but will keep the router reachable to them.

Is there some single rule -- or, at least, single command -- I can make for each attacking IP to intercept any and all traffic to and from it?

Thank you!

  • Does iptables -I FORWARD -s $IP -j DROP; iptables -I INPUT -s $IP -j DROP count as a "single" command?
    – the-wabbit
    Mar 7 '14 at 23:56
  • That is, what I'm doing right now -- so as to only ssh into the router once. But no, it does not count, in my opinion... And, ideally, I'd like a single rule -- not just a single command (that creates multiple rules) -- because I'm a little concerned for the router-memory. I don't want these rules to occupy all the RAM after a few weeks.
    – Mikhail T.
    Mar 8 '14 at 0:21
  • iptables rules are not expensive; I have many routers running with chains of 400-800 rules (for valid business reasons), plus ipsec tunnels and all the usual overhead, in 1GB of system memory - and they're fine. In addition, I believe it's a deliberate design decision by the netfilter people to pretty much completely separate the to/from-the-host and the through-the-host traffic inside the netfilter engine. Just use two rules and be done with it.
    – MadHatter
    Mar 8 '14 at 8:50
  • I might add that the magnitude of 400-800 rules is running happily even in 32 MB of memory on a couple of "my" OpenWRT nodes. The routers do not do much except routing and filtering, though
    – the-wabbit
    Mar 8 '14 at 9:21

Is there some single rule -- or, at least, single command -- I can make for each attacking IP to intercept any and all traffic to and from it?

You need the two iptables rules because you need to block two different flows.

But rather than blocking the ip-addresses directly: set up an ipset blacklist

ipset create blacklist hash:ip hashsize 4096

Setup the iptables rules to match against that blacklist, a one time effort:

 iptables -I INPUT  -m set --match-set blacklist src -j DROP 

iptables -I FORWARD  -m set --match-set blacklist src -j DROP 

And then you can use a single command to add each of the ip-addresses you need to block:

 ipset add blacklist 
 ipset add blacklist 


  • very neat solution, also applicable for OpenWRT / LEDE router software: just make sure you install ipset, this is easily done through the web interface of your router
    – ExploWare
    Oct 7 '19 at 15:05
  • Very nice indeed. I do wish this were built into Luci as a blacklist management page. Aug 17 at 1:52

There isn't a single rule that I know of but I think if you block one you should be good. You could join the two commands with && if you really need it to be on one line. Here's how you block inbound traffic:

iptables -I INPUT -p tcp -s $IP -j DROP

If you want to block port probing you can change the protocol to icmp instead. The outbound traffic can be blocked with -I OUTPUT and forwarding traffic can be blocked with -I FORWARD.


The Prerouting chain on the mangle table is checked for connections to the host and to be forwarded.

I don't have a system to test on at the moment, but try creating a rule here.

  • I would try the "raw" table first. If the OP is concerned about memory usage, blocking in PREROUTING/raw would spare the conntrack entries associated with any connection attempt.
    – the-wabbit
    Mar 8 '14 at 9:17
  • Using iptables -I PREROUTING -s $IP -j DROP blocks the $IP from neither the router itself nor from LAN. Same when I use "raw" instead of "PREROUTING".
    – Mikhail T.
    Mar 11 '14 at 13:21

If all you want to block is TCP connections then you can use

iptables -I OUTPUT -d $IP -j DROP

This way all replies for all incoming connections to INPUT or replies of connections FORWARDed will not go back to $IP. The only draw back is machines will receive SYN and try to send SYN/ACK for some time before giving up. This should have negligible impact on performance as this is already optimized enough in modern OS to protect against SYN flood attacks.

  • If the primary concern is a bytes-conscious method of reducing table size, this seems to be the best answer. It has some drawbacks, but overall this is a fairly elegant way of dealing with it. Mar 8 '14 at 4:56
  • 1
    This would be elegant, if it worked, which it doesn't. At least on my kernel (2.6.32-431.5.1 on CentOS 6.5, using iptables 1.4.7), FORWARDed traffic doesn't pass through the OUTPUT chain on the way out. My understanding is that that is a deliberate design decision on the part of Rusty and the netfilter people.
    – MadHatter
    Mar 8 '14 at 8:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.