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
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
.\"	$NetBSD: ipf.5,v 1.5.18.1 2019/10/11 18:19:31 martin Exp $
.\"
.TH IPF 5
.SH NAME
ipf, ipf.conf \- IPFilter firewall rules file format
.SH DESCRIPTION
.PP
The ipf.conf file is used to specify rules for the firewall, packet
authentication and packet accounting components of IPFilter. To load rules
specified in the ipf.conf file, the ipf(8) program is used.
.PP
For use as a firewall, there are two important rule types: those that block
and drop packets (block rules) and those that allow packets through (pass
rules.) Accompanying the decision to apply is a collection of statements
that specify under what conditions the result is to be applied and how.
.PP
The simplest rules that can be used in ipf.conf are expressed like this:
.PP
.nf
block in all
pass out all
.fi
.PP
Each rule must contain at least the following three components
.RS
.IP *
a decision keyword (pass, block, etc.)
.IP *
the direction of the packet (in or out)
.IP *
address patterns or "all" to match any address information
.RE
.SS Long lines
.PP
For rules lines that are particularly long, it is possible to split
them over multiple lines implicity like this:
.PP
.nf
pass in on bgeo proto tcp from 1.1.1.1 port > 1000
    to 2.2.2.2 port < 5000 flags S keep state
.fi
.PP
or explicitly using the backslash ('\\') character:
.PP
.nf
pass in on bgeo proto tcp from 1.1.1.1 port > 1000 \\
    to 2.2.2.2 port < 5000 flags S keep state
.fi
.SS Comments
.PP
Comments in the ipf.conf file are indicated by the use of the '#' character.
This can either be at the start of the line, like this:
.PP
.nf
# Allow all ICMP packets in
pass in proto icmp from any to any
.fi
.PP
Or at the end of a like, like this:
.PP
.nf
pass in proto icmp from any to any # Allow all ICMP packets in
.fi
.SH Firewall rules
.PP
This section goes into detail on how to construct firewall rules that
are placed in the ipf.conf file.
.PP
It is beyond the scope of this document to describe what makes a good
firewall rule set or which packets should be blocked or allowed in.
Some suggestions will be provided but further reading is expected to
fully understand what is safe and unsafe to allow in/out.
.SS Filter rule keywords
.PP
The first word found in any filter rule describes what the eventual outcome
of a packet that matches it will be. Descriptions of the many and various
sections that can be used to match on the contents of packet headers will
follow on below.
.PP
The complete list of keywords, along with what they do is as follows:
.RS
.HP
pass
rules that match a packet indicate to ipfilter that it should be
allowed to continue on in the direction it is flowing.
.HP
block
rules are used when it is desirable to prevent a packet from going
any further. Packets that are blocked on the "in" side are never seen by
TCP/IP and those that are blocked going "out" are never seen on the wire.
.HP
log
when IPFilter successfully matches a packet against a log rule a log
record is generated and made available for ipmon(8) to read. These rules
have no impact on whether or not a packet is allowed through or not.
So if a packet first matched a block rule and then matched a log rule,
the status of the packet after the log rule is that it will still be
blocked.
.HP
count
rules provide the administrator with the ability to count packets and
bytes that match the criteria laid out in the configuration file.
The count rules are applied after NAT and filter rules on the inbound
path. For outbound packets, count rules are applied before NAT and
before the packet is dropped. Thus the count rule cannot be used as
a true indicator of link layer
.HP
auth
rules cause the matching packet to be queued up for processing by a
user space program. The user space program is responsible for making
an ioctl system call to collect the information about the queued
packet and another ioctl system call to return the verdict (block,
pass, etc) on what to do with the packet. In the event that the queue
becomes full, the packets will end up being dropped.
.HP
call
provides access to functions built into IPFilter that allow for more
complex actions to be taken as part of the decision making that goes
with the rule.
.HP
decapsulate
rules instruct ipfilter to remove any
other headers (IP, UDP, AH) and then process what is inside as a new packet.
For non-UDP packets, there are builtin checks that are applied in addition
to whatever is specified in the rule, to only allow decapsulation of
recognised protocols. After decapsulating the inner packet, any filtering
result that is applied to the inner packet is also applied to the other
packet.
.PP
The default way in which filter rules are applied is for the last
matching rule to be used as the decision maker. So even if the first
rule to match a packet is a pass, if there is a later matching rule
that is a block and no further rules match the packet, then it will
be blocked.
.SS Matching Network Interfaces
.PP
On systems with more than one network interface, it is necessary
to be able to specify different filter rules for each of them.
In the first instance, this is because different networks will send us
packets via each network interface but it is also because of the hosts,
the role and the resulting security policy that we need to be able to
distinguish which network interface a packet is on.
.PP
To accomodate systems where the presence of a network interface is
dynamic, it is not necessary for the network interface named in a
filter rule to be present in the system when the rule is loaded.
This can lead to silent errors being introduced and unexpected
behaviour with the simplest of keyboard mistakes - for example,
typing in hem0 instead of hme0 or hme2 instead of hme3.
.PP
On Solaris systems prior to Solaris 10 Update 4, it is not possible
to filter packets on the loopback interface (lo0) so filter rules
that specify it will have no impact on the corresponding flow of
packets. See below for Solaris specific tips on how to enable this.
.PP
Some examples of including the network interface in filter rules are:
.PP
.nf
block in on bge0 all
pass out on bge0 all
.fi
.SS Address matching (basic)
.PP
The first and most basic part of matching for filtering rules is to
specify IP addresses and TCP/UDP port numbers. The source address
information is matched by the "from" information in a filter rule
and the destination address information is matched with the "to"
information in a filter rule.
.PP
The typical format used for IP addresses is CIDR notation, where an
IP address (or network) is followed by a '/' and a number representing
the size of the netmask in bits. This notation is used for specifying
address matching in both IPv4 and IPv6. If the '/' and bitmask size
are excluded from the matching string, it is assumed that the address
specified is a host address and that the netmask applied should be
all 1's.
.PP
Some examples of this are:
.PP
.nf
pass in from 10.1.0.0/24 to any
block out from any to 10.1.1.1
.fi
.PP
It is not possible to specify a range of addresses that does not
have a boundary that can be defined by a standard subnet mask.
.IP
.B Names instead of addresses
.RS
.PP
Hostnames, resolved either via DNS or /etc/hosts, or network names,
resolved via /etc/networks, may be used in place of actual addresses
in the filter rules. WARNING: if a hostname expands to more than one
address, only the *first* is used in building the filter rule.
.PP
Caution should be exercised when relying on DNS for filter rules in
case the sending and receiving of DNS packets is blocked when ipf(8)
is processing that part of the configuration file, leading to long
delays, if not errors, in loading the filter rules.
.RE
.SS Protocol Matching
.PP
To match packets based on TCP/UDP port information, it is first necessary
to indicate which protocol the packet must be. This is done using the
"proto" keyword, followed by either the protocol number or a name which
is mapped to the protocol number, usually through the /etc/protocols file.
.PP
.nf
pass in proto tcp from 10.1.0.0/24 to any
block out proto udp from any to 10.1.1.1
pass in proto icmp from any to 192.168.0.0/16
.fi
.SS Sending back error packets
.PP
When a packet is just discarded using a block rule, there is no feedback given
to the host that sent the packet. This is both good and bad. If this is the
desired behaviour and it is not desirable to send any feedback about packets
that are to be denied. The catch is that often a host trying to connect to a
TCP port or with a UDP based application will send more than one packet
because it assumes that just one packet may be discarded so a retry is
required. The end result being logs can become cluttered with duplicate
entries due to the retries.
.PP
To address this problem, a block rule can be qualified in two ways.
The first of these is specific to TCP and instructs IPFilter to send back
a reset (RST) packet. This packet indicates to the remote system that the
packet it sent has been rejected and that it shouldn't make any further
attempts to send packets to that port. Telling IPFilter to return a TCP
RST packet in response to something that has been received is achieved
with the return-rst keyword like this:
.PP
.nf
block return-rst in proto tcp from 10.0.0.0/8 to any
.fi
.PP
When sending back a TCP RST packet, IPFilter must construct a new packet
that has the source address of the intended target, not the source address
of the system it is running on (if they are different.)
.PP
For all of the other protocols handled by the IP protocol suite, to send
back an error indicating that the received packet was dropped requires
sending back an ICMP error packet. Whilst these can also be used for TCP,
the sending host may not treat the received ICMP error as a hard error
in the same way as it does the TCP RST packet. To return an ICMP error
it is necessary to place return-icmp after the block keyword like this:
.PP
.nf
block return-icmp in proto udp from any to 192.168.0.1/24 
.fi
.PP
When electing to return an ICMP error packet, it is also possible to
select what type of ICMP error is returned. Whilst the full compliment
of ICMP unreachable codes can be used by specifying a number instead of
the string below, only the following should be used in conjunction with
return-icmp. Which return code to use is a choice to be made when
weighing up the pro's and con's. Using some of the codes may make it
more obvious that a firewall is being used rather than just the host
not responding.
.RS
.HP
filter-prohib
(prohibited by filter)
sending packets to the destination given in the received packet is
prohibited due to the application of a packet filter
.HP
net-prohib
(prohibited network)
sending packets to the destination given in the received packet is
administratively prohibited.
.HP
host-unk
(host unknown)
the destination host address is not known by the system receiving
the packet and therefore cannot be reached.
.HP
host-unr
(host unreachable)
it is not possible to reach the host as given by the destination address
in the packet header.
.HP
net-unk
(network unknown)
the destination network address is not known by the system receiving
the packet and therefore cannot be reached.
.HP
net-unr
(network unreachable)
it is not possible to forward the packet on to its final destination
as given by the destination address
.HP
port-unr
(port unreachable)
there is no application using the given destination port and therefore
it is not possible to reach that port.
.HP
proto-unr
(protocol unreachable)
the IP protocol specified in the packet is not available to receive
packets.
.DE
.PP
An example that shows how to send back a port unreachable packet for
UDP packets to 192.168.1.0/24 is as follows:
.PP
.nf
block return-icmp(port-unr) in proto udp from any to 192.168.1.0/24 
.fi
.PP
In the above examples, when sending the ICMP packet, IPFilter will construct
a new ICMP packet with a source address of the network interface used to
send the packet back to the original source. This can give away that there
is an intermediate system blocking packets. To have IPFilter send back
ICMP packets where the source address is the original destination, regardless
of whether or not it is on the local host, return-icmp-as-dest is used like
this:
.PP
.nf
block return-icmp-as-dest(port-unr) in proto udp \\
    from any to 192.168.1.0/24 
