[sentinix-list] Creative Netfilter (iptables) rules

Michel Blomgren <[email protected]>
Newsgroups gmane.linux.sentinix
Message-ID <[email protected]>
If someone finds this interesting:  here's my rc.firewall script for my 
router.  It's configured to log and drop spoofs, log excessive new 
connections, log sysflood attempts and drop anything not already connected or 
related to a connection. It uses -m state and -m limit, and the filter table, 
the mangle table and the nat table.

	Michel

_______________________________________________
SENTINIX mailing list
[email protected]
http://elevenprospect.com/mailman/listinfo/sentinix
michels_rc_firewall (text/plain, 13.1 KB)
#!/bin/sh
#
# /etc/rc.d/rc.firewall
#
# Michel's creative Netfilter firewall rules.
# Written by Michel Blomgren <[email protected]>
#
# I use this setup on my gateway (which is a NAT router/firewall).
# The box has 2 NICs, one for Inet, one for the private LAN.
#
# My ISP only provide me with dynamic IPs, so I restart this script in
# /etc/dhcpc/dhcpcd.exe when getting a new address.
#
#
# Basic scheme:
#
# The internal net (eth1) is fully allowed out, without filtering. Anything
# coming from 192.168.0.1/24 from the internal network is NATed (masquearded)
# to eth0's IP. Traffic coming into eth0 is filtered _before_ any routing takes
# place (the PREROUTING chain). All incoming traffic on eth0 is being checked
# for source address spoofing, excessive new connections, etc. Anything
# suspicious coming in on eth0 is logged by Netfilter using regular printk(),
# which is usually taken up by klogd and archived in /var/log/syslog.
#

ipt=/usr/sbin/iptables
[ ! -e $ipt ] && echo "$ipt not found!" && exit 1

echo -n "setting up netfilter (using iptables) . . . "

# there should be a better way to do this:
eth0ip=`/sbin/ifconfig eth0 | grep -o "inet addr:[[:digit:]]\+.[[:digit:]]\+.[[:digit:]]\+.[[:digit:]]\+" | sed "s/inet addr://g"`

# flush all chains down the drain..
$ipt -F
# delete user-defined chains..
$ipt -X
# reset the packet/byte counters..
$ipt -Z

#
# set up policy defaults for the "filter" table
#
$ipt -P INPUT DROP
$ipt -P FORWARD DROP
$ipt -P OUTPUT ACCEPT

#
# we use the mangle table to capture anything coming in, especially
# _before_ NATing anything!
#
$ipt -t mangle -F
$ipt -t mangle -X
$ipt -t mangle -Z

$ipt -t mangle -P PREROUTING DROP
$ipt -t mangle -P POSTROUTING ACCEPT
$ipt -t mangle -P OUTPUT ACCEPT

#
# we use the NAT table to NAT internal traffic going out.
#
$ipt -t nat -F
$ipt -t nat -X
$ipt -t nat -Z

#
# default policies for the NAT table
#
$ipt -t nat -P PREROUTING ACCEPT
$ipt -t nat -P POSTROUTING ACCEPT
$ipt -t nat -P OUTPUT ACCEPT



#
# I have a few user defined rules that are "called" from rules further below.
#

#$ipt -t mangle -N dummy	# create a dummy chain for testing

