#!/bin/sh -e
. /lib/rcscripts/sh/error.sh
. /etc/conf.d/iptables || error "Failed to source config file"
DESCRIPTION="packet filters"
# Hardcode these instead of relying on values from the config
IPTABLES=/usr/sbin/iptables
IP6TABLES=/usr/sbin/ip6tables
[ -x "$IPTABLES" ] || IPTABLES=dummytables
[ -x "$IP6TABLES" ] || IP6TABLES=dummytables
dummytables() {
:
}
FAILED=0
fail() {
if [ "$FAILED" != "1" ]; then
FAILED=1
stop_filter
fi
error "Failed to $@"
}
flush() {
$IPTABLES -F || fail "flush tables!"
$IP6TABLES -F || fail "flush tables!"
}
set_policy() {
$IPTABLES -P INPUT $1 || fail "set $1 policy!"
$IP6TABLES -P INPUT $1 || fail "set $1 policy!"
}
addr_family() {
local family
# This function determines AF but does not validate addresses
# ':' is found in IPv6 addresses but never in IPv4 addresses
[ $# -eq 2 ] || error "addr_family(): Invalid number of arguments"
case $1 in
*[!.:[:xdigit:][:blank:]\/,]*)
error "Invalid characters in IP address"
;
*:*)
family=6
;
*.*)
family=4
;
*)
error "Invalid ip address '$1'"
;
esac
eval $2=\$family || error "Failed to evaluate IP address family"
}
start_filter() {
local added_iptables=0 added_ip6tables=0 af=0
flush
if [ "$IPTABLES_INPUT_POLICY" = allow ]; then
FILTER_ACTION=ACCEPT
set_policy DROP
else
FILTER_ACTION=DROP
set_policy ACCEPT
fi
$IPTABLES -A INPUT -i lo -j ACCEPT || fail "ACCEPT loopback!"
$IP6TABLES -A INPUT -i lo -j ACCEPT || fail "ACCEPT loopback!"
$IPTABLES -A INPUT -p icmp -j ACCEPT || fail "ACCEPT ICMP!"
$IP6TABLES -A INPUT -p icmpv6 -j ACCEPT || fail "ACCEPT ICMP!"
# Accept incoming packets on locally initiated TCP connections.
$IPTABLES -A INPUT -p tcp ! --syn -j ACCEPT || fail "ACCEPT TCP !SYN!"
$IP6TABLES -A INPUT -p tcp ! --syn -j ACCEPT || fail "ACCEPT TCP !SYN!"
for SRC in $IPTABLES_ACCEPT; do
addr_family "$SRC" af
if [ $af = 4 ]; then
if [ "$IPTABLES_LOG_ENABLED" = yes ] &&
[ "$FILTER_ACTION" = DROP ]; then
$IPTABLES -A INPUT -s "$SRC" -j LOG --log-prefix "IP_FILTER: " ||
fail "LOG source address \"$SRC\"!"
fi
added_iptables=1
$IPTABLES -A INPUT -s "$SRC" -j $FILTER_ACTION ||
fail "$FILTER_ACTION source address \"$SRC\"!"
elif [ $af = 6 ]; then
if [ "$IPTABLES_LOG_ENABLED" = yes ] &&
[ "$FILTER_ACTION" = DROP ]; then
$IP6TABLES -A INPUT -s "$SRC" -j LOG --log-prefix "IP_FILTER: " ||
fail "LOG source address \"$SRC\"!"
fi
added_ip6tables=1
$IP6TABLES -A INPUT -s "$SRC" -j $FILTER_ACTION ||
fail "$FILTER_ACTION source address \"$SRC\"!"
fi
done
if [ "$IPTABLES_LOG_ENABLED" = yes ] && [ $added_iptables -eq 1 ] &&
[ "$FILTER_ACTION" = ACCEPT ]; then
$IPTABLES -A INPUT -j LOG --log-prefix "IP_FILTER: " ||
fail "LOG source address \"$SRC\"!"
fi
if [ "$IPTABLES_LOG_ENABLED" = yes ] && [ $added_ip6tables -eq 1 ] &&
[ "$FILTER_ACTION" = ACCEPT ]; then
$IP6TABLES -A INPUT -j LOG --log-prefix "IP_FILTER: " ||
fail "LOG source address \"$SRC\"!"
fi
# drop in-wire ipv4-mapped addresses
$IP6TABLES -A INPUT -s ::ffff:0:1/96 -j DROP
$IP6TABLES -A INPUT -d ::ffff:0:1/96 -j DROP
}
stop_filter() {
flush
set_policy ACCEPT
}
conditional_start() {
if [ "$IPTABLES_ENABLED" = yes ]; then
start_filter
else
information "disabled"
stop_filter
fi
}
case "$1" in
start)
information "Starting $DESCRIPTION"
conditional_start
;
stop)
information "Stopping $DESCRIPTION"
stop_filter
;
*)
error "Usage: $0 start|stop"
;
esac
exit 0