Training courses

Kernel and Embedded Linux

Bootlin training courses

Embedded Linux, kernel,
Yocto Project, Buildroot, real-time,
graphics, boot time, debugging...

Bootlin logo

Elixir Cross Referencer

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
.\"    $NetBSD: npf.conf.5,v 1.91 2020/05/30 14:16:56 rmind Exp $
.\"
.\" Copyright (c) 2009-2020 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This material is based upon work partially supported by The
.\" NetBSD Foundation under a contract with Mindaugas Rasiukevicius.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\"    notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\"    notice, this list of conditions and the following disclaimer in the
.\"    documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd May 19, 2020
.Dt NPF.CONF 5
.Os
.Sh NAME
.Nm npf.conf
.Nd NPF packet filter configuration file
.\" -----
.Sh DESCRIPTION
.Nm
is the default configuration file for the NPF packet filter.
.Pp
This manual page serves as a reference for editing
.Nm .
Please refer to the official NPF documentation website for comprehensive and
in-depth information.
.Pp
There are multiple structural elements that
.Nm
may contain, such as:
.Pp
.Bl -bullet -offset indent -compact
.It
variables
.It
table definitions (with or without content)
.It
abstraction groups
.It
packet filtering rules
.It
map rules for address translation
.It
application level gateways
.It
procedure definitions to call on filtered packets
.It
parameter settings.
.El
.Sh SYNTAX
.Ss Variables
Variables are specified using the dollar
.Pq Li $
sign, which is used for both
definition and referencing of a variable.
Variables are defined by assigning a value to them as follows:
.Pp
.Dl $var1 = 10.0.0.1
.Pp
A variable may also be defined as a set:
.Pp
.Dl $var2 = { 10.0.0.1, 10.0.0.2 }
.Pp
Common variable definitions are for IP addresses, networks, ports,
and interfaces.
.Ss Tables
Tables are specified using a name between angle brackets
.Sq Li <
and
.Sq Li > .
The following is an example of table definition:
.Pp
.Dl table <blocklist> type ipset
.Pp
Currently, tables support three data storage types:
.Cm ipset ,
.Cm lpm ,
or
.Cm const .
The contents of the table may be pre-loaded from the specified file.
The
.Cm const
tables are immutable (no insertions or deletions after loading) and
therefore must always be loaded from a file.
.Pp
The specified file should contain a list of IP addresses and/or networks
in the form of
.Li 10.1.1.1
or
.Li 10.0.0.0/24 .
.Pp
Tables of type
.Cm ipset
and
.Cm const
can only contain IP addresses (without masks).
The
.Cm lpm
tables can contain networks and they will perform the longest
prefix match on lookup.
.Ss Interfaces
In NPF, an interface can be referenced directly by using its name, or can be
passed to an extraction function which will return a list of IP addresses
configured on the actual associated interface.
.Pp
It is legal to pass an extracted list from an interface in keywords where
NPF would expect instead a direct reference to said interface.
In this case, NPF infers a direct reference to the interface, and does not
consider the list.
.Pp
There are two types of IP address lists.
With a static list, NPF will capture the interface addresses on configuration
load, whereas with a dynamic list NPF will capture the runtime list of
addresses, reflecting any changes to the interface, including the attach and
detach.
Note that with a dynamic list, bringing the interface down has no effect,
all addresses will remain present.
.Pp
Three functions exist, to extract addresses from an interface with a chosen
list type and IP address type:
.Bl -tag -width "Fn ifaddrs interface" -offset indent
.It Fn inet4 interface
Static list.
IPv4 addresses.
.It Fn inet6 interface
Static list.
IPv6 addresses.
.It Fn ifaddrs interface
Dynamic list.
Both IPv4 and IPv6.
The
.Cm family
keyword of a filtering rule can be used in combination to explicitly select
an IP address type.
This function can also be used with
.Cm map
to specify the translation address, see below.
.El
.Pp
Example of configuration:
.Bd -literal -offset indent
$var1 = inet4(wm0)
$var2 = ifaddrs(wm0)

