# IPtables quite complete firewall + transp proxy port fwd qos

## Powerslave

I thought that it could be useful for someone who has similar configuration to mine therefore i'm sharing the script with the community.

This script is petty modification of iptales firewall script from http://monmotha.mplug.org/~monmotha/firewall/firewall/

 Icq Jabber Kadu clients work - took a while but thanks to tcpdump it wasn't ethernity  :Wink: 

As for the network configuration mine is ppp0 -> external and eth0 -> internal interface - but i don't use ppp0 at all cause my box is connected to the net through hand made  :Wink:  Slackware router/server by eth0. 

Therefore eth0 is also hardened (if you can call it that way)

This script is very configurable and quite complete so why can't somebody else use it to protect her or his 24(or more)h compiling child  :Wink: 

See ya and great thanks to the original authors of this script since they've done a nice piece of scripting there plus it's very well commented  :Smile: 

If some problems or optimizations emerge  :Wink:  I'll edit the code if I have some spare time  :Smile: 

Cheers once again  :Very Happy: 

firewall script

```
#!/sbin/runscript

IPTABLES=/sbin/iptables

IPTABLESSAVE=/sbin/iptables-save

IPTABLESRESTORE=/sbin/iptables-restore

FIREWALL=/etc/firewall.rules

opts="${opts} showstatus panic save restore showoptions rules"

depend() {

  need net procparam

}

rules() {

  stop

  ebegin "Setting internal rules"

# Main configuration, modify to suit your setup.  Help can be found at:

#    http://www.mplug.org/phpwiki/index.php?MonMothaReferenceGuide

TCP_ALLOW=""              # Allow (open) selected TCP ports

UDP_ALLOW="68"              # Open selected UDP ports

INET_IFACE="ppp0"                                            # the interface your internet's on (one only), must be set

LAN_IFACE="eth0"                                              # the interface your LAN's on (one only)

INTERNAL_LAN="192.168.0.0/24"    # The internal LAN (including DMZs but not censored hosts)

MASQ_LAN="192.168.0.0/24"         # the internal network(s) to be masqueraded (this is overridden by MAC_MASQ)

SNAT_LAN=""                     # Internal networks/hosts to use static NAT (format is <internal ip or network>:<external ip>) (this is overridden by MAC_SNAT)

DROP="TREJECT"                    # What to do with packets we don't want: DROP, REJECT, TREJECT (Reject with tcp-reset for TCP), LDROP (log and drop), LREJECT (log and reject), LTREJECT (log and reject with tcp-reset)

DENY_ALL=""                                     # Internet hosts to explicitly deny from accessing your system at all

DENY_HOSTWISE_TCP=""                   # Specific hosts to deny access to specific TCP ports; format is "IP>PORT"

DENY_HOSTWISE_UDP=""                   # Specific hosts to deny access to specific UDP ports; format is "IP>PORT"

BLACKHOLE=""                                   # People you don't want to have anything to do with (equivlent of my old TK_DROP).  This is a bidirectional drop.

BLACKHOLE_DROP="DROP"                # What to do for the blackholes (same options as DROP directive above)

ALLOW_HOSTWISE_TCP=""                 # Specific hosts allowed access to specific TCP ports; format is "IP>PORT"

ALLOW_HOSTWISE_UDP=""                 # Specific hosts allowed access to specific UDP ports; format is "IP>PORT"

TCP_FW=""                                         # TCP port forwards, form is "SPORT:DPORT>IP"

UDP_FW=""                                         # UDP port forwards, form is "SPORT:DPORT>IP"

MANGLE_TOS_OPTIMIZE="TRUE"        # TOS "optimizations" on or off (TRUE/FALSE toggle)

ENABLE="Y"                                      # Set to 'Y' when it's configured; this is for your own saftey

# Flood Params.  You will still recieve the packets and the bandwidth will be used, but this will cause floods to be ignored (useful against SYNFLOODS especially)

LOG_FLOOD="2/s"                             # Limit on logging (for LTREJECT, LREJECT and LDROP, the packet will always take the policy regardless of logging)

SYN_FLOOD="20/s"                           # GLOBAL limit on SYN packets (servers will probably need even higher sustained rates as this isn't on a per IP basis)

PING_FLOOD="1/s"                            # GLOBAL limit on ICMP echo-requests to reply to

# Outbound filters (they work, but are of limited functionality), probably better to use a proxy here

ALLOW_OUT_TCP=""                        # Internal hosts allowed to be forwarded out on TCP (internet censorship!) (do not put this/these host/s in INTERNAL_LAN, but do define their method of access [snat, masq] if not a public ip)

# Below here is experimental (please report your successes/failures)

MAC_MASQ=""                         # MAC addresses permitted to use masquerading, leave blank to not use

MAC_SNAT=""                          # MAC addresses permitted to use static NAT, leave blank to not use (format is <MAC Address>:<external ip>)

TTL_SAFE=""                            # How many hops packets need to make once they get on your LAN (null disables the mangling) (requires patch from patch-o-matic)

USE_SYNCOOKIES="TRUE"       # TCP SynCookies on or off (TRUE/FALSE toggle)

PROXY=""                                # Redirect for Squid or other transparent proxy. Syntax to specify the proxy is "host:port".

DHCP_SERVER="FALSE"          # Set to true if you run a DHCP server. DHCP clients do not need this. This allows broadcasts to the server from potential clients on the LAN to succeede. MUST DEFINE LAN_IFACE IF YOU USE THIS!

# Only touch these if you're daring (PREALPHA stuff, as in basically non-functional)

DMZ_IFACE=""                        # Interface your DMZ is on (leave blank if you don't have one) MUST DEFINE LAN_IFACE IF YOU USE THIS!

# ----------------------------------------------------------------------|

# These control basic script behavior, there should be no need to   |

#   any of these settings for normal use.            |

# ----------------------------------------------------------------------|

FILTER_CHAINS="INETIN INETOUT DMZIN DMZOUT TCPACCEPT UDPACCEPT LDROP LREJECT TREJECT LTREJECT"

LOOP_IFACE="lo"

# ----------------------------------------------------------------------|

# You shouldn't need to modify anything below here         |

# Main Script Starts                     |

# ----------------------------------------------------------------------|

# Let's load it!

echo "Loading iptables firewall:"

# Configuration Sanity Checks

echo -n "Checking configuration..."

if ! [ -x $IPTABLES ] ; then

   echo

   echo "ERROR IN CONFIGURATION: IPTABLES doesn't exist or isn't executable!"

   exit 1

fi

if [ "$DMZ_IFACE" = "$LAN_IFACE" ] && [ "$LAN_IFACE" != "" ]; then

   echo

   echo "ERROR IN CONFIGURATION: DMZ_IFACE and LAN_IFACE can't be the same!"

   exit 1

fi

if [ "$DROP" = "" ] ; then

   echo

   echo "There needs to be a DROP policy (try TREJECT)!"

   exit 1

fi

if [ "$DROP" = "ACCEPT" ] ; then

   echo

   echo "The DROP policy is set to ACCEPT; there is no point in loading the firewall as there wouldn't be one."

   exit 2

fi

if [ "$BLACKHOLE" != "" ] && [ "$BLACKHOLE_DROP" = "" ] ; then

   echo

   echo "You can't use blackholes and not have a policy for them!"

   exit 1

fi

if ! [ "$ENABLE" = "Y" ] ; then

   echo

   echo "You need to edit your configuration and set ENABLE to Y!"

   exit 99

fi

echo "passed"

# ===============================================

# -------Set some Kernel stuff via SysCTL--------

# ===============================================

# Turn on IP forwarding

if [ "$INTERNAL_LAN" != "" ] ; then

   echo -n "Checking IP Forwarding..."

   if [ -e /proc/sys/net/ipv4/ip_forward ] ; then

      echo 1 > /proc/sys/net/ipv4/ip_forward

      echo "enabled."

   else

      echo "support not found! This will cause problems if you need to do any routing."

   fi

fi

# Enable TCP Syncookies

if [ "$USE_SYNCOOKIES" = "TRUE" ] ; then

   echo -n "Checking IP SynCookies..."

   if [ -e /proc/sys/net/ipv4/tcp_syncookies ] ; then

      echo 1 > /proc/sys/net/ipv4/tcp_syncookies

      echo "enabled."

   else

      echo "support not found, but that's OK."

   fi

fi

# Enable Route Verification to prevent martians and other such crud that

# seems to be commonplace on the internet today

echo -n "Checking Route Verification..."

if [ "$INET_IFACE" != "" ] ; then

   if [ -e /proc/sys/net/ipv4/conf/$INET_IFACE/rp_filter ] ; then

      echo 1 > /proc/sys/net/ipv4/conf/$INET_IFACE/rp_filter

      echo -n "activated:${INET_IFACE} "

   else

      echo "not found:${INET_IFACE} "

   fi

fi

if [ "$LAN_IFACE" != "" ] ; then

   if [ -e /proc/sys/net/ipv4/conf/$LAN_IFACE/rp_filter ] ; then

      echo 1 > /proc/sys/net/ipv4/conf/$LAN_IFACE/rp_filter

      echo -n "activated:${LAN_IFACE} "

   else

      echo "not found:${LAN_IFACE} "

   fi

fi

if [ "$DMZ_IFACE" != "" ] ; then

   if [ -e /proc/sys/net/ipv4/conf/$DMZ_IFACE/rp_filter ] ; then

      echo 1 > /proc/sys/net/ipv4/conf/$DMZ_IFACE/rp_filter

      echo -n "activated:${DMZ_IFACE} "

   else

      echo "not found:${DMZ_IFACE} "

   fi

fi

echo

# Tell the Kernel to Ignore Source Routed Packets

echo -n "Refusing SSR Packets via SysCtl..."

if [ "$INET_IFACE" != "" ] ; then

   if [ -e /proc/sys/net/ipv4/conf/$INET_IFACE/accept_source_route ] ; then

      echo "0" > /proc/sys/net/ipv4/conf/$INET_IFACE/accept_source_route

      echo -n "activated:${INET_IFACE} "

   else

      echo "not found:${INET_IFACE} "

   fi

fi

if [ "$LAN_IFACE" != "" ] ; then

   if [ -e /proc/sys/net/ipv4/conf/$LAN_IFACE/accept_source_route ] ; then

      echo "0" > /proc/sys/net/ipv4/conf/$LAN_IFACE/accept_source_route

      echo -n "activated:${LAN_IFACE} "

   else

      echo "not found:${LAN_IFACE} "

   fi

fi

if [ "$DMZ_IFACE" != "" ] ; then

   if [ -e /proc/sys/net/ipv4/conf/$DMZ_IFACE/accept_source_route ] ; then

      echo "0" > /proc/sys/net/ipv4/conf/$DMZ_IFACE/accept_source_route

      echo -n "activated:${DMZ_IFACE} "

   else

      echo "not found:${DMZ_IFACE} "

   fi

fi

echo

# ===============================================

# --------Actual NetFilter Stuff Follows---------

# ===============================================

# Flush everything

# If you need compatability, you can comment some or all of these out,

# but remember, if you re-run it, it'll just add the new rules in, it

# won't remove the old ones for you then, this is how it removes them.

echo -n "Flush: "

${IPTABLES} -t filter -F INPUT

echo -n "INPUT "

${IPTABLES} -t filter -F OUTPUT

echo -n "OUTPUT1 "

${IPTABLES} -t filter -F FORWARD

echo -n "FORWARD "

${IPTABLES} -t nat -F PREROUTING

echo -n "PREROUTING1 "

${IPTABLES} -t nat -F OUTPUT

echo -n "OUTPUT2 "

${IPTABLES} -t nat -F POSTROUTING

echo -n "POSTROUTING "

${IPTABLES} -t mangle -F PREROUTING

echo -n "PREROUTING2 "

${IPTABLES} -t mangle -F OUTPUT

echo -n "OUTPUT3"

echo

# Create new chains

# Output to /dev/null in case they don't exist from a previous invocation

echo -n "Creating chains: "

for chain in ${FILTER_CHAINS} ; do

   ${IPTABLES} -t filter -F ${chain} > /dev/null 2>&1

   ${IPTABLES} -t filter -X ${chain} > /dev/null 2>&1

   ${IPTABLES} -t filter -N ${chain}

   echo -n "${chain} "

done

echo

# Default Policies

# INPUT policy is drop as of 2.3.7-pre5

# Policy can't be reject becuase of kernel limitations

echo -n "Default Policies: "

${IPTABLES} -t filter -P INPUT DROP

echo -n "INPUT:DROP "

${IPTABLES} -t filter -P OUTPUT ACCEPT

echo -n "OUTPUT:ACCEPT "

${IPTABLES} -t filter -P FORWARD DROP

echo -n "FORWARD:DROP "

echo

# Local traffic to internet or crossing subnets

# This should cover what we need if we don't use masquerading

# Unfortunately, MAC address matching isn't bidirectional (for

#   obvious reasons), so IP based matching is done here

echo -n "Local Traffic Rules: "

if [ "$INTERNAL_LAN" != "" ] ; then

   for subnet in ${INTERNAL_LAN} ; do

      ${IPTABLES} -t filter -A FORWARD -s ${subnet} -j ACCEPT

      ${IPTABLES} -t filter -A FORWARD -d ${subnet} -j ACCEPT

      ${IPTABLES} -t filter -A INPUT -s ${subnet} -j ACCEPT

      echo -n "${subnet}:ACCEPT "

   done

   echo

fi

# 127.0.0.0/8 used to need an entry in INTERNAL_LAN, but routing of that isn't needed

# so an allow is placed on INPUT so that the computer can talk to itself :)

${IPTABLES} -t filter -A INPUT -i ${LOOP_IFACE} -j ACCEPT

echo -n "loopback:ACCEPT "

# DHCP server magic

# Allow broadcasts from LAN to UDP port 67 (DHCP server)

if [ "$DHCP_SERVER" = "TRUE" ] ; then

   ${IPTABLES} -t filter -A INPUT -i ${LAN_IFACE} -p udp --dport 67 -j ACCEPT

fi

echo #newline from local traffic rules

if [ "$PROXY" != "" ] ; then

   echo -n "Setting up Transparent Proxy to ${PROXY}: "

   for subnet in ${INTERNAL_LAN} ; do

         echo "$PROXY" | {

                                IFS=':' read host port

                                if [ "$host" = "localhost" ] || [ "$host" = "127.0.0.1" ] ; then

                                        ${IPTABLES} -t nat -A PREROUTING -s ${subnet} -p tcp --dport 80 -j REDIRECT --to-port ${port}

                                        echo -n "${subnet}:PROXY "

                                else

                                        ${IPTABLES} -t nat -A PREROUTING -s ${subnet} -p tcp --dport 80 -j DNAT --to ${host}:${port}

                                        echo -n "${subnet}:PROXY "

                                fi

                        }

        done

        echo

fi

if [ "$ALLOW_OUT_TCP" != "" ] ; then

   echo -n "Internet censorship TCP allows: "

   for rule in ${ALLOW_OUT_TCP} ; do

      echo "$rule" | {

         IFS=':' read intip destip

              ${IPTABLES} -t filter -A FORWARD -s ${intip} -d ${destip} -o ${INET_IFACE} -j ACCEPT

         ${IPTABLES} -t filter -A FORWARD -d ${intip} -s ${destip} -i ${INET_IFACE} -j ACCEPT

         echo -n "${intip}:${destip} "

      }

   done

   echo

fi

# Set up basic NAT if the user wants it

if [ "$MASQ_LAN" != "" ] ; then

   echo -n "Setting up masquerading: "

   if [ "$MAC_MASQ" = "" ] ; then

      for subnet in ${MASQ_LAN} ; do

         ${IPTABLES} -t nat -A POSTROUTING -s ${subnet} -o ${INET_IFACE} -j MASQUERADE

         echo -n "${subnet}:MASQUERADE "

      done

   else

      for address in ${MAC_MASQ} ; do

         ${IPTABLES} -t nat -A POSTROUTING -m mac --mac-source ${address} -o ${INET_IFACE} -j MASQUERADE

         echo -n "${address}:MASQUERADE "

      done

   fi

   echo

fi

if [ "$SNAT_LAN" != "" ] ; then #Static NAT used

   echo -n "Setting up static NAT: "

        if [ "$MAC_SNAT" = "" ] ; then

                for rule in ${SNAT_LAN} ; do

         echo "$rule" | {

            IFS=':' read host destip

                           ${IPTABLES} -t nat -A POSTROUTING -s ${host} -o ${INET_IFACE} -j SNAT --to-source ${destip}

                           echo -n "${subnet}:SNAT "

         }

                done

        else

                for rule in ${MAC_SNAT} ; do

         echo "$rule" | {

            IFS=':' read address destip   

                           ${IPTABLES} -t nat -A POSTROUTING -m mac --mac-source ${address} -o ${INET_IFACE} -j SNAT --to-source ${destip}

                           echo -n "${address}:SNAT "

         }

                done

        fi

        echo

fi

#TCP Port-Forwards

if [ "$TCP_FW" != "" ] ; then

   echo -n "TCP Port Forwards: "

   for rule in ${TCP_FW} ; do

      echo "$rule" | {

         IFS=':>' read srcport destport host

            echo "$srcport" | {

               IFS='-' read fsp lsp

               if [ "$lsp" != "" ] ; then

                  echo "$destport" | {

                     IFS='-' read fdp ldp

                     ${IPTABLES} -t nat -A PREROUTING -p tcp -i ${INET_IFACE} --dport ${fsp}:${lsp} -j DNAT --to-destination ${host}:${destport}

                     ${IPTABLES} -t filter -A FORWARD -p tcp -d ${host} --dport ${fdp}:${ldp} -j ACCEPT

                  }

               else

                  ${IPTABLES} -t nat -A PREROUTING -p tcp -i ${INET_IFACE} --dport ${srcport} -j DNAT --to-destination ${host}:${destport}

                  ${IPTABLES} -t filter -A FORWARD -p tcp -d ${host} --dport ${destport} -j ACCEPT

               fi

               echo -n "${rule} "

            }

      }

   done

   echo

fi

#UDP Port Forwards

if [ "$UDP_FW" != "" ] ; then

   echo -n "UDP Port Forwards: "

   for rule in ${UDP_FW} ; do

      echo "$rule" | {

         IFS=':>' read srcport destport host

            echo "$srcport" | {

               IFS='-' read fsp lsp

               if [ "$lsp" != "" ] ; then

                  echo "$destport" | {

                     IFS='-' read fdp ldp

                          ${IPTABLES} -t nat -A PREROUTING -p udp -i ${INET_IFACE} --dport ${fsp}:${lsp} -j DNAT --to-destination ${host}:${destport}

                     ${IPTABLES} -t filter -A FORWARD -p udp -d ${host} --dport ${fdp}:${ldp} -j ACCEPT

                  }   

               else

                  ${IPTABLES} -t nat -A PREROUTING -p udp -i ${INET_IFACE} --dport ${srcport} -j DNAT --to-destination ${host}:${destport}

                  ${IPTABLES} -t filter -A FORWARD -p udp -d ${host} --dport ${destport} -j ACCEPT

               fi

               echo -n "${rule} "

                 }

      }

        done

        echo

fi

# ===============================================

# -------Chain setup before jumping to them------

# ===============================================

# Set up INET chains

echo -n "Setting up INET chains: "

${IPTABLES} -t filter -A INPUT -i ${INET_IFACE} -j INETIN

echo -n "INETIN "

${IPTABLES} -t filter -A OUTPUT -o ${INET_IFACE} -j INETOUT

echo -n "INETOUT "

echo

# For now we'll subject the DMZ to the same rules as the internet when going onto the trusted LAN

# And we'll let it go anywhere on the internet

if [ "$DMZ_IFACE" != "" ] ; then

   echo -n "Setting up DMZ Chains: "

   ${IPTABLES} -A OUTPUT -o ${DMZ_IFACE} -j DMZOUT

   echo -n "DMZOUT "

   ${IPTABLES} -A INPUT -i ${DMZ_IFACE} -j DMZIN

   echo -n "DMZIN "

   echo

   echo -n "DMZ for LAN Forwarding to INETIN..."

   ${IPTABLES} -A DMZOUT -o ${LAN_IFACE} -j INETIN

   echo "done"

   echo -n "DMZ for Internet Forwarding to INETOUT..."

   ${IPTABLES} -A DMZOUT -o ${INET_IFACE} -j INETOUT

   echo -n "done"

fi

#These logging chains are valid to specify in DROP= above

#Set up LDROP

echo -n "Setting up drop chains chains: "

${IPTABLES} -t filter -A LDROP -p tcp -m limit --limit ${LOG_FLOOD} -j LOG --log-level info --log-prefix "TCP Dropped "

${IPTABLES} -t filter -A LDROP -p udp -m limit --limit ${LOG_FLOOD} -j LOG --log-level info --log-prefix "UDP Dropped "

${IPTABLES} -t filter -A LDROP -p icmp -m limit --limit ${LOG_FLOOD} -j LOG --log-level info --log-prefix "ICMP Dropped "

${IPTABLES} -t filter -A LDROP -f -m limit --limit ${LOG_FLOOD} -j LOG --log-level warning --log-prefix "FRAGMENT Dropped "

${IPTABLES} -t filter -A LDROP -j DROP

echo -n "LDROP "

#And LREJECT too

${IPTABLES} -t filter -A LREJECT -p tcp -m limit --limit ${LOG_FLOOD} -j LOG --log-level info --log-prefix "TCP Rejected "

${IPTABLES} -t filter -A LREJECT -p udp -m limit --limit ${LOG_FLOOD} -j LOG --log-level info --log-prefix "UDP Rejected "

${IPTABLES} -t filter -A LREJECT -p icmp -m limit --limit ${LOG_FLOOD} -j LOG --log-level info --log-prefix "ICMP Dropped "

${IPTABLES} -t filter -A LREJECT -f -m limit --limit ${LOG_FLOOD} -j LOG --log-level warning --log-prefix "FRAGMENT Rejected "

${IPTABLES} -t filter -A LREJECT -j REJECT

echo -n "LREJECT "

#Don't forget TREJECT

${IPTABLES} -t filter -A TREJECT -p tcp -j REJECT --reject-with tcp-reset

${IPTABLES} -t filter -A TREJECT -p udp -j REJECT --reject-with icmp-port-unreachable

${IPTABLES} -t filter -A TREJECT -p icmp -j DROP

${IPTABLES} -t filter -A TREJECT -j REJECT

echo -n "TREJECT "

#And LTREJECT

${IPTABLES} -t filter -A LTREJECT -p tcp -m limit --limit ${LOG_FLOOD} -j LOG --log-level info --log-prefix "TCP Rejected "

${IPTABLES} -t filter -A LTREJECT -p udp -m limit --limit ${LOG_FLOOD} -j LOG --log-level info --log-prefix "UDP Rejected "

${IPTABLES} -t filter -A LTREJECT -p icmp -m limit --limit ${LOG_FLOOD} -j LOG --log-level info --log-prefix "ICMP Dropped "

${IPTABLES} -t filter -A LTREJECT -f -m limit --limit ${LOG_FLOOD} -j LOG --log-level warning --log-prefix "FRAGMENT Rejected "

${IPTABLES} -t filter -A LTREJECT -p tcp -j REJECT --reject-with tcp-reset

${IPTABLES} -t filter -A LTREJECT -p udp -j REJECT --reject-with icmp-port-unreachable

${IPTABLES} -t filter -A LTREJECT -p icmp -j DROP

${IPTABLES} -t filter -A LTREJECT -j REJECT

echo -n "LTREJECT "

#newline

echo

# Set up the per-proto ACCEPT chains

echo -n "Setting up per-proto ACCEPT: "

# TCPACCEPT

# SYN Flood "Protection"

${IPTABLES} -t filter -A TCPACCEPT -p tcp --syn -m limit --limit ${SYN_FLOOD} -j ACCEPT

${IPTABLES} -t filter -A TCPACCEPT -p tcp --syn -m limit --limit ${LOG_FLOOD} -j LOG --log-prefix "Possible SynFlood "

${IPTABLES} -t filter -A TCPACCEPT -p tcp --syn -j ${DROP}

${IPTABLES} -t filter -A TCPACCEPT -p tcp ! --syn -j ACCEPT

# Log anything that hasn't matched yet and ${DROP} it since it isn't TCP and shouldn't be here

${IPTABLES} -t filter -A TCPACCEPT -m limit --limit ${LOG_FLOOD} -j LOG --log-prefix "Mismatch in TCPACCEPT "

${IPTABLES} -t filter -A TCPACCEPT -j ${DROP}

echo -n "TCPACCEPT "

#UDPACCEPT

${IPTABLES} -t filter -A UDPACCEPT -p udp -j ACCEPT

# Log anything not UDP and ${DROP} it since it's not supposed to be here

${IPTABLES} -t filter -A UDPACCEPT -m limit --limit ${LOG_FLOOD} -j LOG --log-prefix "Mismatch on UDPACCEPT "

${IPTABLES} -t filter -A UDPACCEPT -j ${DROP}

echo -n "UDPACCEPT "

#Done

echo

# ===============================================

# --------------Apply configuration--------------

# ===============================================

#Blackholes will not be overridden by hostwise allows

if [ "$BLACKHOLE" != "" ] ; then

   echo -n "Blackholes: "

   for host in ${BLACKHOLE} ; do

      ${IPTABLES} -t filter -A INETIN -s ${host} -j ${BLACKHOLE_DROP}

      ${IPTABLES} -t filter -A INETOUT -d ${host} -j ${BLACKHOLE_DROP}

      echo -n "${host} "

   done

   echo

fi

#Hostwise allows (to bypass explicit denies)

if [ "$ALLOW_HOSTWISE_TCP" != "" ] ; then

   echo -n "Hostwise TCP Allows: "

   for rule in ${ALLOW_HOSTWISE_TCP} ; do

      echo "$rule" | {

         IFS='>' read  host port

         ${IPTABLES} -t filter -A INETIN -p tcp -s ${host} --dport ${port} -j ACCEPT

         echo -n "${rule} "

      }

   done

   echo

fi

if [ "$ALLOW_HOSTWISE_UDP" != "" ] ; then

   echo -n "Hostwise UDP Allows: "

   for rule in ${ALLOW_HOSTWISE_UDP} ; do

      echo "$rule" | {

         IFS='>' read  host port

         ${IPTABLES} -t filter -A INETIN -p udp -s ${host} --dport ${port} -j ACCEPT

         echo -n "${rule} "

      }

   done

   echo

fi

# =================================================

# ----------------Explicit Denies------------------

# =================================================

if [ "$DENY_ALL" != "" ] ; then

   echo -n "Denying hosts: "

   for host in ${DENY_ALL} ; do

      ${IPTABLES} -t filter -A INETIN -s ${host} -j ${DROP}

      echo -n "${host}:${DROP}"

   done

   echo

fi

if [ "$DENY_HOSTWISE_TCP" != "" ] ; then

   echo -n "Hostwise TCP Denies: "

   for rule in ${DENY_HOSTWISE_TCP} ; do

      echo "$rule" | {

         IFS='>' read host port

         ${IPTABLES} -t filter -A INETIN -p tcp -s ${host} --dport ${port} -j ${DROP}

         echo -n "${rule} "

      }

   done

   echo

fi

if [ "$DENY_HOSTWISE_UDP" != "" ] ; then

   echo -n "Hostwise UDP Denies: "

   for rule in ${DENY_HOSTWISE_UDP} ; do

      echo "$rule" | {

         IFS='>' read host port

         ${IPTABLES} -t filter -A INETIN -p udp -s ${host} --dport ${port} -j ${DROP}

         echo -n "${rule} "

      }

   done

   echo

fi

#Invalid packets are always annoying

echo -n "${DROP}ing invalid packets..."

${IPTABLES} -t filter -A INETIN -m state --state INVALID -j ${DROP}

echo "done"

# ================================================================

# ------------Allow stuff we have chosen to allow in--------------

# ================================================================

# Flood "security"

# You'll still respond to these if they comply with the limits (set in config)

# There is a more elegant way to set this using sysctl, however this has the

#    advantage that the kernel ICMP stack never has to process it, lessening

#   the chance of a very serious flood overloading your kernel.

# This is just a packet limit, you still get the packets on the interface and

#    still may experience lag if the flood is heavy enough

echo -n "Flood limiting: "

# Ping Floods (ICMP echo-request)

${IPTABLES} -t filter -A INETIN -p icmp --icmp-type echo-request -m limit --limit ${PING_FLOOD} -j ACCEPT

${IPTABLES} -t filter -A INETIN -p icmp --icmp-type echo-request -j ${DROP}

echo -n "ICMP-PING "

echo

# Probably shouldn't let em all back in, someone give me a good list of the

#   WORTHWHILE ICMP messages.

echo -n "Allowing the rest of the ICMP messages in..."

${IPTABLES} -t filter -A INETIN -p icmp --icmp-type ! echo-request -j ACCEPT

echo "done"

if [ "$TCP_ALLOW" != "" ] ; then

   echo -n "TCP Input Allow: "

   for port in ${TCP_ALLOW} ; do

                ${IPTABLES} -t filter -A INETIN -p tcp --dport ${port} -j TCPACCEPT

      echo -n "${port} "

   done

   echo

fi

if [ "$UDP_ALLOW" != "" ] ; then

   echo -n "UDP Input Allow: "

   for port in ${UDP_ALLOW} ; do

      ${IPTABLES} -t filter -A INETIN -p udp --dport ${port} -j UDPACCEPT

      echo -n "${port} "

   done

   echo

fi

echo -n "Allowing established outbound connections back in..."

${IPTABLES} -t filter -A INPUT -m state --state ESTABLISHED -j ACCEPT

echo "done"

# RELATED on high ports only for security

echo -n "Allowing related inbound connections..."

${IPTABLES} -t filter -A INETIN -p tcp --dport 1024:65535 -m state --state RELATED -j TCPACCEPT

${IPTABLES} -t filter -A INETIN -p udp --dport 1024:65535 -m state --state RELATED -j UDPACCEPT

echo "done"

# =================================================

# ----------------Packet Mangling------------------

# =================================================

# TTL mangling

# This is probably just for the paranoid, but hey, isn't that what 

#   all security guys are? :)

if [ "$TTL_SAFE" != "" ] ; then

   ${IPTABLES} -t mangle -A PREROUTING -i ${INET_IFACE} -j TTL --ttl-set ${TTL_SAFE}

fi

# Type of Service mangle optimizations (the ACTIVE FTP one will only work for uploads)

if [ "$MANGLE_TOS_OPTIMIZE" = "TRUE" ] ; then

   echo -n "Optimizing traffic: "

   ${IPTABLES} -t mangle -A OUTPUT -p tcp --dport 23 -j TOS --set-tos Minimize-Delay

   echo -n "telnet "

   ${IPTABLES} -t mangle -A OUTPUT -p tcp --dport 22 -j TOS --set-tos Minimize-Delay

   echo -n "ssh "

   ${IPTABLES} -t mangle -A OUTPUT -p tcp --dport 20 -j TOS --set-tos Minimize-Cost

   echo -n "ftp-data "

   ${IPTABLES} -t mangle -A OUTPUT -p tcp --dport 21 -j TOS --set-tos Minimize-Delay

   echo -n "ftp-control "

   ${IPTABLES} -t mangle -A OUTPUT -p udp --dport 4000:7000 -j TOS --set-tos Minimize-Delay

   echo -n "diablo2 "

   echo

fi

#What to do on those INET chains when we hit the end

echo -n "Setting up INET policies: "

#Drop if we cant find a valid inbound rule.

${IPTABLES} -t filter -A INETIN -j ${DROP}

echo -n "INETIN:${DROP} "

#We can send what we want to the internet

${IPTABLES} -t filter -A INETOUT -j ACCEPT

echo -n "INETOUT:ACCEPT "

echo

#All done!

echo "Done loading the firewall!"

   eend $?

}

start() {

  # core netfilter module

  /sbin/modprobe ip_tables

  # the stateful connection tracking module

  /sbin/modprobe ip_conntrack

  # filter table module

  # /sbin/modprobe iptable_filter

  # mangle table module

  # /sbin/modprobe iptable_mangle

  # the module for full ftp connection tracking

  /sbin/modprobe ip_conntrack_ftp

  # the module for full irc connection tracking

  /sbin/modprobe ip_conntrack_irc

  ebegin "Starting firewall"

  if [ -e "${FIREWALL}" ]; then

    restore

  else

    einfo "${FIREWALL} does not exists. Using default rules."

    rules

  fi

  eend $?

}

stop() {

  ebegin "Stopping firewall"

  $IPTABLES -F

  $IPTABLES -t nat -F

  $IPTABLES -X

  $IPTABLES -P FORWARD ACCEPT

  $IPTABLES -P INPUT   ACCEPT

  $IPTABLES -P OUTPUT  ACCEPT

  eend $?

}

showstatus() {

  ebegin "Status"

  $IPTABLES -L -n -v --line-numbers

  einfo "NAT status"

  $IPTABLES -L -n -v --line-numbers -t nat

  eend $?

}

panic() {

  ebegin "Setting panic rules"

  $IPTABLES -F

  $IPTABLES -X

  $IPTABLES -t nat -F

  $IPTABLES -P FORWARD DROP

  $IPTABLES -P INPUT   DROP

  $IPTABLES -P OUTPUT  DROP

  $IPTABLES -A INPUT -i lo -j ACCEPT

  $IPTABLES -A OUTPUT -o lo -j ACCEPT

  eend $?

}

save() {

  ebegin "Saving Firewall rules"

  $IPTABLESSAVE > $FIREWALL

  eend $?

}

restore() {

  ebegin "Restoring Firewall rules"

  $IPTABLESRESTORE < $FIREWALL

  eend $?

}

restart() {

  svc_stop; svc_start

}

showoptions() {

  echo "Usage: $0 {start|save|restore|panic|stop|restart|showstatus}"

  echo "start)      will restore setting if exists else force rules"

  echo "stop)       delete all rules and set all to accept"

  echo "rules)      force settings of new rules"

  echo "save)       will store settings in ${FIREWALL}"

  echo "restore)    will restore settings from ${FIREWALL}"

  echo "showstatus) Shows the status"

}

```

