Sample iptables rules list, inviting your suggestions / criticisms (thanks) :-)
am 04.11.2006 21:47:19 von reply.in.group
Redirected here from the "Post iptables rules in newsgroups" and "What
iptables rules to allow name service" threads...
Thanks to all of your help, I think I have what looks to me like a
reasonable set of iptables rules to shut down unneeded access while
allowing DNS to work to/from the name server that runs on that host.
Please take a look at the following and let me know of any suggestions or
criticisms you may have ... thanks :-)
(DESPERATELY hoping that my newsreader, or yours, doesn't hopelessly hose
the formatting in the following cut-and-paste...)
# Firewall configuration excerpt
#
# Based on the config file written by Fedora Core 2
# system-config-securitylevel (the one that says
# "Manual customization of this file is not recommended.")
#
# This firewall only controls access to the machine on which it
# runs. This machine does not serve as a router to provide
# network access to other machines.
#
# Objectives:
# Allow ftp, http, mail, and ping to and from everybody
# Allow ssh to and from certain (trusted) hosts
# (the firewall allows ssh from all
# and access is controlled in hosts.allow/deny)
# Disable telnet, rlogin, rsh, rexec, etc.
# (all of which are turned off in xinetd.d anyway...)
# Allow name service to and from the name server that
# runs on this host (this is a "primary" name server that
# also serves several "secondary" name servers)
#
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0] # Do I need this? See FORWARD chain below
:OUTPUT ACCEPT [0:0]
#
############################################################ #####
#
# Rule set for the INPUT chain
#
# Allow anything from the localhost
#
-A INPUT -i lo -j ACCEPT
#
# Allow any icmp (mostly ping ... should I restrict it to ping
# only? What other kinds of ICMP are there that could be
# intrusive or dangerous?)
#
-A INPUT -p icmp --icmp-type any -j ACCEPT
#
# Allow ftp, ssh, mail, http, https. ssh access is restricted
# in hosts.allow and hosts.deny.
#
# (NOTE: I don't need "-m tcp -p tcp", do I?
# Isn't "-m tcp" implied by "-p tcp"?
#
-A INPUT -m state --state NEW -m tcp -p tcp --dport 21 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 25 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
#
# Enable DNS for input
#
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p tcp --dport 53 -m state --state NEW -j ACCEPT
-A INPUT -p udp --dport 53 -m state --state NEW -j ACCEPT
#
# Silently drop everything else
#
# NOTE: Could I eliminate the "-A INPUT -j DROP" rule by just
# changing the ":INPUT ACCEPT [0:0]" to ":INPUT DROP [0:0]" up at
# the beginning of this rules list?
#
-A INPUT -j DROP
#
############################################################ #####
#
# Rule set for the FORWARD chain.
# Everything gets silently dropped.
#
# NOTE: Do I even need this at all, or should I just eliminate
# the FORWARD chain entirely, or change ":FORWARD ACCEPT [0:0]"
# to ":FORWARD DROP [0:0]" up near the top of this list?
#
# /proc/sys/net/ipv4/ip_forward is set to 0.
#
# If I don't need this, then should I also eliminate the
# ":FORWARD ACCEPT [0:0]" up near the top of this list?
#
-A FORWARD -j DROP
#
############################################################ #####
#
# Rule set for the OUTPUT chain. These mostly have to do with
# logging although there is one DROP rule.
#
# Don't log things to the localhost
#
-A OUTPUT -o lo -j RETURN
#
# Disable outbound telnet from local users
# (this is the only DROP rule in the chain)
#
-A OUTPUT -m state --state NEW -m tcp -p tcp --dport 23 -j DROP
#
# Enable DNS for output
#
# NOTE: The following three rules were recommended to me by
# 59cobalt on comp.security.firewalls in order to get DNS to
# work. However, everything in the OUTPUT chain is ACCEPTed by
# default except for one specific DROP to disable telnet, noted
# above, so I shouldn't need the following three rules at all,
# right?
#
-A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A OUTPUT -p tcp --dport 53 -m state --state NEW -j ACCEPT
-A OUTPUT -p udp --dport 53 -m state --state NEW -j ACCEPT
#
# Don't log ping (or any ICMP), mail, http, https, X11-over-ssh,
# or dns
#
-A OUTPUT -p icmp --icmp-type any -j RETURN
-A OUTPUT -p tcp --sport 25 -j RETURN
-A OUTPUT -p tcp --dport 25 -j RETURN
-A OUTPUT -p tcp --dport 53 -j RETURN
-A OUTPUT -p udp --dport 53 -j RETURN
-A OUTPUT -p tcp --sport 80 -j RETURN
-A OUTPUT -p tcp --dport 80 -j RETURN
-A OUTPUT -p tcp --sport 443 -j RETURN
-A OUTPUT -p tcp --sport 6010 -j RETURN
-A OUTPUT -p tcp --dport 6010 -j RETURN
#
# Log everything else
#
-A OUTPUT -j LOG
#
COMMIT
Re: Sample iptables rules list, inviting your suggestions / criticisms (thanks) :-)
am 05.11.2006 17:05:57 von Ansgar -59cobalt- Wiechers
C. J. Clegg wrote:
> # This firewall only controls access to the machine on which it
> # runs. This machine does not serve as a router to provide
> # network access to other machines.
> #
> # Objectives:
> # Allow ftp, http, mail, and ping to and from everybody
> # Allow ssh to and from certain (trusted) hosts
> # (the firewall allows ssh from all
> # and access is controlled in hosts.allow/deny)
> # Disable telnet, rlogin, rsh, rexec, etc.
> # (all of which are turned off in xinetd.d anyway...)
> # Allow name service to and from the name server that
> # runs on this host (this is a "primary" name server that
> # also serves several "secondary" name servers)
> #
> *filter
> :INPUT ACCEPT [0:0]
> :FORWARD ACCEPT [0:0] # Do I need this? See FORWARD chain below
> :OUTPUT ACCEPT [0:0]
I'm not familiar with the syntax used above, so I'll be using "default"
iptables commandline syntax.
If I understand correctly the lines above set the default policies for
the three default chains. These should *always* be set do DROP,
otherwise your firewall would fail open, which would be a Really Bad
Thing(tm).
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
Also make sure to delete all user-defined chains and flush the default
chains when starting the firewall:
iptables -F
iptables -X
> # Allow anything from the localhost
> #
> -A INPUT -i lo -j ACCEPT
OK.
> # Allow any icmp (mostly ping ... should I restrict it to ping
> # only? What other kinds of ICMP are there that could be
> # intrusive or dangerous?)
> #
> -A INPUT -p icmp --icmp-type any -j ACCEPT
I wouldn't recommend restricting it to ping only, but I'd definitely
recommend applying some restrictions. I'd also recommend putting the
rules into a user-defined chain, so you need to define them only once.
iptables -N ICMP
iptables -A ICMP -p icmp --icmp-type echo-request -j ACCEPT
iptables -A ICMP -p icmp --icmp-type echo-reply -j ACCEPT
iptables -A ICMP -p icmp --icmp-type destination-unreachable -j ACCEPT
iptables -A ICMP -p icmp --icmp-type source-quench -j ACCEPT
iptables -A ICMP -p icmp --icmp-type time-exceeded -j ACCEPT
iptables -A ICMP -p icmp --icmp-type parameter-problem -j ACCEPT
iptables -A INPUT -p icmp -j ICMP
....
iptables -A OUTPUT -p icmp -j ICMP
....
> # Allow ftp, ssh, mail, http, https. ssh access is restricted
> # in hosts.allow and hosts.deny.
> #
> # (NOTE: I don't need "-m tcp -p tcp", do I?
> # Isn't "-m tcp" implied by "-p tcp"?
> #
> -A INPUT -m state --state NEW -m tcp -p tcp --dport 21 -j ACCEPT
> -A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
> -A INPUT -m state --state NEW -m tcp -p tcp --dport 25 -j ACCEPT
> -A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
> -A INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
Yes, "-m tcp" is implicit, so you can omit it to make the rules more
concise. In addition to that you can use the "multiport" module to
simplify the rules:
ALLOWED_TCP_PORTS="21,22,25,80,443"
....
iptables -A INPUT -p tcp -m multiport --dport ${ALLOWED_TCP_PORTS} \
-m state --state NEW -j ACCEPT
> # Enable DNS for input
> #
> -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
> -A INPUT -p tcp --dport 53 -m state --state NEW -j ACCEPT
> -A INPUT -p udp --dport 53 -m state --state NEW -j ACCEPT
As I had suggested in <4r18j8Fp2djiU1@individual.net> I'd put the DNS
rules into a user-defined chain, so you don't have to define them both
in INPUT and OUTPUT chain (unless you don't want that box to access
other DNS servers, in which case you can simply put the rules into the
INPUT chain as you do above).
iptables -N DNS
iptables -A DNS -p udp --dport 53 -m state --state NEW -j ACCEPT
iptables -A DNS -p tcp --dport 53 -m state --state NEW -j ACCEPT
iptables -A INPUT -j DNS
....
iptables -A OUTPUT -j DNS
....
Keep in mind that you have to put the ESTABLISHED,RELATED rule into the
corresponding chain:
- For allowing *inbound* DNS you need NEW in the INPUT chain and
ESTABLISHED,RELATED in the OUTPUT chain.
- For allowing *outbound* DNS you need NEW in the OUTPUT chain and
ESTABLISHED,RELATED in the INPUT chain.
> # Silently drop everything else
> #
> # NOTE: Could I eliminate the "-A INPUT -j DROP" rule by just
> # changing the ":INPUT ACCEPT [0:0]" to ":INPUT DROP [0:0]" up at
> # the beginning of this rules list?
> #
> -A INPUT -j DROP
As mentioned above you should *always* set the default to DROP. I
suppose ":INPUT DROP [0:0]" would do that. In addition to that I suggest
to REJECT connections rather than DROP them:
iptables -N DENY
iptables -A DENY -p tcp -j REJECT --reject-with tcp-reset
iptables -A DENY -p udp -j REJECT --reject-with icmp-port-unreachable
....
iptables -A INPUT -j DENY
....
iptables -A OUTPUT -j DENY
You can use the "limit" module to limit rejection, causing floods to be
DROPed rather than REJECTed:
RATE="20/s"
BURST="40"
....
iptables -A DENY -p tcp -m limit --limit ${RATE} --limit-burst ${BURST} \
-j REJECT --reject-with tcp-reset
iptables -A DENY -p udp -m limit --limit ${RATE} --limit-burst ${BURST} \
-j REJECT --reject-with icmp-port-unreachable
> # NOTE: Do I even need this at all, or should I just eliminate
> # the FORWARD chain entirely, or change ":FORWARD ACCEPT [0:0]"
> # to ":FORWARD DROP [0:0]" up near the top of this list?
> #
> # /proc/sys/net/ipv4/ip_forward is set to 0.
> #
> # If I don't need this, then should I also eliminate the
> # ":FORWARD ACCEPT [0:0]" up near the top of this list?
> #
> -A FORWARD -j DROP
FORWARD is one of the netfilter default chains, which are *always*
present. Thus you definitely should set a default for it (which should
be to DROP everything).
> ############################################################ #####
> #
> # Rule set for the OUTPUT chain. These mostly have to do with
> # logging although there is one DROP rule.
> #
> # Don't log things to the localhost
> #
> -A OUTPUT -o lo -j RETURN
> #
> # Disable outbound telnet from local users
> # (this is the only DROP rule in the chain)
> #
> -A OUTPUT -m state --state NEW -m tcp -p tcp --dport 23 -j DROP
It is *not* advisable to just disallow specific things and allow
everything else. Find out what you need to allow, allow just that, and
deny everything else.
> # Enable DNS for output
> #
> # NOTE: The following three rules were recommended to me by
> # 59cobalt on comp.security.firewalls in order to get DNS to
> # work. However, everything in the OUTPUT chain is ACCEPTed by
> # default except for one specific DROP to disable telnet, noted
> # above, so I shouldn't need the following three rules at all,
> # right?
> #
> -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
> -A OUTPUT -p tcp --dport 53 -m state --state NEW -j ACCEPT
> -A OUTPUT -p udp --dport 53 -m state --state NEW -j ACCEPT
> #
> # Don't log ping (or any ICMP), mail, http, https, X11-over-ssh,
> # or dns
> #
> -A OUTPUT -p icmp --icmp-type any -j RETURN
> -A OUTPUT -p tcp --sport 25 -j RETURN
> -A OUTPUT -p tcp --dport 25 -j RETURN
> -A OUTPUT -p tcp --dport 53 -j RETURN
> -A OUTPUT -p udp --dport 53 -j RETURN
> -A OUTPUT -p tcp --sport 80 -j RETURN
> -A OUTPUT -p tcp --dport 80 -j RETURN
> -A OUTPUT -p tcp --sport 443 -j RETURN
> -A OUTPUT -p tcp --sport 6010 -j RETURN
> -A OUTPUT -p tcp --dport 6010 -j RETURN
Traffic with one of the given source-ports is most likely related to
inbound requests so there's no need for separate rules for them.
> # Log everything else
> #
> -A OUTPUT -j LOG
OK.
The following (basic) ruleset should cover your needs:
----8<----
#!/bin/sh
ipt=/sbin/iptables
echo=/bin/echo
ALLOWED_IN_TCP_PORTS="21,22,25,80,443"
ALLOWED_OUT_TCP_PORTS="25,80,6010"
RATE="20/s"
BURST="40"
# Explicitly disable IP forwarding
$echo "0" > /proc/sys/net/ipv4/ip_forward
# Set default policies
$ipt -P INPUT DROP
$ipt -P OUTPUT DROP
$ipt -P FORWARD DROP
$ipt -F
$ipt -X
# Set up user-defined chains
$ipt -N ICMP
$ipt -A ICMP -p icmp --icmp-type echo-request -j ACCEPT
$ipt -A ICMP -p icmp --icmp-type echo-reply -j ACCEPT
$ipt -A ICMP -p icmp --icmp-type destination-unreachable -j ACCEPT
$ipt -A ICMP -p icmp --icmp-type source-quench -j ACCEPT
$ipt -A ICMP -p icmp --icmp-type time-exceeded -j ACCEPT
$ipt -A ICMP -p icmp --icmp-type parameter-problem -j ACCEPT
$ipt -N DNS
$ipt -A DNS -p udp --dport 53 -m state --state NEW -j ACCEPT
$ipt -A DNS -p tcp --dport 53 -m state --state NEW -j ACCEPT
$ipt -N DENY
$ipt -A DENY -p tcp -m limit --limit ${RATE} --limit-burst ${BURST} \
-j REJECT --reject-with tcp-reset
$ipt -A DENY -p udp -m limit --limit ${RATE} --limit-burst ${BURST} \
-j REJECT --reject-with icmp-port-unreachable
$ipt -A DENY -j LOG
# INPUT chain
$ipt -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$ipt -A INPUT -i lo -j ACCEPT
$ipt -A INPUT -p icmp -j ICMP
$ipt -A INPUT -j DNS
$ipt -A INPUT -p tcp -m multiport --dport ${ALLOWED_IN_TCP_PORTS} \
-m state --state NEW -j ACCEPT
$ipt -A INPUT -j DENY
# OUTPUT chain
$ipt -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$ipt -A OUTPUT -p icmp -j ICMP
$ipt -A OUTPUT -j DNS
$ipt -A OUTPUT -p tcp -m multiport --dport ${ALLOWED_OUT_TCP_PORTS} \
-m state --state NEW -j ACCEPT
$ipt -A OUTPUT -j DENY
---->8----
cu
59cobalt
--
"If a software developer ever believes a rootkit is a necessary part of
their architecture they should go back and re-architect their solution."
--Mark Russinovich