$ipt -t mangle -N antispoof
    # anti-spoof rules
    #
    # basically, we only need source address spoof checking, but I don't trust
    # my ISP, so I'll do destination address spoofing too.
    #
    # I also do logging of any spoof attacks on this box, but only from eth0.
    # Why not eth1 too? Well... erhhmm... *cough* I do spoof attacks from my box through eth1. ;)
    # Logging is limited, not every packet is logged, only a few each minute are
    # logged, that prevents any incoming resource DoS attacks.
    #

    # traffic on eth0 from eth0's address to eth0's address, good one, but I don't think so!
    # I have actually logged some of these, very interesting :^)
    $ipt -t mangle -A antispoof -i eth0 -s ${eth0ip} -d ${eth0ip} -m limit --limit 30/min --limit-burst 1 -j LOG --log-prefix 'srcdst_spoof: '
    $ipt -t mangle -A antispoof -i eth0 -s ${eth0ip} -d ${eth0ip} -j DROP

    # traffic on eth0 from localhost? no way...
    $ipt -t mangle -A antispoof -i eth0 -s 127.0.0.1/8 -m limit --limit 30/min --limit-burst 1 -j LOG --log-prefix 'srcspoof: '
    $ipt -t mangle -A antispoof -i eth0 -s 127.0.0.1/8 -j DROP

    $ipt -t mangle -A antispoof -i eth0 -d 127.0.0.1/8 -m limit --limit 30/min --limit-burst 1 -j LOG --log-prefix 'dstspoof: '
    $ipt -t mangle -A antispoof -i eth0 -d 127.0.0.1/8 -j DROP

    # traffic on eth0 from RFC1918 private (10.) class A net? drop 'em dead...
    # my ISP's gateway generates HSRP protocol traffic from 10.
    #$ipt -t mangle -A antispoof -i eth0 -s 10.0.0.0/8 -m limit --limit 30/min --limit-burst 1 -j LOG --log-prefix 'srcspoof: '
    $ipt -t mangle -A antispoof -i eth0 -s 10.0.0.0/8 -j DROP

    $ipt -t mangle -A antispoof -i eth0 -d 10.0.0.0/8 -m limit --limit 30/min --limit-burst 1 -j LOG --log-prefix 'dstspoof: '
    $ipt -t mangle -A antispoof -i eth0 -d 10.0.0.0/8 -j DROP

    # traffic on eth0 from RFC1928 private (172.16 - 172.31) class B net? drop!
    $ipt -t mangle -A antispoof -i eth0 -s 172.16.0.0/12 -m limit --limit 30/min --limit-burst 1 -j LOG --log-prefix 'srcspoof: '
    $ipt -t mangle -A antispoof -i eth0 -s 172.16.0.0/12 -j DROP

    $ipt -t mangle -A antispoof -i eth0 -d 172.16.0.0/12 -m limit --limit 30/min --limit-burst 1 -j LOG --log-prefix 'dstspoof: '
    $ipt -t mangle -A antispoof -i eth0 -d 172.16.0.0/12 -j DROP

    # drop traffic on eth0 from RFC1918 private (192.168.) class C net...
    $ipt -t mangle -A antispoof -i eth0 -s 192.168.0.0/16 -m limit --limit 30/min --limit-burst 1 -j LOG --log-prefix 'srcspoof: '
    $ipt -t mangle -A antispoof -i eth0 -s 192.168.0.0/16 -j DROP

    $ipt -t mangle -A antispoof -i eth0 -d 192.168.0.0/16 -m limit --limit 30/min --limit-burst 1 -j LOG --log-prefix 'dstspoof: '
    $ipt -t mangle -A antispoof -i eth0 -d 192.168.0.0/16 -j DROP

    # drop traffic on eth0 from class D multicast...
    $ipt -t mangle -A antispoof -i eth0 -s 224.0.0.0/4 -m limit --limit 30/min --limit-burst 1 -j LOG --log-prefix 'srcspoof: '
    $ipt -t mangle -A antispoof -i eth0 -s 224.0.0.0/4 -j DROP

    $ipt -t mangle -A antispoof -i eth0 -d 224.0.0.0/4 -m limit --limit 30/min --limit-burst 1 -j LOG --log-prefix 'dstspoof: '
    $ipt -t mangle -A antispoof -i eth0 -d 224.0.0.0/4 -j DROP

    # drop traffic on eth0 from class E 'reserved net'...
    $ipt -t mangle -A antispoof -i eth0 -s 240.0.0.0/5 -m limit --limit 30/min --limit-burst 1 -j LOG --log-prefix 'srcspoof: '
    $ipt -t mangle -A antispoof -i eth0 -s 240.0.0.0/5 -j DROP

    $ipt -t mangle -A antispoof -i eth0 -d 240.0.0.0/5 -m limit --limit 30/min --limit-burst 1 -j LOG --log-prefix 'dstspoof: '
    $ipt -t mangle -A antispoof -i eth0 -d 240.0.0.0/5 -j DROP

    # other spoofed IPs are not dropped or logged (out of very obvious reasons
    # of course), but that's OK, I don't have any internal addresses of that
    # nature anyway and I have no trust rules for my own IP range either.


#
# I have commented out the first -p \! tcp rows, I call these chains using -p
# tcp below, so the result is the same.
#

