On 12/27/2012 10:59 PM, Walter Dnes wrote:
> 
>   Here's my revised "Paranoia Plus" ruleset.  Any comments?  Because I'm
> behind a NAT-ing ADSL router/modem, many of my rules rarely see hits.
> However, I do have a backup dialup connection in case of problems, so
> most of my rules don't specify the network interface.  A couple of
> notes...
> 

I did a bunch of inline comments below as I was trying to understand the
rules. At the end I give the tl;dr, but maybe the inline comments are
useful too.


> * My little lan is 192.168.123.248/29
> * I have a TV tuner box that comes up in the zero-config space, so I
>   have to allow 169.254.0.0/16 
> * I "dislike" a certain button following me.
> 
> # Generated by iptables-save v1.4.16.3 on Thu Dec 27 22:43:12 2012
> *filter
> :INPUT DROP [0:0]
> :FORWARD DROP [0:0]
> :OUTPUT DROP [0:0]

You can save yourself some complexity by allowing outbound traffic by
default. I see that your INPUT policy is set to DROP, but you override
this in a few places: at the end of all the chains, you jump to the
PRIVATE table, which ends with a -j ACCEPT. So you'll accept anything
that isn't rejected by a previous rule.

I'd suggesting flipping that: get rid of the -j ACCEPT at the end of the
private table, and allow unmatched traffic to be dropped.



> :DROP_LOG - [0:0]
> :FECESBOOK - [0:0]
> :ICMP_IN - [0:0]
> :PRIVATE - [0:0]
> :PRIVATE_LOG - [0:0]
> :TCP_IN - [0:0]
> :UDP_IN - [0:0]
> :UNSOLICITED - [0:0]

> [0:0] -A INPUT -s 192.168.123.248/29 -i eth0 -j ACCEPT

Since you've self-proclaimed as paranoid, I don't feel bad suggesting
that you choose which ports to allow incoming, even to the LAN. If
somebody brings (or creates!) a compromised machine onto your LAN,
they're going to be able to hit any ports that you've got open and
available through the firewall. Not much you can do about that.

But you might as well prevent them from reaching everything. If you
expect to SSH from the LAN, sure, let that in. But if you're not serving
e.g. web pages, you might as well block port 80 from the LAN. This
allows you the freedom to play with apache without worrying about
whether or not you've secured it.


> [0:0] -A INPUT -s 169.254.0.0/16 -i eth0 -j ACCEPT

I don't know anything about zeroconf, not qualified to comment.


> [0:0] -A INPUT -s 69.63.176.0/20 -j FECESBOOK
> [0:0] -A INPUT -s 69.220.144.0/20 -j FECESBOOK
> [0:0] -A INPUT -s 69.63.176.0/20 -j FECESBOOK
> [0:0] -A INPUT -s 69.171.224.0/19 -j FECESBOOK
> [0:0] -A INPUT -s 200.58.112.0/20 -j FECESBOOK
> [0:0] -A INPUT -s 213.155.64.0/19 -j FECESBOOK
> [0:0] -A FECESBOOK -j LOG --log-prefix "FECESBOOK:" --log-level 6
> [0:0] -A FECESBOOK -j DROP

Cute =) That final DROP is only needed since you -j PRIVATE (which
defaults to ACCEPT) at the end of everything.


> [0:0] -A INPUT -p tcp -m tcp --sport 53 -j ACCEPT
> [0:0] -A INPUT -p udp -m udp --sport 53 -j ACCEPT

Ok, in the INPUT chain you're accepting DNS traffic early. You do it
again below, so I think the later one is redundant.


> [0:0] -A INPUT -i lo -j ACCEPT
> [0:0] -A INPUT -f -j LOG --log-prefix "FRAGMENTS:" --log-level 6
> [0:0] -A INPUT -f -j DROP
> [0:0] -A INPUT -p tcp -j TCP_IN
> [0:0] -A INPUT -p udp -j UDP_IN
> [0:0] -A INPUT -p icmp -j ICMP_IN
> [0:0] -A INPUT -j LOG --log-prefix "BAD_PROTOCOL:" --log-level 6
> [0:0] -A INPUT -j DROP

DROP is redundant, since the INPUT policy is DROP.