Eventually -> procparam <- file contents - but the contents of this file are already merged into firewall script - it's just that i don't have much time to remove some dependencies - if I do I'll edit the post 

procparam file

```

#!/sbin/runscript

depend() {

 before *

}

start() {

 ebegin "Setting /proc options."

 /bin/echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_all

 /bin/echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts

 /bin/echo "0" > /proc/sys/net/ipv4/conf/all/accept_source_route

 /bin/echo "0" > /proc/sys/net/ipv4/conf/all/accept_redirects

 /bin/echo "1" > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses

 for i in /proc/sys/net/ipv4/conf/*; do

   /bin/echo "1" > $i/rp_filter

 done

 /bin/echo "1" > /proc/sys/net/ipv4/conf/all/log_martians

 /bin/echo "0" > /proc/sys/net/ipv4/ip_forward

 eend 0

}

```

Last edited by Powerslave on Sat Oct 11, 2003 10:42 am; edited 3 times in total

----------

## incubator

does this only work for servers with a router using ethernet? Or does this also work with an adsl modem? (i dont know if that has an eth0 interface)

----------

## Powerslave

Briefly speaking it's quite multifunctional script.

I mean that it should work with adsl connection since it's name is usually ppp0 if you use pppoe. [eth1 or smth (this one without ip) is there for hooking ppp0 ;-]