.fi
.SS TCP/UDP Port Matching
.PP
Having specified which protocol is being matched, it is then possible to
indicate which port numbers a packet must have in order to match the rule.
Due to port numbers being used differently to addresses, it is therefore
possible to match on them in different ways. IPFilter allows you to use
the following logical operations:
.IP "< x"
is true if the port number in the packet is less than x 
.IP "<= x"
is true if the port number in the packet is less than or equal to x 
.IP "> x"
is true if the port number in the packet is greater than x
.IP ">= x"
is true if the port number in the packet is greater or equal to x
.IP "= x"
is true if the port number in the packet is equal to x
.IP "!= x"
is true if the port number in the packet is not equal to x
.PP
Additionally, there are a number of ways to specify a range of ports:
.IP "x <> y"
is true if the port number is less than x and greater than y
.IP "x >< y"
is true if the port number is greater than x and less than y
.IP "x:y"
is true if the port number is greater than or equal to x and less than or
equal to y
.PP
Some examples of this are:
.PP
.nf
block in proto tcp from any port >= 1024 to any port < 1024
pass in proto tcp from 10.1.0.0/24 to any port = 22
block out proto udp from any to 10.1.1.1 port = 135
pass in proto udp from 1.1.1.1 port = 123 to 10.1.1.1 port = 123
pass in proto tcp from 127.0.0.0/8 to any port 6000:6009
.fi
.PP
If there is no desire to mention any specific source or destintion
information in a filter rule then the word "all" can be used to
indicate that all addresses are considered to match the rule.
.SS IPv4 or IPv6
.PP
If a filter rule is constructed without any addresses then IPFilter
will attempt to match both IPv4 and IPv6 packets with it. In the
next list of rules, each one can be applied to either network protocol
because there is no address specified from which IPFilter can derive
with network protocol to expect.
.PP
.nf
pass in proto udp from any to any port = 53
block in proto tcp from any port < 1024 to any
.fi
.PP
To explicitly match a particular network address family with a specific
rule, the family must be added to the rule. For IPv4 it is necessary to
add family inet and for IPv6, family inet6. Thus the next rule will
block all packets (both IPv4 and IPv6:
.PP
.nf
block in all
.fi
.PP
but in the following example, we block all IPv4 packets and only allow
in IPv6 packets:
.PP
.nf
block in family inet all
pass in family inet6 all
.fi
.PP
To continue on from the example where we allowed either IPv4 or IPv6
packets to port 53 in, to change that such that only IPv6 packets to
port 53 need to allowed blocked then it is possible to add in a
protocol family qualifier:
.PP
.nf
pass in family inet6 proto udp from any to any port = 53
.fi
.SS First match vs last match
.PP
To change the default behaviour from being the last matched rule decides
the outcome to being the first matched rule, the word "quick" is inserted
to the rule.
.SH Extended Packet Matching
.SS Beyond using plain addresses
.PP
On firewalls that are working with large numbers of hosts and networks
or simply trying to filter discretely against various hosts, it can
be an easier administration task to define a pool of addresses and have
a filter rule reference that address pool rather than have a rule for
each address.
.PP
In addition to being able to use address pools, it is possible to use
the interface name(s) in the from/to address fields of a rule. If the
name being used in the address section can be matched to any of the
interface names mentioned in the rule's "on" or "via" fields then it
can be used with one of the following keywords for extended effect:
.HP
broadcast
use the primary broadcast address of the network interface for matching
packets with this filter rule;
.IP
.nf
pass in on fxp0 proto udp from any to fxp0/broadcast port = 123
.fi
.HP
peer
use the peer address on point to point network interfaces for matching
packets with this filter rule. This option typically only has meaningful
use with link protocols such as SLIP and PPP.
For example, this rule allows ICMP packets from the remote peer of ppp0
to be received if they're destined for the address assigned to the link
at the firewall end.
.IP
.nf
pass in on ppp0 proto icmp from ppp0/peer to ppp0/32
.fi
.HP
netmasked
use the primary network address, with its netmask, of the network interface
for matching packets with this filter rule. If a network interface had an
IP address of 192.168.1.1 and its netmask was 255.255.255.0 (/24), then
using the word "netmasked" after the interface name would match any
addresses that would match 192.168.1.0/24. If we assume that bge0 has
this IP address and netmask then the following two rules both serve
to produce the same effect:
.IP
.nf
pass in on bge0 proto icmp from any to 192.168.1.0/24
pass in on bge0 proto icmp from any to bge0/netmasked
.fi
.HP
network
using the primary network address, and its netmask, of the network interface,
construct an address for exact matching. If a network interface has an
address of 192.168.1.1 and its netmask is 255.255.255.0, using this
option would only match packets to 192.168.1.0.
.IP
.nf
pass in on bge0 proto icmp from any to bge0/network
.fi
.PP
Another way to use the name of a network interface to get the address
is to wrap the name in ()'s. In the above method, IPFilter
looks at the interface names in use and to decide whether or not
the name given is a hostname or network interface name. With the
use of ()'s, it is possible to tell IPFilter that the name should
be treated as a network interface name even though it doesn't
appear in the list of network interface that the rule ias associated
with.
.IP
.nf
pass in proto icmp from any to (bge0)/32
.fi
.SS Using address pools
.PP
Rather than list out multiple rules that either allow or deny specific
addresses, it is possible to create a single object, call an address
pool, that contains all of those addresses and reference that in the
filter rule. For documentation on how to write the configuration file
for those pools and load them, see ippool.conf(5) and ippool(8).
There are two types of address pools that can be defined in ippool.conf(5):
trees and hash tables. To refer to a tree defined in ippool.conf(5),
use this syntax:
.PP
.nf
pass in from pool/trusted to any
.fi
.PP
Either a name or number can be used after the '/', just so long as it
matches up with something that has already been defined in ipool.conf(5)
and loaded in with ippool(8). Loading a filter rule that references a
pool that does not exist will result in an error.
.PP
If hash tables have been used in ippool.conf(5) to store the addresses
in instead of a tree, then replace the word pool with hash:
.IP
.nf
pass in from any to hash/webservers
.fi
.PP
There are different operational characteristics with each, so there
may be some situations where a pool works better than hash and vice
versa.
.SS Matching TCP flags
.PP
The TCP header contains a field of flags that is used to decide if the
packet is a connection request, connection termination, data, etc.
By matching on the flags in conjunction with port numbers, it is
possible to restrict the way in which IPFilter allows connections to
be created.  A quick overview of the TCP
flags is below. Each is listed with the letter used in IPFilter
rules, followed by its three or four letter pneumonic.
.HP
S
SYN - this bit is set when a host is setting up a connection.
The initiator typically sends a packet with the SYN bit and the
responder sends back SYN plus ACK.
.HP
A
ACK - this bit is set when the sender wishes to acknowledge the receipt
of a packet from another host
.HP
P
PUSH - this bit is set when a sending host has send some data that
is yet to be acknowledged and a reply is sought
.HP
F
FIN - this bit is set when one end of a connection starts to close
the connection down
.HP
U
URG - this bit is set to indicate that the packet contains urgent data
.HP
R
RST - this bit is set only in packets that are a reply to another
that has been received but is not targetted at any open port
.HP
C
CWN
.HP
E
ECN
.PP
When matching TCP flags, it is normal to just list the flag that you
wish to be set. By default the set of flags it is compared against
is "FSRPAU". Rules that say "flags S" will be displayed by ipfstat(8)
as having "flags S/FSRPAU". This is normal.
The last two flags, "C" and "E", are optional - they
may or may not be used by an end host and have no bearing on either
the acceptance of data nor control of the connection. Masking them
out with "flags S/FSRPAUCE" may cause problems for remote hosts
making a successful connection.
.PP
.nf
pass in quick proto tcp from any to any port = 22 flags S/SAFR
pass out quick proto tcp from any port = 22 to any flags SA
.fi
.PP
By itself, filtering based on the TCP flags becomes more work but when
combined with stateful filtering (see below), the situation changes.
.SS Matching on ICMP header information
.PP
The TCP and UDP are not the only protocols for which filtering beyond
just the IP header is possible, extended matching on ICMP packets is
also available. The list of valid ICMP types is different for IPv4
vs IPv6.
.PP
As a practical example, to allow the ping command to work
against a specific target requires allowing two different types of
ICMP packets, like this:
.PP
.nf
pass in proto icmp from any to webserver icmp-type echo
pass out proto icmp from webserver to any icmp-type echorep
.fi
.PP
The ICMP header has two fields that are of interest for filtering:
the ICMP type and code. Filter rules can accept either a name or
number for both the type and code. The list of names supported for
ICMP types is listed below, however only ICMP unreachable errors
have named codes (see above.)
.PP
The list of ICMP types that are available for matching an IPv4 packet
are as follows:
.PP
echo (echo request),
echorep (echo reply),
inforeq (information request),
inforep (information reply),
maskreq (mask request),
maskrep (mask reply),
paramprob (parameter problem),
redir (redirect),
routerad (router advertisement),
routersol (router solicit),
squence (source quence),
timest (timestamp),
timestreq (timestamp reply),
timex (time exceeded),
unreach (unreachable).
.PP
The list of ICMP types that are available for matching an IPv6 packet
are as follows:
.PP
echo (echo request),
echorep (echo reply),
fqdnquery (FQDN query),
fqdnreply (FQDN reply),
inforeq (information request),
inforep (information reply),
listendone (MLD listener done),
listendqry (MLD listener query),
listendrep (MLD listener reply),
neighadvert (neighbour advert),
neighborsol (neighbour solicit),
paramprob (parameter problem),
redir (redirect),
renumber (router renumbering),
routerad (router advertisement),
routersol (router solicit),
timex (time exceeded),
toobig (packet too big),
unreach (unreachable,
whoreq (WRU request),
whorep (WRU reply).
.SH Stateful Packet Filtering
.PP
Stateful packet filtering is where IPFilter remembers some information from
one or more packets that it has seen and is able to apply it to future
packets that it receives from the network.
.PP
What this means for each transport layer protocol is different.
For TCP it means that if IPFilter
sees the very first packet of an attempt to make a connection, it has enough
information to allow all other subsequent packets without there needing to
be any explicit rules to match them. IPFilter uses the TCP port numbers,
TCP flags, window size and sequence numbers to determine which packets
should be matched. For UDP, only the UDP port numbers are available.
For ICMP, the ICMP types can be combined with the ICMP id field to
determine which reply packets match a request/query that has already
been seen. For all other protocols, only matching on IP address and
protocol number is available for determining if a packet received is a mate
to one that has already been let through.
.PP
The difference this makes is a reduction in the number of rules from
2 or 4 to 1. For example, these 4 rules:
.PP
.nf
pass in on bge0 proto tcp from any to any port = 22
pass out on bge1 proto tcp from any to any port = 22
pass in on bge1 proto tcp from any port = 22 to any
pass out on bge0 proto tcp from any port = 22 to any
.fi
.PP
can be replaced with this single rule:
.PP
.nf
pass in on bge0 proto tcp from any to any port = 22 flags S keep state
.fi
.PP
Similar rules for UDP and ICMP might be:
.PP
.nf
pass in on bge0 proto udp from any to any port = 53 keep state
pass in on bge0 proto icmp all icmp-type echo keep state
.fi
.PP
When using stateful filtering with TCP it is best to add "flags S" to the
rule to ensure that state is only created when a packet is seen that is
an indication of a new connection. Although IPFilter can gather some
information from packets in the middle of a TCP connection to do stateful
filtering, there are some options that are only sent at the start of the
connection which alter the valid window of what TCP accepts. The end result
of trying to pickup TCP state in mid connection is that some later packets
that are part of the connection may not match the known state information
and be dropped or blocked, causing problems. If a TCP packet matches IP
addresses and port numbers but does not fit into the recognised window,
it will not be automatically allowed and will be flagged inside of
IPFitler as "out of window" (oow). See below, "Extra packet attributes",
for how to match on this attribute.
.PP
Once a TCP connection has reached the established state, the default
timeout allows for it to be idle for 5 days before it is removed from
the state table. The timeouts for the other TCP connection states
vary from 240 seconds to 30 seconds.
Both UDP and ICMP state entries have asymetric timeouts where the timeout
set upon seeing packets in the forward direction is much larger than
for the reverse direction. For UDP the default timeouts are 120 and
12 seconds, for ICMP 60 and 6 seconds. This is a reflection of the
use of these protocols being more for query-response than for ongoing
connections.  For all other protocols the
timeout is 60 seconds in both directions.
.SS Stateful filtering options
.PP
The following options can be used with stateful filtering:
.HP
limit
limit the number of state table entries that this rule can create to
the number given after limit. A rule that has a limit specified is
always permitted that many state table entries, even if creating an
additional entry would cause the table to have more entries than the
otherwise global limit. 
.IP
.nf
pass ... keep state(limit 100)
.fi
.HP
age
sets the timeout for the state entry when it sees packets going through
it. Additionally it is possible to set the tieout for the reply packets
that come back through the firewall to a different value than for the
forward path. allowing a short timeout to be set after the reply has
been seen and the state no longer required.
.RS
.PP
.nf
pass in quick proto icmp all icmp-type echo \\
    keep state (age 3)
pass in quick proto udp from any \\
    to any port = 53 keep state (age 30/1)
.fi
.RE
.HP
strict
only has an impact when used with TCP. It forces all packets that are
allowed through the firewall to be sequential: no out of order delivery
of packets is allowed. This can cause significant slowdown for some
connections and may stall others. Use with caution.
.IP
.nf
pass in proto tcp ... keep state(strict)
.fi
.HP
noicmperr
prevents ICMP error packets from being able to match state table entries
created with this flag using the contents of the original packet included.
.IP
.nf
pass ... keep state(noicmperr)
.fi
.HP
sync
indicates to IPFilter that it needs to provide information to the user
land daemons responsible for syncing other machines state tables up
with this one.
.IP
.nf
pass ... keep state(sync)
.fi
.HP
nolog
do not generate any log records for the creation or deletion of state
table entries.
.IP
.nf
pass ... keep state(nolog)
.fi
.HP
icmp-head
rather than just precent ICMP error packets from being able to match
state table entries, allow an ACL to be processed that can filter in or
out ICMP error packets based as you would with normal firewall rules.
The icmp-head option requires a filter rule group number or name to
be present, just as you would use with head.
.RS
.PP
.nf
pass in quick proto tcp ... keep state(icmp-head 101)
block in proto icmp from 10.0.0.0/8 to any group 101
.fi
.RE
.HP
max-srcs
allows the number of distinct hosts that can create a state entry to
be defined.
.IP
.nf
pass ... keep state(max-srcs 100)
pass ... keep state(limit 1000, max-srcs 100)
.fi
.HP
max-per-src
whilst max-srcs limits the number of individual hosts that may cause
the creation of a state table entry, each one of those hosts is still
table to fill up the state table with new entries until the global
maximum is reached. This option allows the number of state table entries
per address to be limited.
.IP
.nf
pass ... keep state(max-srcs 100, max-per-src 1)
pass ... keep state(limit 100, max-srcs 100, max-per-src 1)
.fi
.IP
Whilst these two rules might seem identical, in that they both
ultimately limit the number of hosts and state table entries created
from the rule to 100, there is a subtle difference: the second will
always allow up to 100 state table entries to be created whereas the
first may not if the state table fills up from other rules.
.IP
Further, it is possible to specify a netmask size after the per-host
limit that enables the per-host limit to become a per-subnet or
per-network limit.
.IP
.nf
pass ... keep state(max-srcs 100, max-per-src 1/24)
.fi
.IP
If there is no IP protocol implied by addresses or other features of
the rule, IPFilter will assume that no netmask is an all ones netmask
for both IPv4 and IPv6.
.SS Tieing down a connection
.PP
For any connection that transits a firewall, each packet will be seen
twice: once going in and once going out. Thus a connection has 4 flows
of packets:
.HP
forward
inbound packets
.HP
forward
outbound packets
.HP
reverse
inbound packets
.HP
reverse
outbound packets
.PP
IPFilter allows you to define the network interface to be used at all
four points in the flow of packets. For rules that match inbound packets,
out-via is used to specify which interfaces the packets go out, For rules
that match outbound packets, in-via is used to match the inbound packets.
In each case, the syntax generalises to this:
.PP
.nf
pass ... in on forward-in,reverse-in \\
       out-via forward-out,reverse-out ...

pass ... out on forward-out,reverse-out \\
         in-via forward-in,reverse-in ...
.fi
.PP
An example that pins down all 4 network interfaces used by an ssh
connection might look something like this:
.PP
.nf
pass in on bge0,bge1 out-via bge1,bge0 proto tcp \\
    from any to any port = 22 flags S keep state
.fi
.SS Working with packet fragments 
.PP
Fragmented packets result in 1 packet containing all of the layer 3 and 4
header information whilst the data is split across a number of other packets.
.PP
To enforce access control on fragmented packets, one of two approaches
can be taken. The first is to allow through all of the data fragments
(those that made up the body of the original packet) and rely on matching
the header information in the "first" fragment, when it is seen. The
reception of body fragments without the first will result in the receiving
host being unable to completely reassemble the packet and discarding all
of the fragments. The following three rules deny all fragmented packets
from being received except those that are UDP and even then only allows
those destined for port 2049 to be completed.
.PP
.nf
block in all with frags
pass in proto udp from any to any with frag-body
pass in proto udp from any to any port = 2049 with frags
.fi
.PP
Another mechanism that is available is to track "fragment state".
This relies on the first fragment of a packet that arrives to be
the fragment that contains all of the layer 3 and layer 4 header
information. With the receipt of that fragment before any other,
it is possible to determine which other fragments are to be allowed
through without needing to explicitly allow all fragment body packets.
An example of how this is done is as follows:
.PP
.nf
pass in proto udp from any prot = 2049 to any with frags keep frags
.fi
.SH Building a tree of rules
.PP
Writing your filter rules as one long list of rules can be both inefficient
in terms of processing the rules and difficult to understand. To make the
construction of filter rules easier, it is possible to place them in groups.
A rule can be both a member of a group and the head of a new group.
.PP
Using filter groups requires at least two rules: one to be in the group
one one to send matchign packets to the group. If a packet matches a
filtre rule that is a group head but does not match any of the rules
in that group, then the packet is considered to have matched the head
rule.
.PP
Rules that are a member of a group contain the word group followed by
either a name or number that defines which group they're in. Rules that
form the branch point or starting point for the group must use the
word head, followed by either a group name or number. If rules are
loaded in that define a group but there is no matching head then they
will effectively be orphaned rules. It is possible to have more than
one head rule point to the same group, allowing groups to be used
like subroutines to implement specific common policies.
.PP
A common use of filter groups is to define head rules that exist in the
filter "main line" for each direction with the interfaces in use. For
example:
.PP
.nf
block in quick on bge0 all head 100
block out quick on bge0 all head 101
block in quick on fxp0 all head internal-in
block out quick on fxp0 all head internal-out
pass in quick proto icmp all icmp-type echo group 100
.fi
.PP
In the above set of rules, there are four groups defined but only one
of them has a member rule. The only packets that would be allowed
through the above ruleset would be ICMP echo packets that are
received on bge0.
.PP
Rules can be both a member of a group and the head of a new group,
allowing groups to specialise.
.PP
.nf
block in quick on bge0 all head 100
block in quick proto tcp all head 1006 group 100
.fi
.PP
Another use of filter rule groups is to provide a place for rules to
be dynamically added without needing to worry about their specific
ordering amongst the entire ruleset. For example, if I was using this
simple ruleset:
.PP
.nf
block in quick all with bad
block in proto tcp from any to any port = smtp head spammers
pass in quick proto tcp from any to any port = smtp flags S keep state
.fi
.PP
and I was getting lots of connections to my email server from 10.1.1.1
to deliver spam, I could load the following rule to complement the above:
.IP
.nf
block in quick from 10.1.1.1 to any group spammers
.fi
.SS Decapsulation
.PP
Rule groups also form a different but vital role for decapsulation rules.
With the following simple rule, if IPFilter receives an IP packet that has
an AH header as its layer 4 payload, IPFilter would adjust its view of the
packet internally and then jump to group 1001 using the data beyond the
AH header as the new transport header.
.PP
.nf
decapsulate in proto ah all head 1001
.fi
.PP
For protocols that
are recognised as being used with tunnelling or otherwise encapsulating
IP protocols, IPFilter is able to decide what it has on the inside
without any assistance. Some tunnelling protocols use UDP as the
transport mechanism. In this case, it is necessary to instruct IPFilter
as to what protocol is inside UDP.
.PP
.nf
decapsulate l5-as(ip) in proto udp from any \\
    to any port = 1520 head 1001
.fi
.PP
Currently IPFilter only supports finding IPv4 and IPv6 headers
directly after the UDP header.
.PP
If a packet matches a decapsulate rule but fails to match any of the rules
that are within the specified group, processing of the packet continues
to the next rule after the decapsulate and IPFilter's internal view of the
packet is returned to what it was prior to the decapsulate rule.
.PP
It is possible to construct a decapsulate rule without the group
head at the end that ipf(8) will accept but such rules will not
result in anything happening.
.SS Policy Based Routing
.PP
With firewalls being in the position they often are, at the boundary
of different networks connecting together and multiple connections that
have different properties, it is often desirable to have packets flow
in a direction different to what the routing table instructs the kernel.
These decisions can often be extended to changing the route based on
both source and destination address or even port numbers.
.PP
To support this kind of configuration, IPFilter allows the next hop
destination to be specified with a filter rule. The next hop is given
with the interface name to use for output. The syntax for this is
interface:ip.address. It is expected that the address given as the next
hop is directly connected to the network to which the interface is.
.PP
.nf
pass in on bge0 to bge1:1.1.1.1 proto tcp \\
    from 1.1.2.3 to any port = 80 flags S keep state
.fi
.PP
When this feature is combined with stateful filtering, it becomes
possible to influence the network interface used to transmit packets
in both directions because we now have a sense for what its reverse
flow of packets is.
.PP
.nf
pass in on bge0 to bge1:1.1.1.1 reply-to hme1:2.1.1.2 \\
    proto tcp from 1.1.2.3 to any port = 80 flags S keep state
.fi
.PP
If the actions of the routing table are perfectly acceptable, but
you would like to mask the presence of the firewall by not changing
the TTL in IP packets as they transit it, IPFilter can be instructed
to do a "fastroute" action like this:
.PP
.nf
pass in on bge0 fastroute proto icmp all
.fi
.PP
This should be used with caution as it can lead to endless packet
loops. Additionally, policy based routing does not change the IP
header's TTL value.
.PP
A variation on this type of rule supports a duplicate of the original
packet being created and sent out a different network. This can be
useful for monitoring traffic and other purposes.
.PP
.nf
pass in on bge0 to bge1:1.1.1.1 reply-to hme1:2.1.1.2 \\
    dup-to fxp0:10.0.0.1 proto tcp from 1.1.2.3 \\
    to any port = 80 flags S keep state
.fi
.SS Matching IPv4 options
.PP
The design for IPv4 allows for the header to be upto 64 bytes long,
however most traffic only uses the basic header which is 20 bytes long.
The other 44 bytes can be uesd to store IP options. These options are
generally not necessary for proper interaction and function on the
Internet today. For most people it is sufficient to block and drop
all packets that have any options set. This can be achieved with this
rule:
.PP
.nf
block in quick all with ipopts
.fi
.PP
This rule is usually placed towards the top of the configuration
so that all incoming packets are blocked.
.PP
If you wanted to allow in a specific IP option type, the syntax
changes slightly:
.PP
.nf
pass in quick proto igmp all with opt rtralrt
.fi
.PP
The following is a list of IP options that most people encounter and
what their use/threat is.
.HP
lsrr
(loose source route) the sender of the packet includes a list of addresses
that they wish the packet to be routed through to on the way to the
destination. Because replies to such packets are expected to use the
list of addresses in reverse, hackers are able to very effectively use
this header option in address spoofing attacks.
.HP
rr
(record route) the sender allocates some buffer space for recording the
IP address of each router that the packet goes through. This is most often
used with ping, where the ping response contains a copy of all addresses
from the original packet, telling the sender what route the packet took
to get there. Due to performance and security issues with IP header
options, this is almost no longer used.
.HP
rtralrt
(router alert) this option is often used in IGMP messages as a flag to
routers that the packet needs to be handled differently. It is unlikely
to ever be received from an unknown sender. It may be found on LANs or
otherwise controlled networks where the RSVP protocol and multicast
traffic is in heavy use.
.HP
ssrr
(strict source route) the sender of the packet includes a list of addresses
that they wish the packet to be routed through to on the way to the
destination. Where the lsrr option allows the sender to specify only
some of the nodes the packet must go through, with the ssrr option,
every next hop router must be specified.
.PP
The complete list of IPv4 options that can be matched on is:
addext (Address Extention),
cipso (Classical IP Security Option),
dps (Dynamic Packet State),
e-sec (Extended Security),
eip (Extended Internet Protocol),
encode (ENCODE),
finn (Experimental Flow Control),
imitd (IMI Traffic Descriptor),
lsrr (Loose Source Route),
mtup (MTU Probe - obsolete),
mtur (MTU response - obsolete),
nop (No Operation),
nsapa (NSAP Address),
rr (Record Route),
rtralrt (Router Alert),
satid (Stream Identifier),
sdb (Selective Directed Broadcast),
sec (Security),
ssrr (Strict Source Route),
tr (Tracerote),
ts (Timestamp),
ump (Upstream Multicast Packet),
visa (Experimental Access Control)
and zsu (Experimental Measurement).
.SS Security with CIPSO and IPSO
.PP
IPFilter supports filtering on IPv4 packets using security attributes embedded
in the IP options part of the packet. These options are usually only used on
networks and systems that are using lablled security. Unless you know that
you are using labelled security and your networking is also labelled, it
is highly unlikely that this section will be relevant to you.
.PP
With the traditional IP Security Options (IPSO), packets can be tagged with
a security level. The following keywords are recognised and match with the
relevant RFC with respect to the bit patterns matched:
confid (confidential),
rserve-1 (1st reserved value),
rserve-2 (2nd reserved value),
rserve-3 (3rd reserved value),
rserve-4 (4th reserved value),
secret (secret),
topsecret (top secret),
unclass (unclassified).
.PP
.nf
block in quick all with opt sec-class unclass
pass in all with opt sec-class secret
.fi
.SS Matching IPv6 extension headers
.PP
Just as it is possible to filter on the various IPv4 header options,
so too it is possible to filter on the IPv6 extension headers that are
placed between the IPv6 header and the transport protocol header.
.PP
dstopts (destination options),
esp (encrypted, secure, payload),
frag (fragment),
hopopts (hop-by-hop options),
ipv6 (IPv6 header),
mobility (IP mobility),
none,
routing.
.SS Logging
.PP
There are two ways in which packets can be logged with IPFilter. The
first is with a rule that specifically says log these types of packets
and the second is a qualifier to one of the other keywords. Thus it is
possible to both log and allow or deny a packet with a single rule.
.PP
.nf
pass in log quick proto tcp from any to any port = 22
.fi
.PP
When using stateful filtering, the log action becomes part of the result
that is remembered about a packet. Thus if the above rule was qualified
with keep state, every packet in the connection would be logged. To only
log the first packet from every packet flow tracked with keep state, it
is necessary to indicate to IPFilter that you only wish to log the first
packet.
.PP
.nf
pass in log first quick proto tcp from any to any port = 22 \\
    flags S keep state
.fi
.PP
If it is a requirement that the logging provide an accurate representation
of which connections are allowed, the log action can be qualified with the
option or-block. This allows the administrator to instruct IPFilter to
block the packet if the attempt to record the packet in IPFilter's kernel
log records (which have an upper bound on size) failed. Unless the system
shuts down or reboots, once a log record is written into the kernel buffer,
it is there until ipmon(8) reads it.
.PP
.nf
block in log proto tcp from any to any port = smtp
pass in log or-block first quick proto tcp from any \\
    to any port = 22 flags S keep state
.fi
.PP
By default, IPFilter will only log the header portion of a packet received
on the network. A portion of the body of a packet, upto 128 bytes, can also
be logged with the body keyword. ipmon(8) will display the contents of the
portion of the body logged in hex.
.PP
.nf
block in log body proto icmp all
.fi
.PP
When logging packets from ipmon(8) to syslog, by default ipmon(8) will
control what syslog facility and priority a packet will be logged with.
This can be tuned on a per rule basis like this:
.PP
.nf
block in quick log level err all with bad
pass in log level local1.info proto tcp \\
    from any to any port = 22 flags S keep state
.fi
.PP
ipfstat(8) reports how many packets have been successfully logged and how
many failed attempts to log a packet there were.
.SS Filter rule comments
.PP
If there is a desire to associate a text string, be it an administrative
comment or otherwise, with an IPFilter rule, this can be achieved by giving
the filter rule a comment.  The comment is loaded with the rule into the
kernel and can be seen when the rules are listed with ipfstat.
.PP
.nf
pass in quick proto tcp from any \\
    to port = 80 comment "all web server traffic is ok"
pass out quick proto tcp from any port = 80 \\
    to any comment "all web server traffic is ok"
.fi
.SS Tags
.PP
To enable filtering and NAT to correctly match up packets with rules,
tags can be added at with NAT (for inbound packets) and filtering (for
outbound packets.) This allows a filter to be correctly mated with its
NAT rule in the event that the NAT rule changed the packet in a way
that would mean it is not obvious what it was.
.PP
For inbound packets, IPFilter can match the tag used in the filter
rules with that set by NAT. For outbound rules, it is the reverse,
the filter sets the tag and the NAT rule matches up with it.
.PP
.nf
pass in ... match-tag(nat=proxy)
pass out ... set-tag(nat=proxy)
.fi
.PP
Another use of tags is to supply a number that is only used with logging.
When packets match these rules, the log tag is carried over into the
log file records generated by ipmon(8). With the correct use of tools
such as grep, extracting log records of interest is simplified.
.PP
.nf
block in quick log ... set-tag(log=33)
.fi
.SH Filter Rule Expiration
.PP
IPFilter allows rules to be added into the kernel that it will remove after
a specific period of time by specifying rule-ttl at the end of a rule.
When listing rules in the kernel using ipfstat(8), rules that are going
to expire will NOT display "rule-ttl" with the timeout, rather what will
be seen is a comment with how many ipfilter ticks left the rule has to
live.
.PP
The time to live is specified in seconds.
.PP
.nf
pass in on fxp0 proto tcp from any \\
    to port = 22 flags S keep state rule-ttl 30
.fi
.SH Internal packet attributes
.PP
In addition to being able to filter on very specific network and transport
header fields, it is possible to filter on other attributes that IPFilter
attaches to a packet. These attributes are placed in a rule after the
keyword "with", as can be seen with frags and frag-body above. The
following is a list of the other attributes available:
.HP
oow
the packet's IP addresses and TCP ports match an existing entry in the
state table but the sequence numbers indicate that it is outside of the
accepted window.
.IP
.nf
block return-rst in quick proto tcp from any to any with not oow
.fi
.HP
bcast
this is set by IPFilter when it receives notification that the link
layer packet was a broadcast packet. No checking of the IP addresses
is performned to determine if it is a broadcast destination or not.
.IP
.nf
block in quick proto udp all with bcast
.fi
.HP
mcast
this is set by IPFilter when it receives notification that the link
layer packet was a multicast packet. No checking of the IP addresses
is performned to determine if it is a multicast destination or not.
.IP
.nf
pass in quick proto udp from any to any port = dns with mcast
.fi
.HP
mbcast
can be used to match a packet that is either a multicast or broadcast
packet at the link layer, as indicated by the operating system.
.IP
.nf
pass in quick proto udp from any to any port = ntp with mbcast
.fi
.HP
nat
the packet positively matched a NAT table entry.
.HP
bad
sanity checking of the packet failed. This could indicate that the
layer 3/4 headers are not properly formed.
.HP
bad-src
when reverse path verification is enabled, this flag will be set when
the interface the packet is received on does not match that which would
be used to send a packet out of to the source address in the received
packet.
.HP
bad-nat
an attempt to perform NAT on the packet failed.
.HP
not
each one of the attributes matched using the "with" keyword can also be
looked for to not be present. For example, to only allow in good packets,
I can do this:
.PP
.nf
block in all
pass in all with not bad
.fi
.SH Tuning IPFilter
.PP
The ipf.conf file can also be used to tune the behaviour of IPFilter,
allowing, for example, timeouts for the NAT/state table(s) to be set
along with their sizes. The presence and names of tunables may change
from one release of IPFilter to the next. The tunables that can be
changed via ipf.conf is the same as those that can be seen and modified
using the -T command line option to ipf(8).
.PP
NOTE: When parsing ipf.conf, ipf(8) will apply the settings before
loading any rules. Thus if your settings are at the top, these may
be applied whilst the rules not applied if there is an error further
down in the configuration file.
.PP
To set one of the values below, the syntax is simple: "set", followed
by the name of the tuneable to set and then the value to set it to.
.PP
.nf
set state_max 9999;
set state_size 10101;
.fi
.PP
A list of the currently available variables inside IPFilter that may
be tuned from ipf.conf are as follows:
.HP
active
set through -s command line switch of ipf(8). See ipf(8) for detals.
.HP
chksrc
when set, enables reverse path verification on source addresses and
for filters to match packets with bad-src attribute.
.HP
control_forwarding
when set turns off kernel forwarding when IPFilter is disabled or unloaded.
.HP
default_pass
the default policy - whether packets are blocked or passed, etc - is
represented by the value of this variable. It is a bit field and the
bits that can be set are found in <netinet/ip_fil.h>. It is not
recommended to tune this value directly.
.HP
ftp_debug
set the debugging level of the in-kernel FTP proxy.
Debug messages will be printed to the system console.
.HP
ftp_forcepasv
when set the FTP proxy must see a PASV/EPSV command before creating
the state/NAT entries for the 227 response.
.HP
ftp_insecure
when set the FTP proxy will not wait for a user to login before allowing
data connections to be created.
.HP
ftp_pasvonly
when set the proxy will not create state/NAT entries for when it
sees either the PORT or EPRT command.
.HP
ftp_pasvrdr
when enabled causes the FTP proxy to create very insecure NAT/state
entries that will allow any connection between the client and server
hosts when a 227 reply is seen.  Use with extreme caution.
.HP
ftp_single_xfer
when set the FTP proxy will only allow one data connection at a time.
.HP
hostmap_size
sets the size of the hostmap table used by NAT to store address mappings
for use with sticky rules.
.HP
icmp_ack_timeout
default timeout used for ICMP NAT/state when a reply packet is seen for
an ICMP state that already exists
.HP
icmp_minfragmtu
sets the minimum MTU that is considered acceptable in an ICMP error
before deciding it is a bad packet.
.HP
icmp_timeout
default timeout used for ICMP NAT/state when the packet matches the rule
.HP
ip_timeout
default timeout used for NAT/state entries that are not TCP/UDP/ICMP.
.HP
ipf_flags
.HP
ips_proxy_debug
this sets the debugging level for the proxy support code.
When enabled, debugging messages will be printed to the system console.
.HP
log_all
when set it changes the behaviour of "log body" to log the entire packet
rather than just the first 128 bytes.
.HP
log_size
sets the size of the in-kernel log buffer in bytes.
.HP
log_suppress
when set, IPFilter will check to see if the packet it is logging is
similar to the one it previously logged and if so, increases
the occurance count for that packet. The previously logged packet
must not have yet been read by ipmon(8).
.HP
min_ttl
is used to set the TTL value that packets below will be marked with
the low-ttl attribute.
.HP
nat_doflush
if set it will cause the NAT code to do a more aggressive flush of the
NAT table at the next opportunity. Once the flush has been done, the
value is reset to 0.
.HP
nat_lock
this should only be changed using ipfs(8)
.HP
nat_logging
when set, NAT will create log records that can be read from /dev/ipnat.
.HP
nat_maxbucket
maximum number of entries allowed to exist in each NAT hash bucket.
This prevents an attacker trying to load up the hash table with
entries in a single bucket, reducing performance.
.HP
nat_rules_size
size of the hash table to store map rules.
.HP
nat_table_max
maximum number of entries allowed into the NAT table
.HP
nat_table_size
size of the hash table used for NAT
.HP
nat_table_wm_high
when the fill percentage of the NAT table exceeds this mark, more
aggressive flushing is enabled.
.HP
nat_table_wm_low
this sets the percentage at which the NAT table's agressive flushing
will turn itself off at.
.HP
rdr_rules_size
size of the hash table to store rdr rules.
.HP
state_lock
this should only be changed using ipfs(8)
.HP
state_logging
when set, the stateful filtering will create log records
that can be read from /dev/ipstate.
.HP
state_max
maximum number of entries allowed into the state table
.HP
state_maxbucket
maximum number of entries allowed to exist in each state hash bucket.
This prevents an attacker trying to load up the hash table with
entries in a single bucket, reducing performance.
.HP
state_size
size of the hash table used for stateful filtering
.HP
state_wm_freq
this controls how often the agressive flushing should be run once the
state table exceeds state_wm_high in percentage full.
.HP
state_wm_high
when the fill percentage of the state table exceeds this mark, more
aggressive flushing is enabled.
.HP
state_wm_low
this sets the percentage at which the state table's agressive flushing
will turn itself off at.
.HP
tcp_close_wait
timeout used when a TCP state entry reaches the FIN_WAIT_2 state.
.HP
tcp_closed
timeout used when a TCP state entry is ready to be removed after either
a RST packet is seen.
.HP
tcp_half_closed
timeout used when a TCP state entry reaches the CLOSE_WAIT state.
.HP
tcp_idle_timeout
timeout used when a TCP state entry reaches the ESTABLISHED state.
.HP
tcp_last_ack
timeout used when a TCP NAT/state entry reaches the LAST_ACK state.
.HP
tcp_syn_received
timeout applied to a TCP NAT/state entry after SYN-ACK packet has been seen.
.HP
tcp_syn_sent
timeout applied to a TCP NAT/state entry after SYN packet has been seen.
.HP
tcp_time_wait
timeout used when a TCP NAT/state entry reaches the TIME_WAIT state.
.HP
tcp_timeout
timeout used when a TCP NAT/state entry reaches either the half established
state (one ack is seen after a SYN-ACK) or one side is in FIN_WAIT_1.
.HP
udp_ack_timeout
default timeout used for UDP NAT/state when a reply packet is seen for
a UDP state that already exists
.HP
udp_timeout
default timeout used for UDP NAT/state when the packet matches the rule
.HP
update_ipid
when set, turns on changing the IP id field in NAT'd packets to a random
number.
.SS Table of visible variables
.PP
A list of all of the tunables, their minimum, maximum and current
values is as follows.
.PP
.nf
Name				Min	Max	Current
active			0	0	0
chksrc			0	1	0
control_forwarding	0	1	0
default_pass		0	MAXUINT	134217730
ftp_debug			0	10	0
ftp_forcepasv		0	1	1
ftp_insecure		0	1	0
ftp_pasvonly		0	1	0
ftp_pasvrdr		0	1	0
ftp_single_xfer	0	1	0
hostmap_size		1	MAXINT	2047
icmp_ack_timeout	1	MAXINT	12
icmp_minfragmtu	0	1	68
icmp_timeout		1	MAXINT	120
ip_timeout		1	MAXINT	120
ipf_flags			0	MAXUINT	0
ips_proxy_debug	0	10	0
log_all			0	1	0
log_size			0	524288	32768
log_suppress		0	1	1
min_ttl			0	1	4
nat_doflush		0	1	0
nat_lock			0	1	0
nat_logging		0	1	1
nat_maxbucket		1	MAXINT	22
nat_rules_size		1	MAXINT	127
nat_table_max		1	MAXINT	30000
nat_table_size		1	MAXINT	2047
nat_table_wm_high	2	100	99
nat_table_wm_low	1	99	90
rdr_rules_size		1	MAXINT	127
state_lock		0	1	0
state_logging		0	1	1
state_max			1	MAXINT	4013
state_maxbucket	1	MAXINT	26
state_size		1	MAXINT	5737
state_wm_freq		2	999999	20
state_wm_high		2	100	99
state_wm_low		1	99	90
tcp_close_wait		1	MAXINT	480
tcp_closed		1	MAXINT	60
tcp_half_closed	1	MAXINT	14400
tcp_idle_timeout	1	MAXINT	864000
tcp_last_ack		1	MAXINT	60
tcp_syn_received	1	MAXINT	480
tcp_syn_sent		1	MAXINT	480
tcp_time_wait		1	MAXINT	480
tcp_timeout		1	MAXINT	480
udp_ack_timeout	1	MAXINT	24
udp_timeout		1	MAXINT	240
update_ipid		0	1	0
.fi
.SH Calling out to internal functions
.PP
IPFilter provides a pair of functions that can be called from a rule
that allow for a single rule to jump out to a group rather than walk
through a list of rules to find the group. If you've got multiple
networks, each with its own group of rules, this feature may help
provide better filtering performance.
.PP
The lookup to find which rule group to jump to is done on either the
source address or the destination address but not both.
.PP
In this example below, we are blocking all packets by default but then
doing a lookup on the source address from group 1010. The two rules in
the ipf.conf section are lone members of their group. For an incoming
packet that is from 1.1.1.1, it will go through three rules: (1) the
block rule, (2) the call rule and (3) the pass rule for group 1020.
For a packet that is from 3.3.2.2, it will also go through three rules:
(1) the block rule, (2) the call rule and (3) the pass rule for group
1030. Should a packet from 3.1.1.1 arrive, it will be blocked as it
does not match any of the entries in group 1010, leaving it to only
match the first rule.
.PP
.nf
from ipf.conf
-------------
block in all
call now srcgrpmap/1010 in all
pass in proto tcp from any to any port = 80 group 1020
pass in proto icmp all icmp-type echo group 1030 

from ippool.conf
----------------
group-map in role=ipf number=1010
    { 1.1.1.1 group = 1020, 3.3.0.0/16 group = 1030; };
.fi
.SS IPFilter matching expressions
.PP
An experimental feature that has been added to filter rules is to use
the same expression matching that is available with various commands
to flush and list state/NAT table entries. The use of such an expression
precludes the filter rule from using the normal IP header matching.
.PP
.nf
pass in exp { "tcp.sport 23 or tcp.sport 50" } keep state
.fi
.SS Filter rules with BPF
.PP
On platforms that have the BPF built into the kernel, IPFilter can be
built to allow BPF expressions in filter rules. This allows for packet
matching to be on arbitrary data in the packt. The use of a BPF expression
replaces all of the other protocol header matching done by IPFilter.
.PP
.nf
pass in bpf-v4 { "tcp and (src port 23 or src port 50)" } \\
    keep state
.fi
.PP
These rules tend to be
write-only because the act of compiling the filter expression into the
BPF instructions loaded into the kernel can make it difficut to
accurately reconstruct the original text filter. The end result is that
while ipf.conf() can be easy to read, understanding the output from
ipfstat might not be.
.SH VARIABLES
.PP
This configuration file, like all others used with IPFilter, supports the
use of variable substitution throughout the text.
.PP
.nf
nif="ppp0";
pass in on $nif from any to any
.fi
.PP
would become
.PP
.nf
pass in on ppp0 from any to any
.fi
.PP
Variables can be used recursively, such as 'foo="$bar baz";', so long as
$bar exists when the parser reaches the assignment for foo.
.PP
See
.B ipf(8)
for instructions on how to define variables to be used from a shell
environment.
.DT
.SH FILES
/dev/ipf
/etc/ipf.conf
.br
/usr/share/examples/ipf  Directory with examples.
.SH SEE ALSO
ipf(8), ipfstat(8), ippool.conf(5), ippool(8)