ipf (SFF)


     ipf, ipf.conf, ipf6.conf - IP packet filter rule syntax


     A rule file for ipf may have any name or even be stdin.   As
     ipfstat  produces  parsable  rules as output when displaying
     the internal kernel filter lists, it is quite  plausible  to
     use  its  output to feed back into ipf.  Thus, to remove all
     filters on input packets, the following could be done:

     # ipfstat -i | ipf -rf -


     The format used by ipf for construction of  filtering  rules
     can be described using the following grammar in BNF:

     filter-rule = [ insert ] action in-out [ options ] [ tos ] [ ttl ]
                [ proto ] ip [ group ].

     insert    = "@" decnumber .
     action    = block | "pass" | log | "count" | skip | auth | call .
     in-out    = "in" | "out" .
     options   = [ log ] [ tag ] [ "quick" ] [ "on" interface-name [ dup ]
                [ froute ] [ replyto ] ] .
     tos  = "tos" decnumber | "tos" hexnumber .
     ttl  = "ttl" decnumber .
     proto     = "proto" protocol .
     ip   = srcdst [ flags ] [ with withopt ] [ icmp ] [ keep ] .
     group     = [ "head" decnumber ] [ "group" decnumber ] .

     block     = "block" [ return-icmp[return-code] | "return-rst" ] .
     log  = "log" [ "body" ] [ "first" ] [ "or-block" ] [ "level" loglevel ] .
     tag     = "tag" tagid .
     skip = "skip" decnumber .
     auth = "auth" | "preauth" .
     call = "call" [ "now" ] function-name .
     dup  = "dup-to" interface-name [ ":" ipaddr ] .
     froute    = "fastroute" | "to" interface-name [ ":" ipaddr ] .
     replyto = "reply-to" interface-name [ ":" ipaddr ] .
     protocol = "tcp/udp" | "udp" | "tcp" | "icmp" | decnumber .
     srcdst    = "all" | fromto .
     fromto    = "from" [ "!" ] object "to" [ "!" ] object .

     return-icmp = "return-icmp" | "return-icmp-as-dest" .
     return-code = "(" icmp-code ")" .
     object    = addr [ port-comp | port-range ] .
     addr = "any" | nummask | host-name [ "mask" ipaddr | "mask" hexnumber ] .
     addr = "any" | "<thishost>" | nummask |
            host-name [ "mask" ipaddr | "mask" hexnumber ] .
     port-comp = "port" compare port-num .
     port-range = "port" port-num range port-num .
     flags     = "flags" flag { flag } [ "/" flag { flag } ] .
     with = "with" | "and" .
     icmp = "icmp-type" icmp-type [ "code" decnumber ] .
     return-code = "("icmp-code")" .
     keep = "keep" "state" | "keep" "frags" .
     loglevel = facility"."priority | priority .

     nummask   = host-name [ "/" decnumber ] .
     host-name = ipaddr | hostname | "any" .
     ipaddr    = host-num "." host-num "." host-num "." host-num .
     host-num = digit [ digit [ digit ] ] .
     port-num = service-name | decnumber .

     withopt = [ "not" | "no" ] opttype [ withopt ] .
     opttype = "ipopts" | "short" | "frag" | "opt" optname .
     optname   = ipopts [ "," optname ] .
     ipopts  = optlist | "sec-class" [ secname ] .
     secname   = seclvl [ "," secname ] .
     seclvl  = "unclass" | "confid" | "reserv-1" | "reserv-2" | "reserv-3" |
            "reserv-4" | "secret" | "topsecret" .
     icmp-type = "unreach" | "echo" | "echorep" | "squench" | "redir" |
              "timex" | "paramprob" | "timest" | "timestrep" | "inforeq" |
              "inforep" | "maskreq" | "maskrep"  | decnumber .
     icmp-code = decumber | "net-unr" | "host-unr" | "proto-unr" | "port-unr" |
              "needfrag" | "srcfail" | "net-unk" | "host-unk" | "isolate" |
              "net-prohib" | "host-prohib" | "net-tos" | "host-tos" |
              "filter-prohib" | "host-preced" | "cutoff-preced" .
     optlist   = "nop" | "rr" | "zsu" | "mtup" | "mtur" | "encode" | "ts" |
            "tr" | "sec" | "lsrr" | "e-sec" | "cipso" | "satid" | "ssrr" |
            "addext" | "visa" | "imitd" | "eip" | "finn" .
     facility = "kern" | "user" | "mail" | "daemon" | "auth" | "syslog" |
             "lpr" | "news" | "uucp" | "cron" | "ftp" | "authpriv" |
             "audit" | "logalert" | "local0" | "local1" | "local2" |
             "local3" | "local4" | "local5" | "local6" | "local7" .
     priority = "emerg" | "alert" | "crit" | "err" | "warn" | "notice" |
             "info" | "debug" .

     hexnumber = "0" "x" hexstring .
     hexstring = hexdigit [ hexstring ] .
     decnumber = digit [ decnumber ] .

     compare = "=" | "!=" | "<" | ">" | "<=" | ">=" | "eq" | "ne" | "lt" |
            "gt" | "le" | "ge" .
     range     = "<>" | "><" .
     hexdigit = digit | "a" | "b" | "c" | "d" | "e" | "f" .
     digit     = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" .
     flag = "F" | "S" | "R" | "P" | "A" | "U" .

     This syntax is somewhat  simplified  for  readability,  some
     combinations  that  match this grammar are disallowed by the
     software because they do not make sense (such as  tcp  flags
     for non-TCP packets).


     The "briefest" valid rules are (currently) no-ops and are of
     the form:
            block in all
            pass in all
            log out all
            count in all

     Filter rules are checked in order, with  the  last  matching
     rule  determining  the fate of the packet (but see the quick
     option, below).

     Filters are installed by default at the end of the  kernel's
     filter  lists,  prepending the rule with @n will cause it to
     be inserted as the n'th entry in the current list.  This  is
     especially  useful  when modifying and testing active filter
     rulesets. See ipf(ADMN) for more information.


     The action indicates what  to  do  with  the  packet  if  it
     matches  the rest of the filter rule. Each rule MUST have an
     action. The following actions are recognised:

          indicates that the  packet  should  be  flagged  to  be
          dropped.  In  response to blocking a packet, the filter
          may be instructed to send a  reply  packet,  either  an
          ICMP  packet (return-icmp), an ICMP packet masquerading
          as  being  from  the  original   packet's   destination
          (return-icmp-as-dest),  or  a TCP "reset" (return-rst).
          An ICMP packet may be generated in response to  any  IP
          packet, and its type may optionally be specified, but a
          TCP reset may only be used with a rule which  is  being
          applied  to  TCP  packets.   When  using return-icmp or
          return-icmp-as-dest, it  is  possible  to  specify  the
          actual  unreachable  `type'.   That is, whether it is a
          network unreachable, port unreachable or even  adminis-
          tratively  prohibited.  This  is  done by enclosing the
          ICMP code associated with it  in  parenthesis  directly
          following  return-icmp  or  return-icmp-as-dest as fol-
                  block return-icmp(11) ...

     Would return a Type-Of-Service (TOS) ICMP unreachable error.

     pass will flag the packet to be let through the filter.

     log  causes the packet to be logged  (as  described  in  the
          LOGGING section below) and has no effect on whether the
          packet will be allowed through the filter.

          causes the packet to  be  included  in  the  accounting
          statistics  kept  by  the  filter, and has no effect on
          whether the packet will be allowed through the  filter.
          These statistics are viewable with ipfstat(ADMN).

     call this action is used to invoke the named function in the
          kernel, which must conform to a specific calling inter-
          face. Customised actions  and  semantics  can  thus  be
          implemented to supplement those available. This feature
          is  for  use  by  knowledgeable  hackers,  and  is  not
          currently documented.

     skip <n>
          causes the filter to skip over the next n filter rules.
          If  a  rule  is  inserted  or deleted inside the region
          being skipped over, then the value  of  n  is  adjusted

     auth this allows authentication to be performed by  a  user-
          space  program  running and waiting for packet informa-
          tion to validate.  The packet is held for a  period  of
          time in an internal buffer whilst it waits for the pro-
          gram to return to the kernel the real flags for whether
          it  should  be  allowed through or not.  Such a program
          might look at the source address and request some  sort
          of  authentication  from  the user (such as a password)
          before allowing the packet through or telling the  ker-
          nel to drop it if from an unrecognised source.

          tells the filter that for packets  of  this  class,  it
          should  look  in the pre-authenticated list for further
          clarification.  If no further matching rule  is  found,
          the  packet  will be dropped (the FR_PREAUTH is not the
          same as FR_PASS).  If a further matching rule is found,
          the  result  from  that  is  used in its instead.  This
          might be used in a situation where a person logs in  to
          the firewall and it sets up some temporary rules defin-
          ing the access for that person.

     The next word must be either in or out.  Each packet  moving
     through  the kernel is either inbound (just been received on
     an interface, and moving towards the kernel's protocol  pro-
     cessing) or outbound (transmitted or forwarded by the stack,
     and on its way to an interface). There is a requirement that
     each  filter  rule explicitly state which side of the I/O it
     is to be used on.


     The list of options is brief, and all are  indeed  optional.
     Where  options  are  used, they must be present in the order
     shown here. These are the currently supported options:
     log  indicates that, should this be the last matching  rule,
          the  packet  header  will be written to the ipl log (as
          described in the LOGGING section below).

     tag tagid
          indicates that, if this rule causes the  packet  to  be
          logged or entered in the state table, the tagid will be
          logged as part of the log entry.  This can be  used  to
          quickly match "similar" rules in scripts that post pro-
          cess the log files  for  e.g.  generation  of  security
          reports  or  accounting purposes. The tagid is a 32 bit
          unsigned integer.

          allows "short-cut" rules  in  order  to  speed  up  the
          filter  or override later rules.  If a packet matches a
          filter rule which is marked as quick, this rule will be
          the  last rule checked, allowing a "short-circuit" path
          to avoid processing later rules for  this  packet.  The
          current  status of the packet (after any effects of the
          current rule) will determine whether it  is  passed  or

          If this option is missing, the rule is taken  to  be  a
          "fall-through"  rule,  meaning  that  the result of the
          match (block/pass) is saved and  that  processing  will
          continue to see if there are any more matches.

     on   allows an interface name to be  incorporated  into  the
          matching  procedure.  Interface names are as printed by
          "netstat -i". If this option is  used,  the  rule  will
          only  match  if the packet is going through that inter-
          face in  the  specified  direction  (in/out).  If  this
          option  is absent, the rule is taken to be applied to a
          packet regardless of the interface  it  is  present  on
          (i.e.  on  all interfaces).  Filter rulesets are common
          to all interfaces, rather than having a filter list for
          each interface.

          This option is especially useful for simple IP-spoofing
          protection:   packets  should  only  be allowed to pass
          inbound on  the  interface  from  which  the  specified
          source  address would be expected, others may be logged
          and/or dropped.

          causes the packet  to  be  copied,  and  the  duplicate
          packet  to be sent outbound on the specified interface,
          optionally with the destination IP address  changed  to
          that  specified.  This  is useful for off-host logging,
          using a network sniffer.

     to   causes the packet to be moved to the outbound queue  on
          the specified interface. This can be used to circumvent
          kernel routing decisions, and even to bypass  the  rest
          of  the  kernel processing of the packet (if applied to
          an inbound rule). It is thus possible  to  construct  a
          firewall  that  behaves transparently, like a filtering
          hub or switch, rather than a router. The fastroute key-
          word is a synonym for this option.


     The keywords described in this section are used to  describe
     attributes of the packet to be used when determining whether
     rules match or don't match.  The  following  general-purpose
     attributes  are  provided  for matching, and must be used in
     this order:

     tos  packets with different Type-Of-Service  values  can  be
          filtered.   Individual  service  levels or combinations
          can be filtered upon.  The value for the TOS  mask  can
          either  be  represented  as  a  hex number or a decimal
          integer value.

     ttl  packets may also  be  selected  by  their  Time-To-Live
          value.  The value given in the filter rule must exactly
          match that in the packet for a match  to  occur.   This
          value can only be given as a decimal integer value.

          allows a specific protocol to be matched against.   All
          protocol  names  found in /etc/protocols are recognised
          and may be used.  However, the  protocol  may  also  be
          given  as a DECIMAL number, allowing for rules to match
          your own protocols, or new ones  which  would  out-date
          any attempted listing.

          The special protocol keyword tcp/udp  may  be  used  to
          match  either a TCP or a UDP packet, and has been added
          as a convenience  to  save  duplication  of  otherwise-
          identical rules.

     The from and to  keywords  are  used  to  match  against  IP
     addresses  (and optionally port numbers). Rules must specify
     BOTH source and destination parameters.

     IP addresses may be specified in  one  of  two  ways:  as  a
     numerical  address/mask, or as a hostname mask netmask.  The
     hostname may either be a valid  hostname,  from  either  the
     hosts  file  or  DNS  (depending  on  your configuration and
     library) or of the dotted numeric form.  There is no special
     designation  for  networks but network names are recognised.
     Note that having your filter rules depend on DNS results can
     introduce an avenue of attack, and is discouraged.
     There is a special case for the hostname any which is  taken
     to  be (see below for mask syntax) and matches all
     IP addresses.  Only the presence of  "any"  has  an  implied
     mask,  in  all  other  situations, a hostname MUST be accom-
     panied by a mask.  It is possible to give "any" a  hostmask,
     but in the context of this language, it is non-sensical.

     The numerical format "x/y" indicates that a mask of  y  con-
     secutive  1 bits set is generated, starting with the MSB, so
     a y value of 16 would give 0xffff0000. The symbolic "x  mask
     y"  indicates  that the mask y is in dotted IP notation or a
     hexadecimal number of the form 0x12345678.   Note  that  all
     the  bits  of  the  IP address indicated by the bitmask must
     match  the  address  on  the  packet  exactly;  there  isn't
     currently  a  way  to  invert  the sense of the match, or to
     match ranges of IP addresses which do not express themselves
     easily  as bitmasks (anthropomorphization; it's not just for
     breakfast anymore).

     If a port match is included, for either or  both  of  source
     and  destination,  then  it  is  only applied to TCP and UDP
     packets. If there is no proto match parameter, packets  from
     both  protocols  are  compared. This is equivalent to "proto
     tcp/udp".  When composing port comparisons, either the  ser-
     vice  name  or an integer port number may be used. Port com-
     parisons may be done in a number of forms, with a number  of
     comparison  operators, or port ranges may be specified. When
     the port appears as part of the from object, it matches  the
     source  port  number,  when  it  appears  as  part of the to
     object, it matches the destination  port  number.   See  the
     examples for more information.

     The all keyword is essentially a synonym for  "from  any  to
     any" with no other match parameters.

     Following the source and  destination  matching  parameters,
     the following additional parameters may be used:

     with is used to match irregular attributes that some packets
          may  have  associated with them.  To match the presence
          of IP options in general, use  with  ipopts.  To  match
          packets  that  are  too  short  to  contain  a complete
          header, use with short. To  match  fragmented  packets,
          use  with  frag.   For  more  specific  filtering on IP
          options, individual options can be listed.

          Before any parameter used after the with  keyword,  the
          word not or no may be inserted to cause the filter rule
          to only match if the option(s) is not present.

          Multiple consecutive with clauses are allowed.   Alter-
          natively, the keyword and may be used in place of with,
          this is provided purely to make the rules more readable
          ("with  ...  and  ...").   When  multiple  clauses  are
          listed, all those must match to cause a  match  of  the

          is only effective  for  TCP  filtering.   Each  of  the
          letters  possible  represents one of the possible flags
          that can be set in the TCP header.  The association  is
          as follows:

             F - FIN
             S - SYN
             R - RST
             P - PUSH
             A - ACK
             U - URG

          The various flag symbols may be used in combination, so
          that "SA" would represent a SYN-ACK combination present
          in a packet.  There is nothing preventing the  specifi-
          cation  of  combinations, such as "SFR", that would not
          normally be generated by  law-abiding  TCP  implementa-
          tions.  However, to guard against weird aberrations, it
          is necessary to state which  flags  you  are  filtering
          against.   To  allow this, it is possible to set a mask
          indicating which TCP flags you wish to  compare  (i.e.,
          those you deem significant).  This is done by appending
          "/<flags>" to the set of TCP flags you  wish  to  match
          against, e.g.:

          ... flags S
                    # becomes "flags S/AUPRFS" and will match
                    # packets with ONLY the SYN flag set.

          ... flags SA
                    # becomes "flags SA/AUPRFS" and will match any
                    # packet with only the SYN and ACK flags set.

          ... flags S/SA
                    # will match any packet with just the SYN flag set
                    # out of the SYN-ACK pair; the common "establish"
                    # keyword action.  "S/SA" will NOT match a packet
                    # with BOTH SYN and ACK set, but WILL match "SFP".

          is only effective when used with proto  icmp  and  must
          NOT  be  used  in  conjunction with flags.  There are a
          number of types, which can be referred to by an  abbre-
          viation  recognised  by  this  language, or the numbers
          with which they are associated can be used.   The  most
          important  from  a  security  point of view is the ICMP


     The second last parameter which can be set for a filter rule
     is  whether or not to record historical information for that
     packet, and what sort to keep. The following information can
     be kept:

          keeps information about the  flow  of  a  communication
          session. State can be kept for TCP, UDP, and ICMP pack-

          keeps information on fragmented packets, to be  applied
          to later fragments.

     allowing packets which match these to flow straight through,
     rather than going through the access control list.


     The last pair of parameters control filter rule  "grouping".
     By  default,  all  filter  rules are placed in group 0 if no
     other group is specified.  To add a rule  to  a  non-default
     group,  the  group must first be started by creating a group
     head.  If a packet matches a rule which is  the  head  of  a
     group,  the  filter  processing  then switches to the group,
     using that rule as the default for the group.  If  quick  is
     used  with  a head rule, rule processing isn't stopped until
     it has returned from processing the group.

     A rule may be both the head for a new group and a member  of
     a  non-default group (head and group may be used together in
     a rule).

     head <n>
          indicates  that  a  new  group  (number  n)  should  be

     group <n>
          indicates that the rule should be put in group  (number
          n) rather than group 0.


     When a packet is logged,  with  either  the  log  action  or
     option,  the  headers  of  the packet are written to the ipl
     packet logging pseudo-device. Immediately following the  log
     keyword, the following qualifiers may be used (in order):

     body indicates that the first 128 bytes of the  packet  con-
          tents will be logged after the headers.

          If log is being  used  in  conjunction  with  a  "keep"
          option,  it  is  recommended  that  this option is also
          applied so that only the triggering  packet  is  logged
          and  not  every  packet  which thereafter matches state

          indicates that, if for some reason the filter is unable
          to  log  the  packet  (such as the log reader being too
          slow) then the rule should be  interpreted  as  if  the
          action was block for this packet.

     level <loglevel>
          indicates what logging facility and priority,  or  just
          priority  with the default facility being used, will be
          used to log information about this packet using ipmon's
          -s option.

     See ipl(ADMP) for the format of records written to this device.
     The  ipmon(ADMN)  program  can  be used to read and format this


     The quick option is good for rules such as:

     block in quick from any to any with ipopts

     which will match  any  packet  with  a  non-standard  header
     length  (IP options present) and abort further processing of
     later rules, recording a match  and  also  that  the  packet
     should be blocked.

     The "fall-through" rule parsing allows for effects  such  as

             block in from any to any port < 6000
             pass in from any to any port >= 6000
             block in from any to any port > 6003

     which sets up the range 6000-6003 as being permitted and all
     others being denied.  Note that the effect of the first rule
     is overridden by subsequent rules.  Another (easier) way  to
     do the same is:

             block in from any to any port 6000 <> 6003
             pass in from any to any port 5999 >< 6004

     Note that both the "block" and "pass"  are  needed  here  to
     effect a result as a failed match on the "block" action does
     not imply a pass, only that the rule  hasn't  taken  effect.
     To then allow ports < 1024, a rule such as:
             pass in quick from any to any port < 1024

     would be needed before the first block.   To  create  a  new
     group  for  processing  all  inbound packets on le0/le1/lo0,
     with the default being to  block  all  inbound  packets,  we
     would do something like:

            block in all
            block in quick on le0 all head 100
            block in quick on le1 all head 200
            block in quick on lo0 all head 300

     and to then allow ICMP packets in on le0, only, we would do:

            pass in proto icmp all group 100

     Note that because only inbound packets on le0 are used  pro-
     cessed  by  group  100,  there  is  no need to respecify the
     interface name.  Likewise, we could further breakup process-
     ing of TCP, etc, as follows:

            block in proto tcp all head 110 group 100
            pass in from any to any port = 23 group 110

     and so on.  The last line, if  written  without  the  groups
     would be:

            pass in on le0 proto tcp from any to any port = telnet

     Note, that if we wanted to say "port = telnet", "proto  tcp"
     would  need  to  be  specified as the parser interprets each
     rule on its own and qualifies all  service/port  names  with
     the protocol specified.




     ipftest(ADMN),   mkfilters(ADMN),   ipf(SFF),    ipnat(SFF),
     ipf(ADMN), ipfstat(TC)

Man(1) output converted with man2html