INET_IFACE - is the variable responsible for holding your internet interface name

Additionally to functioning as quite complete firewall script for single box you also have a possibility of masquerading connections from your internal network (to allow sharing of a single internet connection among several computers)

plus you can choose method of droping of connection - reset (you send reset packet) or drop (gives you stealth firewall no response just drop)

plus port forwarding

plus demilitarized zone

plus basic qos (quality of service)

plus defence against some attack patterns like floods 

plus transparent proxy

plus dhcp_server options

plus you can tailor it to your needs and educate a little bit in terms of iptables - since open source spirit lives here also  :Wink: 

----------

## incubator

thats great  :Very Happy: 

you came just in time  :Smile: 

our teacher of networks & firewalls uses ipchains instead of iptables so most likely we wont get to see how the latter works.

looks like some real good stuff   :Cool: 

----------

## Powerslave

I'm pleased that i've done something useful and on time - since the later is sometimes quite hard to fulfill  :Wink: 

My main goal was to provide a first line of defence for anyone including myself  :Wink:  without trying all the stuff that is available on the net.

This is just a remake of the firewall script from the link in initial post - but since everyone wants to have a solution right away - i've posted a bit modified script here.

Cheers

----------

## incubator

uhm, it says I am missing modules but I cannot find these in the kernel :s

```

* Could not get dependency info for "fwallscript"!

 * Please run:

 *   # /sbin/depscan.sh

 * to fix this.

modprobe: Can't locate module ip_tables

modprobe: Can't locate module ip_conntrack

modprobe: Can't locate module ip_conntrack_ftp

modprobe: Can't locate module ip_conntrack_irc

```

----------

## Powerslave

Some kernel options must be activated

Networking->Network packet filtering [*] (Mandatory for activating IPTABLES)

Networking->IP: Netfilter Configuration -> Connection tracking <M>

Networking->IP: Netfilter Configuration -> FTP protocol <M>

Networking->IP: Netfilter Configuration -> IRC protocol <M>

Networking->IP: Netfilter Configuration -> IP tables support <M>

+ some of options from this section if you wish to include them like packet filtering + REJECT option but it's up to you

Generally if there is a need for some modules it's quite easy to find them - since nearly all of modules for generating iptables firewall are in networking section

----------