group default {
	block in on wm0 all               # rule 1
	block in on $var1 all             # rule 2
	block in on inet4(wm0) all        # rule 3
	pass in on inet6(wm0) from $var2  # rule 4
	pass in on wm0 from ifaddrs(wm0)  # rule 5
}
.Ed
.Pp
In the above example,
.Li $var1
is the static list of IPv4 addresses configured
on wm0, and
.Li $var2
is the dynamic list of all the IPv4 and IPv6 addresses configured on wm0.
The first three rules are equivalent, because with the
.Ic block Ar "..." Cm on Li < Ns Ar interface Ns Li >
syntax, NPF expects a direct reference to an interface, and therefore does
not consider the extraction functions.
The fourth and fifth rules are equivalent, for the same reason.
.Ss Groups
NPF requires that all rules be defined within groups.
Groups can be thought of as higher level rules which can contain subrules.
Groups may have the following options: name, interface, and 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
.Dv default
group.
The
.Dv default
group must always be defined.
.Pp
Example of configuration:
.Bd -literal -offset indent
group "my-name" in on wm0 {
	# List of rules, for packets received on wm0
}
group default {
	# List of rules, for the other packets
}
.Ed
.Ss Rules
With a rule statement NPF is instructed to
.Ic pass
or
.Ic block
a packet depending on packet header information, transit direction and
the interface it arrived on, either immediately upon match or using the
last match.
.Pp
If a packet matches a rule which has the
.Cm final
option set, this rule is considered the last matching rule, and
evaluation of subsequent rules is skipped.
Otherwise, the last matching rule is used.
.Pp
The
.Cm proto
keyword can be used to filter packets by layer 4 protocol (TCP, UDP, ICMP
or other).
Its parameter should be a protocol number or its symbolic name,
as specified in the
.Pa /etc/protocols
file.
This keyword can additionally have protocol-specific options, such as
.Cm flags .
.Pp
The
.Cd flags
keyword can be used to match the packets against specific TCP flags,
according to the following syntax:
.Pp
.D1 Ic proto Cm tcp flags Ar match Ns Op Li / Ns Ar mask
.Pp
Where
.Ar match
is the set of TCP flags to be matched, out of the
.Ar mask
set, both sets being represented as a string combination of:
.Sq Cm S
(SYN),
.Sq Cm A
(ACK),
.Sq Cm F
(FIN), and
.Sq Cm R
(RST).
The flags that are not present in
.Ar mask
are ignored.
.Pp
To notify the sender of a blocking decision, three
.Cm return
options can be used in conjunction with a
.Ic block
rule:
.Bl -tag -width "Cm return-icmp" -offset indent
.It Cm return
Behaves as
.Cm return-rst
or
.Cm return-icmp ,
depending on whether the packet being blocked is TCP or UDP.
.It Cm return-rst
Return a TCP RST message, when the packet being blocked is a TCP packet.
Applies to IPv4 and IPv6.
.It Cm return-icmp
Return an ICMP UNREACHABLE message, when the packet being blocked is a UDP packet.
Applies to IPv4 and IPv6.
.El
.Pp
The
.Cm from
and
.Cm to
keywords are provided to filter by source or destination IP addresses.
They can be used in conjunction with the
.Cm port
keyword.
Negation (the exclamation mark) can be used in front of the address
filter criteria.
.Pp
Further packet specification at present is limited to TCP and UDP
understanding source and destination ports, and ICMP and IPv6-ICMP
understanding icmp-type.
.Pp
A rule can also instruct NPF to create an entry in the state table when
passing the packet or to apply a procedure to the packet (e.g. "log").
.Pp
A
.Dq fully-featured
rule would for example be:
.Bd -literal -offset indent
pass stateful in final family inet4 proto tcp flags S/SA \e
        from $source port $sport to $dest port $dport    \e
        apply \*qsomeproc\*q
