iptables: allow certain ips and block all other connection
I wrote a blog post on basic Iptables rules for the desktop user a long time ago and you should probably read it, and its linked article on Stateful firewall design. But pre kernel 2.6.39 (which includes
ipsetand you may want to use that for whitelisting IP's if you have more than 10 to whitelist (where 10 is arbitrary)).
First handle state's that we know we want to accept or drop, and interfaces.
iptables -P FORWARD DROP # we aren't a router iptables -A INPUT -m state --state INVALID -j DROP iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -s 192.168.1.1 -j ACCEPT iptables -P INPUT DROP # Drop everything we don't accept
If you just want to do an allow by IP only, without state
iptables -A INPUT -s 192.168.1.1 -j ACCEPT iptables -A OUTPUT -d 192.168.1.1 -j ACCEPT iptables -P INPUT DROP iptables -P OUTPUT DROP
you are likely to run into problems doing this though, and I suggest using state to make your life easier. For example, not allowing
-o lowill certainly cause problems for certain applications.
Rather than DROP, you should REJECT unwanted packets, because it makes diagnosing issues a lot easier and prevents timeouts. See Reject IP packets with an ICMP error, or just drop them?
I tried both setups and KeePass2 won't start, any idea? Also if I do `iptables -F` that supposed to clear all rules, can't even ping ubuntu.com
Here's an (untested!) example that blocks incoming connections only. Connections over the loopback interface, coming from 192.168.3.x, ICMP, or to the SSH port are allowed. All other connections are rejected.
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A INPUT -p icmp -j ACCEPT iptables -A INPUT -p tcp --dport 22 -j ACCEPT iptables -A INPUT -s 192.168.3.0/24 -j ACCEPT iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -j REJECT
@Gilles to properly use RELATED and ESTABLISHED states, you need to match the initial packet as a NEW state. `lo` in the above example is excluded from state matching and always allowed.
@penguin359: Could you elaborate on why NEW is needed? I'm far from an iptables expert, I partly copied these rules from my home router, which doesn't match on NEW. As far as I understand, all that's left after the first rule is NEW (or UNTRACKED) packets anyway. (If I'm too far off the mark and you can't explain in a comment, post your versions with explanations as an answer and I'll delete mine.)
@Gilles I always drop INVALID state before accepting anything... which makes anything not INVALID, RELATED, ESTABLISHED, must be NEW state. But I don't know any reason that everything else must specify NEW. In theory though if you don't handle INVALID, and you don't specify NEW, you could end up accepting INVALID. But once INVALID is handled, it seems to me that checking for NEW state on every rule simply requires more processing for the packet.
@Gilles also a default policy of reject is bad, because it sends a reject packet for every packet that is received, this compounds a DOS attack.
@xenoterracide: Good point. Should REJECT ever be used? I've asked: Reject IP packets with an ICMP error, or just drop them?
The below rule will allow only your IP and Block all other IPs over port 22 or ssh. Test with a new terminal before disconnecting.
iptables -I INPUT -p tcp ! -s yourIPaddress --dport 22 -j DROP
thank you for the succinct answer. How would this change if I want to allow a few IPs and IP ranges. In place of `yourIPaddress` could I add a few IP addresses and ranges? And if I'm using SSH on a non-standard port like 2888, then the command would change the `22` in your example to `2288`? Also, will this also block rsync, sftp, etc to this server from all IPs except the allowed ones?
Note that `-p tcp` is important here because `--dport` does not work without it. I would also suggest using `-j REJECT` instead of `DROP` because `REJECT` makes the port identical to closed port and `DROP` makes packets destined to that port black holed. In practice, remote attacker can detect `DROP` configured ports from actually closed ports.
Here is full working example.
Also makes the applications work (re: my comment about keepass not starting)