NPF.CONF(5)

NAME
npf.conf - NPF packet filter configuration file

DESCRIPTION
npf.conf is the default configuration file for NPF packet filter. It can contain definitions, grouped rules, rule procedures, and tables.

  Definitions
Definitions are general purpose keywords which can be used in the ruleset to make it more flexible and easier to manage. Most commonly, definitions are used to define one of the following: IP addresses, networks, ports, or interfaces. Definitions can contain multiple elements.

  Groups
Having one huge ruleset for all interfaces or directions might be inefficient; therefore, NPF requires that all rules be defined within groups. Groups can be thought of as higher level rules which have subrules. The main properties of a group are its interface and traffic direction. Packets matching group criteria are passed to the ruleset of that group. If a packet does not match any group, it is passed to the default group. The default group must always be defined.

  Rules
Rules, which are the main part of NPF configuration, describe the criteria used to inspect and make decisions about packets. Currently, NPF supports filtering on the following criteria: interface, traffic direction, protocol, IPv4 address or network, TCP/UDP port or range, TCP flags, and ICMP type/code. Supported actions are blocking or passing the packet.

Each rule has a priority, which is set according to its order in the ruleset. Rules defined first are accordingly inspected first. All rules in the group are inspected sequentially, and the last matching dictates the action to be taken. Rules, however, may be explicitly marked as final (that is, "quick"). In such cases, processing stops after encountering the first matching rule marked as final. If there is no matching rule in the custom group, then rules in the default group will be inspected.

Stateful filtering is supported using the "keep state" keyword. In such cases, state (a session) is created and any further packets of the connection are tracked. Packets in backwards stream, after having been confirmed to belong to the same connection, are passed without ruleset inspection. Rules may have associated rule procedures (described in a later section), which are applied for all packets of a connection.

Definitions (prefixed with "$") and tables (specified by an ID within "" marks) can be used in the filter options of rules.

  Rule procedures and normalisation
Rule procedures are provided to perform packet transformations and various additional procedures on the packets. It should be noted that rule procedures are applied for the connections, that is, both for packets which match the rule and for further packets of the connection, which are passed without ruleset inspection. Currently, two facilities are supported: traffic normalisation and packet logging. Packet normalisation has the following functionality: IP ID randomisation, IP_DF flag cleansing, TCP minimum TTL enforcement, and maximum MSS enforcement ("MSS clamping"). If a matching rule is going to drop the packet, normalisation functions are not performed. Packet logging is performed both in packet passing and blocking cases. Note that the logging interface has to be created manually, using ifconfig(8) routine, for example:

ifconfig npflog0 create

  Network address translation
Rules for address translation can be added. Translation is performed on the specified interface, assigning the specified address of said interface. There are three types of translation: Network Address Port Translation (NAPT) - a regular NAT, also known as "outbound NAT"; Port forwarding (redirection) - also known as "inbound NAT"; Bi-directional NAT - a combination of inbound and outbound NAT.

Minimal filtering criteria on local network and destination are provided. Note that address translation implies routing, therefore IP forwarding is required to be enabled: net.inet.ip.forwarding = 1. See sysctl(7) for more details.

  Tables
Certain configurations might use very large sets of IP addresses or change sets frequently. Storing large IP sets in the configuration file or performing frequent reloads can have a significant performance cost.

In order to achieve high performance, NPF has tables. NPF tables provide separate storage designed for large IP sets and frequent updates without reloading the entire ruleset. Tables can be managed dynamically or loaded from a separate file, which is useful for large static tables. There are two types of storage: "tree" (red-black tree is used) and "hash".

GRAMMAR

    line		= ( def | table | nat | group | rproc )
    def		= ( name "=" "{ a, b, ... }" | "text" | "$interface" )
    iface		= ( interface | def )
    table		= "table" tid "type" ( "hash" | "tree" )
    		  ( "dynamic" | "file" path )
    nat		= "nat" iface filt-opts "->" addr
    binat		= "binat" iface filt-opts "->" addr
    rdr		= "rdr" iface filt-opts "->" addr port-opts
    rproc		= "procedure" name procs
    procs		= "{" op1 newline, op2 newline, ... "}"
    op		= ( "log" iface | "normalise" "(" norm-opt1 "," norm-opt2 ... ")" )
    norm-opt	= [ "random-id" | "min-ttl" num | "max-mss" num | "no-df" ]
    group		= "group" "(" ( "default" | group-opts ) ")" ruleset
    group-opts	= "interface" iface "," [ "in" | "out" ]
    ruleset		= "{" rule1 newline, rule2 newline, ... "}"
    rule		= ( "block" block-opts | "pass" ) [ "in" | out" ] [ "quick" ]
    		  [ "on" iface ] [ "family" fam-opt ] [ "proto" protocol ]
    		  ( "all" | filt-opts ) [ "keep state" ] [ "apply" rproc ] }
    fam-opt		= [ "inet" | "inet6" ]
    block-opts	= [ "return-rst" | "return-icmp" | "return" ]
    filt-addr	= iface | def | addr/mask | tid
    port-opts	= [ "port" ( port-num | port-from "-" port-to | def ) ]
    filt-opts	= [ "from" filt-addr [ port-opts ] ] [ "to" filt-addr [ port-opts ] ]
    proto-opts	= [ "flags" tcp_flags | "icmp-type" type "code" code ]

FILES
/dev/npf
    control device
/etc/npf.conf
    default configuration file

EXAMPLES

    $ext_if = "wm0"
    $int_if = "wm1"
    $services_tcp = { http, https, smtp, domain, 6000 }
    $services_udp = { domain, ntp, 6000 }
    table <1> type hash file "/etc/npf_blacklist"
    table <2> type tree dynamic
    nat $ext_if from 192.168.0.0/24 to any -> $ext_if
    procedure "log" {
    	log: npflog0
    }
    procedure "rid" {
    	normalise: "random-id"
    }
    group (name "external", interface $ext_if) {
    	block in quick from 1
    	pass out quick from $ext_if keep state apply "rid"
    	pass in quick family inet proto tcp to $ext_if port ssh apply "log"
    	pass in quick proto tcp to $ext_if port $services_tcp
    	pass in quick proto udp to $ext_if port $services_udp
    	pass in quick proto tcp to $ext_if port 49151-65535	# Passive FTP
    	pass in quick proto udp to $ext_if port 33434-33600	# Traceroute
    }
    group (name "internal", interface $int_if) {
    	block in all
    	pass in quick from 2
    	pass out quick all
    }
    group (default) {
    	block all
    }

SEE ALSO
npfctl(8), npf_ncode(9)

HISTORY
NPF first appeared in NetBSD 6.0.