.Ed
.Pp
Alternatively, NPF supports
.Xr pcap-filter 7
syntax, for example:
.Pp
.Dl block out final pcap-filter \*qtcp and dst 10.1.1.252\*q
.Pp
Fragments are not selectable since NPF always reassembles packets
before further processing.
.Ss Stateful
NPF supports stateful packet inspection which can be used to bypass
unnecessary rule processing as well as to complement NAT.
The connection state is uniquely identified by an n-tuple: IP version,
layer 4 protocol, source and destination IP addresses and port numbers.
Each state is represented by two keys: one for the original flow and
one for the reverse flow, so that the reverse lookup on the returning
packets would succeed.
The packets are matched against the connection direction respectively.
.Pp
Depending on the settings (see the section on
.Li state.key
in the
.Xr npf-params 7
manual), the connection identifier (keys) may also include the interface ID,
making the states per-interface.
.Pp
Stateful packet inspection is enabled using the
.Cm stateful
or
.Cm stateful-all
keywords.
The former matches the interface after the state lookup, while the latter
avoids matching the interface (assuming the
.Li state.key.interface
parameter is disabled),
i.e. making the state global, and must be used with caution.
In both cases, a full TCP state tracking is performed for TCP connections
and a limited tracking for message-based protocols (UDP and ICMP).
.Pp
By default, a stateful rule implies SYN-only flag check
.Pq Dq Li flags S/SAFR
for the TCP packets.
It is not advisable to change this behavior; however,
it can be overridden with the aforementioned
.Cm flags
keyword.
.Ss Map
Network Address Translation (NAT) is expressed in a form of segment mapping.
The translation may be
.Cm dynamic
(stateful) or
.Cm static
(stateless).
The following mapping types are available:
.Pp
.Bl -tag -width "Cm \&<->" -offset indent -compact
.It Cm \&->
outbound NAT (translation of the source)
.It Cm \&<-
inbound NAT (translation of the destination)
.It Cm \&<->
bi-directional NAT (combination of inbound and outbound NAT)
.El
.Pp
The following would translate the source (10.1.1.0/24) to the IP address
specified by
.Li $pub_ip
for the packets on the interface
.Li $ext_if .
.Pp
.Dl map $ext_if dynamic 10.1.1.0/24 -> $pub_ip
.Pp
Translations are implicitly filtered by limiting the operation to the
network segments specified, that is, translation would be performed only
on packets originating from the 10.1.1.0/24 network.
Explicit filter criteria can be specified using
.Cm pass Ar criteria ...
as an additional option of the mapping.
.Pp
The dynamic NAT implies network address and port translation (NAPT).
The port translation can be controlled explicitly.
For example, the following provides
.Dq port forwarding ,
redirecting the public port 9022 to the port 22 of an internal host:
.Pp
.Dl map $ext_if dynamic proto tcp 10.1.1.2 port 22 <- $ext_if port 9022
.Pp
In the regular dynamic NAT case, it is also possible to disable port
translation using the
.Cm no-ports
flag.
.Pp
The translation address can also be dynamic, based on the interface.
The following would select the IPv4 address(es) currently assigned to the
interface:
.Pp
.Dl map $ext_if dynamic 10.1.1.0/24 -> ifaddrs($ext_if)
.Pp
If the dynamic NAT is configured with multiple translation addresses,
then a custom selection algorithm can be chosen using the
.Cm algo
keyword.
The currently available algorithms for the dynamic translation are:
.Bl -tag -width "Cm round-robin" -offset indent
.It Cm ip-hash
The translation address for a new connection is selected based on a
hash of the original source and destination addresses.
This algorithms attempts to keep all connections of particular client
associated with the same translation address.
This is the default algorithm.
.It Cm round-robin
The translation address for each new connection is selected on a
round-robin basis.
.It Cm netmap
See the description below.
.El
.Pp
The static NAT can also have different address translation algorithms,
chosen using the
.Cm algo
keyword.
The currently available algorithms are:
.Bl -tag -width "Cm netmap" -offset indent
.It Cm netmap
Network address mapping from one segment to another, leaving the host
part as-is.
The new address is computed as following:
.Pp
.Dl addr = net-addr | (orig-addr & ~mask)
.It Cm npt66
IPv6-to-IPv6 network prefix translation (NPTv6).
.El
.Pp
If no algorithm is specified, then 1:1 address mapping is assumed.
Currently, the static NAT algorithms do not perform port translation.
.Ss Application Level Gateways
Certain application layer protocols are not compatible with NAT and require
translation outside layers 3 and 4.
Such translation is performed by packet filter extensions called
Application Level Gateways (ALGs).
.Pp
NPF supports the following ALGs:
.Bl -tag -width "Cm icmp" -offset indent
.It Cm icmp
ICMP ALG.
Applies to IPv4 and IPv6.
Allows to find an active connection by looking at the ICMP payload, and to
perform NAT translation of the ICMP payload.
Generally, this ALG is necessary to support
.Xr traceroute 8
behind the NAT, when using the UDP or TCP probes.
.El
.Pp
The ALGs are built-in.
If NPF is used as kernel module, then they come as kernel modules too.
In such case, the ALG kernel modules can be autoloaded through the
configuration, using the
.Cm alg
keyword.
.Pp
For example:
.Pp
.Dl alg \*qicmp\*q
.Pp
Alternatively, the ALG kernel modules can be loaded manually, using
.Xr modload 8 .
.Ss Procedures
A rule procedure is defined as a collection of extension calls (it
may have none).
Every extension call has a name and a list of options in the form of
key-value pairs.
Depending on the call, the key might represent the argument and the value
might be optional.
Available options:
.Bl -tag -width "Cm log: Ar interface" -offset indent
.It Cm log : Ar interface
Log events.
This requires the
.Pa npf_ext_log
kernel module, which would normally get
auto-loaded by NPF.
The specified npflog interface would also be auto-created once the
configuration is loaded.
The log packets can be written to a file using the
.Xr npfd 8
daemon.
.It Cm normalize : Ar option1 Ns Op Li \&, Ar option2 ...
Modify packets according to the specified normalization options.
This requires the
.Pa npf_ext_normalize kernel
module, which would normally get auto-loaded by NPF.
.El
.Pp
The available normalization options are:
.Bl -tag -width "Cm \*qmin-mss\*q Ar value" -offset indent
.It Cm \*qmax-mss\*q Ar value
Enforce a maximum value for the Maximum Segment Size (MSS) TCP option.
Typically, for
.Dq MSS clamping .
.It Cm \*qmin-ttl\*q Ar value
Enforce a minimum value for the IPv4 Time To Live (TTL) parameter.
.It Cm \*qno-df\*q
Remove the Don't Fragment (DF) flag from IPv4 packets.
.It Cm \*qrandom-id\*q
Randomize the IPv4 ID parameter.
.El
.Pp
For example:
.Bd -literal -offset indent
procedure "someproc" {
	log: npflog0
	normalize: "random-id", "min-ttl" 64, "max-mss" 1432
}
.Ed
.Pp
In this case, the procedure calls the logging and normalization modules.
.Ss Parameter settings
NPF supports a set of dynamically tunable configuration-wide parameters.
For example:
.Bd -literal -offset indent
set state.tcp.timeout.time_wait 0  # destroy the state immediately
.Ed
.Pp
See
.Xr npf-params 7
for the list of parameters and their details.
.Ss Misc
Text after a hash
.Pq Sq #
character is considered a comment.
The backslash
.Pq Sq \e
character at the end of a line marks a continuation line,
i.e., the next line is considered an extension of the present line.
.Sh GRAMMAR
The following is a non-formal BNF-like definition of the grammar.
The definition is simplified and is intended to be human readable,
therefore it does not strictly represent the formal grammar.
.Bd -literal
# Syntax of a single line.  Lines can be separated by LF (\\n) or
# a semicolon.  Comments start with a hash (#) character.