> [0:0] -A OUTPUT -d 192.168.123.248/29 -o eth0 -j ACCEPT
> [0:0] -A OUTPUT -o lo -j ACCEPT
> [0:0] -A OUTPUT -p icmp -m icmp --icmp-type 3 -j ACCEPT
> [0:0] -A OUTPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
> [0:0] -A OUTPUT -p icmp -m icmp --icmp-type 30 -j ACCEPT
> [0:0] -A OUTPUT -p tcp -m tcp --sport 0:1023 -j DROP_LOG
> [0:0] -A OUTPUT -p udp -m udp --sport 0:1023 -j DROP_LOG
> [0:0] -A OUTPUT -p tcp -m tcp --sport 6000:6063 -j DROP_LOG
> [0:0] -A OUTPUT -p udp -m udp --sport 6000:6063 -j DROP_LOG
> [0:0] -A OUTPUT -j ACCEPT

Aha, you're overriding the OUTPUT policy of DROP here with an ACCEPT.
You might as well set the policy to ACCEPT, and get rid of the trailing
-j ACCEPT. Anything that is explicitly ACCEPTed above but not otherwise
DROPped is also redundant, since traffic will be accepted by default if
not dropped. I see that you want to log-before-drop specific traffic;
that would still work with a policy of ACCEPT. You would add only those
rules to the OUTPUT chain.


> [0:0] -A DROP_LOG -j LOG --log-level 6
> [0:0] -A DROP_LOG -j DROP

DROP would be redundant without the -j ACCEPT at the end of the PRIVATE
TABLE.


> [0:0] -A ICMP_IN -p icmp -m conntrack --ctstate NEW -j UNSOLICITED
> [0:0] -A ICMP_IN -p icmp -m icmp --icmp-type 0 -j PRIVATE
> [0:0] -A ICMP_IN -p icmp -m icmp --icmp-type 3 -j PRIVATE
> [0:0] -A ICMP_IN -p icmp -m icmp --icmp-type 4 -j PRIVATE
> [0:0] -A ICMP_IN -p icmp -m icmp --icmp-type 11 -j PRIVATE
> [0:0] -A ICMP_IN -p icmp -m icmp --icmp-type 12 -j PRIVATE
> [0:0] -A ICMP_IN -j LOG --log-prefix "IN_BAD_ICMP:" --log-level 6
> [0:0] -A ICMP_IN -j DROP

DROP would be redundant without the -j ACCEPT at the end of the PRIVATE
TABLE.


> [0:0] -A PRIVATE -s 10.0.0.0/8 -j PRIVATE_LOG
> [0:0] -A PRIVATE -s 127.0.0.0/8 -j PRIVATE_LOG
> [0:0] -A PRIVATE -s 172.16.0.0/12 -j PRIVATE_LOG
> [0:0] -A PRIVATE -s 192.168.0.0/16 -j PRIVATE_LOG
> [0:0] -A PRIVATE -j ACCEPT

This is where you essentially set an ACCEPT policy, since all unmatched
traffic winds up here.


> [0:0] -A PRIVATE_LOG -j LOG --log-prefix "IN_BAD_ADDR:" --log-level 6
> [0:0] -A PRIVATE_LOG -j DROP

DROP would be redundant without the -j ACCEPT at the end of the PRIVATE
TABLE.


> [0:0] -A TCP_IN -p tcp -m tcp --dport 0:1023 -j DROP_LOG
> [0:0] -A TCP_IN -p tcp -m tcp --dport 6000:6063 -j DROP_LOG
> [0:0] -A TCP_IN -p tcp -m tcp --sport 53 -j PRIVATE

I think you already accepted the DNS traffic.


> [0:0] -A TCP_IN -p tcp -m tcp --sport 80 -j PRIVATE
> [0:0] -A TCP_IN -p tcp -m conntrack --ctstate NEW -m tcp -j UNSOLICITED
> [0:0] -A TCP_IN -p tcp -j PRIVATE

By jumping to the PRIVATE table at the end, you've basically set a
policy of ACCEPT, since the PRIVATE chain ends with a -j ACCEPT.


> [0:0] -A UDP_IN -p udp -m udp --dport 0:1023 -j DROP_LOG
> [0:0] -A UDP_IN -p udp -m udp --dport 6000:6063 -j DROP_LOG
> [0:0] -A UDP_IN -p udp -m udp --sport 53 -j PRIVATE