# attempt to capture synfloods for statistic reasons
#
# I don't have that much traffic on this box, so I keep quite short timings
# here, you may need to increase these a lot or logging itself will be
# excessive.
$ipt -t mangle -N synflood
#    $ipt -t mangle -A synflood -p \! tcp -j RETURN
    $ipt -t mangle -A synflood -p tcp --tcp-flags SYN,ACK,RST,FIN SYN -m limit --limit 10/sec --limit-burst 1 -j RETURN
    $ipt -t mangle -A synflood -p tcp --tcp-flags SYN,ACK,RST,FIN SYN -m limit --limit 15/min --limit-burst 1 -j LOG --log-prefix 'possible synflood: '
# uncomment to drop synflood attempts, NOT RECOMMENDED!
#    $ipt -t mangle -A synflood -i eth0 -p tcp --tcp-flags SYN,ACK,RST,FIN SYN -j DROP


# capture excessive NEW connection states
# see the synflood comment above
$ipt -t mangle -N exnew
#    # not NEW states are skipped
#    $ipt -t mangle -A exnew -m state --state \! NEW -j RETURN
    # only 10 new connections per second, otherwise log it
    $ipt -t mangle -A exnew -m state --state NEW -m limit --limit 10/sec --limit-burst 1 -j RETURN
    $ipt -t mangle -A exnew -m limit --limit 15/min --limit-burst 1 -j LOG --log-prefix 'excessive NEW: '


# attempt to capture Nmap xmastree packets (FIN, URG, PSH). 
# Hping2 --xmas and --ymas generates a ECE (or ECNE, ECN-Echo) and CWR
# respectively, which we can't match directly, but the Nullscan rule
# below will take care of those anyway. :)
$ipt -t mangle -N xmas
#    $ipt -t mangle -A xmas -p \! tcp -j RETURN
    $ipt -t mangle -A xmas -p tcp --tcp-flags FIN,URG,PSH FIN,URG,PSH -m limit --limit 30/min --limit-burst 1 -j LOG --log-prefix 'xmastree: '

# capture FIN packets (FIN)
$ipt -t mangle -N finscan
#    $ipt -t mangle -A finscan -p \! tcp -j RETURN
    $ipt -t mangle -A finscan -p tcp --tcp-flags ALL FIN -m limit --limit 30/min --limit-burst 1 -j LOG --log-prefix 'finscan: '

# attempt to capture NULL scans
$ipt -t mangle -N nullscan
#    $ipt -t mangle -A nullscan -p \! tcp -j RETURN
    $ipt -t mangle -A nullscan -p tcp --tcp-flags ALL NONE -m limit --limit 30/min --limit-burst 1 -j LOG --log-prefix 'nullscan: '

# create a chain for icmp ECHO request logging,
# then do some limiting, only 5 icmp ECHO request (type 8) packets per second,
# the others (excessive) we drop.
$ipt -t mangle -N icmpchk
    $ipt -t mangle -A icmpchk -p icmp --icmp-type 8 -m limit --limit 5/sec --limit-burst 1 -j ACCEPT
    $ipt -t mangle -A icmpchk -p icmp --icmp-type 8 -m limit --limit 15/min --limit-burst 1 -j LOG --log-prefix 'excessive icmp echo: '
    $ipt -t mangle -A icmpchk -p icmp --icmp-type 8 -j DROP



################################################################
# the mangle table
#
# We'll be using the PREROUTING target to capture spoofs and other
# mal-traffic. PREROUTING is packets coming in, can be designated to
# anywhere, unlike FORWARD. We'll use PREROUTING to detect spoofs and
# scans. PREROUTING is checked before INPUT and FORWARD, etc., so we can
# use it for both INPUT (traffic coming into the box itself) and FORWARD
# (the NAT traffic we need to check, before even NATing it).
#
# Worth noting: _all_ interfaces go through (naturally) the PREROUTING chain,
# including lo, so we need to allow lo through explicitly.
#

# let packets in to loopback
$ipt -t mangle -A PREROUTING -i lo -j ACCEPT
# let packets in on eth1
$ipt -t mangle -A PREROUTING -i eth1 -j ACCEPT

# the synflood test chain is called first in the PREROUTING chain for incoming traffic on eth0
$ipt -t mangle -A PREROUTING -i eth0 -p tcp -j synflood