syntax		= var-def | set-param | alg | table-def |
		  map | group | proc | comment

# Variable definition.  Names can be alpha-numeric, including "_"
# character.

var-name	= "$" . string
interface	= interface-name | var-name
var-def		= var "=" ( var-value | "{" value *[ "," value ] "}" )

# Parameter setting.
set-param	= "set" param-value

# Application level gateway.  The name should be in double quotes.

alg		= "alg" alg-name
alg-name	= "icmp"

# Table definition.  Table ID shall be numeric.  Path is in the
# double quotes.

table-id	= <table-name>
table-def	= "table" table-id "type" ( "ipset" | "lpm" | "const" )
		  [ "file" path ]

# Mapping for address translation.

map		= map-common | map-ruleset
map-common	= "map" interface
		  ( "static" [ "algo" map-algo ] | "dynamic" )
		  [ map-flags ] [ proto ]
		  map-seg ( "->" | "<-" | "<->" ) map-seg
		  [ "pass" [ proto ] filt-opts ]
map-ruleset	= "map" "ruleset" group-opts

map-algo	= "ip-hash" | "round-robin" | "netmap" | "npt66"
map-flags	= "no-ports"
map-seg		= ( addr-mask | interface ) [ port-opts ]

# Rule procedure definition.  The name should be in the double quotes.
#
# Each call can have its own options in a form of key-value pairs.
# Both key and values may be strings (either in double quotes or not)
# and numbers, depending on the extension.

