#!/bin/bash #Copyright (c) 1999, William L. Stearns #Released under the GPL. #Credit goes to Paul 'Rusty' Russell's ipchains-howto, especially #the conversion table in the appendix. #Home page is at http://www.pobox.com/~wstearns/ipfwadm2ipchains/ #Version 0.5.0, first release, May 2, 1999 #Version 0.5.1, fixed -I parameter order, May 1999 #Version 0.5.2, handle blank input lines correctly, May 10, 1999 ACCOUNTINGPREPARED='' echo "------------------------------------------------------------------" >/dev/stderr echo "---- ipfwadm2ipchains rule converter ----" >/dev/stderr echo "---- See http://www.pobox.com/~wstearns/ for more info on ----" >/dev/stderr echo "---- this and Mason, the automatic firewall creator. ----" >/dev/stderr echo "---- Copyright (c) 1999 William Stearns ----" >/dev/stderr echo "---- Released under the GNU GPL. ----" >/dev/stderr echo "------------------------------------------------------------------" >/dev/stderr Fshift () { F1=$F2 ; F2=$F3 ; F3=$F4 ; F4=$F5 ; F5=$F6 F6=$F7 ; F7=$F8 ; F8=$F9 ; F9=$F10 ; F10=$F11 F11=$F12 ; F12=$F13 ; F13=$F14 ; F14=$F15 ; F15=$F16 F16=$F17 ; F17=$F18 ; F18=$F19 ; F19=$F20 ; F20=$F21 F21=$F22 ; F22=$F23 ; F23=$F24 ; F24=$F25 ; F25=$F26 F26=$F27 ; F27=$F28 ; F28=$F29 ; F29=$F30 ; F30=$F31 F31=$F32 ; F32=$F33 ; F33=$F34 ; F34=$F35 ; F35=$F36 F36=$F37 ; F37=$F38 ; F38=$F39 ; F39=$F40 ; F40=$F41 F41=$F42 ; F42=$F43 ; F43=$F44 ; F44=$F45 ; F45=$F46 F46=$F47 ; F47=$F48 ; F48=$F49 ; F49=$F50 ; F50=$F51 F51=$F52 ; F52=$F53 ; F53=$F54 ; F54=$F55 ; F55=$F56 F56=$F57 ; F57=$F58 ; F58=$F59 ; F59=$F60 ; F60='' } SetupAccounting () { if [ "$ACCOUNTINGPREPARED" != 'YES' ]; then echo \#The following block may be used to initialize the echo \#Accounting chains that must be explicitly prepared echo \#in ipchains. The lines starting with \"/sbin/ipchains\" echo \#should be uncommented and a single echo \#copy of the block placed at the top of your firewall. echo \#/sbin/ipchains -N acctin echo \#/sbin/ipchains -N acctout echo \#/sbin/ipchains -N acctio echo \#/sbin/ipchains -I input 1 -j acctio echo \#/sbin/ipchains -I input 1 -j acctin echo \#/sbin/ipchains -I output 1 -j acctio echo \#/sbin/ipchains -I output 1 -j acctout ACCOUNTINGPREPARED='YES' fi } if [ "$1" = '--help' ]; then echo Usage: $0 [--help] >/dev/stderr echo This program converts ipfwadm rules to ipchains rules. >/dev/stderr echo Example of use: >/dev/stderr echo >/dev/stderr echo cat ipfwadm_rulefile \| ipfwadm2ipchains \>ipchains_rulefile >/dev/stderr echo echo if [ -f /proc/net/ip_fwchains ]\; then \>\>new_rules >/dev/stderr echo cat ipchains_rulefile \>\>new_rules >/dev/stderr echo echo elif [ -f /proc/net/ip_input ]\; then \>\>new_rules >/dev/stderr echo cat ipfwadm_rulefile \>\>new_rules >/dev/stderr echo echo fi \>\>new_rules >/dev/stderr echo >/dev/stderr echo The new_rules file will now work on ipchains and ipfwadm kernels. >/dev/stderr exit fi CHAINRULE='' ; NEXT='' ; MASQ='' ; COMMENT='' SOURCEPORT='' ; DESTPORT='' ; ACCTDIR='both' REDIR='' ; REDIRPORT='' #Start of main loop. Read one ipfwadm rule for processing. while read F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 \ F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 F32 F33 F34 F35 F36 F37 F38 F39 F40 \ F41 F42 F43 F44 F45 F46 F47 F48 F49 F50 F51 F52 F53 F54 F55 F56 F57 F58 F59 F60 ; do #While there is another line of input #Formerly [ -n "$F1" ] && in the above test while [ -n "$F1" ]; do #While there is another field to process in this line case "$F1" in /sbin/ipfwadm) CHAINRULE="$CHAINRULE /sbin/ipchains" NEXT='' ;; ipfwadm) CHAINRULE="$CHAINRULE ipchains" NEXT='' ;; */ipfwadm) CHAINRULE="$CHAINRULE `echo $F1 | sed -e 's@/ipfwadm$@/ipchains@'`" NEXT='' ;; -A) #Create an accounting rule SetupAccounting CHAINRULE="$CHAINRULE -A ZZACCTDIRZZ" NEXT='ACCTDIR' ;; -F) #Forwarding rule CHAIN='forward' NEXT='' ;; -I) #Input rule CHAIN='input' NEXT='' ;; -O) #Output rule CHAIN='output' NEXT='' ;; -M) #Masquerading administration (used for -l and -s) CHAINRULE="$CHAINRULE -M" NEXT='' ;; -l) #List the rules in this chain CHAINRULE="$CHAINRULE -L ZZCHAINZZ" NEXT='' ;; -s) #Set timeouts for masquerading CHAINRULE="$CHAINRULE -S $F2 $F3 $F4" ; Fshift ; Fshift ; Fshift NEXT='' ;; -a) #Append this rule CHAINRULE="$CHAINRULE -A ZZCHAINZZ -j ZZPOLICYZZ" NEXT='POLICY' ;; -d) #Delete this rule CHAINRULE="$CHAINRULE -D ZZCHAINZZ -j ZZPOLICYZZ" NEXT='POLICY' ;; -i) #Insert this rule CHAINRULE="$CHAINRULE -I ZZCHAINZZ 1 -j ZZPOLICYZZ" NEXT='POLICY' ;; -z) #Zero out the counters CHAINRULE="$CHAINRULE -Z" NEXT='' ;; -f) #Flush the rules in this chain CHAINRULE="$CHAINRULE -F ZZCHAINZZ" NEXT='' ;; -p) #Default policy for the chain CHAINRULE="$CHAINRULE -P ZZCHAINZZ ZZPOLICYZZ" NEXT='POLICY' ;; -c) #Check if packet would be accepted or not CHAINRULE="$CHAINRULE -C" NEXT='' ;; -P) #Protocol if [ "$F2" != "all" ]; then CHAINRULE="$CHAINRULE -p $F2" fi Fshift NEXT='' ;; -S) #Specify packet source CHAINRULE="$CHAINRULE -s $F2" ; Fshift NEXT='SOURCEPORT' ;; -D) #Specify packet destination CHAINRULE="$CHAINRULE -d $F2" ; Fshift NEXT='DESTPORT' ;; -V) #Use this IP address; convert to an IF name. HOSTIP="$F2" IFNAME=`ifconfig | grep -B 1 "inet addr:$HOSTIP" | head -1 | awk '{print $1}'` if [ -z "$IFNAME" ]; then HOSTIP=`host -t a $F2 2>/dev/null | grep 'has address' | head -1 | awk '{print $4}'` if [ -n "$HOSTIP" ]; then IFNAME=`ifconfig | grep -B 1 "inet addr:$HOSTIP" | head -1 | awk '{print $1}'` else echo Unable to find the interface name for $F2 . >/dev/stderr echo Please convert it by hand. >/dev/stderr IFNAME="interface_name_for_${F2}" fi fi CHAINRULE="$CHAINRULE -i $IFNAME" ; Fshift NEXT='' ; IFNAME='' ; HOSTIP='' ;; -W) #Use this interface CHAINRULE="$CHAINRULE -i $F2" ; Fshift NEXT='' ;; -b) #bidirectional mode CHAINRULE="$CHAINRULE -b" NEXT='' ;; -e) #Extended/verbose output CHAINRULE="$CHAINRULE -v" NEXT='' ;; -k) #Check ack flag CHAINRULE="$CHAINRULE ! -y" NEXT='' ;; -m) #Masquerade this traffic MASQ='YES' ; NEXT='' ;; -n) #Numeric output CHAINRULE="$CHAINRULE -n" NEXT='' ;; -o) #log these packets CHAINRULE="$CHAINRULE -l" NEXT='' ;; -r) #REDIRECT to local port REDIR='YES' NEXT='REDIRPORT' ;; -t) #Set TOS masks CHAINRULE="$CHAINRULE -t $F2 $F3" Fshift ; Fshift NEXT='' ;; -v) #Verbose CHAINRULE="$CHAINRULE -v" NEXT='' ;; -x) #Expand numbers CHAINRULE="$CHAINRULE -x" NEXT='' ;; -y) #Syn flag set and ack cleared CHAINRULE="$CHAINRULE -y" NEXT='' ;; \#*) #Append comments verbatim. while [ -n "$F1" ]; do CHAINRULE="$CHAINRULE $F1" Fshift done ;; *) case "$NEXT" in 'ACCTDIR') ACCTDIR="$F1" ; NEXT='' ;; 'REDIRPORT') REDIRPORT="$F1" ; NEXT='' ;; 'SOURCEPORT') if [ -z "`echo $CHAINRULE | grep 'ZZSOURCEPORTZZ'`" ]; then CHAINRULE="$CHAINRULE ZZSOURCEPORTZZ" fi SOURCEPORT="$SOURCEPORT $F1" ;; "DESTPORT") if [ -z "`echo $CHAINRULE | grep 'ZZDESTPORTZZ'`" ]; then CHAINRULE="$CHAINRULE ZZDESTPORTZZ" fi DESTPORT="$DESTPORT $F1" ;; "POLICY") POLICY=`echo $F1 | tr a-z A-Z` case "$POLICY" in A*) POLICY="ACCEPT" ;; D*) POLICY="DENY" ;; M*) POLICY="MASQ" ;; R*) POLICY="REJECT" ;; esac NEXT='' ;; *) #Just return the field - we don't know what to do. CHAINRULE="$CHAINRULE $F1" NEXT='' ;; esac esac Fshift done #Replace Policy, Accounting and Chain placeholders if [ "$MASQ" = "YES" ]; then POLICY="MASQ" fi if [ "$REDIR" = "YES" ]; then if [ -n "$REDIRPORT" ]; then POLICY="REDIRECT $REDIRPORT" else POLICY="REDIRECT" fi fi case "$ACCTDIR" in 'in') CHAINRULE=`echo $CHAINRULE | sed -e "s/ZZACCTDIRZZ/acctin/g"` ;; 'out') CHAINRULE=`echo $CHAINRULE | sed -e "s/ZZACCTDIRZZ/acctout/g"` ;; 'both'|''|*) CHAINRULE=`echo $CHAINRULE | sed -e "s/ZZACCTDIRZZ/acctio/g"` ;; esac CHAINRULE=`echo $CHAINRULE | sed -e "s/ZZPOLICYZZ/$POLICY/g" \ -e "s/ZZCHAINZZ/$CHAIN/g"` #Output the rule. Handle looping through multiple source and dest ports if [ -z "$SOURCEPORT" ] && [ -z "$DESTPORT" ]; then #No src/dest ports specified echo $CHAINRULE elif [ -n "$SOURCEPORT" ] && [ -z "$DESTPORT" ]; then #>=1 src port, no dest ports for ONESOURCE in $SOURCEPORT ; do echo $CHAINRULE | sed -e "s/ZZSOURCEPORTZZ/$ONESOURCE/g" done elif [ -z "$SOURCEPORT" ] && [ -n "$DESTPORT" ]; then #no src ports, >=1 dest port for ONEDEST in $DESTPORT ; do echo $CHAINRULE | sed -e "s/ZZDESTPORTZZ/$ONEDEST/g" done else #>=1 src port and >=1 dest port for ONESOURCE in $SOURCEPORT ; do for ONEDEST in $DESTPORT ; do echo $CHAINRULE | sed -e "s/ZZSOURCEPORTZZ/$ONESOURCE/g" -e "s/ZZDESTPORTZZ/$ONEDEST/g" done done fi CHAINRULE='' ; NEXT='' ; MASQ='' ; COMMENT='' SOURCEPORT='' ; DESTPORT='' ; ACCTDIR='both' REDIR='' ; REDIRPORT='' done