📄 lib.config
字号:
#!/bin/sh## Shorewall 4.2 -- /usr/share/shorewall/lib.config## This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt]## (c) 1999,2000,2001,2002,2003,2004,2005,2006,2007 - Tom Eastep (teastep@shorewall.net)## Complete documentation is available at http://shorewall.net## This program is free software; you can redistribute it and/or modify# it under the terms of Version 2 of the GNU General Public License# as published by the Free Software Foundation.## This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.## You should have received a copy of the GNU General Public License# along with this program; if not, write to the Free Software# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.## This library contains the configuration file parsing code common to# /usr/share/shorewall/compiler and /usr/share/shorewall/firewall#SHOREWALL_CONFIGVERSION=40000## Replace commas with spaces and echo the result#separate_list() { local list list="$@" local part local newlist local firstpart local lastpart local enclosure case "$list" in *,|,*|*,,*|*[[:space:]]*) # # There's been whining about us not catching embedded white space in # comma-separated lists. This is an attempt to snag some of the cases. # # The 'TERMINATOR' function will be set by the 'firewall' script to # either 'startup_error' or 'fatal_error' depending on the command and # command phase # [ -n "$TERMINATOR" ] && \ $TERMINATOR "Invalid comma-separated list \"$@\"" echo "WARNING -- invalid comma-separated list \"$@\"" >&2 ;; *\[*\]*) # # Where we need to embed comma-separated lists within lists, we enclose them # within square brackets. # firstpart=${list%%\[*} lastpart=${list#*\[} enclosure=${lastpart%%\]*} lastpart=${lastpart#*\]} case $lastpart in \,*) case $firstpart in *\,) echo "$(separate_list ${firstpart%,}) [$enclosure] $(separate_list ${lastpart#,})" ;; *) echo "$(separate_list $firstpart)[$enclosure] $(separate_list ${lastpart#,})" ;; esac ;; *) case $firstpart in *\,) echo "$(separate_list ${firstpart%,}) [$enclosure]$(separate_list $lastpart)" ;; *) echo "$(separate_list $firstpart)[$enclosure]$(separate_list $lastpart)" ;; esac ;; esac return ;; esac list="$@" part="${list%%,*}" newlist="$part" while [ "x$part" != "x$list" ]; do list="${list#*,}"; part="${list%%,*}"; newlist="$newlist $part"; done echo "$newlist"}## Display elements of a list with leading white space#display_list() # $1 = List Title, rest of $* = list to display{ [ $# -gt 1 ] && echo " $*"}## Determine if a chain is a policy chain#is_policy_chain() # $1 = name of chain{ eval test \"\$${1}_is_policy\" = Yes}## Return a space separated list of values matching#list_walk() # $1 = element to search for, $2-$n = list{ local e e=$1 local result result= while [ $# -gt 1 ]; do shift case $1 in $e*) result="$result ${1##$e}" ;; esac done echo $result}## Functions to count list elements# - - - - - - - - - - - - - - - -# Whitespace-separated list#list_count1() { echo $#}## Comma-separated list#list_count() { list_count1 $(separate_list $1)}## Filter that expands variables#expand_line() { local line while read line; do echo $(expand $line) done}## Add whitespace after leading "!"#fix_bang(){ local result result= while [ $# -gt 0 ]; do case $1 in !*) result="$result ! ${1#!}" ;; *) result="$result $1" ;; esac shift done echo $result}## Read the zones file and find the firewall zone#get_firewall_zone() { local zone local type local rest local comment comment='#*' local f f=$(find_file zones) [ -f $f ] || startup_error "Unable to find zones file" while read zone type rest; do case $zone in $comment) ;; *) if [ "x$type" = xfirewall ]; then FW=$zone return fi ;; esac done < $f startup_error "No firewall zone defined in $f"}## This function assumes that the TMP_DIR variable is set and that# its value names an existing directory.#determine_zones(){ local zone local parent local parents local rest local new_zone_file new_zone_file= local r merge_zone() { local z local zones zones="$ZONES" local merged merged= if [ -n "$parents" ]; then ZONES= for z in $zones; do if [ -z "$merged" ] && list_search $z $parents; then ZONES="$ZONES $zone" merged=Yes fi ZONES="$ZONES $z" done else ZONES="$ZONES $zone" fi } ZONES= IPV4_ZONES= IPSEC_ZONES= [ "$IPSECFILE" = zones ] && new_zone_file=Yes || test -n "${FW:=fw}" while read zone type rest; do case $zone in *:*) parents=${zone#*:} zone=${zone%:*} [ -n "$zone" ] || startup_error "Invalid nested zone syntax: :$parents" parents=$(separate_list $parents) eval ${zone}_parents=\"$parents\" ;; *) parents= eval ${zone}_parents= ;; esac for parent in $parents; do [ "$parent" = "$FW" ] && startup_error "Sub-zones of the firewall zone are not allowed" list_search $parent $ZONES || startup_error "Parent zone not defined: $parent" done [ ${#zone} -gt $MAXZONENAMELENGTH ] && startup_error "Zone name longer than $MAXZONENAMELENGTH characters: $zone" case "$zone" in [0-9*]) startup_error "Illegal zone name \"$zone\" in zones file" ;; all|none|SOURCE|DEST) startup_error "Reserved zone name \"$zone\" in zones file" ;; esac if [ -n "$new_zone_file" ]; then case ${type:=ipv4} in ipv4|IPv4|IPV4|plain|-) list_search $zone $ZONES $FW && startup_error "Zone $zone is defined more than once" merge_zone IPV4_ZONES="$IPV4_ZONES $zone" ;; ipsec|IPSEC|ipsec4|IPSEC4) list_search $zone $ZONES $FW && startup_error "Zone $zone is defined more than once" [ -n "$POLICY_MATCH" ] || startup_error "Your kernel and/or iptables does not support policy match" eval ${zone}_is_ipsec=Yes eval ${zone}_is_complex=Yes merge_zone IPSEC_ZONES="$IPSEC_ZONES $zone" ;; firewall) [ -n "$FW" ] && startup_error "Only one firewall zone may be defined" list_search $zone $ZONES && startup_error "Zone $zone is defined more than once" [ -n "$parents" ] && startup_error "The firewall zone may not be nested" for r in $rest; do [ "x$r" = x- ] || startup_error "OPTIONS not allowed on the firewall zone" done FW=$zone ;; bport|bport4) [ "$PROGRAM" = compiler ] && startup_error "Invalid Zone Type: $type" list_search $zone $ZONES $FW && startup_error "Zone $zone is defined more than once" merge_zone BRIDGING=Yes ;; *) startup_error "Invalid Zone Type: $type" ;; esac eval ${zone}_type=$type else list_search $zone $ZONES $FW && startup_error "Zone $zone is defined more than once" ZONES="$ZONES $zone" IPV4_ZONES="$IPV4_ZONES $zone" eval ${zone}_type=ipv4 fi done < $TMP_DIR/zones [ -z "$ZONES" ] && startup_error "No ipv4 or ipsec Zones Defined" [ -z "$FW" ] && startup_error "No Firewall Zone Defined"}## Validate the zone names and options in the interfaces file#validate_interfaces_file() { local wildcard local found_obsolete_option found_obsolete_option= local z local interface local networks local options local r local iface local option while read z interface networks options; do r="$z $interface $networks $options" [ "x$z" = "x-" ] && z= if [ -n "$z" ]; then validate_zone $z || startup_error "Invalid zone ($z) in record \"$r\"" fi list_search $interface $ALL_INTERFACES && \ startup_error "Duplicate Interface $interface" wildcard= case $interface in *:*) if [ "$PROGRAM" != compiler ]; then # # Assume that this is 4.0 syntax for a bridge # local bridge bridge=${interface%:*} list_search $bridge $ALL_INTERFACES || startup_error "Unknown Interface: $bridge" interface=${interface#*:} else startup_error "Invalid Interface Name: $interface" fi ;; +) startup_error "Invalid Interface Name: +" ;; *+) wildcard=Yes ;; esac ALL_INTERFACES="$ALL_INTERFACES $interface" options=$(separate_list $options) iface=$(chain_base $interface) eval ${iface}_broadcast="$networks" eval ${iface}_zone="$z" eval ${iface}_options=\"$options\" for option in $options; do case $option in -) ;; dhcp|tcpflags|arp_filter|routefilter|logmartians|sourceroute|blacklist|nosmurfs|upnp|-) ;; proxyarp) [ "$PROGRAM" = compiler ] && lib_load proxyarp "The 'proxyarp' option on interface $interface" ;; maclist) [ "$PROGRAM" = compiler ] && lib_load maclist "The 'maclist' option" ;; norfc1918) if [ "$PROGRAM" != compiler ]; then addr=$(ip -f inet addr show $interface 2> /dev/null | grep inet | head -n1) if [ -n "$addr" ]; then addr=$(echo $addr | sed 's/inet //;s/\/.*//;s/ peer.*//') for network in 10.0.0.0/8 176.16.0.0/12 192.168.0.0/16; do if in_network $addr $network; then startup_error "The 'norfc1918' option may not be specified on an interface with an RFC 1918 address. Interface:$interface" fi done fi fi ;; arp_ignore=*) eval ${iface}_arp_ignore=${option#*=} ;; arp_ignore) eval ${iface}_arp_ignore=1 ;; detectnets) [ -n "$wildcard" ] && \ startup_error "The \"detectnets\" option may not be used with a wild-card interface" [ -n "$EXPORT" ] && \ startup_error "'detectnets' not permitted with the -e run-line option" ;; routeback) [ -n "$z" ] || startup_error "The routeback option may not be specified on a multi-zone interface" ;; *) [ $PROGRAM = compiler ] && error_message "WARNING: Invalid option ($option) in record \"$r\"" ;; esac done done < $TMP_DIR/interfaces [ -z "$ALL_INTERFACES" ] && startup_error "No Interfaces Defined"}## Process the ipsec information in the zones file#setup_ipsec() { local zone local using_ipsec using_ipsec= # # Add a --set-mss rule to the passed chain # set_mss1() # $1 = chain, $2 = MSS { local policy eval policy=\$${1}_policy if [ "$policy" != NONE ]; then ensurechain $1 local match match= [ "$TCPMSS_MATCH" ] && match="-m tcpmss --mss $2: " run_iptables -I $1 -p tcp --tcp-flags SYN,RST SYN ${match}-j TCPMSS --set-mss $2 fi } # # Set up rules to set MSS to and/or from zone "$zone" # set_mss() # $1 = MSS value, $2 = _in, _out or "" { for z in $ZONES $FW; do case $2 in _in) set_mss1 ${zone}2${z} $1 ;; _out) set_mss1 ${z}2${zone} $1 ;; *) set_mss1 ${z}2${zone} $1 set_mss1 ${zone}2${z} $1 ;; esac done } do_options() # $1 = _in, _out or "" - $2 = option list { local option local newoptions newoptions= local val [ x${2} = x- ] && return for option in $(separate_list $2); do val=${option#*=} case $option in mss=[0-9]*) [ "$PROGRAM" = compiler ] && set_mss $val $1 ;; strict) newoptions="$newoptions --strict" ;; next) newoptions="$newoptions --next" ;; reqid=*) newoptions="$newoptions --reqid $val" ;; spi=*) newoptions="$newoptions --spi $val" ;; proto=*) newoptions="$newoptions --proto $val" ;; mode=*) newoptions="$newoptions --mode $val" ;; tunnel-src=*) newoptions="$newoptions --tunnel-src $val" ;; tunnel-dst=*) newoptions="$newoptions --tunnel-dst $val" ;; reqid!=*) newoptions="$newoptions ! --reqid $val" ;; spi!=*) newoptions="$newoptions ! --spi $val" ;; proto!=*) newoptions="$newoptions ! --proto $val" ;; mode!=*) newoptions="$newoptions ! --mode $val" ;; tunnel-src!=*) newoptions="$newoptions ! --tunnel-src $val" ;; tunnel-dst!=*) newoptions="$newoptions ! --tunnel-dst $val" ;; *) fatal_error "Invalid option \"$option\" for zone $zone" ;; esac done if [ -n "$newoptions" ]; then [ -n "$POLICY_MATCH" ] || fatal_error "Your kernel and/or iptables does not support policy match" eval ${zone}_is_complex=Yes eval ${zone}_ipsec${1}_options=\"${newoptions# }\" fi } case $IPSECFILE in zones) f=zones progress_message "$DOING IPSEC..." [ $PROGRAM = compiler -a -n "$IPSEC_ZONES" ] && save_progress_message "Setting up IPSEC management..." ;; ipsec) using_ipsec=Yes if [ -s ${TMP_DIR}/ipsec ]; then progress_message "$DOING ipsec..." [ $PROGRAM = compiler ] && save_progress_message "Setting up IPSEC management..." f=ipsec else return fi ;; esac while read zone type options in_options out_options mss; do if [ -n "$using_ipsec" ]; then validate_zone1 $zone || fatal_error "Unknown zone: $zone" fi if [ -n "$type" ]; then if [ -n "$using_ipsec" ]; then case $type in No|no) ;; Yes|yes) [ -n "$POLICY_MATCH" ] || fatal_error "Your kernel and/or iptables does not support policy match" eval ${zone}_is_ipsec=Yes eval ${zone}_is_complex=Yes eval ${zone}_type=ipsec4 ;; *) fatal_error "Invalid IPSEC column contents" ;; esac fi do_options "" $options do_options "_in" $in_options
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -