diff --git a/Shorewall/firewall b/Shorewall/firewall index b44f429ae..65079cf5f 100755 --- a/Shorewall/firewall +++ b/Shorewall/firewall @@ -529,7 +529,7 @@ validate_interfaces_file() { for option in `separate_list $options`; do case $option in - dhcp|noping|filterping|routestopped|norfc1918|multi) + dhcp|noping|filterping|routestopped|norfc1918|multi|tcpflags) ;; routefilter|dropunclean|logunclean|blacklist|proxyarp|maclist|-) ;; @@ -3211,6 +3211,47 @@ add_common_rules() { done fi + + interfaces=`find_interfaces_by_option tcpflags` + + if [ -n "$interfaces" ]; then + echo "Setting up TCP Flags checking..." + + createchain tcpflags no + + if [ -n "$TCP_FLAGS_LOG_LEVEL" ]; then + createchain logflags no + + run_iptables -A logflags -j LOG $LOGPARMS \ + --log-level $TCP_FLAGS_LOG_LEVEL \ + --log-prefix "Shorewall:logflags:$TCP_FLAGS_DISPOSITION:" \ + --log-tcp-options --log-ip-options + + case $TCP_FLAGS_DISPOSITION in + REJECT) + run_iptables -A logflags -j REJECT --reject-with tcp-reset + ;; + *) + run_iptables -A logflags -j $TCP_FLAGS_DISPOSITION + ;; + esac + + disposition="-j logflags" + else + disposition="-j $TCP_FLAGS_DISPOSITION" + fi + + run_iptables -A tcpflags -p tcp --tcp-flags ALL FIN,URG,PSH $disposition + run_iptables -A tcpflags -p tcp --tcp-flags ALL NONE $disposition + run_iptables -A tcpflags -p tcp --tcp-flags SYN,RST SYN,RST $disposition + run_iptables -A tcpflags -p tcp --tcp-flags SYN,FIN SYN,FIN $disposition + + for interface in $interfaces; do + for chain in `first_chains $interface`; do + run_iptables -A $chain -p tcp -j tcpflags + done + done + fi # # Process Black List # @@ -3723,6 +3764,7 @@ add_to_zone() # $1 = [:] $2 = zone blacklist_interfaces=`find_interfaces_by_option blacklist` filterping_interfaces=`find_interfaces_by_option filterping` maclist_interfaces=`find_interfaces_by_maclist` + tcpflags_interfaces=`find_interfaces_by_option tcpflags` # # Normalize the first argument to this function # @@ -3786,6 +3828,10 @@ add_to_zone() # $1 = [:] $2 = zone rulenum=$(($rulenum + 1)) fi + if ! list_search $interface $tcpflags_interfaces; then + rulenum=$(($rulenum + 1)) + fi + do_iptables -I `input_chain $interface` $rulenum -s $host -j $chain else # @@ -3810,6 +3856,10 @@ add_to_zone() # $1 = [:] $2 = zone if ! list_search $interface $maclist_interfaces; then rulenum=$(($rulenum + 1)) fi + + if ! list_search $interface $tcpflags_interfaces; then + rulenum=$(($rulenum + 1)) + fi fi for h in $dest_hosts; do @@ -4076,6 +4126,8 @@ do_initialize() { FORWARDPING= MACLIST_DISPOSITION= MACLIST_LOG_LEVEL= + TCP_FLAGS_DISPOSITION= + TCP_FLAGS_LOG_LEVEL= stopping= have_mutex= masq_seq=1 @@ -4173,6 +4225,18 @@ do_initialize() { MACLIST_DISPOSITION=REJECT fi + if [ -n "$TCP_FLAGS_DISPOSITION" ] ; then + case $TCP_FLAGS_DISPOSITION in + REJECT|ACCEPT|DROP) + ;; + *) + startup_error "Invalid value ($TCP_FLAGS_DISPOSITION) for TCP_FLAGS_DISPOSITION" + ;; + esac + else + TCP_FLAGS_DISPOSITION=DROP + fi + } # diff --git a/Shorewall/interfaces b/Shorewall/interfaces index 8be1de806..8ac277fa7 100644 --- a/Shorewall/interfaces +++ b/Shorewall/interfaces @@ -89,6 +89,14 @@ # is specified, the interface must be # an ethernet NIC and must be up before # Shorewall is started. +# tcpflags - Packets arriving on this interface are +# checked for certain illegal combinations +# of TCP flags. Packets found to have +# such a combination of flags are handled +# according to the setting of +# TCP_FLAGS_DISPOSITION after having been +# logged according to the setting of +# TCP_FLAGS_LOG_LEVEL. # proxyarp - # Sets # /proc/sys/net/ipv4/conf//proxy_arp. diff --git a/Shorewall/shorewall.conf b/Shorewall/shorewall.conf index ba0fdb069..5a97918ec 100755 --- a/Shorewall/shorewall.conf +++ b/Shorewall/shorewall.conf @@ -404,4 +404,24 @@ MACLIST_DISPOSITION=REJECT MACLIST_LOG_LEVEL=info +# +# TCP FLAGS Disposition +# +# This variable determins the disposition of packets having an invalid +# combination of TCP flags that are received on interfaces having the +# 'tcpflags' option specified in /etc/shorewall/interfaces. If not specified +# or specified as empty (TCP_FLAGS_DISPOSITION="") then DROP is assumed. + +TCP_FLAGS_DISPOSITION=DROP + +# +# TCP FLAGS Log Level +# +# Specifies the logging level for packets that fail TCP Flags +# verification. If set to the empty value (TCP_FLAGS_LOG_LEVEL="") then +# such packets will not be logged. +# + +TCP_FLAGS_LOG_LEVEL=info + #LAST LINE -- DO NOT REMOVE