Anyone mind reviewing this iptables script?

Anyone mind reviewing this iptables script?

am 08.01.2007 18:48:51 von nrholder

Kubuntu 6.06 Dapper
Laptop used at home and various cafe's.

My primary goal is to simply secure my laptop while connected at home
and at several places I frequently haunt which have wireless internet.
I don't want a barmate trying to attack me.

I know the open TCP/UDP range is insecure but I'm running some tests
with various services between those ports. I'll close them as soon as
the testing is complete.

Also, I'm going to restrict outgoing as well but I'd like input on the
script thus far.

Any comments would be appreciated!

Nick

#!/bin/sh
#
# copyright (c) the KMyFirewall developers 2002-2005
# mail to: Christian Hubinger
#
# KMyFirewall v1.0
# This is an automatic generated file DO NOT EDIT
#
startFirewall() {

echo -n "Starting iptables (created by KMyFirewall)... "

if [ "$verbose" = "1" ]; then
echo -n "
Loading needed modules... "
fi

$MOD ip_tables
$MOD ip_conntrack
$MOD ipt_LOG
$MOD ipt_limit
$MOD ipt_state
$MOD ip_conntrack_ftp
$MOD ip_conntrack_irc
$MOD iptable_filter

if [ "$verbose" = "1" ]; then
echo "Done."
fi

# Define all custom chains
if [ "$verbose" = "1" ]; then
echo -n "Create custom chains... "
fi

# Create Chain: ANTISPOOF
$IPT -t filter -N ANTISPOOF || { status="1"; echo "Setting up Chain:
ANTISPOOF FAILED !!!"; exit 1; }

# Create Chain: ICMP_FILTER
$IPT -t filter -N ICMP_FILTER || { status="1"; echo "Setting up Chain:
ICMP_FILTER FAILED !!!"; exit 1; }

# Create Chain: SERVICES
$IPT -t filter -N SERVICES || { status="1"; echo "Setting up Chain:
SERVICES FAILED !!!"; exit 1; }

# Create Chain: TCP_CHECKS
$IPT -t filter -N TCP_CHECKS || { status="1"; echo "Setting up Chain:
TCP_CHECKS FAILED !!!"; exit 1; }

# Create Chain: LOCAL_LANS
$IPT -t filter -N LOCAL_LANS || { status="1"; echo "Setting up Chain:
LOCAL_LANS FAILED !!!"; exit 1; }

if [ "$verbose" = "1" ]; then
echo " Done."
fi

# Rules:
if [ "$verbose" = "1" ]; then
echo "Settup Rules in Table FILTER:"
fi

# Define Rules for Chain: INPUT
if [ "$verbose" = "1" ]; then
echo "Create Rules for Chain: INPUT"
fi

$IPT -t filter -A INPUT --in-interface lo -j ACCEPT || { status="1";
echo " Setting up Rule: LOOPBACK FAILED! "; exit 1; }

$IPT -t filter -A INPUT -p tcp --destination-port bootpc -j ACCEPT ||
{ status="1"; echo " Setting up Rule: DHCP FAILED! "; exit 1; }

$IPT -t filter -A INPUT --match state --state RELATED,ESTABLISHED -j
ACCEPT || { status="1"; echo " Setting up Rule: CONNTRACK FAILED! ";
exit 1; }

$IPT -t filter -A INPUT -j LOCAL_LANS || { status="1"; echo " Setting
up Rule: FWD_LOCAL_LANS FAILED! "; exit 1; }

$IPT -t filter -A INPUT -j ANTISPOOF || { status="1"; echo " Setting
up Rule: FWD_ANTISPOOF FAILED! "; exit 1; }

$IPT -t filter -A INPUT -j TCP_CHECKS || { status="1"; echo " Setting
up Rule: FWD_TCP_CHECKS FAILED! "; exit 1; }

$IPT -t filter -A INPUT -j ICMP_FILTER || { status="1"; echo " Setting
up Rule: FWD_ICMP_FILTER FAILED! "; exit 1; }

$IPT -t filter -A INPUT -j SERVICES || { status="1"; echo " Setting up
Rule: FWD_SERVICES FAILED! "; exit 1; }

$IPT -t filter -P INPUT DROP || { status="1"; echo " Setting up Rule:
Chain: INPUT Default Target FAILED! "; exit 1; }

# Define Rules for Chain: OUTPUT
if [ "$verbose" = "1" ]; then
echo "Create Rules for Chain: OUTPUT"
fi

$IPT -t filter -P OUTPUT ACCEPT || { status="1"; echo " Setting up
Rule: Chain: OUTPUT Default Target FAILED! "; exit 1; }

# Define Rules for Chain: FORWARD
if [ "$verbose" = "1" ]; then
echo "Create Rules for Chain: FORWARD"
fi

$IPT -t filter -P FORWARD DROP || { status="1"; echo " Setting up Rule:
Chain: FORWARD Default Target FAILED! "; exit 1; }

# Define Rules for Chain: ANTISPOOF
if [ "$verbose" = "1" ]; then
echo "Create Rules for Chain: ANTISPOOF"
fi

$IPT -t filter -A ANTISPOOF --in-interface ! lo --source 127.0.0.1/8 -j
DROP || { status="1"; echo " Setting up Rule: Loopback_Spoof FAILED!
"; exit 1; }

# Define Rules for Chain: ICMP_FILTER
if [ "$verbose" = "1" ]; then
echo "Create Rules for Chain: ICMP_FILTER"
fi

$IPT -t filter -A ICMP_FILTER -p icmp --icmp-type echo-request -j
ACCEPT || { status="1"; echo " Setting up Rule: ECHO_REQUEST FAILED!
"; exit 1; }

$IPT -t filter -A ICMP_FILTER -p icmp --icmp-type echo-reply -j
LOCAL_LANS || { status="1"; echo " Setting up Rule: ECHO_REPLY FAILED!
"; exit 1; }

$IPT -t filter -A ICMP_FILTER -p icmp --icmp-type host-unreachable -j
ACCEPT || { status="1"; echo " Setting up Rule: HOST_UNREACHABLE
FAILED! "; exit 1; }

$IPT -t filter -A ICMP_FILTER -p icmp --icmp-type network-unreachable
-j ACCEPT || { status="1"; echo " Setting up Rule: NET_UNREACHABLE
FAILED! "; exit 1; }

# Define Rules for Chain: SERVICES
if [ "$verbose" = "1" ]; then
echo "Create Rules for Chain: SERVICES"
fi

$IPT -t filter -A SERVICES -p tcp --source-port 1024:65535
--destination-port 8000:10000 -j ACCEPT || { status="1"; echo "
Setting up Rule: Custom_TCP_Ports FAILED! "; exit 1; }

$IPT -t filter -A SERVICES -p udp --source-port 1024:65535
--destination-port 8000:10000 -j ACCEPT || { status="1"; echo "
Setting up Rule: Custom_UDP_Ports FAILED! "; exit 1; }

$IPT -t filter -A SERVICES -p tcp --destination-port 137:139 -j
LOCAL_LANS || { status="1"; echo " Setting up Rule: SMB FAILED! ";
exit 1; }

$IPT -t filter -A SERVICES -p tcp --destination-port 445 -j LOCAL_LANS
|| { status="1"; echo " Setting up Rule: SSMB FAILED! "; exit 1; }

$IPT -t filter -A SERVICES -p tcp --source-port 1024:65535
--destination-port ssh -j LOCAL_LANS || { status="1"; echo " Setting
up Rule: SSH FAILED! "; exit 1; }

$IPT -t filter -A SERVICES -p tcp --source-port 1024:65535
--destination-port 20:21 -j LOCAL_LANS || { status="1"; echo " Setting
up Rule: FTP FAILED! "; exit 1; }

$IPT -t filter -A SERVICES -p tcp --source-port 1024:65535
--destination-port www -j LOCAL_LANS || { status="1"; echo " Setting
up Rule: HTTP FAILED! "; exit 1; }

$IPT -t filter -A SERVICES -p tcp --source-port 1024:65535
--destination-port https -j LOCAL_LANS || { status="1"; echo " Setting
up Rule: HTTPS FAILED! "; exit 1; }

# Define Rules for Chain: TCP_CHECKS
if [ "$verbose" = "1" ]; then
echo "Create Rules for Chain: TCP_CHECKS"
fi

$IPT -t filter -A TCP_CHECKS -p tcp --tcp-flags ALL NONE -j DROP || {
status="1"; echo " Setting up Rule: TCP_FLAGS_1 FAILED! "; exit 1; }

$IPT -t filter -A TCP_CHECKS -p tcp --tcp-flags FIN,ACK FIN -j DROP ||
{ status="1"; echo " Setting up Rule: TCP_FLAGS_2 FAILED! "; exit 1; }

$IPT -t filter -A TCP_CHECKS -p tcp --tcp-flags ACK,PSH PSH -j DROP ||
{ status="1"; echo " Setting up Rule: TCP_FLAGS_3 FAILED! "; exit 1; }

$IPT -t filter -A TCP_CHECKS -p tcp --tcp-flags ACK,URG URG -j DROP ||
{ status="1"; echo " Setting up Rule: TCP_FLAGS_4 FAILED! "; exit 1; }

$IPT -t filter -A TCP_CHECKS -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
|| { status="1"; echo " Setting up Rule: TCP_FLAGS_5 FAILED! "; exit
1; }

$IPT -t filter -A TCP_CHECKS -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
|| { status="1"; echo " Setting up Rule: TCP_FLAGS_6 FAILED! "; exit
1; }

$IPT -t filter -A TCP_CHECKS -p tcp --tcp-flags FIN,RST FIN,RST -j DROP
|| { status="1"; echo " Setting up Rule: TCP_FLAGS_7 FAILED! "; exit
1; }

$IPT -t filter -A TCP_CHECKS -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP
|| { status="1"; echo " Setting up Rule: TCP_FLAGS_8 FAILED! "; exit
1; }

# Define Rules for Chain: LOCAL_LANS
if [ "$verbose" = "1" ]; then
echo "Create Rules for Chain: LOCAL_LANS"
fi

$IPT -t filter -A LOCAL_LANS --source 192.168.1.0/24 -j ACCEPT || {
status="1"; echo " Setting up Rule: Trusted_Network_1 FAILED! "; exit
1; }

if [ "$verbose" = "1" ]; then
echo -n "Disable IP Forwarding. "
fi
echo 0 > /proc/sys/net/ipv4/ip_forward
if [ "$verbose" = "1" ]; then
echo "Done."
fi

if [ "$verbose" = "1" ]; then
echo -n "Enable Reverse Path Filtering "
fi

for i in /proc/sys/net/ipv4/conf/*/rp_filter ; do
echo 2 > $i
done

if [ "$verbose" = "1" ]; then
echo "Done."
fi

if [ "$verbose" = "1" ]; then
echo -n "Enable log_martians (logging). "
fi

for i in /proc/sys/net/ipv4/conf/*/log_martians ; do
echo 1 > $i
done

if [ "$verbose" = "1" ]; then
echo "Done."
fi

if [ "$verbose" = "1" ]; then
echo -n "Enable Syn Cookies. "
fi

echo 1 > /proc/sys/net/ipv4/tcp_syncookies
if [ "$verbose" = "1" ]; then
echo "Done."
fi

echo Done.
}

stopFirewall() {
echo -n "Clearing iptables (created by KMyFirewall)... "
$IPT -t filter -F || status="1"
$IPT -t filter -X || status="1"
$IPT -t filter -P INPUT ACCEPT || status="1"
$IPT -t filter -P OUTPUT ACCEPT || status="1"
$IPT -t filter -P FORWARD ACCEPT || status="1"
echo "Done."
}

IPT="/sbin/iptables"
MOD="/sbin/modprobe"
status="0"
verbose="0"
action="$1"

if [ "$1" = "-v" ]; then
verbose="1"
fi

if [ "$1" = "--verbose" ]; then
verbose="1"
fi

if [ "$verbose" = "1" ]; then
if [ "$2" = "" ]; then
echo "Usage: sh kmyfirewall.sh [-v|--verbose] { start | stop |
restart }"
exit 1
fi

action="$2"
fi

case $action in
start)
stopFirewall
startFirewall
;;
stop)
stopFirewall
;;
restart)
stopFirewall
startFirewall
;;
*)
echo "Invalid action!
Usage: sh kmyfirewall.sh [-v|--verbose] { start | stop | restart }"
;;
esac
if [ "$status" = "1" ]; then
exit 1
else
exit 0
fi

Re: Anyone mind reviewing this iptables script?

am 08.01.2007 19:44:36 von Jim Ford

nrholder wrote:
> Kubuntu 6.06 Dapper
> Laptop used at home and various cafe's.

How about installing Shorewall - it makes iptables much easier.

Jim Ford

Re: Anyone mind reviewing this iptables script?

am 08.01.2007 21:00:11 von Ansgar -59cobalt- Wiechers

nrholder wrote:
> Kubuntu 6.06 Dapper
> Laptop used at home and various cafe's.
>
> My primary goal is to simply secure my laptop while connected at home
> and at several places I frequently haunt which have wireless internet.
> I don't want a barmate trying to attack me.
>
> I know the open TCP/UDP range is insecure but I'm running some tests
> with various services between those ports. I'll close them as soon as
> the testing is complete.
>
> Also, I'm going to restrict outgoing as well but I'd like input on the
> script thus far.
[...]
> $MOD ip_tables
> $MOD ip_conntrack
> $MOD ipt_LOG
> $MOD ipt_limit
> $MOD ipt_state
> $MOD ip_conntrack_ftp
> $MOD ip_conntrack_irc
> $MOD iptable_filter

Do you use FTP or IRC? If not: don't load the respective modules.

[...]
> $IPT -t filter -A INPUT -p tcp --destination-port bootpc -j ACCEPT ||
> { status="1"; echo " Setting up Rule: DHCP FAILED! "; exit 1; }
>
> $IPT -t filter -A INPUT --match state --state RELATED,ESTABLISHED -j
> ACCEPT || { status="1"; echo " Setting up Rule: CONNTRACK FAILED! ";
> exit 1; }

Do you run a DHCP server on that host? If so: why? If not: the first
rule is pointless, because DHCPOFFER and DHCPACK are RELATED traffic,
which is covered by the second rule.

[...]
> $IPT -t filter -A INPUT -j ICMP_FILTER || { status="1"; echo " Setting
> up Rule: FWD_ICMP_FILTER FAILED! "; exit 1; }

Since this rule is apparently supposed to filter ICMP traffic, it would
be appropriate to redirect only ICMP traffic to the chain ICMP_FILTER.

$IPT -A INPUT -p icmp -j ICMP_FILTER

Besides, applying rules to the filter table is the default for iptables,
so "-t filter" is redundant.

[...]
> $IPT -t filter -P INPUT DROP || { status="1"; echo " Setting up Rule:
> Chain: INPUT Default Target FAILED! "; exit 1; }
[...]
> $IPT -t filter -P OUTPUT ACCEPT || { status="1"; echo " Setting up
> Rule: Chain: OUTPUT Default Target FAILED! "; exit 1; }
[...]
> $IPT -t filter -P FORWARD DROP || { status="1"; echo " Setting up Rule:
> Chain: FORWARD Default Target FAILED! "; exit 1; }

Set the default policies *before* creating any new rules/chains. Also
flush the chains and delete all user-defined chains before creating new
rules/chains.

$IPT -P INPUT DROP
$IPT -P OUTPUT ACCEPT
$IPT -P FORWARD DROP
$IPT -F
$IPT -X

I suggest you reject unwanted traffic rather than dropping it, too.

....
$IPT -A INPUT -j DENY

$IPT -N DENY
$IPT -A DENY -p tcp -j REJECT --reject-with tcp-reset
$IPT -A DENY -p udp -j REJECT --reject-with icmp-port-unreachable

[...]
> $IPT -t filter -A ANTISPOOF --in-interface ! lo --source 127.0.0.1/8 -j
> DROP || { status="1"; echo " Setting up Rule: Loopback_Spoof FAILED!
> "; exit 1; }

Will the computer be on networks with private IP addresses? If not you
may want to add some more rules to cover RFC1918 and APIPA addresses.
Maybe multicast addresses as well.

[...]
> $IPT -t filter -A ICMP_FILTER -p icmp --icmp-type echo-request -j
> ACCEPT || { status="1"; echo " Setting up Rule: ECHO_REQUEST FAILED!
> "; exit 1; }
>
> $IPT -t filter -A ICMP_FILTER -p icmp --icmp-type echo-reply -j
> LOCAL_LANS || { status="1"; echo " Setting up Rule: ECHO_REPLY FAILED!
> "; exit 1; }
>
> $IPT -t filter -A ICMP_FILTER -p icmp --icmp-type host-unreachable -j
> ACCEPT || { status="1"; echo " Setting up Rule: HOST_UNREACHABLE
> FAILED! "; exit 1; }
>
> $IPT -t filter -A ICMP_FILTER -p icmp --icmp-type network-unreachable
> -j ACCEPT || { status="1"; echo " Setting up Rule: NET_UNREACHABLE
> FAILED! "; exit 1; }

Use destination-unreachable instead of allowing distinct codes of this
type. You may want to allow source-quench, time-exceeded, and parameter-
problem as well. Also I'd allow all types except echo-request only for
RELATED traffic.

[...]
> $IPT -t filter -A SERVICES -p tcp --source-port 1024:65535
> --destination-port 8000:10000 -j ACCEPT || { status="1"; echo "
> Setting up Rule: Custom_TCP_Ports FAILED! "; exit 1; }
>
> $IPT -t filter -A SERVICES -p udp --source-port 1024:65535
> --destination-port 8000:10000 -j ACCEPT || { status="1"; echo "
> Setting up Rule: Custom_UDP_Ports FAILED! "; exit 1; }

Don't allow traffic only based on ports. netfilter does stateful
filtering. Use it. That'll most likely spare you the trouble of opening
broad port ranges.

[...]
> $IPT -t filter -A SERVICES -p tcp --destination-port 137:139 -j
> LOCAL_LANS || { status="1"; echo " Setting up Rule: SMB FAILED! ";
> exit 1; }
>
> $IPT -t filter -A SERVICES -p tcp --destination-port 445 -j LOCAL_LANS
> || { status="1"; echo " Setting up Rule: SSMB FAILED! "; exit 1; }
>
> $IPT -t filter -A SERVICES -p tcp --source-port 1024:65535
> --destination-port ssh -j LOCAL_LANS || { status="1"; echo " Setting
> up Rule: SSH FAILED! "; exit 1; }

Why are you discriminating on the source port? It is possible, though
unusual, to have traffic originating from privileged ports. Rather check
the connection state instead.

$IPT -A SERVICES -p tcp --dport 22 -m state --state NEW -j LOCAL_LANS

> $IPT -t filter -A SERVICES -p tcp --source-port 1024:65535
> --destination-port 20:21 -j LOCAL_LANS || { status="1"; echo " Setting
> up Rule: FTP FAILED! "; exit 1; }

You're running an FTP server on your notebook? Why?

> $IPT -t filter -A SERVICES -p tcp --source-port 1024:65535
> --destination-port www -j LOCAL_LANS || { status="1"; echo " Setting
> up Rule: HTTP FAILED! "; exit 1; }
>
> $IPT -t filter -A SERVICES -p tcp --source-port 1024:65535
> --destination-port https -j LOCAL_LANS || { status="1"; echo " Setting
> up Rule: HTTPS FAILED! "; exit 1; }

Same as for SSH:

$IPT -A SERVICES -p tcp --dport 80 -m state --state NEW -j LOCAL_LANS
$IPT -A SERVICES -p tcp --dport 443 -m state --state NEW -j LOCAL_LANS

You could use the multiport module to make a single rule from these:

$IPT -A SERVICES -p tcp -m multiport --dport 22,80,443 \
-m state --state NEW -j LOCAL_LANS

[...]
> $IPT -t filter -A LOCAL_LANS --source 192.168.1.0/24 -j ACCEPT || {
> status="1"; echo " Setting up Rule: Trusted_Network_1 FAILED! "; exit
> 1; }

Maybe put the network address into a variable. Makes it easier to
change.

[...]
> echo 0 > /proc/sys/net/ipv4/ip_forward
[...]
> for i in /proc/sys/net/ipv4/conf/*/rp_filter ; do
> echo 2 > $i
> done
[...]
> for i in /proc/sys/net/ipv4/conf/*/log_martians ; do
> echo 1 > $i
> done
[...]
> echo 1 > /proc/sys/net/ipv4/tcp_syncookies

I'd suggest to set these first, before creating any rules.

[...]
> stopFirewall() {
> echo -n "Clearing iptables (created by KMyFirewall)... "
> $IPT -t filter -F || status="1"
> $IPT -t filter -X || status="1"
> $IPT -t filter -P INPUT ACCEPT || status="1"
> $IPT -t filter -P OUTPUT ACCEPT || status="1"
> $IPT -t filter -P FORWARD ACCEPT || status="1"
[...]
> case $action in
> start)
> stopFirewall
> startFirewall

This will disable your firewall before applying new rules. Don't do
that. The time frame until the new rules get applied may be short, but
may be long enough for an attacker/worm/whatever.

My 0.02$.

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

Re: Anyone mind reviewing this iptables script?

am 08.01.2007 21:43:58 von Ansgar -59cobalt- Wiechers

Jim Ford wrote:
> nrholder wrote:
>> Kubuntu 6.06 Dapper
>> Laptop used at home and various cafe's.
>
> How about installing Shorewall - it makes iptables much easier.

How about actually learning how iptables/netfilter works? There's
nothing that makes things as easy as understanding what you're doing,
and the netfilter homepage [1] has a boatload of tutorials and other
documentation.

Besides, an iptables ruleset for a notebook is almost a no-brainer, if
you must have iptables in the first place (you could simply not start
the services you don't need instead).

[1] http://www.netfilter.org/

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