DNS, probably already accepted this.


> [0:0] -A UDP_IN -p udp -m udp --sport 80 -j PRIVATE
> [0:0] -A UDP_IN -p udp -m conntrack --ctstate NEW -j UNSOLICITED
> [0:0] -A UDP_IN -p udp -j PRIVATE

Same as at the end of TCP_IN. By jumping to the PRIVATE table at the
end, you've basically set a policy of ACCEPT for anything tcp, udp, or icmp.


> [0:0] -A UNSOLICITED -j LOG --log-prefix "UNSOLICITED:" --log-level 6
> [0:0] -A UNSOLICITED -j DROP

DROP would be redundant without the -j ACCEPT at the end of the PRIVATE
TABLE.


In the TCP_IN and UDP_IN tables, you try to reject NEW connections
before passing onto the PRIVATE chain which eventually allows the
traffic. So you kind-of have an ACCEPT policy, but you want to reject
any traffic that isn't for an established connection. This can be
simplified by switching to a default-DROP policy, and allowing
RELATED,ESTABLISHED connections through instead.

Here's an example that will almost certainly need some work (I haven't
even tried to run it).

# Flush existing rules
iptables -F

# Delete user-defined chains.
iptables -X FECESBOOK
iptables -X DROP_LOG
iptables -X TCP_IN
iptables -X UDP_IN
iptables -X ICMP_IN

# Recreate (empty) user-defined chains.
iptables -N FECESBOOK
iptables -N DROP_LOG
iptables -N TCP_IN
iptables -N UDP_IN
iptables -N ICMP_IN

# Set policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

#
# Add FECESBOOK rules
#
iptables -A FECESBOOK -j LOG --log-prefix "FECESBOOK:" --log-level 6
iptables -A FECESBOOK -j DROP

#
# Add DROP_LOG rules
#
iptables -A DROP_LOG -j LOG --log-level 6
iptables -A DROP_LOG -j DROP

#
# Add ICMP_IN rules
#
ALLOWED_ICMP="0 3 4 8 11 12 30"

for ok_icmp in ALLOWED_ICMP; do
  iptables -A ICMP_IN -p icmp --icmp-type "${ok_icmp}" -j ACCEPT
done

iptables -A ICMP_IN -j LOG --log-prefix "IN_BAD_ICMP:" --log-level 6

#
# Add TCP_IN rules
#
iptables -A TCP_IN -p tcp -m tcp --dport 0:1023 -j DROP_LOG
iptables -A TCP_IN -p tcp -m tcp --dport 6000:6063 -j DROP_LOG

# Add UDP_IN rules
iptables -A UDP_IN -p udp -m udp --dport 0:1023 -j DROP_LOG
iptables -A UDP_IN -p udp -m udp --dport 6000:6063 -j DROP_LOG


#
# Main INPUT chain
#
#
# Allow your LAN/Zeroconf stuff. For more paranoia (recommended), allow
# only specific ports.
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A INPUT -s 192.168.123.248/29 -i eth0 -j ACCEPT
iptables -A INPUT -s 169.254.0.0/16 -i eth0 -j ACCEPT

# Block this stuff before allowing related, established traffic.
# That is, block Facebook traffic, period.
# A list of Facebook CIDRs.
FECESBOOK="69.63.176.0/20 69.220.144.0/20 69.63.176.0/20 69.171.224.0/19
200.58.112.0/20 213.155.64.0/19"

for fb in $FECESBOOK; do
    iptables -A INPUT -s "${fb} -j FECESBOOK
done

# Drop fragmented packets without further consideration.
iptables -A INPUT -f -j LOG --log-prefix "FRAGMENTS:" --log-level 6
iptables -A INPUT -f -j DROP

# If you initiate a connection, allow the response to come back in.
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# For all other (i.e. NEW) traffic, filter by protocol.
iptables -A INPUT -p tcp -j TCP_IN
iptables -A INPUT -p udp -j UDP_IN
iptables -A INPUT -p icmp -j ICMP_IN

# If it isn't TCP, UDP, or ICMP, we probably don't want it.
iptables -A INPUT -j LOG --log-prefix "BAD_PROTOCOL:" --log-level 6

#
# At this point, anything not matched is dropped.
#

Reply via email to