No, once a packet gets sent to ACCEPT, that's the end of the line for it (pun intended). Same goes for DROP and REJECT. If the purpose of this example is to allow any IP except 123.456.789.000 to connect to port 22, you could do it like:
Code:
iptables -A INPUT -p TCP --dport 22 -s 123.456.789.000 -j DROP
iptables -A INPUT -p TCP --dport 22 -m state --state NEW -j ACCEPT
Packets traverse chains from top to bottom, so the order is important. Notice how, since we specificed TCP port 22 in both rules, a person using IP 123.456.789.000 won't be able to connect to TCP port 22, but will be able to connect to any other port (including UDP port 22). To *completely* filter packets from that IP, regardless of the port (or protocol), we'd need to make the rule more general:
Code:
iptables -A INPUT -s 123.456.789.000 -j DROP
iptables -A INPUT -p TCP --dport 22 -m state --state NEW -j ACCEPT
Now we can say the IP has been completely blacklisted.
If you would like to have a chain specifically designed to make sure no blacklisted IPs connect to our box it's sort of the same as with a bad packet chain. For example, let's say we have a box with HTTP (TCP port 80), HTTPS (TCP port 443), SSH (TCP port 22), and BitTorrent (TCP ports 6881-6999) services:
Code:
iptables -P INPUT DROP
iptables -N CHECKLIST
iptables -A CHECKLIST -s 123.123.123.123 -j DROP
iptables -A CHECKLIST -s 456.456.456.456 -j DROP
iptables -A CHECKLIST -s 789.789.789.789 -j DROP
iptables -A CHECKLIST -j RETURN
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -m state --state NEW -j CHECKLIST
iptables -A INPUT -p TCP -m multiport --dports 80,443,22,6881:6999 \
-m state --state NEW -j ACCEPT
iptables -A INPUT -j LOG --log-prefix "INPUT DROP: "
A couple things to point-out here. Notice how I've placed the "-j CHECKLIST" rule _below_ the RELATED,ESTABLISHED rule. This is so that packets which are already part of RELATED or ESTABLISHED connections don't have to each get checked. On systems with a crapload of blacklisted IPs and a crapload of connections this *could* be a performance saver. Only attempts to start new connections get checked to see if the connection is trying to be started by a bad IP.
The second thing I'd like to point-out is that we are only sending to CHECKLIST packets of state NEW, so if, for example, one of the bad IPs would send us packets in state INVALID, they wouldn't get sent to CHECKLIST, but would run into the chain's policy of DROP right after they got sent to LOG. This could be useful if we wanted to know about INVALID packets even if they came from a bad IP. If we didn't really care about anything from a bad IP then removing the NEW state match from the rule would suffice to send anything from a bad IP to DROP silently:
Code:
iptables -P INPUT DROP
iptables -N CHECKLIST
iptables -A CHECKLIST -s 123.123.123.123 -j DROP
iptables -A CHECKLIST -s 456.456.456.456 -j DROP
iptables -A CHECKLIST -s 789.789.789.789 -j DROP
iptables -A CHECKLIST -j RETURN
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -j CHECKLIST
iptables -A INPUT -p TCP -m multiport --dports 80,443,22,6881:6999 \
-m state --state NEW -j ACCEPT
iptables -A INPUT -j LOG --log-prefix "INPUT DROP: "
Also, if we wanted to have a log of all packets from blacklisted IPs wihtout having to make a LOG rule for each IP we could do it by creating a chain specially for blacklisting IPs:
Code:
iptables -P INPUT DROP
iptables -N CHECKLIST
iptables -N BLACKLIST
iptables -A CHECKLIST -s 123.123.123.123 -j BLACKLIST
iptables -A CHECKLIST -s 456.456.456.456 -j BLACKLIST
iptables -A CHECKLIST -s 789.789.789.789 -j BLACKLIST
iptables -A CHECKLIST -j RETURN
iptables -A BLACKLIST -j LOG --log-prefix "BLACKLISTED PACKET: "
iptables -A BLACKLIST -j DROP
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -j CHECKLIST
iptables -A INPUT -p TCP -m multiport --dports 80,443,22,6881:6999 \
-m state --state NEW -j ACCEPT
iptables -A INPUT -j LOG --log-prefix "INPUT DROP: "
Of course, bad packet chains would be applied to *all* packets, so you'd usually see the bad packet rule appear even before the RELATED,ESTABLISHED one, like:
Code:
iptables -P INPUT DROP
iptables -N CHECKLIST
iptables -N BLACKLIST
iptables -N BADPACKETS
iptables -A CHECKLIST -s 123.123.123.123 -j BLACKLIST
iptables -A CHECKLIST -s 456.456.456.456 -j BLACKLIST
iptables -A CHECKLIST -s 789.789.789.789 -j BLACKLIST
iptables -A CHECKLIST -j RETURN
iptables -A BLACKLIST -j LOG --log-prefix "BLACKLISTED PACKET: "
iptables -A BLACKLIST -j DROP
iptables -A BADPACKETS -p TCP ! --syn -m state --state NEW -j LOG \
--log-prefix "BAD PACKET NEW NOT SYN: "
iptables -A BADPACKETS -p TCP ! --syn -m state --state NEW -j DROP
iptables -A BADPACKETS -p TCP --tcp-flags ALL NONE -j LOG \
--log-prefix "BAD PACKET NO FLAGS: "
iptables -A BADPACKETS -p TCP --tcp-flags ALL NONE -j DROP
iptables -A INPUT -j BADPACKETS
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -j CHECKLIST
iptables -A INPUT -p TCP -m multiport --dports 80,443,22,6881:6999 \
-m state --state NEW -j ACCEPT
iptables -A INPUT -j LOG --log-prefix "INPUT DROP: "
Remember that packets will only traverse user-created chains when they are sent there from a built-in chain. This is why we can have our user-created chains at the top of the script without any problems, since the packet will hit the INPUT chain first (in these examples). But note that if you execute an INPUT rule (or any other rule in a built-in chain) where you send the packet to a user-created chain, that user-created chain must have already been created when the command is executed, otherwise an error will occur.
That is why we can do a:
Code:
iptables -N CHECKLIST
iptables -N BLACKLIST
iptables -A CHECKLIST -s 123.123.123.123 -j BLACKLIST
iptables -A CHECKLIST -s 456.456.456.456 -j BLACKLIST
iptables -A CHECKLIST -s 789.789.789.789 -j BLACKLIST
iptables -A CHECKLIST -j RETURN
iptables -A BLACKLIST -j LOG --log-prefix "BLACKLISTED PACKET: "
iptables -A BLACKLIST -j DROP
But we can NOT do a:
Code:
iptables -N CHECKLIST
iptables -A CHECKLIST -s 123.123.123.123 -j BLACKLIST
iptables -A CHECKLIST -s 456.456.456.456 -j BLACKLIST
iptables -A CHECKLIST -s 789.789.789.789 -j BLACKLIST
iptables -A CHECKLIST -j RETURN
iptables -N BLACKLIST
iptables -A BLACKLIST -j LOG --log-prefix "BLACKLISTED PACKET: "
iptables -A BLACKLIST -j DROP