From 40ad9defcc545c2925f6c37d17a64707f17f5b78 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Wed, 19 May 2010 21:35:23 +0000 Subject: [PATCH] firewall: - fix ip6tables rules when icmp_type option is set - add "family" option to zones, forwardings, redirects and rules to selectively apply rules to iptables and/or ip6tables SVN-Revision: 21508 --- package/firewall/Makefile | 2 +- package/firewall/files/lib/core_forwarding.sh | 5 +- package/firewall/files/lib/core_init.sh | 64 +++++++++++++------ package/firewall/files/lib/core_interface.sh | 33 +++++----- package/firewall/files/lib/core_redirect.sh | 7 +- package/firewall/files/lib/core_rule.sh | 5 +- package/firewall/files/lib/fw.sh | 30 ++++++++- 7 files changed, 105 insertions(+), 41 deletions(-) diff --git a/package/firewall/Makefile b/package/firewall/Makefile index 1a7216ce17..4f4f71c325 100644 --- a/package/firewall/Makefile +++ b/package/firewall/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=firewall PKG_VERSION:=2 -PKG_RELEASE:=3 +PKG_RELEASE:=4 include $(INCLUDE_DIR)/package.mk diff --git a/package/firewall/files/lib/core_forwarding.sh b/package/firewall/files/lib/core_forwarding.sh index 766e48e38e..689e2628c2 100644 --- a/package/firewall/files/lib/core_forwarding.sh +++ b/package/firewall/files/lib/core_forwarding.sh @@ -7,6 +7,7 @@ fw_config_get_forwarding() { string name "" \ string src "" \ string dest "" \ + string family "" \ } || return [ -n "$forwarding_name" ] || forwarding_name=$forwarding__name } @@ -26,7 +27,9 @@ fw_load_forwarding() { target=zone_${forwarding_dest}_ACCEPT } - fw add i f $chain $target ^ + local mode=$(fw_get_family_mode ${forwarding_family:-x} ${forwarding_dest:-${forwarding_src:--}} i) + + fw add $mode f $chain $target ^ # propagate masq zone flag [ -n "$forwarding_src" ] && list_contains CONNTRACK_ZONES $forwarding_src && { diff --git a/package/firewall/files/lib/core_init.sh b/package/firewall/files/lib/core_init.sh index 2dd989e494..92d117160f 100644 --- a/package/firewall/files/lib/core_init.sh +++ b/package/firewall/files/lib/core_init.sh @@ -4,6 +4,8 @@ FW_INITIALIZED= FW_ZONES= +FW_ZONES4= +FW_ZONES6= FW_CONNTRACK_ZONES= FW_NOTRACK_DISABLED= @@ -140,6 +142,7 @@ fw_config_get_zone() { boolean conntrack 0 \ boolean mtu_fix 0 \ boolean custom_chains "$FW_ADD_CUSTOM_CHAINS" \ + string family "" \ } || return [ -n "$zone_name" ] || zone_name=$zone_NAME [ -n "$zone_network" ] || zone_network=$zone_name @@ -158,46 +161,67 @@ fw_load_zone() { [ $zone_conntrack = 1 -o $zone_masq = 1 ] && \ append FW_CONNTRACK_ZONES "$zone_NAME" + local mode + case "$zone_family" in + *4) + mode=4 + append FW_ZONES4 $zone_name + uci_set_state firewall core ${zone_name}_ipv4 1 + ;; + *6) + mode=6 + append FW_ZONES6 $zone_name + uci_set_state firewall core ${zone_name}_ipv6 1 + ;; + *) + mode=i + append FW_ZONES4 $zone_name + append FW_ZONES6 $zone_name + uci_set_state firewall core ${zone_name}_ipv4 1 + uci_set_state firewall core ${zone_name}_ipv6 1 + ;; + esac + local chain=zone_${zone_name} - fw add i f ${chain}_ACCEPT - fw add i f ${chain}_DROP - fw add i f ${chain}_REJECT - fw add i f ${chain}_MSSFIX + fw add $mode f ${chain}_ACCEPT + fw add $mode f ${chain}_DROP + fw add $mode f ${chain}_REJECT + fw add $mode f ${chain}_MSSFIX # TODO: Rename to ${chain}_input - fw add i f ${chain} - fw add i f ${chain} ${chain}_${zone_input} $ + fw add $mode f ${chain} + fw add $mode f ${chain} ${chain}_${zone_input} $ - fw add i f ${chain}_forward - fw add i f ${chain}_forward ${chain}_${zone_forward} $ + fw add $mode f ${chain}_forward + fw add $mode f ${chain}_forward ${chain}_${zone_forward} $ # TODO: add ${chain}_output - fw add i f output ${chain}_${zone_output} $ + fw add $mode f output ${chain}_${zone_output} $ # TODO: Rename to ${chain}_MASQUERADE - fw add i n ${chain}_nat - fw add i n ${chain}_prerouting + fw add $mode n ${chain}_nat + fw add $mode n ${chain}_prerouting - fw add i r ${chain}_notrack + fw add $mode r ${chain}_notrack [ $zone_masq == 1 ] && \ - fw add i n POSTROUTING ${chain}_nat $ + fw add $mode n POSTROUTING ${chain}_nat $ [ $zone_mtu_fix == 1 ] && \ - fw add i f FORWARD ${chain}_MSSFIX ^ + fw add $mode f FORWARD ${chain}_MSSFIX ^ [ $zone_custom_chains == 1 ] && { [ $FW_ADD_CUSTOM_CHAINS == 1 ] || \ fw_die "zone ${zone_name}: custom_chains globally disabled" - fw add i f input_${zone_name} - fw add i f ${chain} input_${zone_name} ^ + fw add $mode f input_${zone_name} + fw add $mode f ${chain} input_${zone_name} ^ - fw add i f forwarding_${zone_name} - fw add i f ${chain}_forward forwarding_${zone_name} ^ + fw add $mode f forwarding_${zone_name} + fw add $mode f ${chain}_forward forwarding_${zone_name} ^ - fw add i n prerouting_${zone_name} - fw add i n ${chain}_prerouting prerouting_${zone_name} ^ + fw add $mode n prerouting_${zone_name} + fw add $mode n ${chain}_prerouting prerouting_${zone_name} ^ } fw_callback post zone diff --git a/package/firewall/files/lib/core_interface.sh b/package/firewall/files/lib/core_interface.sh index 9b35c8b2bc..de5fd9a0ea 100644 --- a/package/firewall/files/lib/core_interface.sh +++ b/package/firewall/files/lib/core_interface.sh @@ -17,23 +17,26 @@ fw_configure_interface() { fw__do_rules() { local action=$1 - local chain=$2 + local zone=$2 + local chain=zone_${zone} local ifname=$3 - fw $action i f ${chain}_ACCEPT ACCEPT ^ { -o "$ifname" } - fw $action i f ${chain}_ACCEPT ACCEPT ^ { -i "$ifname" } - fw $action i f ${chain}_DROP DROP ^ { -o "$ifname" } - fw $action i f ${chain}_DROP DROP ^ { -i "$ifname" } - fw $action i f ${chain}_REJECT reject ^ { -o "$ifname" } - fw $action i f ${chain}_REJECT reject ^ { -i "$ifname" } + local mode=$(fw_get_family_mode x $zone i) - fw $action i n ${chain}_nat MASQUERADE ^ { -o "$ifname" } - fw $action i f ${chain}_MSSFIX TCPMSS ^ { -o "$ifname" -p tcp --tcp-flags SYN,RST SYN --clamp-mss-to-pmtu } + fw $action $mode f ${chain}_ACCEPT ACCEPT ^ { -o "$ifname" } + fw $action $mode f ${chain}_ACCEPT ACCEPT ^ { -i "$ifname" } + fw $action $mode f ${chain}_DROP DROP ^ { -o "$ifname" } + fw $action $mode f ${chain}_DROP DROP ^ { -i "$ifname" } + fw $action $mode f ${chain}_REJECT reject ^ { -o "$ifname" } + fw $action $mode f ${chain}_REJECT reject ^ { -i "$ifname" } - fw $action i f input ${chain} $ { -i "$ifname" } - fw $action i f forward ${chain}_forward $ { -i "$ifname" } - fw $action i n PREROUTING ${chain}_prerouting ^ { -i "$ifname" } - fw $action i r PREROUTING ${chain}_notrack ^ { -i "$ifname" } + fw $action $mode n ${chain}_nat MASQUERADE ^ { -o "$ifname" } + fw $action $mode f ${chain}_MSSFIX TCPMSS ^ { -o "$ifname" -p tcp --tcp-flags SYN,RST SYN --clamp-mss-to-pmtu } + + fw $action $mode f input ${chain} $ { -i "$ifname" } + fw $action $mode f forward ${chain}_forward $ { -i "$ifname" } + fw $action $mode n PREROUTING ${chain}_prerouting ^ { -i "$ifname" } + fw $action $mode r PREROUTING ${chain}_notrack ^ { -i "$ifname" } } local old_zones old_ifname @@ -42,7 +45,7 @@ fw_configure_interface() { config_get old_ifname core "${iface}_ifname" for z in $old_zones; do fw_log info "removing $iface ($old_ifname) from zone $z" - fw__do_rules del zone_$z $old_ifname + fw__do_rules del $z $old_ifname ACTION=remove ZONE="$z" INTERFACE="$iface" DEVICE="$ifname" /sbin/hotplug-call firewall done @@ -57,7 +60,7 @@ fw_configure_interface() { list_contains zone_network "$iface" || return fw_log info "adding $iface ($ifname) to zone $zone_name" - fw__do_rules add zone_${zone_name} "$ifname" + fw__do_rules add ${zone_name} "$ifname" append new_zones $zone_name ACTION=add ZONE="$zone_name" INTERFACE="$iface" DEVICE="$ifname" /sbin/hotplug-call firewall diff --git a/package/firewall/files/lib/core_redirect.sh b/package/firewall/files/lib/core_redirect.sh index 0f0ccffe00..c19c494084 100644 --- a/package/firewall/files/lib/core_redirect.sh +++ b/package/firewall/files/lib/core_redirect.sh @@ -16,6 +16,7 @@ fw_config_get_redirect() { string dest_mac "" \ string dest_port "" \ string proto "tcpudp" \ + string family "" \ } || return [ -n "$redirect_name" ] || redirect_name=$redirect__name } @@ -29,6 +30,8 @@ fw_load_redirect() { fw_die "redirect ${redirect_name}: needs src and dest_ip" } + local mode=$(fw_get_family_mode ${redirect_family:-x} $redirect_src I) + local nat_dest_port=$redirect_dest_port redirect_dest_port=$(fw_get_port_range $redirect_dest_port) redirect_src_port=$(fw_get_port_range $redirect_src_port) @@ -37,7 +40,7 @@ fw_load_redirect() { [ "$redirect_proto" == "tcpudp" ] && redirect_proto="tcp udp" for redirect_proto in $redirect_proto; do - fw add I n zone_${redirect_src}_prerouting DNAT $ { $redirect_src_ip $redirect_dest_ip } { \ + fw add $mode n zone_${redirect_src}_prerouting DNAT $ { $redirect_src_ip $redirect_dest_ip } { \ ${redirect_proto:+-p $redirect_proto} \ ${redirect_src_ip:+-s $redirect_src_ip} \ ${redirect_src_dip:+-d $redirect_src_dip} \ @@ -47,7 +50,7 @@ fw_load_redirect() { --to-destination ${redirect_dest_ip}${redirect_dest_port:+:$nat_dest_port} \ } - fw add I f zone_${redirect_src}_forward ACCEPT ^ { $redirect_src_ip $redirect_dest_ip } { \ + fw add $mode f zone_${redirect_src}_forward ACCEPT ^ { $redirect_src_ip $redirect_dest_ip } { \ -d $redirect_dest_ip \ ${redirect_proto:+-p $redirect_proto} \ ${redirect_src_ip:+-s $redirect_src_ip} \ diff --git a/package/firewall/files/lib/core_rule.sh b/package/firewall/files/lib/core_rule.sh index e6a276e5f3..1dc3f1cde6 100644 --- a/package/firewall/files/lib/core_rule.sh +++ b/package/firewall/files/lib/core_rule.sh @@ -16,6 +16,7 @@ fw_config_get_rule() { string icmp_type "" \ string proto "tcpudp" \ string target "" \ + string family "" \ } || return [ -n "$rule_name" ] || rule_name=$rule__name [ "$rule_proto" == "icmp" ] || rule_icmp_type= @@ -49,9 +50,11 @@ fw_load_rule() { local rule_pos eval 'rule_pos=$((++FW__RULE_COUNT_'$chain'))' + local mode=$(fw_get_family_mode ${rule_family:-x} $rule_src I) + [ "$rule_proto" == "tcpudp" ] && rule_proto="tcp udp" for rule_proto in $rule_proto; do - fw add I f $chain $target $rule_pos { $rule_src_ip $rule_dest_ip } { \ + fw add $mode f $chain $target $rule_pos { $rule_src_ip $rule_dest_ip } { \ ${rule_proto:+-p $rule_proto} \ ${rule_src_ip:+-s $rule_src_ip} \ ${rule_src_port:+--sport $rule_src_port} \ diff --git a/package/firewall/files/lib/fw.sh b/package/firewall/files/lib/fw.sh index 1dd5227c16..553642070c 100644 --- a/package/firewall/files/lib/fw.sh +++ b/package/firewall/files/lib/fw.sh @@ -155,7 +155,14 @@ fw__exec() { # { } fi fi while [ $# -gt 1 ]; do - echo -n "$1" + case "$app:$1" in + ip6tables:--icmp-type) echo -n "--icmpv6-type" ;; + ip6tables:icmp|ip6tables:ICMP) echo -n "icmpv6" ;; + iptables:--icmpv6-type) echo -n "--icmp-type" ;; + iptables:icmpv6) echo -n "icmp" ;; + *:}|*:{) shift; continue ;; + *) echo -n "$1" ;; + esac echo -ne "\0" shift done | xargs -0 ${FW_TRACE:+-t} \ @@ -180,3 +187,24 @@ fw_get_port_range() { fi } +fw_get_family_mode() { + local hint="$1" + local zone="$2" + local mode="$3" + + local ipv4 ipv6 + [ -n "$FW_ZONES4$FW_ZONES6" ] && { + list_contains FW_ZONES4 $zone && ipv4=1 || ipv4=0 + list_contains FW_ZONES6 $zone && ipv6=1 || ipv6=0 + } || { + ipv4=$(uci_get_state firewall core ${zone}_ipv4 0) + ipv6=$(uci_get_state firewall core ${zone}_ipv6 0) + } + + case "$hint:$ipv4:$ipv6" in + *4:1:*|*:1:0) echo 4 ;; + *6:*:1|*:0:1) echo 6 ;; + *) echo $mode ;; + esac +} +