From e085262d2957736ba4e2302239125797abd35b2c Mon Sep 17 00:00:00 2001 From: teastep Date: Thu, 5 May 2005 20:37:31 +0000 Subject: [PATCH] Implement support for ipsets git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@2085 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb --- Shorewall2/action.template | 17 ++++- Shorewall2/blacklist | 12 ++- Shorewall2/changelog.txt | 2 + Shorewall2/firewall | 144 +++++++++++++++++++++++++++++------- Shorewall2/help | 5 +- Shorewall2/releasenotes.txt | 26 +++++++ Shorewall2/rules | 13 ++++ 7 files changed, 187 insertions(+), 32 deletions(-) diff --git a/Shorewall2/action.template b/Shorewall2/action.template index a0688dcd9..f2c7ef97a 100644 --- a/Shorewall2/action.template +++ b/Shorewall2/action.template @@ -70,7 +70,17 @@ # # 10.0.0.4-10.0.0.9 Range of IP addresses; your # kernel and iptables must have -# iprange match support. +# iprange match support. +# +# +remote The name of an ipset prefaced +# by "+". Your kernel and +# iptables must have set match +# support +# +# +remote[4] The name of the ipset may +# followed by a number of +# levels of ipset bindings +# enclosed in square brackets. # # 192.168.1.1,192.168.1.2 # Hosts 192.168.1.1 and @@ -85,8 +95,9 @@ # another colon (":") and an IP/MAC/subnet address # as described above (e.g., eth1:192.168.1.5). # -# DEST Location of Server. Same as above with the exception that -# MAC addresses are not allowed. +# DEST Location of destination host. Same as above with the exception that +# MAC addresses are not allowed and that you cannot specify +# an ipset name in both the SOURCE and DEST columns. # # PROTO Protocol - Must be "tcp", "udp", "icmp", a number, or # "all". diff --git a/Shorewall2/blacklist b/Shorewall2/blacklist index 800f1be44..1b587e45b 100755 --- a/Shorewall2/blacklist +++ b/Shorewall2/blacklist @@ -7,9 +7,10 @@ # # Columns are: # -# ADDRESS/SUBNET - Host address, subnetwork, MAC address or IP address +# ADDRESS/SUBNET - Host address, subnetwork, MAC address, IP address # range (if your kernel and iptables contain iprange -# match support). +# match support) or ipset name prefaced by "+" (if +# your kernel supports ipset match). # # MAC addresses must be prefixed with "~" and use "-" # as a separator. @@ -38,6 +39,13 @@ # ADDRESS/SUBNET PROTOCOL PORT # 192.0.2.126 udp 53 # +# Example: +# +# To block DNS queries from addresses in the ipset 'dnsblack': +# +# ADDRESS/SUBNET PROTOCOL PORT +# +dnsblack udp 53 +# # Please see http://shorewall.net/blacklisting_support.htm for additional # information. # diff --git a/Shorewall2/changelog.txt b/Shorewall2/changelog.txt index cfa2a7bdb..472ec4371 100644 --- a/Shorewall2/changelog.txt +++ b/Shorewall2/changelog.txt @@ -1,3 +1,5 @@ Changes in 2.3.0 1) Implement support for --cmd-owner + +2) Implement support for ipsets. diff --git a/Shorewall2/firewall b/Shorewall2/firewall index 6bba34e94..bd093dc40 100755 --- a/Shorewall2/firewall +++ b/Shorewall2/firewall @@ -218,6 +218,19 @@ run_tc() { fi } +# +# Run ipset and if an error occurs, stop the firewall and quit +# +run_ipset() { + if ! ipset $@ ; then + if [ -z "$stopping" ]; then + error_message "ERROR: Command \"ipset $@\" Failed" + stop_firewall + exit 2 + fi + fi +} + # # Create a filter chain # @@ -541,6 +554,29 @@ iprange_echo() fi } +# +# Get set flags +# +get_set_flags() # $1 = set name and optional [levels], $2 = src or dst +{ + local temp setname options=$2 + + case $1 in + *\[*[1-6]\]) + temp=${1#*\[} + temp=${temp%\]} + setname=${1%\[*} + while [ $temp -gt 1 ]; do + options="$options,$2" + temp=$(($temp - 1)) + done + echo "--set ${setname#+} $options" + ;; + *) + echo "--set ${1#+} $2" + ;; + esac +} # # Source IP range @@ -558,6 +594,12 @@ source_ip_range() # $1 = Address or Address Range ;; esac ;; + !+*) + echo "-m set ! $(get_set_flags ${1#!} src)" + ;; + +*) + echo "-m set $(get_set_flags $1 src)" + ;; *) echo "-s $1" ;; @@ -580,6 +622,12 @@ dest_ip_range() # $1 = Address or Address Range ;; esac ;; + !+*) + echo "-m set ! $(get_set_flags ${1#!} dst)" + ;; + +*) + ipset_echo "-m set $(get_set_flags ${1#+} dst)" + ;; *) echo "-d $1" ;; @@ -595,6 +643,10 @@ both_ip_ranges() # $1 = Source address or range, $2 = dest address or range prefix="-m iprange" match="--src-range $1" ;; + +*) + prefix="-m set" + match="--set ${1#+} src" + ;; *) match="-s $1" ;; @@ -605,6 +657,18 @@ both_ip_ranges() # $1 = Source address or range, $2 = dest address or range prefix="-m iprange" match="$match --dst-range $2" ;; + +*) + case $1 in + *.*.*.*-*.*.*.*) + prefix="$iprange -m set" + ;; + *) + prefix="-m set" + ;; + esac + + match="--set ${1#+} dst" + ;; *) match="$match -d $2" ;; @@ -749,6 +813,22 @@ match_ipsec_out() # $1 = zone, $2 = host fi } +# +# Generate a match for packets whose source matches the passed IPSET +# +match_ipset_source() +{ + echo "-m set --set ${1#+} src" +} + +# +# Generate a match for packets whose destination matches the passed IPSET +# +match_ipset_dest() +{ + echo "-m set --set ${1#+} dst" +} + # # Jacket for ip_range() that takes care of iprange match # @@ -1002,7 +1082,7 @@ validate_hosts_file() { startup_error "Bridged interfaces may not be defined in /etc/shorewall/interfaces: $host" check_bridge_port ${host%%:*} ;; - *.*.*.*) + *.*.*.*|+*) ;; *) known_interface $host && \ @@ -2380,7 +2460,7 @@ process_tc_rule() if [ "x$source" != "x-" ]; then case $source in - *.*.*) + *.*.*|+*|!+*) r="$(source_ip_range $source) " ;; ~*) @@ -2431,7 +2511,7 @@ process_tc_rule() if [ "x$dest" != "x-" ]; then case $dest in - *.*.*) + *.*.*|+*|!+*) r="${r}$(dest_ip_range $dest) " ;; *) @@ -2685,8 +2765,8 @@ process_accounting_rule() { accounting_interface_verify ${source%:*} rule="-s ${source#*:} $(match_source_dev ${source%:*})" ;; - *.*.*.*) - rule="-s $source" + *.*.*.*|+*|!+*) + rule="$(source_ip_range)" ;; -|all|any) ;; @@ -2703,7 +2783,7 @@ process_accounting_rule() { accounting_interface_verify ${dest%:*} rule="$rule $(dest_ip_range ${dest#*:}) $(match_dest_dev ${dest%:*})" ;; - *.*.*.*) + *.*.*.*|+*|!*) rule="$rule $(dest_ip_range $dest)" ;; -|all|any) @@ -3036,8 +3116,8 @@ add_an_action() action_interface_verify ${client%:*} cli="$(match_source_dev ${client%:*}) $(source_ip_range ${client#*:})" ;; - *.*.*) - cli="-s $client" + *.*.*|+*|!+*) + cli="$(source_ip_range $client)" ;; ~*) cli=$(mac_match $client) @@ -3058,7 +3138,7 @@ add_an_action() case "$server" in -) ;; - *.*.*) + *.*.*|+*|!+*) serv=$server ;; ~*) @@ -3116,7 +3196,7 @@ add_an_action() for srv in $(firewall_ip_range $serv1); do if [ -n "$loglevel" ]; then log_rule_limit $loglevel $chain $action $logtarget "$ratelimit" "$logtag" -A $userandgroup \ - $(fix_bang $proto $sports $multiport $cli $(source_ip_range $srv) $dports) + $(fix_bang $proto $sports $multiport $cli $(dest_ip_range $srv) $dports) fi run_iptables2 -A $chain $proto $multiport $cli $sports \ @@ -4082,7 +4162,7 @@ add_a_rule() rule_interface_verify ${client%:*} cli="$(match_source_dev ${client%:*}) $(source_ip_range ${client#*:})" ;; - *.*.*) + *.*.*|+*) cli="$(source_ip_range $client)" ;; ~*) @@ -4104,7 +4184,7 @@ add_a_rule() case "$server" in -) ;; - *.*.*) + *.*.*|+*) serv=$server ;; ~*) @@ -4763,7 +4843,7 @@ process_tos_rule() { fi [ -n "$src" ] && case "$src" in - *.*.*) + *.*.*|+*|!+*) # # IP Address or networks # @@ -4811,7 +4891,7 @@ process_tos_rule() { fi [ -n "$dst" ] && case "$dst" in - *.*.*) + *.*.*|+*|!+*) # # IP Address or networks # @@ -5245,7 +5325,7 @@ setup_masq() source="$networks" case $source in - *.*.*) + *.*.*|+*|!+*) ;; *) networks=$(get_routed_networks $networks) @@ -5254,9 +5334,7 @@ setup_masq() ;; esac - [ "x$addresses" = x- ] && addresses= - - + [ "x$addresses" = x- ] && addresses= if [ -n "$addresses" -a -n "$add_snat_aliases" ]; then for address in $(separate_list $addresses); do @@ -5502,16 +5580,18 @@ process_blacklist_rec() { local addr local proto local dport + local temp + local setname for addr in $(separate_list $networks); do case $addr in - ~*) - addr=$(echo $addr | sed 's/~//;s/-/:/g') - source="--match mac --mac-source $addr" - ;; - *) - source="$(source_ip_range $addr)" - ;; + ~*) + addr=$(echo $addr | sed 's/~//;s/-/:/g') + source="--match mac --mac-source $addr" + ;; + *) + source="$(source_ip_range $addr)" + ;; esac if [ -n "$protocol" ]; then @@ -5825,6 +5905,16 @@ report_capabilities() { report_capability "Owner Match" $OWNER_MATCH } +# +# Restore ipsets +# +restore_ipsets() +{ + local restore_sets=/var/lib/shorewall/${RESTOREFILE:-restore}-ipsets + + [ -x $restore_sets ] && $restore_sets +} + # # Perform Initialization # - Delete all old rules @@ -5918,6 +6008,7 @@ initialize_netfilter () { deleteallchains + setcontinue FORWARD setcontinue INPUT setcontinue OUTPUT @@ -6918,7 +7009,7 @@ define_firewall() # $1 = Command (Start or Restart) for file in chains nat proxyarp zones; do append_file $file done - + save_progress_message "Restoring Netfilter Configuration..." save_command 'iptables-restore << __EOF__' @@ -7469,6 +7560,7 @@ do_initialize() { DROPINVALID= RFC1918_STRICT= MACLIST_TTL= + RESTOREFILE= RESTOREBASE= TMP_DIR= diff --git a/Shorewall2/help b/Shorewall2/help index d5aed8394..96f0f8dad 100644 --- a/Shorewall2/help +++ b/Shorewall2/help @@ -55,7 +55,10 @@ address|host) May be either a host IP address such as 192.168.1.4 or a network address in CIDR format like 192.168.1.0/24. If your kernel and iptables contain iprange match support then IP address ranges of the form - - are also permitted." + are also permitted. If your kernel and iptables contain ipset match support + then you may specify the name of an ipset prefaced by "+". The name of the + ipsec may be optionally followed by a number of levels of ipset bindings + (1 - 6) that are to be followed" ;; allow) diff --git a/Shorewall2/releasenotes.txt b/Shorewall2/releasenotes.txt index b8c1ef7ae..26990f322 100755 --- a/Shorewall2/releasenotes.txt +++ b/Shorewall2/releasenotes.txt @@ -36,4 +36,30 @@ New Features in version 2.3.0 symbolic links, it's easy to alias command names to be anything you want. +2) Support has been added for ipsets + (see http://people.netfilter.org/kadlec/ipset/). + + In most places where an host or network address may be used, you may + also use the name of an ipset prefaced by "+". The name of the set + may optionally followed by a number from 1 to 6 enclosed in square + brackets ([]) -- this number indicates the maximum number of ipset + binding levels that are to be matched. Depending on the context + where the ipset name is used, either all "src" or all "dst" matches + will be used. + + Example 1: Blacklist all hosts in an ipset named "blacklist" + + /etc/shorewall/blacklist + + #ADDRESS/SUBNET PROTOCOL PORT + +blacklist + + Example 2: Allow SSH from all hosts in an ipset named "sshok: + + /etc/shorewall/rules + + #ACTION SOURCE DEST PROTO DEST PORT(S) + ACCEPT +sshok fw tcp 22 + + diff --git a/Shorewall2/rules b/Shorewall2/rules index 76a7086e2..ab0be283c 100755 --- a/Shorewall2/rules +++ b/Shorewall2/rules @@ -134,6 +134,11 @@ # Hosts may be specified as an IP address range using the # syntax -. This requires that # your kernel and iptables contain iprange match support. +# If you kernel and iptables have ipset match support then +# you may give the name of an ipset prefaced by "+". The +# ipset name may be optionally followed by a number from +# 1 to 6 enclosed in square brackets ([]) to indicate the +# number of levels of source bindings to be matched. # # dmz:192.168.2.2 Host 192.168.2.2 in the DMZ # @@ -189,6 +194,14 @@ # the connections will be assigned to addresses in the # range in a round-robin fashion. # +# If you kernel and iptables have ipset match support then +# you may give the name of an ipset prefaced by "+". The +# ipset name may be optionally followed by a number from +# 1 to 6 enclosed in square brackets ([]) to indicate the +# number of levels of destination bindings to be matched. +# Only one of the SOURCE and DEST columns may specify an +# ipset name. +# # The port that the server is listening on may be # included and separated from the server's IP address by # ":". If omitted, the firewall will not modifiy the