proc		= "procedure" proc-name "{" *( proc-call [ new-line ] ) "}"
proc-opts	= key [ " " val ] [ "," proc-opts ]
proc-call	= call-name ":" proc-opts new-line

# Group definition and the rule list.

group		= "group" ( "default" | group-opts ) "{" rule-list "}"
group-opts	= name-string [ "in" | "out" ] [ "on" interface ]
rule-list	= [ rule new-line ] rule-list

npf-filter	= [ "family" family-opt ] [ proto ] ( "all" | filt-opts )
static-rule	= ( "block" [ block-opts ] | "pass" )
		  [ "stateful" | "stateful-all" ]
		  [ "in" | "out" ] [ "final" ] [ "on" interface ]
		  ( npf-filter | "pcap-filter" pcap-filter-expr )
		  [ "apply" proc-name ]

dynamic-ruleset	= "ruleset" group-opts
rule		= static-rule | dynamic-ruleset

tcp-flag-mask	= tcp-flags
tcp-flags	= [ "S" ] [ "A" ] [ "F" ] [ "R" ]
block-opts	= "return-rst" | "return-icmp" | "return"

family-opt	= "inet4" | "inet6"
proto-opts	= "flags" tcp-flags [ "/" tcp-flag-mask ] |
		  "icmp-type" type [ "code" icmp-code ]
proto		= "proto" protocol [ proto-opts ]

filt-opts	= "from" filt-addr [ port-opts ] "to" filt-addr [ port-opts ]
filt-addr	= [ "!" ] [ interface | addr-mask | table-id | "any" ]

port-opts	= "port" ( port-num | port-from "-" port-to | var-name )
addr-mask	= addr [ "/" mask ]
.Ed
.\" -----
.Sh FILES
.Bl -tag -width Pa -compact
.It Pa /dev/npf
control device
.It Pa /etc/npf.conf
default configuration file
.It Pa /usr/share/examples/npf
directory containing further examples
.El
.\" -----
.Sh EXAMPLES
.Bd -literal
$ext_if = { inet4(wm0) }
$int_if = { inet4(wm1) }

table <blocklist> type ipset file "/etc/npf_blocklist"
table <limited> type lpm

$services_tcp = { http, https, smtp, domain, 6000, 9022 }
$services_udp = { domain, ntp, 6000 }
$localnet = { 10.1.1.0/24 }

alg "icmp"

# These NAT rules will dynamically select the interface address(es).
map $ext_if dynamic 10.1.1.0/24 -> ifaddrs($ext_if)
map $ext_if dynamic proto tcp 10.1.1.2 port 22 <- ifaddrs($ext_if) port 9022

procedure "log" {
	# The logging facility can be used together with npfd(8).
	log: npflog0
}

group "external" on $ext_if {
	pass stateful out final all

	block in final from <blocklist>
	pass stateful in final family inet4 proto tcp to $ext_if \e
		port ssh apply "log"
	pass stateful in final proto tcp to $ext_if \e
		port $services_tcp
	pass stateful in final proto udp to $ext_if \e
		port $services_udp
	pass stateful in final proto tcp to $ext_if \e
		port 49151-65535  # passive FTP
	pass stateful in final proto udp to $ext_if \e
		port 33434-33600  # traceroute
}

group "internal" on $int_if {
	block in all
	block in final from <limited>

	# Ingress filtering as per BCP 38 / RFC 2827.
	pass in final from $localnet
	pass out final all
}

group default {
	pass final on lo0 all
	block all
}
.Ed
.\" -----
.Sh SEE ALSO
.Xr bpf 4 ,
.Xr npf 7 ,
.Xr npf-params 7 ,
.Xr pcap-filter 7 ,
.Xr npfctl 8 ,
.Xr npfd 8
.Pp
.Lk http://rmind.github.io/npf/ "NPF documentation website"
.Sh HISTORY
NPF first appeared in
.Nx 6.0 .
.Sh AUTHORS
NPF was designed and implemented by
.An Mindaugas Rasiukevicius .