# log excessive NEW connection states (any protocol but icmp)
$ipt -t mangle -A PREROUTING -i eth0 -p \! icmp -m state --state NEW -j exnew

# log xmastree packets (Nmap)
$ipt -t mangle -A PREROUTING -i eth0 -p tcp -j xmas

# log FIN-only packets
$ipt -t mangle -A PREROUTING -i eth0 -p tcp -j finscan

# log NULL packets (will log nmap -sN, hping2 --xmas and/or --ymas, e.g.)
$ipt -t mangle -A PREROUTING -i eth0 -p tcp -j nullscan

# log and drop any spoof attempts to and through this box
$ipt -t mangle -A PREROUTING -i eth0 -j antispoof

#
# after spoof filtering, allow all already ESTABLISHED and RELATED traffic through.
#
$ipt -t mangle -A PREROUTING -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT

# icmp:
# log and drop excessive ICMP Echo Requests
$ipt -t mangle -A PREROUTING -i eth0 -p icmp -j icmpchk
#
# allow ICMP destination unreachable (type 3)
# allow host-unreachable (type 3, code 1)
$ipt -t mangle -A PREROUTING -i eth0 -p icmp --icmp-type 3/1 -j ACCEPT

# allow port-unreachable (type 3, code 3)
$ipt -t mangle -A PREROUTING -i eth0 -p icmp --icmp-type 3/3 -j ACCEPT

# fragmentation-needed (type 3, code 4) must be allowed through, or we're not RFC compliant
$ipt -t mangle -A PREROUTING -i eth0 -p icmp --icmp-type 3/4 -j ACCEPT

# icmp source quench (type 4).  bad idea to filter out.
$ipt -t mangle -A PREROUTING -i eth0 -p icmp --icmp-type 4 -j ACCEPT

#
# final check, don't allow any internal addresses in packets coming into eth0
#
$ipt -t mangle -A PREROUTING -i eth0 -s \! 192.168.0.0/24 -d \! 192.168.0.0/24 -j ACCEPT

# policy kicks in here (DROP)




##############################################################################
# INPUT chain - traffic coming in to the box (designated for the box)
#
# This is in the "filter" table, it could've probably been better to have
# what's below in the mangle table above and have the "filter" table all open,
# or change the mangle table's PREROUTING policy to ACCEPT. It's all up to you
# how to solve it.
#
# You have to open up any traffic you want in both here  _and_ in the mangle
# table above!
#

# trust loopback
$ipt -A INPUT -i lo -j ACCEPT

# accept already established/related traffic to the box
$ipt -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT

# only allow incoming traffic on port 53 from the windoze box
$ipt -A INPUT -i eth1 -s 192.168.0.203 -p udp --dport 53 -j ACCEPT

# drop packets from windoze box, spoofed packets (from the windoze box)
# are still allowed through though!
$ipt -A INPUT -i eth1 -s 192.168.0.203 -j DROP
# otherwise trust whatever eth1 is connected to (backend)
$ipt -A INPUT -i eth1 -j ACCEPT

# accept all ICMP, it's been filtered in the PREROUTING chain above.
$ipt -A INPUT -p icmp -j ACCEPT

## open http
#$ipt -A INPUT -p tcp --dport http -j ACCEPT
#$ipt -A INPUT -p tcp --dport https -j ACCEPT

## open ftp
#$ipt -A INPUT -p tcp --dport ftp -j ACCEPT

# policy kicks in here (DROP)



#################################################################################################
# NAT from "backend" (eth1) to "frontend" (eth0)
#

# Allow forwarding between eth1 and eth0, we are light on security here,
# since we've already (hopefully) captured any spoofs. We do allow spoofs
# coming from the private net though.
$ipt -A FORWARD -i eth1 -o eth0 -s 192.168.0.0/24 -j ACCEPT
$ipt -A FORWARD -i eth0 -o eth1 -d 192.168.0.0/24 -j ACCEPT

# Source NAT altering
#$ipt -t nat -A POSTROUTING -o eth0 -s 192.168.0.0/24 -j SNAT --to ${eth0ip}

# MASQUERADE instead, since I have dynamic IPs.
$ipt -t nat -A POSTROUTING -o eth0 -s 192.168.0.0/24 -j MASQUERADE

#
# end of NAT
#

echo "done!"
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.