#!/bin/bash cat </dev/null (The above line allows me to put the documentation right in the script... Cool, eh? Yes, I know I should break it up....) >>>>>>>>>>>>>>>If you read nothing else, read this<<<<<<<<<<<<<<<< This program offers an aid to creating firewall rules. It offers ABSOLUTELY NO intelligence in deciding what should be allowed or disallowed. It has ABSOLUTELY NO ability to understand your security policy and implement it. YOU are responsible for reviewing the rules and massaging them to fit your needs. As the GNU GPL states, 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. Mason builds a wall ... what else? Copyright 1998 William Stearns This code is entirely owned by William Stearns (wstearns@pobox.com) and has no relation to any employer or employer sponsored project. The impatient can find a "Quick Start" section below. Background and motivation: The built-in firewall features of the Linux kernel offer a powerful set of packet filtering features that can be used to build a firewall. The various pieces of available documentation provide an introduction on how to configure the firewall for simple setups, but can't possibly explain how to configure a firewall for more complex setups, including fine-grained allow and deny lists. This is especially obvious when trying to create a firewall with a default policy of deny. Someone looking to configure a linux firewall is simultaneously hit with the complexity of trying to understand the ipfwadm syntax, trying to understand the structure of TCP/IP connections, and trying to create and implement a security policy. No wonder firewalls are daunting! The mason application you're looking at attempts to handle the first two problems by dynamically creating the firewall based on the traffic flowing through it. For example, if you start up a telnet session through your firewall from a machine on your LAN to a machine out on the WAN while mason is running, mason will create all the rules necessary to allow this traffic. Conversely, if you're looking to block incoming NFS requests, simply launch mason, make the NFS connection, and change the output rules to deny rules. When the firewall is restarted, voila! No more incoming NFS. Creating a firewall no longer requires understanding the ipfwadm syntax. Even novices can create a firewall under Linux. _HOWEVER_, creating a _good_ firewall _still_ requires some understanding of TCP/IP protocols and packet filtering. Many good books cover this. Check out O'Reilly and Associates (www.ora.com or www.oreilly.com) for some excellent general coverage of firewall designs. Basic theory of operation: Before starting, if the user has some rules that he or she knows should be used in this machine, the user can implement them. The last rules are the ones that log all other packets to /var/log/messages. The "tail" command is used to feed the log messages in this script. The script converts each log entry into the corresponding command necessary to allow that kind of traffic. In the previous telnet example, 6 different firewall rules would be created on the firewall, three for the original request packet, 3 for the response back from the server: pkt 1: Allow telnet request in from LAN pkt 1: Forward request through system pkt 1: Allow request to exit to WAN pkt 2: Allow telnet response back into machine from WAN pkt 2: Forward response through system pkt 2: Allow response to exit back to the original machine on the LAN. All packets from 3 on are handled by these rules. There may be a short delay in the initial connection. The script creates the actual ipfwadm commands to accomodate the packet flow. When the command is executed the new rule is inserted at the head of the existing rules so that future packets of this type no longer reach the logging rule at the bottom. The rules are also echoed to the console so that you can see the rules as they are executed or redirect them to a file. I prefer the latter; this allows me to go back later to review the rules and massage them. Special considerations - PLEASE read: Kernel: IP firewalling and firewall packet logging have to be compiled into the kernel. To see if IP firewalling is compiled into your kernel, type the command: ipfwadm -F -l -e (while you're root) If you get "command not found", you're either not root or you haven't installed the ipfwadm package. See if it's included in your distribution. It's definitely included in RedHat 4.1 and higher. ipfwadm 2.3.0 has been around for a long time and is stable. If you get something like "/proc/net/ip_forward not found", your kernel does not support ipfwadm firewalling. One of the following three is true: - Your kernel is too old. It appears that linux firewalling switched from the old "ipfw" firewalling in 1.3.66, but some features require 2.0.0. - Your kernel is too new. Somewhere between 2.1.101 and 2.1.104 the kernel switched over from "ipfwadm" firewalling to "ipchains" firewalling. At some point I'll add a command line option to choose ipfwadm or ipchains. - You have the right version of the kernel, but firewalling is not enabled. You must recompile the kernel and turn on firewalling. See the HOWTO's at http://sunsite.unc.edu/linux/HOWTO to see how this is done. In particular, see the masquerading and kernel HOWTO's. To see if firewall packet logging is enabled in your kernel, type the following command: ipfwadm -a deny -F -S 127.12.2.3/32 -D 127.12.2.4/32 -o The "-o" at the end tells the kernel to log this particular packet type (one which should never show up). If your kernel does not support logging, I _think_ you would get an error. On the other hand, I've never had a kernel that has firewalling but does not have logging. DNS: If the firewall or one of the machines behind it is a DNS server, you have a situation where mason issues a steady flow of DNS requests to resolve the machine names and each DNS request requires a new rule, which in turn requires more DNS requests... ugh. There are a couple of ways around this: - Write the correct rules for DNS lookup for your particular setup. - Use trusted external DNS servers, ie servers that do not have to resolve through your firewall. This reduces the number of rules necessary to handle DNS to just a few. - Put the names of all relevant hosts in /etc/hosts. Mason uses this file before going out to DNS to try to minimize the snowball effect when it occurs. - Comment out the DNS lookup code in Mason. At some point this will be command line configurable, but not quite yet. - Insert general rules for DNS in your rule set. If you're not sure what these should be, the following six rules should allow all DNS requests from anywhere to anywhere. Please note that depending on your security policy, this may be too general and should be reviewed. ipfwadm -I -i accept -S 0/0 53 -P udp ipfwadm -I -i accept -D 0/0 53 -P udp ipfwadm -O -i accept -S 0/0 53 -P udp ipfwadm -O -i accept -D 0/0 53 -P udp ipfwadm -F -i accept -S 0/0 53 -P udp ipfwadm -F -i accept -D 0/0 53 -P udp Note that I don't include tcp dns zone transfers here. These transfers are generally rare and between a few machines. These are good candidates for having explicit rules added by mason. Rule order: When a packet needs to be processed (at entry, forwarding, or exit), the firewall scans the existing list of rules to decide whether to allow, deny or reject the packet. As this scans stops at the first rule that matches the packet, the order in which your final firewall rules are executed can make a difference. This document does not cover how to order your rules - sorry. The best place to find out about this is in the O'Reilly and associates books. Generalization: When a rule is created, it covers packet transfer between specific ports on specific machines. For example: ipfwadm -i accept -W ppp0 -I -P tcp -S linux.kernel.org/32 ftp -D \ devel1.goober.net/32 1024:65535 # ftp/tcp If you wanted to also allow this machine to reach any other ftp server in the world, you might want to edit this rule and remove "-S linux.kernel.org/32" (remember that a missing source or destination port or address are the equivalent of "anywhere". If you simply wanted to allow more than one machine to get to linux.kernel.org, you could replace "-D devel1.goober.net/32" with "-D 210.134.12.0/24" (the network address block that covers the machines in question). This generalization could also be for protocols. If you wanted the users on devel1.goober.net to be able to reach linux.kernel.org with any protocol, simply remove the "ftp" keyword in the command. The port used at the goober.net end would still have to be one of the high ports (1024 to 65535), but they could talk to any port (ftp, smtp, http, telnet, etc.) at the linux.kernel.org end. Router or end node: This program was originally intended for use on a traditional firewall - a router (linux box that connects 2 or more networks through one or more interfaces) that does packet filtering. It works equally well on Linux boxes with only one interface. These could be workstations on a LAN, servers outside of your firewall, or even slip or ppp connected workstations. The number of interfaces and their type and speed are irrelevant to the firewall creation process. Slow machines or fast nics As a shell script, Mason is much less efficient at its work than a C app would be. On my 486sx-33, it can take a couple of seconds from the time the log entry is fed into it until the ipfwadm rule is implemented. If the system is slow or if it has a lot of packets traveling through it, it can take Mason a long time to catch up. If this is the case, start slow. Try one connection type at a time and give the system a chance to settle before you move on. In the step by step instructions below, I suggest turning on packet logging for input, forward, and output filters at the same time (see the three almost identical ipfwadm lines below with the "-o" at the end). If Mason is having trouble keeping up, you might want to start off with just one of those lines (say "input" or "-I"). Run Mason for a little while to build up the input rules. Then turn on the "forward" rules, etc. If you take this approach, make sure you run the same kinds of traffic through the system at every step. Active hacking while mason running: If at all possible, try to set up these rules in a controlled environment. Hook up your firewall to machines that simulate the routers and networks that will be used in its final location. It is not a good idea to create a firewall in an environment not completely under your control. If you must create the firewall rules in a live environment be warned: Mason simply creates rules based on what traffic is passing through it. IT CANNOT DISTINGUISH BETWEEN THE TRAFFIC YOU'RE CREATING TO TEACH IT AND SOMEONE ACTIVELY TRYING TO HACK THROUGH YOUR FIREWALL. IF THIS HAPPENS, MASON WILL CREATE RULES THAT _SPECIFICALLY_ _ALLOW_ PEOPLE TO GET BACK IN LATER. _Please_ read and try to understand the rules before you put them to use in a production environment. (I hate all caps too, but the "boldface" button on my keyboard is jammed :-). The "hacker" mentioned above does not need to be a computer criminal in a far-off country. This individual could be someone in accounting that is (without malicious intent) connecting to an Internet IRC server, even though this doesn't fit in the security policy you're trying to implement. If you don't read and understand the rules Mason spits out, you may very well leave an explicit opening for this user's future IRC use. Doesn't teach what to block or allow: One more time: Mason _does_ _not_ understand the traffic flowing through your firewall; it just creates the rules that you can later use to specifically allow or disallow this traffic. Masquerading: One of the common uses for Linux firewalling is to act not only as a packet filter but also as a masquerading host, allowing multiple machines to share a single IP address. In this setup, simply create the masquerading forwarding rule on the firewall before you run Mason. Mason will simply accept the forwarding specification you've made and create input and output rules around it. Mason is actually even more useful in this case as the packet rules are even more confusing when packets are being rewritten under you. See the masquerading HOWTO to see how this rule is created. Offline creation: If you are especially cautious, you might not want Mason actively creating rules on your production server. Or maybe you think you've created a good firewall, but keep getting log messages and don't know how to create the matching rules. Or perhaps your CPU can't keep up. In all of the above circumstances, Mason can create the commands without actually being fed the log messages live. For example, if you have packet logging entries in /var/log/messages, try this: cat /var/log/messages | grep 'IP fw-' | mason The output can, of course, be tee'd, redirected to a file, piped to less, etc. "... | sort | uniq" can be useful too when you're not converting it live. Obviously, the source file can be one that has been transferred from another machine. One final use for this technique is creating the rules when you're not root. Simply edit the script to change DOCOMMAND="YES" to DOCOMMAND="NO" and the script will still output the appropriate ipfwadm commands but won't try to execute them, allowing non-root users to create the firewall rules. Note that you still need to be root long enough to turn on some kind of logging, or /var/log/messages will never contain any entries to convert. Root privileges are also required to implement the rules once you've created them. /etc/services: Mason converts the protocol number and type (i.e. 53, udp) into the more common name (domain, in this example). It uses the /etc/services file to do make this conversion. Before you start, make sure all the protocols you will work with are listed there. If a particular protocol is not in that file, Mason will simply leave it as a numeric entry. Having this entry is especially important if you are working with services whose ports are >= 1024 (nfs, X, squid, irc, vdolive, etc.). If a service >= 1024 is not found in /etc/services, it will be automatically (and incorrectly) generalized to the port range of 1024-65535. If your favourite service isn't in there, simply edit the file and add it in the same format as the other entries. If you plan to do the conversion on one machine and actually run the firewall on another, make sure all of the protocols used are listed in the /etc/services on both machines. ftp: Ahhh, yes, ftp. The scourge of firewall creators everywhere. Ftp starts off well because the client opens a connection from a high port (1024-65535) to the ftp control port 21. This part of the connection follows the same model as other tcp protocols: client uses a random high port and connects to a fixed low port. The problem arises when it's time to actually transmit data. The client and server exchange directory listings and files over additional tcp connections that are between a random high port at the client end and a random high port at the server end. Remember that packet filtering firewalls depend on being able to identify connections by their (generally low) server port. Here we have connections that need to be allowed if ftp is going to work, but can't be identified. It really comes down to a choice: does the firewall allow ftp traffic (leaving at least one high to high rule which is a generally considered a security risk), or do we block ftp? You'll need to decide. Mason creates these rules as transparently as any others. It opens up the ports for the control channel and the high to high rule (called the data channel). A single ftp connection could therefore open 12 rules. Insert vs. append: Ipfwadm has two ways of adding rules: at the beginning of the rule list using insert ("-i"), or at the end of the list using append ("-a"). The usual way of creating the firewall is to flush the existing rules and then add each of the rules using append so they will be kept in the same order in which they were run. For this reason, the rules that Mason spits out to stdout use "append" so they can easily be put in a rule set. Mason needs some way to tell the kernel to not log already logged packets anymore. The way to do this is to put a matching rule before the logging rule. Unfortunately, that means one of two things: deleting the logging rule at the end, implementing the new rule at the end, and reinstating the logging rule, or simply inserting the new rule at the top of the list. The first option is tricky to do well. It's also a bad choice because the user using mason may not be logging everything, so mason doesn't know what logging rule to reinstate. That leaves using "-i" to insert the rule at the very top of the list. The end effect is that the rules that Mason displays use "-a" to match how that would be put into a rule file, but the rules that are actually implemented while Mason is running use "-i" to avoid relogging those packets in the future. It's my understanding that ipchains allows one to insert rules into a specific location in the list. This would get around this quirk of ipfwadm. Allow versus deny and reject: To be written; allow user to change on the fly with a flag file. Input, Output, and Forwarding: To implement packet filtering, the Linux kernel needs to inspect each packet at at least one of the following three times: when the packet enters the system, as it passes through the system on the way to its exit interface, and as it leaves the system. At each of those three times, the kernel can decide to allow or deny/reject the packet. The rules can be different at each stage - it's perfectly legal to, for example, allow it in, allow it to be forwarded, but then block it at the last second before it leaves the system. A simple firewall could be implemented using just, say, input rules(*). It's when you get complex firewalls that having rules at all three stages is useful. You might want to allow hosts from eth0 to get to a pop-3 server on eth1, but not allow hosts from eth2 to get to the same server. This kind of restriction might be impossible to do without forwarding rules, especially if eth2 hosts _should_ be allowed to get to a pop-3 server on eth0. Anyways, if you want less than the imposing granduer of a firewall ruleset that goes on for pages and pages, Mason can accomodate you. If you just want input rules, follow the instructions below, but only run the logging rule for input ("ipfwadm -I -a deny -o"). If you just want input and forwarding rules, just log input and forwarded packets. You might even take an approach such as allowing unrestricted access between the hosts on eth0 and eth1 and the firewall itself, but wanting tight control over what passes in and out of eth2. Instead of taking one of the canned logging rules below, make up your own, such as: ipfwadm -I -W eth2 -a deny -o ipfwadm -O -W eth2 -a deny -o Mason will only create rules corresponding to what you're actively logging, allowing you room to be a firewall artist. (*) The exceptions to this are the special rules for redirecting packets (which must be done as an input rule), and masquerading packets, (which must be done as a forwarding rule). Even in the cases where you wish to use these facilities, it's still legal to implement packet filtering using another rule type. Limitations and Ideas: - Mason only does ipfwadm rules. At some point I'll add a command line option to do ipchain rules as these will be the default in kernel 2.2. Don't hold your breath for ipfw rules; is there anyone that is actively creating firewalls based on these? - I don't implement flags as I don't understand how they get logged. I would like to implement -y or -k flags to further restrict the direction in which connections get created. - I do not use "-b" (bidirectional) rules so that I can later implement the -y and -k rules. - run newrules, then append to it - group local machines into subnet rule (configurable) - group foreign machines into additional rule? - pad if and proto fields to line up - have flag file with current policy and quick scripts to change it so the current policy can be changed on the fly. Quick start: - compile a kernel with firewall and firewall logging enabled, boot into it. - run the following ONLY IF you want to start with an empty set of rules (if you simply want to fill in the gaps of your current rule set, do NOT run the next three commands which erase all existing rules): ipfwadm -I -f ipfwadm -O -f ipfwadm -F -f - Set any custom firewall rules you wish. Here is where you might put in a masquerading forwarding rule if that is one of the uses of this firewall. - If you have not already put in rules for allowing DNS requests through your firewall, put them in now. I offer the following rules as a general way to allow DNS requests through, but as I mentioned above, these may be way too general for security. Note that these rules would allow someone from the outside world to make requests of a nameserver running on your firewall or on your LAN. A cracker with root access could actually use the following rules to get to arbitrary services on your LAN or the firewall. Please think about what you really want to accomplish before using these in the final production environment. ipfwadm -I -i accept -S 0/0 53 -P udp ipfwadm -I -i accept -D 0/0 53 -P udp ipfwadm -O -i accept -S 0/0 53 -P udp ipfwadm -O -i accept -D 0/0 53 -P udp ipfwadm -F -i accept -S 0/0 53 -P udp ipfwadm -F -i accept -D 0/0 53 -P udp # ipfwadm -O -i accept -W ppp0 -P udp -D 0/0 53 # ipfwadm -I -i accept -W ppp0 -P udp -S 0/0 53 - in one window, do tail --lines=0 -f /var/log/messages | mason | tee -a newrules - To actaully start logging packets, switch to another window and run: ipfwadm -I -a deny -o ipfwadm -F -a deny -o ipfwadm -O -a deny -o (see the section "Input, Output, and Forwarding" for examples of how to get a smaller set of rules or only rules of a certain type). This will start the kernel logging packets into /var/log/messages. Since no other rules (except for masquerading and DNS) have been defined, _all_ other packets will be logged. See the above documentation if your machine is too slow to keep up with the initial flood of logged packets; you may wish to execute these one at a time, waiting for the load to settle a bit before implementing the next. When a packet is logged, the corresponding ipfwadm rule will be simultaneously executed, displayed on the terminal, and appended to newrules for later editing. - To watch the fireworks, do: tail -f --lines=0 /var/log/messages newrules in another window. - At this point, start making the connections of the type that you'd like to allow in the production environment. Mason will spit out the appropriate rules for the traffic you're creating. - When you've gotten all the rules you want, press Ctrl-C in the window running mason. If you're going to be working on these rules for a while and don't want to fill up your logs with additional messages, you might want to either delete the logging rules or flush the firewall entirely. These are done, respectively, with the following commands: ipfwadm -I -d deny -o ipfwadm -F -d deny -o ipfwadm -O -d deny -o or ipfwadm -I -f ipfwadm -O -f ipfwadm -F -f - I find the upcoming editing to be easier if similar rules are placed next to each other. Here's how: cat newrules | sort -t '#' +1 >>edited_rules Strictly speaking, this sorts the rules according to the comments at the end of the line. This has the effect of placing similar rules together as the comments indicate the rule type. Make sure you run this after adding any new rules to "newrules". Edit the edited_rules file to generalize and reorder the rules. If this is the complete set of rules for your environment, you might be able to get away with creating the following wrapper script to create a full firewall: ---- cut here ---- firewall.run ---- cut here ---- #!/bin/bash /sbin/ipfwadm -I -f /sbin/ipfwadm -O -f /sbin/ipfwadm -F -f /sbin/ipfwadm -I -p def_policy* /sbin/ipfwadm -O -p def_policy* /sbin/ipfwadm -F -p def_policy* [place any rules you want to appear before the generated rules here. These might include the masquerading rule and/or DNS rules] . ./edited_rules [place any rules you want to appear after the generated rules here. These might include any logging rules] ---- cut here ---- firewall.run ---- cut here ---- * def_policy is either deny or accept, as appropriate for your firewall. All three of the files should be hidden from public view by executing: chmod 700 firewall.run edited_rules newrules The firewall can be started automatically at boot time by adding the following line to /etc/rc.d/rc.local (or the appropriate boot script for your linux): /path/to/firewall.run - Bill Stearns "read" bash function syntax read [-r] [name ...] One line is read from the standard input, and the first word is assigned to the first name, the sec- ond word to the second name, and so on, with left- over words assigned to the last name. Only the characters in IFS are recognized as word delim- iters. If no names are supplied, the line read is assigned to the variable REPLY. The return code is zero, unless end-of-file is encountered. If the -r option is given, a backslash-newline pair is not ignored, and the backslash is considered to be part of the line. The following line is the end of the text and the start of the code. EOTEXT1 #DEBUG="YES" DEBUG="NO" #ECHOCOMMAND="NO" #DOCOMMAND="NO" ECHOCOMMAND="YES" DOCOMMAND="YES" LAST1="" LAST2="" LAST3="" LAST4="" LAST5="" CURRENT="" #FIXME - break up into read field1, field2, etc. read MESSAGE while [ "${MESSAGE}" != "" ]; do unset COMMENT DESTHOST DESTIP DESTPORT DIR IF PROTO SRCHOST SRCIP SRCPORT MESSAGE=`echo ${MESSAGE} | grep ' kernel\: ' \ | sed -e 's/.* kernel\: //' \ | grep '^IP fw\-'` if [ "${DEBUG}" = "YES" ]; then echo message= ${MESSAGE} ; fi if [ "${MESSAGE}" != "" ]; then case `echo ${MESSAGE} | awk '{print $2}'` in fw-out) DIR='O' ;; fw-in) DIR='I' ;; fw-fwd) DIR='F' ;; *) echo Huh? X`echo ${MESSAGE} | awk '{print $2}'`X ;; esac IF=`echo ${MESSAGE} | awk '{print $4}'` PROTO=`echo ${MESSAGE} | awk '{print $5}' | tr A-Z a-z` SRCIP=`echo ${MESSAGE} | awk '{print $6}' | sed -e 's/\:.*//'` SRCPORT=`echo ${MESSAGE} | awk '{print $6}' | sed -e 's/.*\://'` DESTIP=`echo ${MESSAGE} | awk '{print $7}' | sed -e 's/\:.*//'` DESTPORT=`echo ${MESSAGE} | awk '{print $7}' | sed -e 's/.*\://'` if [ `echo ${IF} | wc --bytes` -lt 5 ]; then IF=`echo "${IF} " | cut -b 1-4` fi #Configurable name lookup? SRCHOST=`cat /etc/hosts | egrep "^${SRCIP}[^0-9]" | awk '{print $2}'` if [ "${SRCHOST}" != "" ]; then SRCIP=${SRCHOST} elif [ "${SRCPORT}" != "53" -a "${DESTPORT}" != "53" ]; then SRCHOST=`host ${SRCIP} | grep '^Name' | sed -e 's/.* //'` if [ "${SRCHOST}" != "" ]; then SRCIP=${SRCHOST} fi fi DESTHOST=`cat /etc/hosts | egrep "^${DESTIP}[^0-9]" | awk '{print $2}'` if [ "${DESTHOST}" != "" ]; then DESTIP=${DESTHOST} elif [ "${SRCPORT}" != "53" -a "${DESTPORT}" != "53" ]; then DESTHOST=`host ${DESTIP} | grep '^Name' | sed -e 's/.* //'` if [ "${DESTHOST}" != "" ]; then DESTIP=${DESTHOST} fi fi if [ "`echo ${PROTO} | sed -e 's/\/.*//'`" = "icmp" ]; then SRCPORT=`echo ${PROTO} | sed -e 's/.*\///'` PROTO="icmp" DESTPORT="" if [ "${DEBUG}" = "YES" ]; then echo proto= ${PROTO} srcport= ${SRCPORT} destport= ${DESTPORT} ; fi case ${SRCPORT} in 0) COMMENT="# Echo reply/icmp(${DIR})" ;; 3) COMMENT="# Dest Unreach/icmp(${DIR})" ;; 4) COMMENT="# Source Quench/icmp(${DIR})" ;; 5) COMMENT="# Redirect/icmp(${DIR})" ;; 8) COMMENT="# Echo req/icmp(${DIR})" ;; 11) COMMENT="# Time exceeded/icmp(${DIR})" ;; 12) COMMENT="# Parameter prob/icmp(${DIR})" ;; 13) COMMENT="# Timestamp req/icmp(${DIR})" ;; 14) COMMENT="# Timestamp reply/icmp(${DIR})" ;; 15) COMMENT="# Info req/icmp(${DIR})" ;; 16) COMMENT="# Info reply/icmp(${DIR})" ;; 17) COMMENT="# Addr Mask req/icmp(${DIR})" ;; 18) COMMENT="# Addr Mask reply/icmp(${DIR})" ;; *) COMMENT="# unknown-${SRCPORT}/icmp(${DIR})" ;; esac else COMMENT="#" MATCHSERVICE=`cat /etc/services | grep "${SRCPORT}/${PROTO}"` if [ "${MATCHSERVICE}" != "" ]; then SRCPORT=`echo ${MATCHSERVICE} | awk '{print $1}'` else case ${SRCPORT} in [0-9]|[1-9][0-9]|[1-9][0-9][0-9]|10[0-1][0-9]|102[0-3]) : ;; *) SRCPORT="1024:65535" ;; esac fi if [ "${SRCPORT}" != "1024:65535" ]; then COMMENT="${COMMENT} ${SRCPORT}/${PROTO} " fi MATCHSERVICE=`cat /etc/services | grep "${DESTPORT}/${PROTO}"` if [ "${MATCHSERVICE}" != "" ]; then DESTPORT=`echo ${MATCHSERVICE} | awk '{print $1}'` else case ${DESTPORT} in [0-9]|[1-9][0-9]|[1-9][0-9][0-9]|10[0-1][0-9]|102[0-3]) : ;; *) DESTPORT="1024:65535" ;; esac fi if [ "${DESTPORT}" != "1024:65535" ]; then if [ "${SRCPORT}" != "${DESTPORT}" ]; then COMMENT="${COMMENT} ${DESTPORT}/${PROTO}" fi fi COMMENT="${COMMENT} (${DIR})" fi case ${PROTO} in tcp) PROTO="tcp " ;; udp) PROTO="udp " ;; esac CURRENT="ipfwadm -a accept -W ${IF} -${DIR} -P ${PROTO} -S ${SRCIP}/32 ${SRCPORT} -D ${DESTIP}/32 ${DESTPORT}" if [ `echo ${CURRENT} | wc --bytes` -lt 101 ]; then CURRENT=`echo "${CURRENT} " | cut -b 1-100` fi CURRENT="${CURRENT} ${COMMENT}" if [ "${DEBUG}" = "YES" ]; then echo current= ${CURRENT} ; fi case ${CURRENT} in ${LAST1}) : ;; ${LAST2}) : ;; ${LAST3}) : ;; ${LAST4}) : ;; ${LAST5}) : ;; *) if [ "${ECHOCOMMAND}" = "YES" ]; then echo "${CURRENT}" fi if [ "${DOCOMMAND}" = "YES" ]; then ipfwadm -i accept -W ${IF} -${DIR} -P ${PROTO} -S ${SRCIP}/32 ${SRCPORT} -D ${DESTIP}/32 ${DESTPORT} fi LAST5=${LAST4} LAST4=${LAST3} LAST3=${LAST2} LAST2=${LAST1} LAST1=${CURRENT} ;; esac if [ "${DEBUG}" = "YES" ]; then echo ${MESSAGE} echo src= ${SRCIP} ${SRCPORT} dest= ${DESTIP} ${DESTPORT} echo if= ${IF} proto= ${PROTO} echo fi fi read MESSAGE done