#!/bin/bash #Copyright (c) 1999, William L. Stearns #Released under the GPL. #Home page is at http://www.pobox.com/~wstearns/ ##Version 0.5.0, first test release, Sep 6, 1999 #FIXME - finish keeping track of needed modules and listing them. #FIXME - icmp needs icmp-type, not --sport/--dport #FIXME - ipnatctl doesn't seem to do /etc/hosts lookups echo "------------------------------------------------------------------" >/dev/stderr echo "---- ipchains2iptables 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='' } islocalip () { #Returns true if the $1 IP address is an ip address on this box. #This is used to identify which packets are destined to/coming from #local processes. #param: ip address to check for ONEIP in $LOCALNAMES ; do if [ "$1" = "$ONEIP" ] || [ "$1" = "$ONEIP/32" ]; then return 0 #True fi done return 1 #False } suggestif () { #Add a note in the comment that the user might want to add in #an additional interface specification. #params: -i/-o, srcaddr, optional actual interface to suggest if [ -n "$2" ]; then if [ -n "$3" ]; then COMMENT="$COMMENT Suggestion: \"$1 $3\"." else COMMENT="$COMMENT Suggestion: \"$1 IF-of-$2\"." fi fi } addprotoholder () { #This adds a placeholder for "-p protocol", if it's not already there, #to CHAINRULE and NATSPEC. This is used to make sure that "-p proto" #always comes before any other specifications that depend on the #protocol module (ipt_TCP, etc) being loaded. if [ -z "`echo $CHAINRULE | grep ' -p '`" ]; then CHAINRULE="$CHAINRULE -p ZZPROTOZZ" fi if [ -n "`echo $NATSPEC | grep ' -p '`" ] || [ -n "`echo $NATSPEC | grep '^-p '`" ]; then : else NATSPEC="$NATSPEC -p ZZPROTOZZ" fi } if [ "$1" = '--help' ] || [ "$1" = '-h' ]; then echo Usage: $0 [--help] >/dev/stderr echo This program converts ipchains rules to iptables rules. >/dev/stderr echo Example of use: >/dev/stderr echo >/dev/stderr echo cat ipchains_rulefile \| ipchains2iptables \>iptables_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 #Global settings: NEEDEDMODULES='' if which ipnatctl >/dev/null ; then IPNATCTLBIN=`which ipnatctl | head -1` elif [ -x /usr/local/bin/ipnatctl ]; then IPNATCTLBIN='/usr/local/bin/ipnatctl' else IPNATCTLBIN='ipnatctl' echo '#ipnatctl was not found in your path or in /usr/local/bin. You may need' echo '#to copy it or add an explicit path to it in the following commands.' fi if which iptables >/dev/null ; then IPTABLESBIN=`which iptables | head -1` elif [ -x /sbin/iptables ]; then IPTABLESBIN='/sbin/iptables' elif [ -x /usr/local/bin/iptables ]; then IPTABLESBIN='/usr/local/bin/iptables' else IPTABLESBIN='iptables' echo '#iptables was not found in your path or in /usr/local/bin. You may need' echo '#to copy it or add an explicit path to it in the following commands.' fi NATBANGWARNING='' #For me... #export LOCALIPS="`ifconfig | grep 'inet addr' | awk '{print $2}' | sed -e 's/.*://'` 172.20.0.253 \${ppp0ADDR}" if [ -z "$LOCALNAMES" ]; then LOCALIPS=${LOCALIPS:-`ifconfig | grep 'inet addr' | awk '{print $2}' | sed -e 's/.*://'`} for ONEIP in $LOCALIPS ; do LOCALNAMES="$LOCALNAMES $ONEIP $ONEIP/32" for ONENAME in `egrep "^$ONEIP[^0-9]" /etc/hosts | tail --lines=1 | sed -e "s/^$ONEIP//"` ; do LOCALNAMES="$LOCALNAMES $ONENAME $ONENAME/32" done done fi #echo $LOCALNAMES #Variables that need to be reset for each line: COMMENT='' DISABLELINE='' BIDIRECTIONAL='' CHAINRULE='' ; NEXT='' REDIR='' ; REDIRPORT='' NEGATE='' CHAIN='' LOGME='' MASQME='' NATSPEC='' SRCIP='' ; DESTIP='' IFSPEC='' PROTOCOL='' SOURCEPARAM='' ; SOURCESPEC='' ; DESTPARAM='' ; DESTSPEC='' #Start of main loop. Read one iptables 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 while [ -n "$F1" ]; do #While there is another field to process in this line case "$F1" in /sbin/ipchains|ipchains|*/ipchains) CHAINRULE="$CHAINRULE $IPTABLESBIN" NEEDEDMODULES="$NEEDEDMODULES iptables" NEXT='' ; NEGATE='' ;; #*/ipchains) #We're not guaranteed iptables will be in the same dir. # CHAINRULE="$CHAINRULE `echo $F1 | sed -e 's@/ipchains$@/iptables@'`" # NEEDEDMODULES="$NEEDEDMODULES iptables" # NEXT='' ; NEGATE='' ;; #"!" always applies to the _following_ object. As the -x and --x try to handle ! in _their_ #parameters, this could be either "-s 192.168.0.1 ! www" or "! -f". Just remember it for the #moment and let individual choices handle it in a minute. !) #Negate the following object. "NEXT" stays as is. NEGATE=" !" ;; #---------- Single uppercase character options, alphabetically ---------- #ipchains -[ADC] chain rule-specification [options] #Append one or more rules to the end of the selected chain. When the source and/or destination names #resolve to more than one address, a rule will be added for each possible address combination. -A|--append) #Append this rule (1 param, handled here) CHAIN="$F2" CHAINRULE="$CHAINRULE $F1 ZZCHAINZZ" ; Fshift NEXT='' ; NEGATE='' ;; #ipchains -[ADC] chain rule-specification [options] #Check the given packet against the selected chain. This is extremely useful for testing, as the same #kernel routines used to check "real" network packets are used to check this packet. It can be used to #check user-defined chains as well as the builtin ones. The same arguments used to specify firewall #rules are used to construct the packet to be tested. In particular, the -s (source), -d (destination), #-p (protocol), and -i (interface) flags are compulsory. -C|--check) #Check if packet would be accepted or not (1 param, handled here) CHAIN="$F2" CHAINRULE="$CHAINRULE $F1 ZZCHAINZZ" ; Fshift NEXT='' ; NEGATE='' ;; #ipchains -[ADC] chain rule-specification [options] #ipchains -D chain rulenum [options] #Delete one or more rules from the selected chain. There are two versions of this command: the rule can #be specified as a number in the chain (starting at 1 for the first rule) or a rule to match. -D|--delete) #Delete this rule (1 or 2 params, needs NEXT support) CHAIN="$F2" CHAINRULE="$CHAINRULE $F1 ZZCHAINZZ" ; Fshift NEXT='APPEND' ; NEGATE='' ;; #ipchains -[LFZNX] [chain] [options] #Flush the selected chain. This is equivalent to deleting all the rules one by one. -F|--flush) #Flush the rules in this chain (0 or 1 params, needs NEXT support) CHAINRULE="$CHAINRULE $F1" NEXT='CHAIN' ; NEGATE='' ;; #ipchains -[RI] chain rulenum rule-specification [options] #Insert one or more rules in the selected chain as the given rule number. So, if the rule number is 1, #the rule or rules are inserted at the head of the chain. -I|--insert) #Insert this rule (1 or 2 params, needs NEXT support) CHAIN="$F2" CHAINRULE="$CHAINRULE $F1 ZZCHAINZZ" ; Fshift NEXT='APPEND' ; NEGATE='' ;; #ipchains -[LFZNX] [chain] [options] #List all rules in the selected chain. If no chain is selected, all chains are listed. It is legal to #specify the -Z (zero) option as well, in which case no chain may be specified. The exact output is #effected by the other arguments given. -L|--list) #List the rules in this chain (0 or 1 params, needs NEXT support) CHAINRULE="$CHAINRULE $F1" NEXT='CHAIN' ; NEGATE='' ;; #ipchains -M [ -L | -S ] [options] #This option allows viewing of the currently masqueraded connections (in conjuction with the -L option) #or to set the kernel masqerading parameters (with the -S option). -M|--masquerading) #Masquerading administration (used for -L and -S, 0 params, handled here) COMMENT="$COMMENT Remove -M." DISABLELINE='# ' NEXT='' ; NEGATE='' ;; #ipchains -[LFZNX] [chain] [options] #Create a new user-defined chain of the given name. There must be no target of that name already. #No need to adjust the chain name as it's never a builtin. -N|--new-chain) #Create a new chain (1 param, handled here) CHAINRULE="$CHAINRULE $F1 $F2" ; Fshift NEXT='' ; NEGATE='' ;; #ipchains -P chain target [options] #Set the policy for the chain to the given target. See the section TARGETS for the legal targets. Only #non-userdefined chains can have policies, and neither built-in nor user-defined chains can be policy #targets. -P|--policy) #Default policy for the chain (2 params, handled here) CHAIN="$F2" CHAINRULE="$CHAINRULE $F1 ZZCHAINZZ $F3" ; Fshift ; Fshift NEXT='' ; NEGATE='' ;; #ipchains -[RI] chain rulenum rule-specification [options] #Replace a rule in the selected chain. If the source and/or destination names resolve to multiple #addresses, the command will fail. Rules are numbered starting at 1. -R|--replace) #Replace a rule (2 params, handled here) CHAIN="$F2" CHAINRULE="$CHAINRULE $F1 ZZCHAINZZ $F3" ; Fshift ; Fshift NEXT='' ; NEGATE='' ;; #-S, --set tcp tcpfin udp #Change the timeout values used for masquerading. This command always takes 3 parameters, representing #the timeout values (in seconds) for TCP sessions, TCP sessions after receiving a FIN packet, and UDP #packets, respectively. A timeout value 0 means that the current timeout value of the corresponding #entry is preserved. This option is only allowed in combination with the -M flag. -S|--set) #Set timeouts for masquerading COMMENT="$COMMENT Remove -S $F2 $F3 $F4." Fshift ; Fshift ; Fshift DISABLELINE='# ' NEXT='' ; NEGATE='' ;; #ipchains -[LFZNX] [chain] [options] #Delete the specified user-defined chain. There must be no references to the chain (if there are you #must delete or replace the referring rules before the chain can be deleted). If no argument is given, #it will attempt to delete every non-builtin chain. #No need to adjust the chain name as it's never a builtin. -X|--delete-chain) # (1 param, handled here) CHAINRULE="$CHAINRULE $F1 $F2" ; Fshift NEXT='' ; NEGATE='' ;; #ipchains -[LFZNX] [chain] [options] #Zero the packet and byte counters in all chains. It is legal to specify the -L, --list (list) option #as well, to see the counters immediately before they are cleared; if this is done, then no specific #chain can be specified (they will all be displayed and cleared. -Z|--zero) #Zero out the counters (0 params) CHAINRULE="$CHAINRULE $F1" NEXT='' ; NEGATE='' ;; #---------- Single lowercase character options, alphabetically ---------- #Bidirectional mode. The rule will match with IP packets in both directions; this has the same effect #as repeating the rule with the source & destination reversed. -b|--bidirectional) #bidirectional mode BIDIRECTIONAL='YES' NEXT='' ; NEGATE='' ;; #-d, --destination [!] address[/mask] [!] [port[:port]] #Destination specification. See the desciption of the -s (source) flag for a detailed description of #the syntax. For ICMP, which does not have ports, a "destination port" refers to the numeric ICMP code. #The flag --dst is a convenience alias for this option. -d|--destination|--dst) #Specify packet destination (1 - 4 params, portspec must be stripped off, needs NEXT support) if [ "$F2" = "!" ]; then CHAINRULE="$CHAINRULE $F1 $F2 $F3" NATSPEC="$NATSPEC -d $F2 $F3" NATBANGWARNING='YES' Fshift ; Fshift #elif [ "$F2" = "0/0" ]; then #No need to add -d 0/0 anymore, but it doesn't hurt to leave it there # Fshift else CHAINRULE="$CHAINRULE $F1 $F2" NATSPEC="$NATSPEC -d $F2" DESTIP="$F2" Fshift fi NEXT='dport' ; NEGATE='' ;; #[!] -f, --fragment #This means that the rule only refers to second and furthur fragments of fragmented packets. Since #there is no way to tell the source or destination ports of such a packet (or ICMP type), such a packet #will not match any rules which specify them. When the "!" argument precedes the "-f" flag, the sense #is inverted. -f|--fragment) #Match second or further fragments (0 params, NEGATABLE) CHAINRULE="$CHAINRULE$NEGATE $F1" NEXT='' ; NEGATE='' ;; #-h Help. Give a (currently very brief) description of the command syntax. -h) #Show help (0 or 1 params) if [ "$F2" = "icmp" ]; then CHAINRULE="$CHAINRULE -p $F2 $F1" ; Fshift else CHAINRULE="$CHAINRULE $F1" fi NEXT='' ; NEGATE='' ;; #-i, --interface [!] name #Optional name of an interface via which a packet is received, or via which is packet is going to be #sent. When this option is omitted, the empty string is assumed, which has a special meaning and will #match with any interface name. When the "!" argument is used before the interface name, the sense is #inverted. If the interface name ends in a "+", then any interface which begins with this name will #match. -i|--interface) #Use this interface (1 or 2 params, handled here) CHAINRULE="$CHAINRULE ZZIFSPECZZ" if [ "$F2" = "!" ]; then IFSPEC="$F2 $F3" Fshift ; Fshift else IFSPEC="$F2" Fshift fi NEXT='' ; NEGATE='' ;; #-j, --jump target #This specifies the target of the rule; ie. what to do if the packet matches it. The target can be a #user-defined chain (not the one this rule is in) or one of the special targets which decide the fate of #the packet immediately. If this option is omitted in a rule, then matching the rule will have no #effect on the packets fate, but the counters on the rule will be incremented. #5.1.1.1. iptables takes away... #o -j MASQ: Masquerading packets #o -j REDIRECT: Redirecting packets to the local machine #o -j REJECT: ICMP repies for dropped packets* -j|--jump) #Jump to this chain or target (1 param, handled here) case "$F2" in DENY) CHAINRULE="$CHAINRULE $F1 DROP" ; Fshift NEXT='' ; NEGATE='' ;; MASQ) MASQME='YES' CHAINRULE="$CHAINRULE $F1 ACCEPT" ; Fshift NEXT='' ; NEGATE='' ;; REJECT) CHAINRULE="$CHAINRULE $F1 REJECT" ; Fshift NEEDEDMODULES="$NEEDEDMODULES ipt_REJECT" NEXT='' ; NEGATE='' ;; #FIXME ? REDIRECT) COMMENT="$COMMENT Unable to convert -j REDIRECT " DISABLELINE='# ' CHAINRULE="$CHAINRULE $F1 REDIRECT" ; Fshift NEXT='REDIRPORT' ; NEGATE='' ;; *) #Including ACCEPT and all user-defined chains CHAINRULE="$CHAINRULE $F1 $F2" ; Fshift NEXT='' ; NEGATE='' ;; esac ;; #Turn on kernel logging of matching packets. When this option is set for a rule, the Linux kernel will #print some information of all matching packets (like most IP header fields) via printk(). -l|--log) #log these packets LOGME='YES' NEEDEDMODULES="$NEEDEDMODULES ipt_LOG" NEXT='' ; NEGATE='' ;; #-m, --mark markvalue #Mark matching packets. Packets can be marked with a 32-bit unsigned value which may (one day) change #how they are handled internally. If you are not a kernel hacker you are unlikely to care about this. #If the string markvalue begins with a + or -, then this value will be added or subtracted from the cur- #rent marked value of the packet (which starts at zero). #FIXME - check to see if the MARK extension is simply a planned but currently unimmplemented feature. -m|--mark) # #CHAINRULE="$CHAINRULE " COMMENT="$COMMENT $F1 $F2 Removed." Fshift NEXT='' ; NEGATE='' ;; #Numeric output. IP addresses and port numbers will be printed in numeric format. By default, the pro- #gram will try to display them as host names, network names, or services (whenever applicable). -n|--numeric) #Numeric output CHAINRULE="$CHAINRULE $F1" NATSPEC="$NATSPEC -n" NEXT='' ; NEGATE='' ;; #-o, --output [maxsize] #Copy matching packets to the userspace device. This is currently mainly for developers who want to #play with firewalling effects in userspace. The optional maxsize argument can be used to limit the #maximum number of bytes from the packet which are to be copied. This option is only valid if the ker- #nel has been compiled with CONFIG_IP_FIREWALL_NETLINK set. #FIXME - can this be replaced with -j QUEUE somehow? -o|--output) #Copy packets to userspace device #CHAINRULE="$CHAINRULE " COMMENT="$COMMENT Removed $F1 " #DISABLELINE='# ' NEXT='MAXSIZE' ; NEGATE='' ;; #-p, --protocol[!] protocol #The protocol of the rule or of the packet to check. The specified protocol can be one of tcp, udp, #icmp, or all, or it can be a numeric value, representing one of these protocols or a different one. #Also a protocol name from /etc/protocols is allowed. A "!" argument before the protocol inverts the #test. The number zero is equivalent to all. Protocol all will match with all protocols and is taken #as default when this option is omitted. All may not be used in in combination with the check command. -p|--protocol) #Protocol (1 or 2 params, handled here) addprotoholder if [ "$F1" = "--protocol" ]; then F1="--proto" ; fi case "$F2" in "!") #CHAINRULE="$CHAINRULE $F1 $F2 $F3" #NATSPEC="$NATSPEC $F1 $F2 $F3" PROTOCOL="$F2 $F3" NATBANGWARNING='YES' Fshift ; Fshift ;; #Implicitly handles the case of "! all". If it's technically possible, _some_ bozo is going to do it. 0|all) Fshift ;; [Tt][Cc][Pp]) #CHAINRULE="$CHAINRULE $F1 $F2" #NATSPEC="$NATSPEC $F1 $F2" NEEDEDMODULES="$NEEDEDMODULES ipt_tcp" PROTOCOL="tcp" Fshift ;; [Uu][Dd][Pp]) #CHAINRULE="$CHAINRULE $F1 $F2" #NATSPEC="$NATSPEC $F1 $F2" NEEDEDMODULES="$NEEDEDMODULES ipt_udp" PROTOCOL="udp" Fshift ;; [Ii][Cc][Mm][Pp]) #CHAINRULE="$CHAINRULE $F1 $F2" #NATSPEC="$NATSPEC $F1 $F2" NEEDEDMODULES="$NEEDEDMODULES ipt_icmp" PROTOCOL="icmp" Fshift ;; *) #CHAINRULE="$CHAINRULE $F1 $F2" #NATSPEC="$NATSPEC $F1 $F2" PROTOCOL="$F2" Fshift ;; esac NEXT='' ; NEGATE='' ;; #-s, --source [!] address[/mask] [!] [port[:port]] #Source specification. Address can be either a hostname, a network name, or a plain IP address. The #mask can be either a network mask or a plain number, specifying the number of 1s at the left side of #the network mask. Thus, a mask of 24 is equivalent to 255.255.255.0. A "!" argument before the #address specification inverts the sense of the address. #The source may include a port specification or ICMP type. This can either be a service name, a port #number, a numeric ICMP type, or one of the ICMP type names shown by the command #ipchains -h icmp Note that many of these ICMP names refer to both a type and code, meaning that an ICMP #code after the -d flag is illegal. In the rest of this paragraph, a port means either a port specifi- #cation or an ICMP type. An inclusive range is can also be specified, using the format port:port. If #the first port is omitted, "0" is assumed; if the last is omitted, "65535" is assumed. #Ports may only be specified in combination with the tcp, udp, or icmp protocols. A "!" before the port #specification inverts the sense. When the check command is specified, exactly one port is required, #and if the -f (fragment) flag is specified, no ports are allowed. The flag --src is a convenience #alias for this option. -s|--source|--src) #Specify packet source (1 - 4 params, portspec must be stripped off, needs NEXT support) if [ "$F2" = "!" ]; then CHAINRULE="$CHAINRULE $F1 $F2 $F3" NATSPEC="$NATSPEC -s $F2 $F3" NATBANGWARNING='YES' Fshift ; Fshift #elif [ "$F2" = "0/0" ]; then #No need to add -s 0/0 anymore, but it doesn't hurt to leave it there # Fshift else CHAINRULE="$CHAINRULE $F1 $F2" NATSPEC="$NATSPEC -s $F2" SRCIP='' ; DESTIP='' SRCIP="$F2" Fshift fi NEXT='sport' ; NEGATE='' ;; #-t, --TOS andmask xormask #Masks used for modifying the TOS field in the IP header. When a packet matches a rule, its TOS field #is first bitwise anded with first mask and the result of this will be bitwise xored with the second #mask. The masks should be specified as hexadecimal 8-bit values. As the LSB of the TOS field must be #unaltered (RFC 1349), TOS values which would cause it to be altered are rejected, as are any rules #which always set more than TOS bit. Rules which might set multiple TOS bits for certain packets result #in warnings (sent to stdout) which can be ignored if you know that packets with those TOS values will #never reach that rule. Obviously, manipulating the TOS is a meaningless gesture if the rules target #is DENY or REJECT. -t|--TOS) #Set TOS masks COMMENT="$COMMENT $F1 $F2 $F3 Removed." Fshift ; Fshift NEXT='' ; NEGATE='' ;; #Verbose output. This option makes the list command show the interface address, the rule options (if #any), and the TOS masks. The packet and byte counters are also listed, with the suffix 'K', 'M' or 'G' #for 1000, 1,000,000 and 1,000,000,000 multipliers respectively (but see the -x flag to change this). #When used in combination with -M, information related to delta sequence numbers will also be listed. #For appending, insertion, deletion and replacement, this causes detailed information on the rule or #rules to be printed. -v|--verbose) #Extended/verbose output (0 params) CHAINRULE="$CHAINRULE $F1" NEXT='' ; NEGATE='' ;; #Expand numbers. Display the exact value of the packet and byte counters, instead of only the rounded #number in Ks (multiples of 1000) Ms (multiples of 1000K) or Gs (multiples of 1000M). This option is #only relevent for the -L command. -x|--exact) #Expand numbers CHAINRULE="$CHAINRULE $F1" NEXT='' ; NEGATE='' ;; #[!] -y, --syn #Only match TCP packets with the SYN bit set and the ACK and FIN bits cleared. Such packets are used to #request TCP connection initiation; for example, blocking such packets coming in an interface will pre- #vent incoming TCP connections, but outgoing TCP connections will be unaffected. This option is only #meaningful when the protocol type is set to TCP. If the "!" flag precedes the "-y", the sense of the #option is inverted. -y|--syn) #Syn flag set and ack cleared (0 params, NEGATABLE) addprotoholder CHAINRULE="$CHAINRULE$NEGATE --syn" NEEDEDMODULES="$NEEDEDMODULES ipt_tcp" NEXT='' ; NEGATE='' ;; #--destination-port [!] [port[:port]] #This allows separate specifiction of the ports. See the description of the -s flag for details. The #flag --dport is an alias for this option. --destination-port|--dport) #Destination port (1-2 params, all handled here) addprotoholder DESTPARAM="$F1" CHAINRULE="$CHAINRULE ZZDESTPARAMZZ ZZDESTSPECZZ" NATSPEC="$NATSPEC ZZDESTPARAMZZ ZZDESTSPECZZ" if [ "$F2" = "!" ]; then DESTSPEC="$F2 $F3" NATBANGWARNING='YES' Fshift ; Fshift else DESTSPEC="$F2" Fshift fi NEXT='' ; NEGATE='' ;; #--icmp-type [!] typename #This allows specification of the ICMP type (use the -h icmp option to see valid ICMP type names). This #is often more convenient to appending it to the destination specification. --icmp-type) #icmp type addprotoholder if [ "$F2" = "!" ]; then CHAINRULE="$CHAINRULE $F1 $F2 $F3" ; Fshift ; Fshift else CHAINRULE="$CHAINRULE $F1 $F2" ; Fshift fi NEEDEDMODULES="$NEEDEDMODULES ipt_icmp" NEXT='' ; NEGATE='' ;; #--source-port [!] [port[:port]] #This allows separate specifiction of the source port or port range. See the description of the -s flag #above for details.The flag --sport is an alias for this option. --source-port|--sport) #Source port (1-2 params, all handled here) addprotoholder SOURCEPARAM="$F1" CHAINRULE="$CHAINRULE ZZSOURCEPARAMZZ ZZSOURCESPECZZ" NATSPEC="$NATSPEC ZZSOURCEPARAMZZ ZZSOURCESPECZZ" if [ "$F2" = "!" ]; then SOURCESPEC="$F2 $F3" NATBANGWARNING='YES' Fshift ; Fshift else SOURCESPEC="$F2" Fshift fi NEXT='' ; NEGATE='' ;; \#*) #Append comments verbatim. while [ -n "$F1" ]; do CHAINRULE="$CHAINRULE $F1" Fshift done ;; *) case "$NEXT" in #FIXME - should we be clearing NEXT below, especially on APPEND? 'APPEND') #Just a generic parameter that needs to be appended. CHAINRULE="$CHAINRULE$NEGATE $F1" NEXT='' ; NEGATE='' ;; 'CHAIN') CHAIN="$F2" CHAINRULE="$CHAINRULE ZZCHAINZZ" ; NEXT='' ; NEGATE='' ;; 'MAXSIZE') #-o's maxsize. COMMENT="$COMMENT $F1." NEXT='' ; NEGATE='' ;; 'REDIRPORT') REDIRPORT="$F1" COMMENT="$COMMENT $F1." NEXT='' ; NEGATE='' ;; #ipfwadm->ipchains needed support for expanding multiple port specifications into multiple rules; ipchains->iptables doesn't. dport) addprotoholder DESTPARAM="--dport" CHAINRULE="$CHAINRULE ZZDESTPARAMZZ ZZDESTSPECZZ" NATSPEC="$NATSPEC ZZDESTPARAMZZ ZZDESTSPECZZ" if [ -n "$NEGATE" ]; then DESTSPEC="$NEGATE $F1" NATBANGWARNING='YES' else DESTSPEC="$F1" fi NEXT='' ; NEGATE='' ;; sport) addprotoholder SOURCEPARAM="--sport" CHAINRULE="$CHAINRULE ZZSOURCEPARAMZZ ZZSOURCESPECZZ" NATSPEC="$NATSPEC ZZSOURCEPARAMZZ ZZSOURCESPECZZ" if [ -n "$NEGATE" ]; then SOURCESPEC="$NEGATE $F1" NATBANGWARNING='YES' else SOURCESPEC="$F1" fi NEXT='' ; NEGATE='' ;; *) #Just return the field - we don't know what to do. CHAINRULE="$CHAINRULE$NEGATE $F1" NEXT='' ; NEGATE='' ;; esac esac Fshift done #---------- Chain and interface conversion logic ---------- #If IFSPEC unset, do not set it but suggest. #If CHAIN unset, no problem; there will be no ZZCHAINZZ placeholder so the variable will be ignored #Missing src or destip handled by islocalip / suggest. #Hmmm... This is my best read on the way to convert the rules: # --------Given--------, ----------Set---------------- # | | | | # SRCIP DESTIP CHAIN NEW CHAIN NEW INTERFACE # (any) (any) forward FORWARD -o $IFSPEC (suggest -i if-of-src-ip) (never a local src or local dest ip) # local local input INPUT -i $IFSPEC (probably lo) # local local output OUTPUT -o $IFSPEC (probably lo) # local local user (leave as is) -i $IFSPEC or -o $IFSPEC (probably lo) # local not (any) OUTPUT -o $IFSPEC (never an ipchains input rule, just output or user) # not local (any) INPUT -i $IFSPEC (never an ipchains output rule, just input or user) # not not input FORWARD -i $IFSPEC (suggest -o if-of-dest-ip) # not not output FORWARD -o $IFSPEC (suggest -i if-of-src-ip) # not not user FORWARD (suggest -i if-of-src-ip -o if-of-dest-ip) # $SRCIP $DESTIP $CHAIN CHAIN= IFSPEC= case $CHAIN in input) CHAIN='INPUT' ;; output) CHAIN='OUTPUT' ;; forward) CHAIN='FORWARD' ;; esac if [ "$CHAIN" = "FORWARD" ]; then #----Rule is already a forward rule---- if [ -n "$IFSPEC" ]; then IFSPEC="-o $IFSPEC" ; else suggestif "-o" "$DESTIP" ; fi suggestif "-i" "$SRCIP" elif islocalip $SRCIP ; then if islocalip $DESTIP ; then #----Both SRCIP and DESTIP local---- case $CHAIN in INPUT) CHAIN="INPUT" if [ -n "$IFSPEC" ]; then IFSPEC="-i $IFSPEC" ; else suggestif "-i" "$SRCIP" "lo" ; fi ;; OUTPUT) CHAIN="OUTPUT" if [ -n "$IFSPEC" ]; then IFSPEC="-o $IFSPEC" ; else suggestif "-o" "$DESTIP" "lo" ; fi ;; *) if [ -n "$IFSPEC" ]; then IFSPEC="-i $IFSPEC" COMMENT="$COMMENT \"-i $IFSPEC\" may need to be \"-o $IFSPEC\"." else suggestif "-i" "$SRCIP" ; suggestif "-o" "$DESTIP" fi ;; esac else #----Only SRCIP local---- CHAIN="OUTPUT" if [ -n "$IFSPEC" ]; then IFSPEC="-o $IFSPEC" ; else suggestif "-o" "$DESTIP" ; fi fi else #----SRCIP is not local---- if islocalip $DESTIP ; then #Only DESTIP local CHAIN="INPUT" if [ -n "$IFSPEC" ]; then IFSPEC="-i $IFSPEC" ; else suggestif "-i" "$SRCIP" ; fi else #----Neither SRCIP nor DESTIP local---- case $CHAIN in INPUT) CHAIN="FORWARD" if [ -n "$IFSPEC" ]; then IFSPEC="-i $IFSPEC" ; else suggestif "-i" "$SRCIP" ; fi suggestif "-o" "$DESTIP" ;; OUTPUT) CHAIN="FORWARD" if [ -n "$IFSPEC" ]; then IFSPEC="-o $IFSPEC" ; else suggestif "-o" "$DESTIP" ; fi suggestif "-i" "$SRCIP" ;; *) CHAIN="FORWARD" suggestif "-i" "$SRCIP" ; suggestif "-o" "$DESTIP" if [ -n "$IFSPEC" ]; then COMMENT="$COMMENT Originally \"-i $IFSPEC\"." IFSPEC="" fi ;; esac fi fi case $PROTOCOL in #iptables can't use --sport for icmp. [Ii][Cc][Mm][Pp]) SOURCEPARAM="--icmp-type" DESTPARAM="" if [ -n "$DESTSPEC" ]; then SOURCESPEC="$SOURCESPEC/$DESTSPEC" DESTSPEC="" fi ;; esac #echo 1 $CHAIN 2 $IFSPEC 3 $PROTOCOL 4 $SOURCEPARAM 5 $SOURCESPEC 6 $DESTPARAM 7 $DESTSPEC CHAINRULE=`echo $CHAINRULE | sed -e "s@ZZCHAINZZ@$CHAIN@g" \ -e "s@ZZIFSPECZZ@$IFSPEC@g" \ -e "s@ZZPROTOZZ@$PROTOCOL@g" \ -e "s@ZZSOURCEPARAMZZ@$SOURCEPARAM@g" \ -e "s@ZZSOURCESPECZZ@$SOURCESPEC@g" \ -e "s@ZZDESTPARAMZZ@$DESTPARAM@g" \ -e "s@ZZDESTSPECZZ@$DESTSPEC@g" ` NATSPEC=`echo $NATSPEC | sed -e "s@ZZPROTOZZ@$PROTOCOL@g" \ -e "s@ZZSOURCEPARAMZZ@$SOURCEPARAM@g" \ -e "s@ZZSOURCESPECZZ@$SOURCESPEC@g" \ -e "s@ZZDESTPARAMZZ@$DESTPARAM@g" \ -e "s@ZZDESTSPECZZ@$DESTSPEC@g" ` if [ -n "$COMMENT" ]; then CHAINRULE="$CHAINRULE ###$COMMENT" ; fi #Output the rule. ipchains only allows a single portspec so we don't need to handle looping through multiple source and dest ports. if [ "$MASQME" = "YES" ]; then echo $IPNATCTLBIN -I $NATSPEC -b source -m masquerade fi if [ "$LOGME" = "YES" ]; then if [ -z "`echo $CHAINRULE | grep ' -j '`" ]; then echo "$DISABLELINE$CHAINRULE -j LOG" else echo "$DISABLELINE$CHAINRULE" | sed -e 's/ -j [^ ]*/ -j LOG/' fi fi echo "$DISABLELINE$CHAINRULE" if [ "$BIDIRECTIONAL" = "YES" ]; then #Probably not a good choice with --syn, but hey, if it worked for them in ipchains... #-d|--destination|--dst <-> -s|--source|--src #--destination-port|--dport <-> --source-port|--sport #-i|--interface <-> -o, --out-interface CHAINRULE=`echo "$CHAINRULE" | \ sed \ -e 's/ -d / ZZHOLDZZ /' -e 's/ -s / -d /' -e 's/ ZZHOLDZZ / -s /' \ -e 's/ --destination / ZZHOLDZZ /' -e 's/ --source / --destination /' -e 's/ ZZHOLDZZ / --source /' \ -e 's/ --dst / ZZHOLDZZ /' -e 's/ --src / --dst /' -e 's/ ZZHOLDZZ / --src /' \ -e 's/ --destination-port / ZZHOLDZZ /' -e 's/ --source-port / --destination-port /' -e 's/ ZZHOLDZZ / --source-port /' \ -e 's/ --dport / ZZHOLDZZ /' -e 's/ --sport / --dport /' -e 's/ ZZHOLDZZ / --sport /' \ -e 's/ -i / ZZHOLDZZ /' -e 's/ -o / -i /' -e 's/ ZZHOLDZZ / -o /' \ -e 's/ --interface / ZZHOLDZZ /' -e 's/ --out-interface / --interface /' -e 's/ ZZHOLDZZ / --out-interface /'` NATSPEC=`echo "$NATSPEC" | \ sed \ -e 's/ -d / ZZHOLDZZ /' -e 's/ -s / -d /' -e 's/ ZZHOLDZZ / -s /' \ -e 's/ --destination / ZZHOLDZZ /' -e 's/ --source / --destination /' -e 's/ ZZHOLDZZ / --source /' \ -e 's/ --dst / ZZHOLDZZ /' -e 's/ --src / --dst /' -e 's/ ZZHOLDZZ / --src /' \ -e 's/ --destination-port / ZZHOLDZZ /' -e 's/ --source-port / --destination-port /' -e 's/ ZZHOLDZZ / --source-port /' \ -e 's/ --dport / ZZHOLDZZ /' -e 's/ --sport / --dport /' -e 's/ ZZHOLDZZ / --sport /'` if [ "$MASQME" = "YES" ]; then #Bidirectional masq? Aughhhhhhhhh! echo $IPNATCTLBIN -I $NATSPEC -b source -m masquerade fi if [ "$LOGME" = "YES" ]; then if [ -z "`echo $CHAINRULE | grep ' -j '`" ]; then echo "$DISABLELINE$CHAINRULE -j LOG" else echo "$DISABLELINE$CHAINRULE" | sed -e 's/ -j [^ ]*/ -j LOG/' fi fi echo "$DISABLELINE$CHAINRULE" fi COMMENT='' DISABLELINE='' BIDIRECTIONAL='' CHAINRULE='' ; NEXT='' REDIR='' ; REDIRPORT='' NEGATE='' CHAIN='' LOGME='' MASQME='' NATSPEC='' SRCIP='' ; DESTIP='' IFSPEC='' PROTOCOL='' SOURCEPARAM='' ; SOURCESPEC='' ; DESTPARAM='' ; DESTSPEC='' done if [ -n "$NEEDEDMODULES" ]; then echo '#The following modules may be needed - insert by hand if not autoloaded:' echo "$NEEDEDMODULES" | tr ' ' '\012' | sort | uniq | grep -v '^$' | sed -e 's/^/#/' fi if [ "$NATBANGWARNING" = "YES" ]; then echo '#One or more of the above ipnatctl rules has an exclamation point in it' echo '#which, in iptables, negates the specification. At this time, though,' echo '#ipnatctl does not support negated specifications. Please fix.' fi #---------- Graveyard: ---------- #Global Initialize: #ACCOUNTINGPREPARED='' #Function: #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 #} #Per line initialize: #ACCTDIR='both' #SOURCEPORT='' ; DESTPORT='' #MASQ='' #ipfwadm options: # -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='' ;; # -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='' ;; # -m) #Masquerade this traffic # MASQ='YES' ; NEXT='' ;; #Next fields: # case "$NEXT" in # 'ACCTDIR') # ACCTDIR="$F1" ; NEXT='' ;; # "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='' ; NEGATE='' ;; #Pre-output processing: #Replace Policy and Chain placeholders # if [ "$REDIR" = "YES" ]; then # if [ -n "$REDIRPORT" ]; then # POLICY="REDIRECT $REDIRPORT" # else # POLICY="REDIRECT" # fi # fi # CHAINRULE=`echo $CHAINRULE | sed -e "s/ZZPOLICYZZ/$POLICY/g" \ # -e "s/ZZCHAINZZ/$CHAIN/g"` # 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 # if [ "$MASQ" = "YES" ]; then # POLICY="MASQ" # fi #Output with looping through portspecs: # 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