Name | Description | Options | Examples | Files | Attributes | See Also
The ipf or ipf.conf configuration files are associated with the Solaris IP Filter feature. See ipfilter(5).
A rule file for ipf(1M) can have any name or can be stdin. You can use ipfstat(1M) output as input to ipf(1M). ipfstat outputs parseable rules, suitable for input to ipf, when displaying the internal kernel filter lists. Thus, for example, to remove all filters on input packets, you can enter:
# ipfstat -i | ipf -rf - |
The IP filter feature uses the grammar shown below to construct filtering rules. The syntax is simplified for readability. Note that some combinations that match this grammar are disallowed by the software because they do not make sense (for example, tcp flags for non-TCP packets).
filter-rule = [ insert ] action in-out [ options ] [ tos ] [ ttl ] [ proto ] ip [ group ]. insert = "@" decnumber . action = block | "pass" | log | "count" | skip | auth . 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 ] [ icmp ] [ with withopt ] [ keep ] . group = [ "head" decnumber ] [ "group" decnumber ] . block = "block" [ return-icmp[return-code] | "return-rst" ] . auth = "auth" | "preauth" . log = "log" [ "body" ] [ "first" ] [ "or-block" ] [ "level" loglevel ] . tag = "set-tag" tagid skip = "skip" decnumber . 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" . 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" | "keep" "state" "keep" "frags" |"keep" "frags" | "keep" "state". loglevel = facility"."priority | priority . nummask = host-name [ "/" decnumber ] . host-name = ipaddr | hostname | "any" . ipaddr = host-num "." host-num "." host-num "." host-num | ipv6addr . host-num = digit [ digit [ digit ] ] . port-num = service-name | decnumber . withopt = [ "not" | "no" ] opttype [ withopt ] v6hdrs [ ipv6hdr ] . opttype = "ipopts" | "short" | "frag" | "frag-body" | "frags" | "opt" optname | "nat" | "multicast" | "bcast" | "mbcast" | "state" | "bad-nat" | "bad" | "oow" | "lowttl" | "bad-src" optname . optname = ipopts [ "," optname ] . ipopts = optlist | "sec-class" [ secname ] . ipv6hdr = "ah" | "esp" | "dstopts" | "hopopts" | "ipv6" | "none" | "routing" | "frag" 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" . |
Filter rules are checked in order, with the last matching rule determining the treatment of the packet. An exception to this is the quick option, which is discussed below.
By default, filters are installed at the end of the kernel's filter lists. Prepending a rule with @<num> causes it to be inserted as the <num>th entry in the current list. This is especially useful when modifying and testing active filter rule sets. See ipf(1M) for more information.
The simplest valid rules are:
block in all pass in all log out all count in all |
These rules do not have an effect on filtering, but are listed here to illustrate the grammar.
Each rule must have an action. The action indicates what to do with the packet if it matches the filter rule. The IP filter feature recognizes the following actions:
Indicates that a packet should be flagged to be dropped. In response to blocking a packet, the filter can be instructed to send a reply packet, either an ICMP packet (return-icmp), an ICMP packet that fakes being from the original packet's destination (return-icmp-as-dest), or a TCP reset (return-rst). An ICMP packet can be generated in response to any IP packet and its type can optionally be specified, but a TCP reset can only be used with a rule that 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 administratively prohibited. You do this by enclosing the ICMP code associated with the action in parentheses directly following return-icmp or return-icmp-as-dest. For example:
block return-icmp(11) ... |
The preceding entry causes a return of a Type-Of-Service (TOS) ICMP unreachable error.
Flag the packet to be let through the filter without any action being taken.
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(1M).
Causes the filter to skip over the next <num> filter rules. If a rule is inserted or deleted inside the region being skipped over, then the value of <num> is adjusted appropriately.
Allows authentication to be performed by a user-space program running and waiting for packet information to validate. The packet is held for a period of time in an internal buffer while it waits for the program to return to the kernel the “real” flags for whether it should be allowed through. 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 kernel to drop it if the packet is from an unrecognized 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 rule is used in instead. This might be used in a situation where a person logs in to the firewall and it sets up some temporary rules defining the access for that person.
The word following the action keyword must be either in or out. Each packet moving through the kernel is either inbound or outbound. “Inbound” means that a packet has just been received on an interface and is moving towards the kernel's protocol processing. “Outbound” means that a packet has been transmitted or forwarded by the stack and is on its way to an interface. There is a requirement that each filter rule explicitly state on which side of the I/O it is to be used.
The currently supported options are listed below. Where you use options, you must use them in the order shown here.
If this is the last matching rule, the packet header is written to the ipl log, as described in the LOGGING section below.
Allows short-cut rules to speed up the filter or override later rules. If a packet matches a filter rule that 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) determine whether it is passed or blocked.
If the quick option is missing, the rule is taken to be a “fall-through” rule, meaning that the result of the match (block or pass) is saved and that processing will continue to see if there are any more matches.
Allows an interface name to be incorporated into the matching procedure. Interface names are as displayed by netstat i. If this option is used, the rule matches only if the packet is going through that interface in the specified direction (in or out). If this option is absent, the rule is applied to a packet regardless of the interface it is present on (that is, on all interfaces). Filter rule sets 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 be allowed to pass inbound only on the interface from which the specified source address would be expected. Others can be logged, or logged and dropped.
Causes the packet to be copied, with the duplicate packet sent outbound on a specified interface, optionally with the destination IP address changed to that specified. This is useful for off-host logging, using a network sniffer.
Causes the packet to be moved to the outbound queue on the specified interface. This can be used to circumvent kernel routing decisions, and, if applied to an inbound rule, even to bypass the rest of the kernel processing of the packet. It is thus possible to construct a firewall that behaves transparently, like a filtering hub or switch, rather than a router. The fastroute keyword 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 do or do not match. The following general-purpose attributes are provided for matching and must be used in the order shown below.
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 be represented either as a hexadecimal or decimal integer.
Packets can 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 be given only as a decimal integer.
Allows a specific protocol to be matched against. All protocol names found in /etc/protocols are recognized and can be used. However, the protocol can also be given as a decimal number, allowing for rules to match your own protocols and for new protocols.
The special protocol keyword tcp/udp can 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.
IP addresses can be specified in one of two ways: as a numerical address/mask, or as a hostname mask/netmask. The hostname can be either of the dotted numeric form or a valid hostname, from the hosts file or DNS (depending on your configuration and library). There is no special designation for networks, but network names are recognized. 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 0.0.0.0/0 (mask syntax is discussed below) and matches all IP addresses. Only the presence of any has an implied mask. In all other situations, a hostname must be accompanied by a mask. It is possible to give any a hostmask, but in the context of this language, it would accomplish nothing.
The numerical format x/y indicates that a mask of y consecutive 1 bits set is generated, starting with the MSB, so that a y value of 16 would result in 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 is currently not a way to invert the sense of the match or to match ranges of IP addresses that do not express themselves easily as bitmasks.
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 service name or an integer port number can be used. Port comparisons can be done in a number of forms, with a number of comparison operators, or you can specify port ranges. 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 EXAMPLES.
The all keyword is essentially a synonym for “from any to any” with no other match parameters.
Following the source and destination matching parameters, you can use the following additional parameters:
Used to match irregular attributes that some packets might 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, you can list individual options.
Before any parameter used after the with keyword, you can insert the word not or no to cause the filter rule to match only if the option(s) is not present.
Multiple consecutive with clauses are allowed. Alternatively, you can use the keyword and in place of with. This alternative is provided to make the rules more readable (“with ... and ...”). When multiple clauses are listed, all clauses must match to cause a match of the rule.
Effective only 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 can be used in combination, so that SA matches a SYN-ACK combination in a packet. There is nothing preventing the specification of combinations, such as SFR, that would not normally be generated by fully conformant TCP implementations. However, to guard against unpredictable behavior, it is necessary to state which flags you are filtering against. To allow this, it is possible to set a mask indicating against which TCP flags you wish to compare (that is, those you deem significant). This is done by appending /<flags> to the set of TCP flags you wish to match against, for example:
Becomes flags S/AUPRFS and matches packets with only the SYN flag set.
Becomes flags SA/AUPRFSC and matches any packet with only the SYN and ACK flags set.
Matches any packet with just the SYN flag set out of the SYN-ACK pair, which is the common establish keyword action. S/SA will not match a packet with both SYN and ACK set, but will match SFP.
Effective only 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 abbreviation recognized by this language or by the numbers with which they are associated. The most important type from a security point of view is the ICMP redirect.
The penultimate parameter that can be set for a filter rule is whether or not to record historical information for a 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 packets.
Keeps information on fragmented packets, to be applied to later fragments.
Presence of these parameters allows matching packets 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 is not stopped until it has returned from processing the group.
A rule can be both the head for a new group and a member of a non-default group (head and group can be used together in a rule).
Indicates that a new group (number <n>) should be created.
Indicates that the rule should be put in group (number <n>) rather than group 0.
When a packet is logged, by means of either the log action or log option, the headers of the packet are written to the ipl packet logging pseudo-device. Immediately following the log keyword, you can use the following qualifiers in the order listed below:
Indicates that the first 128 bytes of the packet contents will be logged after the headers.
If log is being used in conjunction with a keep option, it is recommended that you also apply this option so that only the triggering packet is logged and not every packet which thereafter matches state information.
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.
Indicates what logging facility and priority (or, if the default facility is used, priority only) will be used to log information about this packet using ipmon's -s option.
You can use ipmon(1M) to read and format the log.
By default, the IP Filter feature will not filter or intercept any packets that are local to the machine. This includes traffic to or from the loopback addresses (127.0.0.1, and so forth), traffic between sockets that are on the same host (for example, from eri0 to eri1), and traffic between zones.
To enable loopback or zone filtering, you must add the following line to ipf.conf file:
set intercept_loopback true; |
This line must be placed before any block or pass rules in this file or, put another way, it must be the first non-comment line in ipf.conf.
When you enable filtering of packets in any one of the scenarios described above, you enabling filtering for all them. That is, when you enable the IP Filter feature to intercept packets between zones, you also cause it to receive packets that are involved in loopback traffic.
The quick option works well for rules such as:
block in quick from any to any with ipopts |
This rule matches any packet with a non-standard header length (IP options present) and aborts further processing of later rules, recording a match and also indicating that the packet should be blocked.
The “fall-through” rule parsing allows for effects such as the following:
block in from any to any port < 6000 pass in from any to any port >= 6000 block in from any to any port > 6003 |
These rules set 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, because a failed match on the block action does not imply a pass. It implies only that the rule has not taken effect. To then allow ports lower than 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, you would use a rule such as:
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, you would use:
pass in proto icmp all group 100 |
Note that because only inbound packets on le0 are processed by group 100, there is no need to respecify the interface name. Likewise, you could further breakup processing of TCP 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 you wanted to specify port = telnet, you would need to specify proto tcp, because the parser interprets each rule on its own and qualifies all service and port names with the protocol specified.
Location of rules file that is read upon startup of IP Filter feature.
/dev/ipauth
/dev/ipl
/dev/ipstate
/etc/hosts
/etc/services
See attributes(5) for a description of the following attributes:
ATTRIBUTE TYPE |
ATTRIBUTE VALUE |
---|---|
Interface Stability |
Evolving |
Name | Description | Options | Examples | Files | Attributes | See Also