iptables: allow certain ips and block all other connection

  • How do I allow certain ips and block all other connection in iptables?

    As Gilles demonstrates the concept goes like this: Add ACCEPT rules for each specific thing you want to allow whether by source IP or other qualifications, then set the default policy to REJECT.

  • 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 ipset and 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 -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 -j ACCEPT
    iptables -A OUTPUT -d -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 -i lo and -o lo will 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

    @PawelCioch why would KeePass2 need internet connection anyway?

    @Alex to store DB file in the remote location, this I want single IP. But I figure out everything, the setup is more complicated that the example here

  • 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 -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?

    @gilles yes, but if you're going to use it you should LIMIT it.

  • 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)


License under CC-BY-SA with attribution

Content dated before 6/26/2020 9:53 AM