Changeset 27317


Ignore:
Timestamp:
2011-06-30T03:31:23+02:00 (7 years ago)
Author:
jow
Message:

[package] firewall:

  • allow multiple ports, protocols, macs, icmp types per rule
  • implement "limit" and "limit_burst" options for rules
  • implement "extra" option to rules and redirects for passing arbritary flags to iptables
  • implement negations for "src_port", "dest_port", "src_dport", "src_mac", "proto" and "icmp_type" options
  • allow wildcard (*) "src" and "dest" options in rules to allow specifying "any" source or destination
  • validate symbolic icmp-type names against the selected iptables binary
  • properly handle forwarded ICMPv6 traffic in the default configuration
Location:
trunk/package/firewall
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/package/firewall/Makefile

    r27196 r27317  
    1010 
    1111PKG_VERSION:=2 
    12 PKG_RELEASE:=26 
     12PKG_RELEASE:=27 
    1313 
    1414include $(INCLUDE_DIR)/package.mk 
  • trunk/package/firewall/files/firewall.config

    r26961 r27317  
    99config zone 
    1010        option name             lan 
    11         option network  'lan' 
    12         option input    ACCEPT  
    13         option output   ACCEPT  
    14         option forward  REJECT 
     11        option network          'lan' 
     12        option input            ACCEPT  
     13        option output           ACCEPT  
     14        option forward          REJECT 
    1515 
    1616config zone 
    1717        option name             wan 
    18         option network  'wan' 
    19         option input    REJECT 
    20         option output   ACCEPT  
    21         option forward  REJECT 
     18        option network          'wan' 
     19        option input            REJECT 
     20        option output           ACCEPT  
     21        option forward          REJECT 
    2222        option masq             1  
    23         option mtu_fix  1 
     23        option mtu_fix          1 
    2424 
    2525config forwarding  
    26         option src      lan 
    27         option dest     wan 
     26        option src              lan 
     27        option dest             wan 
    2828 
    2929# We need to accept udp packets on port 68, 
     
    3434        option dest_port        68 
    3535        option target           ACCEPT 
    36         option family   ipv4 
     36        option family           ipv4 
    3737 
    38 #Allow ping 
     38# Allow IPv4 ping 
    3939config rule 
    40         option src wan 
    41         option proto icmp 
    42         option icmp_type echo-request 
    43         option target ACCEPT 
     40        option src              wan 
     41        option proto            icmp 
     42        option icmp_type        echo-request 
     43        option family           ipv4 
     44        option target           ACCEPT 
     45 
     46# Allow essential incoming IPv6 ICMP traffic 
     47config rule                                    
     48        option src              wan 
     49        option dest             * 
     50        option proto            icmp 
     51        list icmp_type          router-solicitation 
     52        list icmp_type          router-advertisement 
     53        list icmp_type          neighbour-solicitation 
     54        list icmp_type          neighbour-advertisement 
     55        list icmp_type          echo-request 
     56        list icmp_type          destination-unreachable 
     57        list icmp_type          packet-too-big 
     58        list icmp_type          time-exceeded 
     59        option limit            1000/sec 
     60        option family           ipv6 
     61        option target           ACCEPT 
     62 
     63# Drop leaking router advertisements on WAN 
     64config rule 
     65        option src              * 
     66        option dest             wan 
     67        option proto            icmp 
     68        option icmp_type        router-advertisement 
     69        option family           ipv6 
     70        option target           DROP 
    4471 
    4572# include a file with users custom iptables rules 
  • trunk/package/firewall/files/lib/core_redirect.sh

    r26617 r27317  
    1414                string dest "" \ 
    1515                ipaddr dest_ip "" \ 
    16                 string dest_mac "" \ 
    1716                string dest_port "" \ 
    1817                string proto "tcpudp" \ 
    1918                string family "" \ 
    2019                string target "DNAT" \ 
     20                string extra "" \ 
    2121        } || return 
    2222        [ -n "$redirect_name" ] || redirect_name=$redirect__name 
     
    3030        local fwdchain natchain natopt nataddr natports srcdaddr srcdports 
    3131        if [ "$redirect_target" == "DNAT" ]; then 
    32                 [ -n "$redirect_src" -a -n "$redirect_dest_ip$redirect_dest_port" ] || { 
     32                [ -n "${redirect_src#*}" -a -n "$redirect_dest_ip$redirect_dest_port" ] || { 
    3333                        fw_log error "DNAT redirect ${redirect_name}: needs src and dest_ip or dest_port, skipping" 
    3434                        return 0 
    3535                } 
    3636 
    37                 fwdchain="zone_${redirect_src}${redirect_dest_ip:+_forward}" 
     37                fwdchain="zone_${redirect_src}_forward" 
    3838 
    3939                natopt="--to-destination" 
    4040                natchain="zone_${redirect_src}_prerouting" 
    4141                nataddr="$redirect_dest_ip" 
    42                 fw_get_port_range natports "$redirect_dest_port" "-" 
     42                fw_get_port_range natports "${redirect_dest_port#!}" "-" 
    4343 
    4444                fw_get_negation srcdaddr '-d' "${redirect_src_dip:+$redirect_src_dip/$redirect_src_dip_prefixlen}" 
    4545                fw_get_port_range srcdports "$redirect_src_dport" ":" 
     46                fw_get_negation srcdports '--dport' "$srcdports" 
    4647 
    4748                list_contains FW_CONNTRACK_ZONES $redirect_src || \ 
     
    4950 
    5051        elif [ "$redirect_target" == "SNAT" ]; then 
    51                 [ -n "$redirect_dest" -a -n "$redirect_src_dip" ] || { 
     52                [ -n "${redirect_dest#*}" -a -n "$redirect_src_dip" ] || { 
    5253                        fw_log error "SNAT redirect ${redirect_name}: needs dest and src_dip, skipping" 
    5354                        return 0 
     
    5960                natchain="zone_${redirect_dest}_nat" 
    6061                nataddr="$redirect_src_dip" 
    61                 fw_get_port_range natports "$redirect_src_dport" "-" 
     62                fw_get_port_range natports "${redirect_src_dport#!}" "-" 
    6263 
    6364                fw_get_negation srcdaddr '-d' "${redirect_dest_ip:+$redirect_dest_ip/$redirect_dest_ip_prefixlen}" 
    6465                fw_get_port_range srcdports "$redirect_dest_port" ":" 
     66                fw_get_negation srcdports '--dport' "$srcdports" 
    6567 
    6668                list_contains FW_CONNTRACK_ZONES $redirect_dest || \ 
     
    8082        local srcports 
    8183        fw_get_port_range srcports "$redirect_src_port" ":" 
     84        fw_get_negation srcports '--sport' "$srcports" 
    8285 
    8386        local destaddr 
     
    8689        local destports 
    8790        fw_get_port_range destports "${redirect_dest_port:-$redirect_src_dport}" ":" 
     91        fw_get_negation destports '--dport' "$destports" 
    8892 
    8993        [ "$redirect_proto" == "tcpudp" ] && redirect_proto="tcp udp" 
    9094        for redirect_proto in $redirect_proto; do 
    91                 local pos 
    92                 eval 'pos=$((++FW__REDIR_COUNT_'${mode#G}'_'$natchain'))' 
     95                fw_get_negation redirect_proto '-p' "$redirect_proto" 
     96                for redirect_src_mac in ${redirect_src_mac:-""}; do 
     97                        fw_get_negation redirect_src_mac '--mac-source' "$redirect_src_mac" 
     98                        fw add $mode n $natchain $redirect_target + \ 
     99                                { $redirect_src_ip $redirect_dest_ip } { \ 
     100                                $srcaddr $srcdaddr $redirect_proto \ 
     101                                $srcports $srcdports \ 
     102                                ${redirect_src_mac:+-m mac $redirect_src_mac} \ 
     103                                $natopt $nataddr${natports:+:$natports} \ 
     104                                $redirect_options \ 
     105                        } 
    93106 
    94                 fw add $mode n $natchain $redirect_target $pos { $redirect_src_ip $redirect_dest_ip } { \ 
    95                         $srcaddr $srcdaddr \ 
    96                         ${redirect_proto:+-p $redirect_proto} \ 
    97                         ${srcports:+--sport $srcports} \ 
    98                         ${srcdports:+--dport $srcdports} \ 
    99                         ${redirect_src_mac:+-m mac --mac-source $redirect_src_mac} \ 
    100                         $natopt $nataddr${natports:+:$natports} \ 
    101                 } 
    102  
    103                 fw add $mode f ${fwdchain:-forward} ACCEPT ^ { $redirect_src_ip $redirect_dest_ip } { \ 
    104                         $srcaddr ${destaddr:--m conntrack --ctstate DNAT} \ 
    105                         ${redirect_proto:+-p $redirect_proto} \ 
    106                         ${srcports:+--sport $srcports} \ 
    107                         ${destports:+--dport $destports} \ 
    108                         ${redirect_src_mac:+-m mac --mac-source $redirect_src_mac} \ 
    109                 } 
     107                        [ -n "$destaddr" ] && \ 
     108                        fw add $mode f ${fwdchain:-forward} ACCEPT + \ 
     109                                { $redirect_src_ip $redirect_dest_ip } { \ 
     110                                $srcaddr $destaddr $redirect_proto \ 
     111                                $srcports $destports \ 
     112                                $redirect_src_mac \ 
     113                                $redirect_extra \ 
     114                        } 
     115                done 
    110116        done 
    111117 
  • trunk/package/firewall/files/lib/core_rule.sh

    r25179 r27317  
    1717                string target "" \ 
    1818                string family "" \ 
     19                string limit "" \ 
     20                string limit_burst "" \ 
     21                string extra "" \ 
    1922        } || return 
    2023        [ -n "$rule_name" ] || rule_name=$rule__name 
    21         [ "$rule_proto" == "icmp" ] || rule_icmp_type= 
    2224} 
    2325 
     
    2527        fw_config_get_rule "$1" 
    2628 
    27         [ "$rule_target" != "NOTRACK" ] || [ -n "$rule_src" ] || { 
     29        [ "$rule_target" != "NOTRACK" ] || [ -n "$rule_src" ] || [ "$rule_src" != "*" ] || { 
    2830                fw_log error "NOTRACK rule ${rule_name}: needs src, skipping" 
    2931                return 0 
     
    3133 
    3234        fw_callback pre rule 
    33  
    34         fw_get_port_range rule_src_port $rule_src_port 
    35         fw_get_port_range rule_dest_port $rule_dest_port 
    3635 
    3736        local table=f 
     
    4241                chain="zone_${rule_src}_notrack" 
    4342        else 
    44                 [ -n "$rule_src" ] && chain="zone_${rule_src}${rule_dest:+_forward}" 
    45                 [ -n "$rule_dest" ] && target="zone_${rule_dest}_${target}" 
     43                if [ -n "$rule_src" ]; then 
     44                        if [ "$rule_src" != "*" ]; then 
     45                                chain="zone_${rule_src}${rule_dest:+_forward}" 
     46                        else 
     47                                chain="${rule_dest:+forward}" 
     48                                chain="${chain:-input}" 
     49                        fi 
     50                fi 
     51 
     52                if [ -n "$rule_dest" ]; then 
     53                        if [ "$rule_dest" != "*" ]; then 
     54                                target="zone_${rule_dest}_${target}" 
     55                        elif [ "$target" = REJECT ]; then 
     56                                target=reject 
     57                        fi 
     58                fi 
    4659        fi 
    4760 
     
    5568        [ "$rule_proto" == "tcpudp" ] && rule_proto="tcp udp" 
    5669        for rule_proto in $rule_proto; do 
    57                 local rule_pos 
    58                 eval 'rule_pos=$((++FW__RULE_COUNT_'${mode#G}'_'$chain'))' 
    59  
    60                 fw add $mode $table $chain $target $rule_pos { $rule_src_ip $rule_dest_ip } { \ 
    61                         $src_spec $dest_spec \ 
    62                         ${rule_proto:+-p $rule_proto} \ 
    63                         ${rule_src_port:+--sport $rule_src_port} \ 
    64                         ${rule_src_mac:+-m mac --mac-source $rule_src_mac} \ 
    65                         ${rule_dest_port:+--dport $rule_dest_port} \ 
    66                         ${rule_icmp_type:+--icmp-type $rule_icmp_type} \ 
    67                 } 
     70                fw_get_negation rule_proto '-p' "$rule_proto" 
     71                for rule_src_port in ${rule_src_port:-""}; do 
     72                        fw_get_port_range rule_src_port $rule_src_port 
     73                        fw_get_negation rule_src_port '--sport' "$rule_src_port" 
     74                        for rule_dest_port in ${rule_dest_port:-""}; do 
     75                                fw_get_port_range rule_dest_port $rule_dest_port 
     76                                fw_get_negation rule_dest_port '--dport' "$rule_dest_port" 
     77                                for rule_src_mac in ${rule_src_mac:-""}; do 
     78                                        fw_get_negation rule_src_mac '--mac-source' "$rule_src_mac" 
     79                                        for rule_icmp_type in ${rule_icmp_type:-""}; do 
     80                                                [ "$rule_proto" = "-p icmp" ] || rule_icmp_type="" 
     81                                                fw add $mode $table $chain $target + \ 
     82                                                        { $rule_src_ip $rule_dest_ip } { \ 
     83                                                        $src_spec $dest_spec $rule_proto \ 
     84                                                        $rule_src_port $rule_dest_port \ 
     85                                                        ${rule_src_mac:+-m mac $rule_src_mac} \ 
     86                                                        ${rule_icmp_type:+--icmp-type $rule_icmp_type} \ 
     87                                                        ${rule_limit:+-m limit --limit $rule_limit \ 
     88                                                                ${rule_limit_burst:+--limit-burst $rule_limit_burst}} \ 
     89                                                        $rule_extra \ 
     90                                                } 
     91                                        done 
     92                                done 
     93                        done 
     94                done 
    6895        done 
    6996 
  • trunk/package/firewall/files/lib/fw.sh

    r27198 r27317  
    138138                -) tgt= ;; 
    139139        esac 
     140 
     141        local rule_offset 
    140142        case "$pos" in 
    141143                ^) pos=1 ;; 
    142144                $) pos= ;; 
    143145                -) pos= ;; 
     146                +) eval "rule_offset=\${FW__RULE_OFS_${app}_${tab}_${chn}:-1}" ;; 
    144147        esac 
    145148 
     
    160163        fi 
    161164 
    162         local cmdline="$app --table ${tab} --${cmd} ${chn} ${pol} ${pos} ${tgt:+--jump "$tgt"}" 
     165        local cmdline="$app --table ${tab} --${cmd} ${chn} ${pol} ${rule_offset:-${pos}} ${tgt:+--jump "$tgt"}" 
    163166        while [ $# -gt 1 ]; do 
    164                 case "$app:$1" in 
    165                         ip6tables:--icmp-type) cmdline="$cmdline --icmpv6-type" ;; 
    166                         ip6tables:icmp|ip6tables:ICMP) cmdline="$cmdline icmpv6" ;; 
    167                         iptables:--icmpv6-type) cmdline="$cmdline --icmp-type" ;; 
    168                         iptables:icmpv6) cmdline="$cmdline icmp" ;; 
     167                # special parameter handling 
     168                case "$1:$2" in 
     169                        -p:icmp*|--protocol:icmp*) 
     170                                [ "$app" = ip6tables ] && \ 
     171                                        cmdline="$cmdline -p icmpv6" || \ 
     172                                        cmdline="$cmdline -p icmp" 
     173                                shift 
     174                        ;; 
     175                        --icmp-type:*|--icmpv6-type:*) 
     176                                local icmp_type 
     177                                if [ "$app" = ip6tables ] && fw_check_icmptype6 icmp_type "$2"; then 
     178                                        cmdline="$cmdline $icmp_type" 
     179                                elif [ "$app" = iptables ] && fw_check_icmptype4 icmp_type "$2"; then 
     180                                        cmdline="$cmdline $icmp_type" 
     181                                else 
     182                                        local fam=IPv4; [ "$app" = ip6tables ] && fam=IPv6 
     183                                        fw_log info "ICMP type '$2' is not valid for $fam address family, skipping rule" 
     184                                        return 1 
     185                                fi 
     186                                shift    
     187                        ;; 
    169188                        *) cmdline="$cmdline $1" ;; 
    170189                esac 
     
    176195        $cmdline 
    177196 
    178         fw__rc $? 
     197        local rv=$? 
     198        [ $rv -eq 0 ] && [ -n "$rule_offset" ] && \ 
     199                export -- "FW__RULE_OFS_${app}_${tab}_${chn}=$(($rule_offset + 1))" 
     200        fw__rc $rv 
    179201} 
    180202 
     
    190212        local _first=${_ports%-*} 
    191213        local _last=${_ports#*-} 
    192         if [ "$_first" != "$_last" ]; then 
    193                 export -- "$_var=$_first$_delim$_last" 
     214        if [ "${_first#!}" != "${_last#!}" ]; then 
     215                export -- "$_var=$_first$_delim${_last#!}" 
    194216        else 
    195217                export -- "$_var=$_first" 
     
    222244        local _var="$1" 
    223245        local _flag="$2" 
    224         local _ipaddr="$3" 
    225  
    226         [ "${_ipaddr#!}" != "$_ipaddr" ] && \ 
    227                 export -n -- "$_var=! $_flag ${_ipaddr#!}" || \ 
    228                 export -n -- "$_var=${_ipaddr:+$_flag $_ipaddr}" 
     246        local _value="$3" 
     247 
     248        [ "${_value#!}" != "$_value" ] && \ 
     249                export -n -- "$_var=! $_flag ${_value#!}" || \ 
     250                export -n -- "$_var=${_value:+$_flag $_value}" 
    229251} 
    230252 
     
    246268        esac 
    247269} 
     270 
     271fw_check_icmptype4() { 
     272        local _var="$1" 
     273        local _type="$2" 
     274        case "$_type" in 
     275                ![0-9]*) export -n -- "$_var=! --icmp-type ${_type#!}"; return 0 ;; 
     276                [0-9]*)  export -n -- "$_var=--icmp-type $_type";       return 0 ;; 
     277        esac 
     278 
     279        [ -z "$FW_ICMP4_TYPES" ] && \ 
     280                export FW_ICMP4_TYPES=$( 
     281                        iptables -p icmp -h 2>/dev/null | \ 
     282                        sed -n -e '/^Valid ICMP Types:/ { 
     283                                n; :r; 
     284                                /router-advertisement/d; 
     285                                /router-solicitation/d; 
     286                                s/[()]/ /g; s/[[:space:]]\+/\n/g; p; n; b r 
     287                        }' | sort -u 
     288                ) 
     289 
     290        local _check 
     291        for _check in $FW_ICMP4_TYPES; do 
     292                if [ "$_check" = "${_type#!}" ]; then 
     293                        [ "${_type#!}" != "$_type" ] && \ 
     294                                export -n -- "$_var=! --icmp-type ${_type#!}" || \ 
     295                                export -n -- "$_var=--icmp-type $_type" 
     296                        return 0 
     297                fi 
     298        done 
     299 
     300        export -n -- "$_var=" 
     301        return 1 
     302} 
     303 
     304fw_check_icmptype6() { 
     305        local _var="$1" 
     306        local _type="$2" 
     307        case "$_type" in 
     308                ![0-9]*) export -n -- "$_var=! --icmpv6-type ${_type#!}"; return 0 ;; 
     309                [0-9]*)  export -n -- "$_var=--icmpv6-type $_type";       return 0 ;; 
     310        esac 
     311 
     312        [ -z "$FW_ICMP6_TYPES" ] && \ 
     313                export FW_ICMP6_TYPES=$( 
     314                        ip6tables -p icmpv6 -h 2>/dev/null | \ 
     315                        sed -n -e '/^Valid ICMPv6 Types:/ { 
     316                                n; :r; s/[()]/ /g; s/[[:space:]]\+/\n/g; p; n; b r 
     317                        }' | sort -u 
     318                ) 
     319 
     320        local _check 
     321        for _check in $FW_ICMP6_TYPES; do 
     322                if [ "$_check" = "${_type#!}" ]; then 
     323                        [ "${_type#!}" != "$_type" ] && \ 
     324                                export -n -- "$_var=! --icmpv6-type ${_type#!}" || \ 
     325                                export -n -- "$_var=--icmpv6-type $_type" 
     326                        return 0 
     327                fi 
     328        done 
     329 
     330        export -n -- "$_var=" 
     331        return 1 
     332} 
  • trunk/package/firewall/files/reflection.hotplug

    r23201 r27317  
    5757                        local dest 
    5858                        config_get dest "$cfg" dest "lan" 
     59                        [ "$dest" != "*" ] || return 
    5960 
    6061                        local net 
Note: See TracChangeset for help on using the changeset viewer.