#!/bin/bash
# ------------------------------------------------------------------------------
# Configure a basic firewall,
# by generating a set of iptables rules (ipv4 and ipv6),
# and saving those to /etc/firewall/ipv4 and /etc/firewall/ipv6 .
# The accompanying script /etc/rc.d/rc.firewall will restore these configs.
#
# This script and rc.firewall are part of liveslak,
# a project by Eric Hameleers, see https://download.liveslak.org/
#
# Iptables ruleset handling courtesy of Easy Firewall Generator for IPTables,
# Copyright 2002 Timothy Scott Morizot
# ------------------------------------------------------------------------------
# The script accepts one parameter: the target filesystem:
DESTDIR="$1"
# This tmp directory is only writable by root:
TMP=${TMP:-"/var/log/setup/tmp"}
if [ ! -d $TMP ]; then
mkdir -p $TMP
fi
# The script defaults to curses dialog but Xdialog is a good alternative:
DIALOG=${DIALOG:-"dialog"}
# The iptables tools we use:
IPT="/usr/sbin/iptables"
IP6T="/usr/sbin/ip6tables"
IPTS="/usr/sbin/iptables-save"
IP6TS="/usr/sbin/ip6tables-save"
IPTR="/usr/sbin/iptables-restore"
IP6TR="/usr/sbin/ip6tables-restore"
# Localhost Interface
LO_IFACE="lo"
LO_IP="127.0.0.1"
LO_IP6="::1"
# The default gateway device will be our primary candidate to firewall:
GWDEV=$(/sbin/ip route show |grep ^default |cut -d' ' -f5)
# Generate a list of network devices, minus the default gateway and loopback:
AVAILDEV=$(ls --indicator-style=none /sys/class/net/ |sed -e "s/${GWDEV}//" -e "s/lo//")
# Store all network interfaces in an associative array:
declare -A NETDEVARR
NETDEVARR=( [$GWDEV]=on )
for INDEV in $AVAILDEV ; do NETDEVARR+=( [$INDEV]=off ) ; done
unset INDEV
# Store network services in another array:
declare -A SERVARR=(
['SSH']=off
['RSYNC']=off
['GIT']=off
['HTTP']=off
['HTTPS']=off
['SMTP']=off
['SMPTS']=off
['IMAP']=off
['IMAPS']=off
['NTP']=off
)
# Store the list of custom ports/port ranges:
CUSTOM_TCP_LIST=""
CUSTOM_UDP_LIST=""
# Will we auto-configure a restrictive firewall?
AUTOCONFIG="YES"
# User pressing ESC will change the default choice in the 1st dialog:
DEFAULTNO=""
# Loop over the configuration until the user is done:
MAINSELECT="start"
while [ "$MAINSELECT" != "done" ]; do
if [ "$MAINSELECT" = "start" ]; then
${DIALOG} --backtitle "@UDISTRO@ (@LIVEDE@) Basic Firewall Setup" \
--title "CONFIGURE FIREWALL" ${DEFAULTNO} \
--yesno "Would you like to protect the system with a basic firewall?\n\n\
You can either block all external connections,
or you can expose specific TCP/UDP ports.\n\n\
DHCP will never be blocked." 11 68
if [ $? != 0 ]; then
# Not needed.
exit 0
else
DEFAULTNO=""
fi
MAINSELECT="devices"
fi
if [ "$MAINSELECT" = "devices" ]; then
# Populate the network device checklist for the dialog:
NETDEVLIST="$(for I in ${!NETDEVARR[@]};do echo $I ${NETDEVARR[$I]};done)"
unset I
${DIALOG} --backtitle "@UDISTRO@ (@LIVEDE@) Basic Firewall Setup" \
--title "PICK INTERFACES" \
--stdout --separate-output \
--no-items \
--ok-label "Next" --no-cancel --extra-button --extra-label "Previous" \
--checklist "\
Select the network interface(s) exposed to the outside world.\n\
Your default gateway is pre-selected.\n\
Un-selected interfaces will accept all incoming traffic." 13 68 5 $NETDEVLIST \
> $TMP/SeTnics
RETVAL=$?
# Zero out the array values and re-enable only the ones we got returned:
for INDEV in ${!NETDEVARR[@]} ; do NETDEVARR[$INDEV]=off ; done
for INDEV in $(cat $TMP/SeTnics) ; do NETDEVARR[$INDEV]=on ; done
unset INDEV
case "$RETVAL" in
0) MAINSELECT="autoselect" ;;
3) MAINSELECT="start" ;;
*) MAINSELECT="start" ; DEFAULTNO="--defaultno" ;;
esac
rm -f $TMP/SeTnics
fi
if [ "$MAINSELECT" = "autoselect" ]; then
${DIALOG} --backtitle "@UDISTRO@ (@LIVEDE@) Basic Firewall Setup" \
--title "ALL CLOSED?" \
--yesno "Do you want to block all incoming external connections?\n\
If 'no', then you will be able to specify ports that need to be open." 7 68
RETVAL=$?
case "$RETVAL" in
0) AUTOCONFIG="YES"
MAINSELECT="done" ;;
1) AUTOCONFIG="NO"
MAINSELECT="services" ;;
*) MAINSELECT="start" ; DEFAULTNO="--defaultno" ;;
esac
fi
if [ "$MAINSELECT" = "services" ]; then
# Populate the services checklist for the dialog:
${DIALOG} --backtitle "@UDISTRO@ (@LIVEDE@) Basic Firewall Setup" \
--title "OPEN PORTS" \
--stdout --separate-output \
--ok-label "Next" --no-cancel --extra-button --extra-label "Previous" \
--checklist "\
Select the service ports you want to remain open for the outside world.\n\
You can enter more ports or portranges in the next dialog." 19 68 13 \
SSH 'SSH (port 22)' ${SERVARR['SSH']} \
RSYNC 'RSYNC (port 873)' ${SERVARR['RSYNC']} \
GIT 'GIT (port 9418)' ${SERVARR['GIT']} \
HTTP 'Web Server (HTTP port 80)' ${SERVARR['HTTP']} \
HTTPS 'Secure Web Server (HTTPS port 443)' ${SERVARR['HTTPS']} \
SMTP 'Receiving Email (SMTP port 25)' ${SERVARR['SMTP']} \
SMTPS 'Secure Receiving Email (SMPTS port 587)' ${SERVARR['SMPTS']} \
IMAP 'IMAP Email Server (IMAP port 143)' ${SERVARR['IMAP']} \
IMAPS 'Secure IMAP Email Server (IMAPS port 993)' ${SERVARR['IMAPS']} \
NTP 'Time Server (NTP port 123)' ${SERVARR['NTP']} \
> $TMP/SeTservices
RETVAL=$?
# Zero out the array values and re-enable only the ones we got returned:
for INSRV in ${!SERVARR[@]} ; do SERVARR[$INSRV]=off ; done
for INSRV in $(cat $TMP/SeTservices) ; do SERVARR[$INSRV]=on ; done
unset INSRV
case $RETVAL in
0) MAINSELECT="customports" ;;
3) MAINSELECT="autoselect" ;;
*) MAINSELECT="start" ; DEFAULTNO="--defaultno" ;;
esac
rm -f $TMP/SeTservices
fi
if [ "$MAINSELECT" = "customports" ]; then
${DIALOG} --backtitle "@UDISTRO@ (@LIVEDE@) Basic Firewall Setup" \
--title "CUSTOM PORTS" \
--stdout \
--ok-label "Next" --no-cancel --extra-button --extra-label "Previous" \
--form "\
Enter additional ports or port ranges.\n\
Port ranges consist of two numbers separated by a colon (example: 3000:3011).\n\
Separate multiple entries with commas,\n\
for example: 22,465,3000:3011,6660:6669,7000" \
13 68 2 \
"TCP ports/portranges:" 1 1 "$CUSTOM_TCP_LIST" 1 25 40 0 \
"UDP ports/portranges:" 2 1 "$CUSTOM_UDP_LIST" 2 25 40 0 \
> $TMP/SeTcustomports
RETVAL=$?
CUSTOM_TCP_LIST=$(head -1 $TMP/SeTcustomports)
CUSTOM_UDP_LIST=$(tail -1 $TMP/SeTcustomports)
case $RETVAL in
0) MAINSELECT="confirm" ;;
3) MAINSELECT="services" ;;
*) MAINSELECT="start" ; DEFAULTNO="--defaultno" ;;
esac
rm -f $TMP/SeTcustomports
fi
if [ "$MAINSELECT" = "confirm" ]; then
# Collect all service ports that need to be remotely accessible.
# TCP:
TCP_LIST=""
if [ "${SERVARR['HTTP']}" = "on" ]; then
TCP_LIST="$TCP_LIST 80"
fi
if [ "${SERVARR['HTTPS']}" = "on" ]; then
TCP_LIST="$TCP_LIST 443"
fi
if [ "${SERVARR['SMTP']}" = "on" ]; then
TCP_LIST="$TCP_LIST 25"
fi
if [ "${SERVARR['SMTPS']}" = "on" ]; then
TCP_LIST="$TCP_LIST 587"
fi
if [ "${SERVARR['IMAP']}" = "on" ]; then
TCP_LIST="$TCP_LIST 143"
fi
if [ "${SERVARR['IMAPS']}" = "on" ]; then
TCP_LIST="$TCP_LIST 993"
fi
if [ "${SERVARR['SSH']}" = "on" ]; then
TCP_LIST="$TCP_LIST 22"
fi
if [ "${SERVARR['GIT']}" = "on" ]; then
TCP_LIST="$TCP_LIST 9418"
fi
if [ "${SERVARR['RSYNC']}" = "on" ]; then
TCP_LIST="$TCP_LIST 873"
fi
TCP_LIST=$(echo $TCP_LIST | sed 's/^ *//g' | tr ' ' ',')
# UDP:
UDP_LIST=""
if [ "${SERVARR['NTP']}" = "on" ]; then
UDP_LIST="$UDP_LIST 123"
fi
if [ "${SERVARR['RSYNC']}" = "on" ]; then
UDP_LIST="$UDP_LIST 873"
fi
UDP_LIST=$(echo $UDP_LIST | sed 's/^ *//g' | tr ' ' ',')
TCP_LIST=$(echo $TCP_LIST $CUSTOM_TCP_LIST | sed 's/^ *//g' | tr ' ' ',')
UDP_LIST=$(echo $UDP_LIST $CUSTOM_UDP_LIST | sed 's/^ *//g' | tr ' ' ',')
DEV_LIST=$(for INDEV in ${!NETDEVARR[@]} ; do if [ "${NETDEVARR[$INDEV]}" = "on" ]; then echo -n $INDEV ; fi ; done)
${DIALOG} --backtitle "@UDISTRO@ (@LIVEDE@) Basic Firewall Setup" \
--title "CONFIRM CONFIGURATION" \
--yes-label "Generate" --no-label "Redo" \
--yesno "These are the ports you configured. Are you OK with them?\n\n\
Press 'Generate' to generate the firewall configuration.\n\
Else press 'Redo' to re-do the setup.\n\n\
Firewalled interface(s): $DEV_LIST \n\
TCP Ports: $TCP_LIST \n\
UDP Ports: $UDP_LIST" 12 68
RETVAL=$?
case $RETVAL in
0) MAINSELECT="done" ;;
1) MAINSELECT="devices" ;;
*) MAINSELECT="start" ; DEFAULTNO="--defaultno" ;;
esac
fi
done
# ------------------------------------------------------------------------------
# End of configuration, let's get to work.
# ------------------------------------------------------------------------------
#
# Flush Any Existing Rules or Chains
#
${DIALOG} --backtitle "@UDISTRO@ (@LIVEDE@) Basic Firewall Setup" \
--infobox "Configuring your firewall ..." 4 68
# Reset Default Policies
$IPT -P INPUT ACCEPT
$IPT -P FORWARD ACCEPT
$IPT -P OUTPUT ACCEPT
$IPT -t nat -P PREROUTING ACCEPT
$IPT -t nat -P POSTROUTING ACCEPT
$IPT -t nat -P OUTPUT ACCEPT
$IPT -t mangle -P PREROUTING ACCEPT
$IPT -t mangle -P OUTPUT ACCEPT
#
$IP6T -P INPUT ACCEPT
$IP6T -P FORWARD ACCEPT
$IP6T -P OUTPUT ACCEPT
$IP6T -t mangle -P PREROUTING ACCEPT
$IP6T -t mangle -P OUTPUT ACCEPT
# Flush all rules
$IPT -F
$IPT -t nat -F
$IPT -t mangle -F
#
$IP6T -F
$IP6T -t mangle -F
# Erase all non-default chains
$IPT -X
$IPT -t nat -X
$IPT -t mangle -X
#
$IP6T -X
$IP6T -t mangle -X
#
# Rules Configuration
#
# Filter Table
#
# Set Policies
$IPT -P INPUT DROP
$IPT -P OUTPUT DROP
$IPT -P FORWARD DROP
#
$IP6T -P INPUT DROP
$IP6T -P OUTPUT DROP
$IP6T -P FORWARD DROP
#
# User-Specified Chains
#
# Create user chains to reduce the number of rules each packet must traverse.
#
# Create a chain to filter INVALID packets
$IPT -N bad_packets
$IP6T -N bad_packets
# Create another chain to filter bad tcp packets
$IPT -N bad_tcp_packets
$IP6T -N bad_tcp_packets
# Create separate chains for icmp, tcp (incoming and outgoing),
# and incoming udp packets.
$IPT -N icmp_packets
$IP6T -N icmp_packets
# Used for UDP packets inbound from the Internet
$IPT -N udp_inbound
$IP6T -N udp_inbound
# Used to block outbound UDP services from internal network
# Default to allow all
$IPT -N udp_outbound
$IP6T -N udp_outbound
# Used to allow inbound services if desired
# Default fail except for established sessions
$IPT -N tcp_inbound
$IP6T -N tcp_inbound
# Used to block outbound services from internal network
# Default to allow all
$IPT -N tcp_outbound
$IP6T -N tcp_outbound
#
# Populate User Chains
#
# bad_packets chain
#
# Drop INVALID packets immediately
$IPT -A bad_packets -p ALL -m state --state INVALID -j DROP
$IP6T -A bad_packets -p ALL -m state --state INVALID -j DROP
# Then check the tcp packets for additional problems
$IPT -A bad_packets -p tcp -j bad_tcp_packets
$IP6T -A bad_packets -p tcp -j bad_tcp_packets
# All good, so return
$IPT -A bad_packets -p ALL -j RETURN
$IP6T -A bad_packets -p ALL -j RETURN
# bad_tcp_packets chain
#
# All tcp packets will traverse this chain.
# Every new connection attempt should begin with
# a syn packet. If it doesn't, it is likely a
# port scan. This drops packets in state
# NEW that are not flagged as syn packets.
$IPT -A bad_tcp_packets -p tcp ! --syn -m state --state NEW -j DROP
$IP6T -A bad_tcp_packets -p tcp ! --syn -m state --state NEW -j DROP
$IPT -A bad_tcp_packets -p tcp --tcp-flags ALL NONE -j DROP
$IP6T -A bad_tcp_packets -p tcp --tcp-flags ALL NONE -j DROP
$IPT -A bad_tcp_packets -p tcp --tcp-flags ALL ALL -j DROP
$IP6T -A bad_tcp_packets -p tcp --tcp-flags ALL ALL -j DROP
$IPT -A bad_tcp_packets -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
$IP6T -A bad_tcp_packets -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
$IPT -A bad_tcp_packets -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
$IP6T -A bad_tcp_packets -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
$IPT -A bad_tcp_packets -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
$IP6T -A bad_tcp_packets -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
$IPT -A bad_tcp_packets -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
$IP6T -A bad_tcp_packets -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
# All good, so return
$IPT -A bad_tcp_packets -p tcp -j RETURN
$IP6T -A bad_tcp_packets -p tcp -j RETURN
# icmp_packets chain
#
# This chain is for inbound (from the Internet) icmp packets only.
# Type 8 (Echo Request) is not accepted by default
# Enable it if you want remote hosts to be able to reach you.
# 11 (Time Exceeded) is the only one accepted
# that would not already be covered by the established
# connection rule. Applied to INPUT on the external interface.
#
# See: http://www.ee.siue.edu/~rwalden/networking/icmp.html
# for more info on ICMP types.
#
# Note that the stateful settings allow replies to ICMP packets.
# These rules allow new packets of the specified types.
# ICMP packets should fit in a Layer 2 frame, thus they should
# never be fragmented. Fragmented ICMP packets are a typical sign
# of a denial of service attack.
$IPT -A icmp_packets --fragment -p icmp -j DROP
$IP6T -A icmp_packets -p ipv6-icmp -m ipv6header --header frag --soft -j DROP
# Echo - uncomment to allow your system to be pinged.
# $IPT -A icmp_packets -p icmp -s 0/0 --icmp-type 8 -j ACCEPT
# $IP6T -A icmp_packets -p ipv6-icmp -s 0/0 --icmpv6-type 8 -j ACCEPT
# By default, however, drop pings without logging. Blaster
# and other worms have infected systems blasting pings.
# Comment the line below if you want pings logged, but it
# will likely fill your logs.
$IPT -A icmp_packets -p icmp -s 0/0 --icmp-type 8 -j DROP
$IP6T -A icmp_packets -p ipv6-icmp -s 0/0 --icmpv6-type 8 -j DROP
# Time Exceeded
$IPT -A icmp_packets -p icmp -s 0/0 --icmp-type 11 -j ACCEPT
$IP6T -A icmp_packets -p ipv6-icmp -s 0/0 --icmpv6-type 11 -j ACCEPT
# Not matched, so return so it will be logged
$IPT -A icmp_packets -p icmp -j RETURN
$IP6T -A icmp_packets -p ipv6-icmp -j RETURN
# TCP & UDP
# Identify ports at:
# http://www.chebucto.ns.ca/~rakerman/port-table.html
# http://www.iana.org/assignments/port-numbers
# udp_inbound chain
#
# This chain describes the inbound UDP packets it will accept.
# It's applied to INPUT on the external or Internet interface.
# Note that the stateful settings allow replies.
# These rules are for new requests.
# It drops netbios packets (windows) immediately without logging.
# Drop netbios calls
# Please note that these rules do not really change the way the firewall
# treats netbios connections. Connections from the localhost and
# internal interface (if one exists) are accepted by default.
# Responses from the Internet to requests initiated by or through
# the firewall are also accepted by default. To get here, the
# packets would have to be part of a new request received by the
# Internet interface. You would have to manually add rules to
# accept these. I added these rules because some network connections,
# such as those via cable modems, tend to be filled with noise from
# unprotected Windows machines. These rules drop those packets
# quickly and without logging them. This prevents them from traversing
# the whole chain and keeps the log from getting cluttered with
# chatter from Windows systems.
$IPT -A udp_inbound -p udp -s 0/0 --dport 137 -j DROP
$IPT -A udp_inbound -p udp -s 0/0 --dport 138 -j DROP
$IP6T -A udp_inbound -p udp -s 0/0 --dport 137 -j DROP
$IP6T -A udp_inbound -p udp -s 0/0 --dport 138 -j DROP
# Ident requests (Port 113) must have a REJECT rule rather than the
# default DROP rule. This is the minimum requirement to avoid
# long delays while connecting. Also see the tcp_inbound rule.
$IPT -A udp_inbound -p udp -s 0/0 --dport 113 -j REJECT
$IP6T -A udp_inbound -p udp -s 0/0 --dport 113 -j REJECT
# A more sophisticated configuration could accept the ident requests.
# $IPT -A udp_inbound -p udp -s 0/0 --dport 113 -j ACCEPT
# $IP6T -A udp_inbound -p udp -s 0/0 --dport 113 -j ACCEPT
# IPv4 only:
# Allow DHCP client request packets inbound from external network
$IPT -A udp_inbound -p udp -s 0/0 --source-port 68 --dport 67 \
-j ACCEPT
# Dynamic Address
# If DHCP, the initial request is a broadcast. The response
# doesn't exactly match the outbound packet. This explicitly
# allow the DHCP ports to alleviate this problem.
# If you receive your dynamic address by a different means, you
# can probably comment this line.
$IPT -A udp_inbound -p udp -s 0/0 --source-port 67 --dport 68 \
-j ACCEPT
# Open the custom UDP ports if they have been configured:
if [ -n "$UDP_LIST" ]; then
$IPT -A INPUT -p udp -m multiport --dport $UDP_LIST -j ACCEPT
$IP6T -A INPUT -p udp -m multiport --dport $UDP_LIST -j ACCEPT
fi
# Not matched, so return for logging
$IPT -A udp_inbound -p udp -j RETURN
$IP6T -A udp_inbound -p udp -j RETURN
# udp_outbound chain
#
# This chain is used with a private network to prevent forwarding for
# UDP requests on specific protocols. Applied to the FORWARD rule from
# the internal network. Ends with an ACCEPT
# No match, so ACCEPT
$IPT -A udp_outbound -p udp -s 0/0 -j ACCEPT
$IP6T -A udp_outbound -p udp -s 0/0 -j ACCEPT
# tcp_inbound chain
#
# This chain is used to allow inbound connections to the
# system/gateway. Use with care. It defaults to none.
# It's applied on INPUT from the external or Internet interface.
# Ident requests (Port 113) must have a REJECT rule rather than the
# default DROP rule. This is the minimum requirement to avoid
# long delays while connecting. Also see the tcp_inbound rule.
$IPT -A tcp_inbound -p tcp -s 0/0 --dport 113 -j REJECT
$IP6T -A tcp_inbound -p tcp -s 0/0 --dport 113 -j REJECT
# A more sophisticated configuration could accept the ident requests.
# $IPT -A tcp_inbound -p tcp -s 0/0 --dport 113 -j ACCEPT
# $IP6T -A tcp_inbound -p tcp -s 0/0 --dport 113 -j ACCEPT
# Open the requested TCP service ports if they have been configured:
if [ -n "$TCP_LIST" ]; then
$IPT -A INPUT -p tcp -m multiport --dport $TCP_LIST -j ACCEPT
$IP6T -A INPUT -p tcp -m multiport --dport $TCP_LIST -j ACCEPT
fi
# Not matched, so return so it will be logged
$IPT -A tcp_inbound -p tcp -j RETURN
$IP6T -A tcp_inbound -p tcp -j RETURN
# tcp_outbound chain
#
# This chain is used with a private network to prevent forwarding for
# requests on specific protocols. Applied to the FORWARD rule from
# the internal network. Ends with an ACCEPT
# No match, so ACCEPT
$IPT -A tcp_outbound -p tcp -s 0/0 -j ACCEPT
$IP6T -A tcp_outbound -p tcp -s 0/0 -j ACCEPT
#
# INPUT Chain
#
# Allow all on localhost interface
$IPT -A INPUT -p ALL -i $LO_IFACE -j ACCEPT
$IP6T -A INPUT -p ALL -i $LO_IFACE -j ACCEPT
# Allow all on other internal interfaces:
for INDEV in ${!NETDEVARR[@]} ; do
if [ "${NETDEVARR[$INDEV]}" = "off" ] ; then
$IPT -A INPUT -p ALL -i $INDEV -j ACCEPT
$IP6T -A INPUT -p ALL -i $INDEV -j ACCEPT
fi
done
unset INDEV
# Drop bad packets
$IPT -A INPUT -p ALL -j bad_packets
$IP6T -A INPUT -p ALL -j bad_packets
# DOCSIS compliant cable modems
# Some DOCSIS compliant cable modems send IGMP multicasts to find
# connected PCs. The multicast packets have the destination address
# 224.0.0.1. You can accept them. If you choose to do so,
# Uncomment the rule to ACCEPT them and comment the rule to DROP
# them The firewall will drop them here by default to avoid
# cluttering the log. The firewall will drop all multicasts
# to the entire subnet (224.0.0.1) by default. To only affect
# IGMP multicasts, change '-p ALL' to '-p 2'. Of course,
# if they aren't accepted elsewhere, it will only ensure that
# multicasts on other protocols are logged.
# Drop them without logging.
$IPT -A INPUT -p ALL -d 224.0.0.1 -j DROP
# The rule to accept the packets.
# $IPT -A INPUT -p ALL -d 224.0.0.1 -j ACCEPT
# Inbound Internet Packet Rules
for INDEV in ${!NETDEVARR[@]} ; do
if [ "${NETDEVARR[$INDEV]}" = "on" ] ; then
# Accept Established Connections
$IPT -A INPUT -p ALL -i $INDEV -m state --state ESTABLISHED,RELATED \
-j ACCEPT
$IP6T -A INPUT -p ALL -i $INDEV -m state --state ESTABLISHED,RELATED \
-j ACCEPT
# Route the rest to the appropriate user chain
$IPT -A INPUT -p tcp -i $INDEV -j tcp_inbound
$IP6T -A INPUT -p tcp -i $INDEV -j tcp_inbound
$IPT -A INPUT -p udp -i $INDEV -j udp_inbound
$IP6T -A INPUT -p udp -i $INDEV -j udp_inbound
$IPT -A INPUT -p icmp -i $INDEV -j icmp_packets
$IP6T -A INPUT -p ipv6-icmp -i $INDEV -j icmp_packets
fi
done
unset INDEV
# Drop without logging broadcasts that get this far.
# Cuts down on log clutter.
# Comment this line if testing new rules that impact
# broadcast protocols.
$IPT -A INPUT -m pkttype --pkt-type broadcast -j DROP
$IP6T -A INPUT -m pkttype --pkt-type broadcast -j DROP
# Log packets that still don't match
$IPT -A INPUT -m limit --limit 3/minute --limit-burst 3 -j LOG \
--log-prefix "INPUT packet died: "
$IP6T -A INPUT -m limit --limit 3/minute --limit-burst 3 -j LOG \
--log-prefix "INPUT packet ipv6 died: "
#
# FORWARD Chain
#
# Used if forwarding for a private network
#
# OUTPUT Chain
#
# Generally trust the firewall on output
# However, invalid icmp packets need to be dropped
# to prevent a possible exploit.
$IPT -A OUTPUT -m state -p icmp --state INVALID -j DROP
$IP6T -A OUTPUT -m state -p ipv6-icmp --state INVALID -j DROP
# Localhost
$IPT -A OUTPUT -p ALL -s $LO_IP -j ACCEPT
$IP6T -A OUTPUT -p ALL -s $LO_IP6 -j ACCEPT
$IPT -A OUTPUT -p ALL -o $LO_IFACE -j ACCEPT
$IP6T -A OUTPUT -p ALL -o $LO_IFACE -j ACCEPT
# Allow all on other internal interfaces:
for OUTDEV in ${!NETDEVARR[@]} ; do
if [ "${NETDEVARR[$OUTDEV]}" = "off" ] ; then
$IPT -A OUTPUT -p ALL -o $OUTDEV -j ACCEPT
$IP6T -A OUTPUT -p ALL -o $OUTDEV -j ACCEPT
fi
done
unset OUTDEV
# To internet
for OUTDEV in ${!NETDEVARR[@]} ; do
if [ "${NETDEVARR[$OUTDEV]}" = "on" ] ; then
$IPT -A OUTPUT -p ALL -o $OUTDEV -j ACCEPT
$IP6T -A OUTPUT -p ALL -o $OUTDEV -j ACCEPT
fi
done
# Log packets that still don't match
$IPT -A OUTPUT -m limit --limit 3/minute --limit-burst 3 -j LOG \
--log-prefix "OUTPUT packet died: "
$IP6T -A OUTPUT -m limit --limit 3/minute --limit-burst 3 -j LOG \
--log-prefix "OUTPUT packet ipv6 died: "
#
# nat table
#
# The nat table is where network address translation occurs if there
# is a private network. If the gateway is connected to the Internet
# with a static IP, snat is used. If the gateway has a dynamic address,
# masquerade must be used instead. There is more overhead associated
# with masquerade, so snat is better when it can be used.
# The nat table has a builtin chain, PREROUTING, for dnat and redirects.
# Another, POSTROUTING, handles snat and masquerade.
#
# PREROUTING chain
#
#
# POSTROUTING chain
#
#
# mangle table
#
# The mangle table is used to alter packets. It can alter or mangle them in
# several ways. For the purposes of this generator, we only use its ability
# to alter the TTL in packets. However, it can be used to set netfilter
# mark values on specific packets. Those marks could then be used in another
# table like filter, to limit activities associated with a specific host, for
# instance. The TOS target can be used to set the Type of Service field in
# the IP header. Note that the TTL target might not be included in the
# distribution on your system. If it is not and you require it, you will
# have to add it. That may require that you build from source.
# Save the firewall configuration so that 'rc.firewall' can load it:
mkdir -p $DESTDIR/etc/firewall
${IPTS} > $DESTDIR/etc/firewall/ipv4
${IP6TS} > $DESTDIR/etc/firewall/ipv6