File: ferm.pod

package info (click to toggle)
ferm 1.2.2-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 464 kB
  • ctags: 250
  • sloc: perl: 2,334; makefile: 138; sh: 128
file content (1456 lines) | stat: -rw-r--r-- 37,163 bytes parent folder | download
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
#
# ferm pod manual file
#

#
# ferm, a firewall setup program that makes firewall rules easy!
#
# Copyright (C) 2001-2006  Auke Kok, Max Kellermann
#
# Comments, questions, greetings and additions to this program
# may be sent to <ferm@foo-projects.org>
#

#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#

=head1 NAME

B<ferm> - a firewall rule parser for linux

=head1 SYNOPSIS

B<ferm> I<options> I<inputfile>

=head1 DESCRIPTION

B<ferm> is a frontend for B<iptables>. It reads the rules from a
structured configuration file and calls iptables(8) to insert them
into the running kernel.

B<ferm>'s goal is to make firewall rules easy to write and easy to
read. It tries to reduce the tedious task of writing down rules, thus
enabling the firewall administrator to spend more time on developing
good rules than the proper implementation of the rule.

To achieve this, B<ferm> uses a simple but powerful configuration
language, which allows variables, functions, arrays, blocks. It also
allows you to include other files, allowing you to create libraries of
commonly used structures and functions.

B<ferm>, pronounced "firm", stands for "For Easy Rule Making".


=head1 CAUTION

This manual page does I<not> indend to teach you how firewalling works
and how to write good rules.  There is already enough documentation on
this topic.


=head1 INTRODUCTION

Let's start with a simple example:

    chain INPUT {
        proto tcp ACCEPT;
    }

This will add a rule to the predefined input chain, matching and
accepting all tcp packets.  Ok, let's make it more complicated:

    chain (INPUT OUTPUT) {
	proto (udp tcp) ACCEPT;
    }

This will insert 4 rules, namely 2 in chain input, and 2 in chain
output, matching and accepting both udp and tcp packets.  Normally you
would type this:

   iptables -A INPUT -p tcp -j ACCEPT
   iptables -A OUTPUT -p tcp -j ACCEPT
   iptables -A INPUT -p udp -j ACCEPT
   iptables -A OUTPUT -p udp -j ACCEPT

Note how much less typing we need to do? :-)

Basically, this is all there is to it, although you can make it quite
more complex. Something to look at:

   chain INPUT {
       policy ACCEPT;
       daddr 10.0.0.0/8 proto tcp dport ! ftp goto mychain sport :1023 TOS 4 settos 8 mark 2;
       daddr 10.0.0.0/8 proto tcp dport ftp REJECT;
   }

My point here is, that *you* need to make nice rules, keep
them readable to you and others, and not make it into a mess.

It would aid the reader if the resulting firewall rules were placed
here for reference. Also, you could include the nested version with
better readability.

Try using comments to show what you are doing:

    # this line enables transparent http-proxying for the internal network:
    proto tcp if eth0 daddr ! 192.168.0.0/255.255.255.0
        dport http REDIRECT 3128;

You will be thankful for it later!

    chain INPUT {
        policy ACCEPT;
        interface (eth0 ppp0) {
            # deny access to notorius hackers, return here if no match
            # was found to resume normal firewalling
            goto badguys;

            protocol tcp goto fw_tcp;
            protocol udp goto fw_udp;
        }
    }

The more you nest, the better it looks. Make sure the order you
specify is correct, you would not want to do this:

    chain FORWARD {
        proto ! udp DROP;
        proto tcp dport ftp ACCEPT;
    }

because the second rule will never match. Best way is to specify
first everyting that is allowed, and then deny everything else.
Look at the examples for more good snapshots. Most people do
something like this:

    proto tcp {
        dport (
            ssh http ftp
        ) ACCEPT;
        dport 1024:65535 ! syn ACCEPT;
        DROP;
    }

=head1 STRUCTURE OF A FIREWALL FILE

The structure of a proper firewall file looks like  simplified
C-code. Only a few syntactic characters are used in ferm-
configuration files. Besides these special caracters, ferm
uses 'keys' and 'values', think of them as options and
parameters, or as variables and values, whatever.

With these words, you define the characteristics of your firewall.
Every firewall consists of two things: First, look if network
traffic matches certain conditions, and second, what to do
with that traffic.

You may specify conditions that are valid for the kernel
interface program you are using, probably iptables(8). For
instance, in iptables, when you are trying to match tcp
packets, you would say:

    iptables --protocol tcp

In ferm, this will become:

    protocol tcp;

Just typing this in ferm doesn't do anything, you need to tell
ferm (actually, you need to tell iptables(8) and the kernel) what
to do with any traffic that matches this condition:

    iptables --protocol tcp -j ACCEPT

Or, translated to B<ferm>:

    protocol tcp ACCEPT;

The B<;> character is at the end of every ferm rule. Ferm ignores line
breaks, meaning the above example is identical to the following:

    protocol tcp
      ACCEPT;

Here's a list of the special characters:

=over 8

=item B<;>

This character finalizes a rule.

Separated by semicolons, you may write multiple rules in one line,
although this decreases readability:

    protocol tcp ACCEPT; protocol udp DROP;

=item B<{}>

The nesting symbol defines a 'block' of rules.

The curly brackets contain any number of nested rules. All matches
before the block are carried forward to these.

The closing curly bracket finalizes the rule set. You should not write
a ';' after that, because that would be an empty rule.

Example:

    chain INPUT proto icmp {
        icmp-type echo-request ACCEPT;
        DROP;
    }

This block shows two rules inside a block, which will both be merged
with anything in front of it, so you will get two rules:

    iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
    iptables -A INPUT -p icmp -j DROP

There can be multiple nesting levels:

    chain INPUT {
        proto icmp {
            icmp-type echo-request ACCEPT;
            DROP;
        }
        daddr 172.16.0.0/12 REJECT;
    }

Note that the 'REJECT' rule is not affected by 'proto icmp', although
there is no ';' after the closing curly brace. Translated to iptables:

    iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
    iptables -A INPUT -p icmp -j DROP
    iptables -A INPUT -d 172.16.0.0/12 -j REJECT

=item B<$>

Variable expansion. Replaces '$FOO' by the value of the variable. See
the section I<VARIABLES> for details.

=item B<&>

Function call. See the section I<FUNCTIONS> for details.

=item B<()>

The array symbol. Using the parentheses, you can define
a 'list' of values that should be applied for the key to the
left of it.

Example:

    protocol ( tcp udp icmp )

this will result in three rules:

    ... -p tcp ...
    ... -p udp ...
    ... -p icmp ...

Only values can be 'listed', so you cannot do something like this:

    proto tcp ( ACCEPT LOG );

but you can do this:

    chain (INPUT OUTPUT FORWARD) proto (icmp udp tcp) DROP;

(which will result in nine rules!)

Values are separated by spaces. The array symbol is both left- and
right-associative, in contrast with the nesting block, which is
left-associative only.

=item C< # >

The comment symbol. Anything that follows this symbol up to
the end of line is ignored.

=item C<`command`>

Execute the command in a shell, and insert the process output. See the
section I<backticks> for details.

=item C<'string'>

Quote a string which may contain whitespaces, the dollar sign etc.

    LOG log-prefix ' hey, this is my log prefix!';

=item C<"string">

Quote a string (see above), but variable references with a dollar sign
are evaluated:

    DNAT to "$myhost:$myport";

=back


=head2 Keywords

In the previous section, we already introduced some basic keywords
like "chain", "protocol" and "ACCEPT". Let's explore their nature.

There are three kinds of keywords:

=over 8

=item

B<location> keywords define where a rule will be created. Example:
"table", "chain".

=item

B<match> keywords perform a test on all passing packets. The current
rule is without effect if one (or more) of the matches does not
pass. Example: "proto", "daddr".

Most matches are followed by a parameter: "proto tcp", "daddr
172.16.0.0/12".

=item

B<target> keywords state what to do with a packet. Example: "ACCEPT",
"REJECT", "goto".

Some targets define more keywords to specify details: "REJECT
reject-with icmp-net-unreachable".

=back

Every rule consists of a B<location> and a B<target>, plus any number
of B<matches>:

    table filter                  # location
    proto tcp dport (http https)  # match
    ACCEPT;                       # target

Strictly speaking, there is a fourth kind: B<ferm> keywords (which
control ferm's internal behaviour), but they will be explained later.


=head2 Parameters

Many keywords take parameters. These can be specified as literals,
variable references or lists (arrays):

    proto udp
    saddr %TRUSTED_HOSTS;
    proto tcp dport (http https ssh);
    LOG log-prefix "funky wardriver alert: ";

Some of them can be negated (lists cannot be negated):

    proto !esp;
    proto udp dport !domain;

Keywords which take no parameters are negated by a prefixed '!':

    proto tcp !syn;

Read iptables(8) to see where the B<!> can be used.


=head1 BASIC KEYWORDS


=head2 Location keywords

=over 8

=item B<domain [ip|ip6]>

Set the domain. "ip" is default and means "IPv4" (iptables). "ip6" is
for IPv6 support, using "ip6tables".

=item B<table [filter|nat|mangle]>

Specifies which netfilter table this rule will be inserted to:
"filter" (default), "nat" or "mangle".

=item B<chain [chain-name]>

Specifies the netfilter chain (within the current table) this rule
will be inserted to. Common predefined chain names are "INPUT",
"OUTPUT", "FORWARD", "PREROUTING", "POSTROUTING", depending on the
table. See the netfilter documentation for details.

If you specify a non-existing chain here, ferm will add the rule to a
custom chain with that name.

=item B<policy [ACCEPT|DROP|..]>

Specifies the default policy for the current chain (built-in
only). Can be one of the built-in targets (ACCEPT, DROP, REJECT,
...). A packet that matches no rules in a chain will be treated as
specified by the policy.

To avoid ambiguity, always specify the policies of all predefined
chains explicitly.

=item B<subchain { ... }>

Works like the normal block operators (i.e. without the I<subchain>
keyword), except that B<ferm> moves rules within the curly braces into
a new custom chain. The name for this chain is chosen automatically by
ferm.

In many cases, this is faster than just a block, because the kernel
may skip a huge block of rules when a precondition is false. Imagine
the following example:

 table filter chain INPUT {
     saddr (1.2.3.4 2.3.4.5 3.4.5.6 4.5.6.7 5.6.7.8) {
         proto tcp dport (http https ssh) ACCEPT;
         proto udp dport domain ACCEPT;
     }
 }

This generates 20 rules. When a packet arrives which does not pass the
B<saddr> match, it nonetheless checks all 20 rules. With B<subchain>,
this check is done once, resulting in faster network filtering and
less CPU load:

 table filter chain INPUT {
     saddr (1.2.3.4 2.3.4.5 3.4.5.6 4.5.6.7 5.6.7.8) subchain {
         proto tcp dport (http https ssh) ACCEPT;
         proto udp dport domain ACCEPT;
     }
 }

You can achieve the same by explicitly declaring a custom chain, but
you may feel that using B<subchain> requires less typing.


=back


=head2 Basic match keywords

=over 8

=item B<interface [interface-name]>

Define the interface name, your outside network card, like eth0,
or dialup like ppp1, or whatever device you want to match for
passing packets. It is equivalent to the C<-i> switch in
iptables(8).

=item B<outerface [interface-name]>

Same as interface, only for matching the outgoing interface
for a packet, as in iptables(8).

=item B<protocol [protocol-name|protocol-number]>

Currently supported by the kernel are tcp, udp and icmp, or
their respective numbers.

=item B<saddr|daddr [address-spec]>

Matches on packets originating from the specified address (saddr) or
targeted at the address (daddr).

Examples:

    saddr 192.168/8 ACCEPT; # (identical to the next one:)
    saddr 192.168.0.0/255.255.255.0 ACCEPT;
    daddr my.domain.com ACCEPT;

=item B<fragment>

Specify that only fragmented IP packets should be matched.
When packets are larger that the maximum packet size your
system can handle (called Maximum Transmission Unit or MTU)
they will be chopped into bits and sent one by one as single
packets. See ifconfig(8) if you want to find the MTU for
your system (the default is usually 1500 bytes).

Fragments are frequently used in DOS attacks, because there
is no way of finding out the origin of a fragment packet.

=item B<sport|dport [port-spec]>

Matches on packets on the specified TCP or UDP port. "sport" matches
the source port, and dport matches the destination port.

This match can be used only after you specified "protocol tcp" or
"protocol udp", because only these two protocols actually have ports.

And some examples of valid ports/ranges:

    dport 80 ACCEPT;
    dport http ACCEPT;
    dport ssh:http ACCEPT;
    dport 0:1023 ACCEPT; # equivalent to :1023
    dport 1023:65535 ACCEPT;

=item B<syn>

Specify that the SYN flag in a tcp package should be matched,
which are used to build new tcp connections. You can identify
incoming connections with this, and decide wether you want
to allow it or not. Packets that do not have this flag are
probably from an already established connection, so it's
considered reasonably safe to let these through.

=item B<module [module-name]>

Load an iptables module. Most modules provide more match
keywords. We'll get to that later.

=back


=head2 Basic target keywords

=over 8

=item B<goto [custom-chain-name]>

Jumps to a custom chain. If no rule in the custom chain matched,
netfilter returns to the next rule in the previous chain.

=item B<ACCEPT>

Accepts matching packets.

=item B<DROP>

Drop matching packets without further notice.

=item B<REJECT>

Rejects matching packets, i.e. send an ICMP packet to the sender,
which is port-unreachable by default. You may specify another ICMP
type.

    REJECT; # default to icmp-port-unreachable
    REJECT reject-with icmp-net-unreachable;

Type "iptables -j REJECT -h" for details.

=item B<RETURN>

Finish the current chain and return to the calling chain (if "goto
[custom-chain-name]" was used).

=item B<NOP>

No action at all.

=back


=head1 ADDITIONAL KEYWORDS

Netfilter is modular. Modules may provide additional targets and match
keywords. The list of netfilter modules is constantly growing, and
ferm tries to keep up with supporting them all. This chapter describes
modules which are currently supported.


=head2 Netfilter match modules

=over 8

=item B<account>

Account traffic for all hosts in defined network/netmask.  This is one
of the match modules which behave like a target, i.e. you will mostly
have to use the B<NOP> target.

    mod account aname mynetwork aaddr 192.168.1.0/24 ashort NOP;

=item B<addrtype>

Check the address type; either source address or destination address.

    mod addrtype src-type BROADCAST;
    mod addrtype dst-type LOCAL;

Type "iptables -m addrtype -h" for details.

=item B<ah>

Checks the SPI header in an AH packet.

    mod ah ahspi 0x101;
    mod ah ahspi ! 0x200:0x2ff;

Additional arguments for IPv6:

    mod ah ahlen 32 ACCEPT;
    mod ah ahlen !32 ACCEPT;
    mod ah ahres ACCEPT;

=item B<comment>

Adds a comment of up to 256 characters to a rule, without an effect.
Note that unlike ferm comments ('#'), this one will show up in
"iptables -L".

    mod comment comment "This is my comment." ACCEPT;

=item B<condition>

Matches if a value in /proc/net/ipt_condition/NAME is 1 (path is
/proc/net/ip6t_condition/NAME for the ip6 domain).

    mod condition condition (abc def) ACCEPT;
    mod condition condition !foo ACCEPT;

=item B<connmark>

Check the mark field associated with the connection, set by the
CONNMARK target.

    mod connmark mark 64;
    mod connmark mark 6/7;

=item B<conntrack>

Check connection tracking information.

    mod conntrack ctstate (ESTABLISHED RELATED);
    mod conntrack ctproto tcp;
    mod conntrack ctorigsrc 192.168.0.2;
    mod conntrack ctorigdst 1.2.3.0/24;
    mod conntrack ctreplsrc 2.3.4.5;
    mod conntrack ctrepldst ! 3.4.5.6;
    mod conntrack ctstatus ASSURED;
    mod conntrack ctexpire 60;
    mod conntrack ctexpire 180:240;

Type "iptables -m conntrack -h" for details.

=item B<dccp>

Check DCCP (Datagram Congestion Control Protocol) specific attributes.
This module is automatically loaded when you use "protocol dccp".

    proto dccp sport 1234 dport 2345 ACCEPT;
    proto dccp dccp-types (SYNCACK ACK) ACCEPT;
    proto dccp dccp-types !REQUEST DROP;
    proto dccp dccp-option 2 ACCEPT;

=item B<dscp>

Match the 6 bit DSCP field within the TOS field.

    mod dscp dscp 11;
    mod dscp dscp-class AF41;

=item B<dst>

Matches the Destination Options header (ip6).

    mod dst dst-len 8 ACCEPT;
    mod dst dst-len !8 ACCEPT;
    mod dst dst-opts (1:4 2:8) ACCEPT;

=item B<ecn>

Match the ECN bits of an IPv4 TCP header.

    mod ecn ecn-tcp-cwr;
    mod ecn ecn-tcp-ece;
    mod ecn ecn-ip-ect 2;

Type "iptables -m ecn -h" for details.

=item B<esp>

Checks the SPI header in an ESP packet.

    mod esp espspi 0x101;
    mod esp espspi ! 0x200:0x2ff;

=item B<eui64>

"This module matches the EUI-64 part of a stateless autoconfigured
IPv6 address.  It compares the EUI-64 derived from the source MAC
address in Ehternet frame with the lower 64 bits of the IPv6 source
address.  But "Universal/Local" bit is not compared.  This module
doesn't match other link layer frame, and is only valid in the
PREROUTING, INPUT and FORWARD chains."

    mod eui64 ACCEPT;

=item B<frag>

Matches the Fragment header (ip6).

    mod frag fragid 123:456 ACCEPT;
    mod frag fragid !123:456 ACCEPT;
    mod frag fragres ACCEPT;
    mod frag fragfirst ACCEPT;
    mod frag fragmore ACCEPT;
    mod frag fraglast ACCEPT;

=item B<fuzzy>

"This module matches a rate limit based on a fuzzy logic controller [FLC]."

    mod fuzzy lower-limit 10 upper-limit 20 ACCEPT;

=item B<hbh>

Matches the Hop-by-Hop Options header (ip6).

    mod hbh hbh-len 8 ACCEPT;
    mod hbh hbh-len !8 ACCEPT;
    mod hbh hbh-opts (1:4 2:8) ACCEPT;

=item B<hl>

Matches the Hop Limit field (ip6).

    mod hl hl-eq (8 10) ACCEPT;
    mod hl hl-eq !5 ACCEPT;
    mod hl hl-gt 15 ACCEPT;
    mod hl hl-lt 2 ACCEPT;

=item B<helper>

Checks which conntrack helper module tracks this connection.  The port
may be specified with "-portnr".

    mod helper helper irc ACCEPT;
    mod helper helper ftp-21 ACCEPT;

=item B<icmp>

Check ICMP specific attributes.  This module is automatically loaded
when you use "protocol icmp".

    proto icmp icmp-type echo-request ACCEPT;

Use "iptables -p icmp C<-h>" to obtain a list of valid ICMP types.

=item B<iprange>

Match a range of IPv4 addresses.

    mod iprange src-range 192.168.2.0-192.168.3.255;
    mod iprange dst-range ! 192.168.6.0-192.168.6.255;

=item B<ipv6header>

Matches the IPv6 extension header (ip6).

    mod ipv6header header !(hop frag) ACCEPT;
    mod ipv6header header (auth dst) ACCEPT;

=item B<length>

Check the package length.

    mod length length 128; # exactly 128 bytes
    mod length length 512:768; # range
    mod length length ! 256; # negated

=item B<limit>

Limits the packet rate.

    mod limit limit 1/second;
    mod limit limit 15/minute limit-burst 10;

Type "iptables -m limit -h" for details.

=item B<mac>

Match the source MAC address.

    mod mac mac-source 01:23:45:67:89;

=item B<mark>

Matches packets based on their netfilter mark field. This may be a 32
bit integer between 0 and 4294967295.

    mod mark mark 42;

=item B<multiport>

Match a set of source or destination ports (UDP and TCP only).

    mod multiport source-ports (https ftp);
    mod multiport destination-ports (mysql domain);

This rule has a big advantage over "dport" and "sport": it generates
only one rule for up to 15 ports instead of one rule for every port.

=item B<nth>

Match every 'n'th packet.

    mod nth every 3;
    mod nth counter 5 every 2;
    mod nth start 2 every 3;
    mod nth start 5 packet 2 every 6;

Type "iptables -m nth -h" for details.

=item B<owner>

Check information about the packet creator, namely user id, group id,
process id, session id and command name.

    mod owner uid-owner 0;
    mod owner gid-owner 1000;
    mod owner pid-owner 5432;
    mod owner sid-owner 6543;
    mod owner cmd-owner "sendmail";

=item B<physdev>

Matches the physical device on which a packet entered or is about to
leave the machine. This is useful for bridged interfaces.

    mod physdev physdev-in ppp1;
    mod physdev physdev-out eth2;
    mod physdev physdev-is-in;
    mod physdev physdev-is-out;
    mod physdev physdev-is-bridged;

=item B<pkttype>

Check the link-layer packet type.

    mod pkttype pkt-type unicast;
    mod pkttype pkt-type broadcase;
    mod pkttype pkt-type multicast;

=item B<policy>

Matches IPsec policy being applied to this packet.

    mod policy dir out pol ipsec ACCEPT;
    mod policy strict reqid 23 spi 0x10 proto ah ACCEPT;
    mod policy mode tunnel tunnel-src 192.168.1.2 ACCEPT;
    mod policy mode tunnel tunnel-dst 192.168.2.1 ACCEPT;
    mod policy strict next reqid 24 spi 0x11 ACCEPT;

=item B<psd>

Detect TCP/UDP port scans.

    mod psd psd-weight-threshold 21 psd-delay-threshold 300
      psd-lo-ports-weight 3 psd-hi-ports-weight 1 DROP;

=item B<quota>

Implements network quotas by decrementing a byte counter with each packet.

    mod quota quota 65536 ACCEPT;

=item B<random>

Match a random percentage of all packets.

    mod random average 70;

=item B<realm>

Match the routing realm. Useful in environments using BGP.

    mod realm realm 3;

=item B<recent>

Temporarily mark source IP addresses.

    mod recent set;
    mod recent rcheck seconds 60;
    mod recent set rsource name "badguy";
    mod recent set rdest;
    mod recent rcheck rsource name "badguy" seconds 60;
    mod recent update seconds 120 hitcount 3 rttl;

This netfilter module has a design flaw: although it is implemented as
a match module, it has target-like behaviour when using the "set"
keyword.

L<http://snowman.net/projects/ipt_recent/>

=item B<rt>

Match the IPv6 routing header (ip6 only).

    mod rt rt-type 2 rt-len 20 ACCEPT;
    mod rt rt-type !2 rt-len !20 ACCEPT;
    mod rt rt-segsleft 2:3 ACCEPT;
    mod rt rt-segsleft !4:5 ACCEPT;
    mod rt rt-0-res rt-0-addrs (::1 ::2) rt-0-not-strict ACCEPT;

=item B<sctp>

Check SCTP (Stream Control Transmission Protocol) specific attributes.
This module is automatically loaded when you use "protocol sctp".

    proto sctp sport 1234 dport 2345 ACCEPT;
    proto sctp chunk-types only DATA:Be ACCEPT;
    proto sctp chunk-types any (INIT INIT_ACK) ACCEPT;
    proto sctp chunk-types !all (HEARTBEAT) ACCEPT;

Use "iptables -p sctp C<-h>" to obtain a list of valid chunk types.

=item B<state>

Checks the connection tracking state.

    mod state state INVALID DROP;
    mod state state (ESTABLISHED RELATED) ACCEPT;

Type "iptables -m state -h" for details.

=item B<tcp>

Checks TCP specific attributes. This module is automatically loaded
when you use "protocol tcp".

    proto tcp sport 1234;
    proto tcp dport 2345;
    proto tcp tcp-flags (SYN ACK) SYN;
    proto tcp tcp-flags ! (SYN ACK) SYN;
    proto tcp tcp-flags ALL (RST ACK);
    proto tcp syn;
    proto tcp tcp-option 2;
    proto tcp mss 512;

Type "iptables -p tcp -h" for details.

=item B<tcpmss>

Check the TCP MSS field of a SYN or SYN/ACK packet.

    mod tcpmss mss 123 ACCEPT;
    mod tcpmss mss 234:567 ACCEPT;

=item B<time>

Check if the time a packet arrives is in given range.

    mod time timestart 12:00;
    mod time timestop 13:30;
    mod time days (Mon Wed Fri);
    mod time datestart 2005:01:01;
    mod time datestart 2005:01:01:23:59:59;
    mod time datestop 2005:04:01;

Type "iptables -m time -h" for details.

=item B<tos>

Matches a packet on the specified TOS-value.

    mod tos tos Minimize-Cost ACCEPT;
    mod tos tos !Normal-Service ACCEPT;

Type "iptables -m tos -h" for details.

=item B<ttl>

Matches the ttl (time to live) field in the IP header.

    mod ttl ttl-eq 12; # ttl equals
    mod ttl ttl-gt 10; # ttl greater than
    mod ttl ttl-lt 16; # ttl less than

=item B<unclean>

Matches packets which seem malformed or unusual. This match has no
further parameters.

=back


=head2 Netfilter target modules

The following additional targets are available in ferm, provided that
you enabled them in your kernel:

=over 8

=item B<DNAT to [ip-address|ip-range|ip-port-range]>

Change the destination address of the packet.

    DNAT to 10.0.0.4;
    DNAT to 10.0.0.4:80;
    DNAT to 10.0.0.4:1024-2048;
    DNAT to 10.0.1.1-10.0.1.20;

=item B<ECN>

This target allows to selectively work around known ECN blackholes.
It can only be used in the mangle table.

    ECN ecn-tcp-remove;

=item B<HL>

Modify the IPv6 Hop Limit field (ip6/mangle only).

    HL hl-set 5;
    HL hl-dec 2;
    HL hl-inc 1;

=item B<LOG>

Log all packets that match this rule in the kernel log. Be carefull
with log flooding. Note that this is a "non-terminating target",
i.e. rule traversal continues at the next rule.

    LOG log-level warning log-prefix "Look at this: ";
    LOG log-tcp-sequence log-tcp-options;
    LOG log-ip-options;

=item B<MARK>

Sets the netfilter mark field for the packet (a 32 bit integer between
0 and 4294967295):

    MARK set-mark 42;

=item B<MASQUERADE>

Masquerades matching packets. Optionally followed by a port or
port-range for iptables. Specify as "123", "123-456" or "123:456".
The port range parameter specifies what local ports masqueraded
connections should originate from.

    MASQUERADE;
    MASQUERADE to-ports 1234:2345;

=item B<REDIRECT to-ports [ports]>

Transparent proxying: alter the destination IP of the packet to the
machine itself.

    proto tcp dport http REDIRECT to-ports 3128;

=item B<SNAT to [ip-address|ip-range|ip-port-range]>

Change the source address of the packet.

    SNAT to 1.2.3.4;
    SNAT to 1.2.3.4:20000-30000;

=item B<TCPMSS>

Alter the MSS value of TCP SYN packets.

    TCPMSS set-mss 1400;
    TCPMSS clamp-mss-to-pmtu;

=item B<TOS set-tos [value]>

Set the tcp package Type Of Service bit to this value.  This will be
used by whatever traffic scheduler is willing to, mostly your own
linux-machine, but maybe more. The original tos-bits are blanked and
overwritten by this value.

    TOS set-tos Maximize-Throughput;

Type "iptables -j TOS -h" for details.

=item B<TTL>

Modify the TTL header field.

    TTL ttl-set 16;
    TTL ttl-dec 1; # decrease by 1
    TTL ttl-inc 4; # increase by 4

=item B<ULOG>

Log packets to a userspace program.

    ULOG ulog-nlgroup 5 ulog-prefix "Look at this: ";
    ULOG ulog-cprange 256;
    ULOG ulog-qthreshold 10;

=back

=head1 ADVANCED FEATURES

=head2 Variables

In complex firewall files, it is helpful to use variables, e.g. to
give a network interface a meaningful name.

To set variables, write:

    def $DEV_INTERNET = eth0;
    def $PORTS = (http ftp);
    def $MORE_PORTS = ($PORTS 8080);

In the real ferm code, variables are used like any other keyword
parameter:

    chain INPUT interface $DEV_INTERNET proto tcp dport $MORE_PORTS ACCEPT;

Note that variables can only be used in keyword parameters
("192.168.1.1", "http"); they cannot contain ferm keywords like
"proto" or "interface".

Variables are only valid in the current block:

    def $DEV_INTERNET = eth1;
    chain INPUT {
        proto tcp {
            def $DEV_INTERNET = ppp0;
            interface $DEV_INTERNET dport http ACCEPT;
        }
        interface $DEV_INTERNET DROP;
    }

will be expanded to:

    chain INPUT {
        proto tcp {
            interface ppp0 dport http ACCEPT;
        }
        interface eth1 DROP;
    }

The "def $DEV_INTERNET = ppp0" is only valid in the "proto tcp" block;
the parent block still knows "set $DEV_INTERNET = eth1".

Include files are special - variables declared in an included file are
still available in the calling block. This is useful when you include
a file which only declares variables.

=head2 Automatic variables

Some variables are set internally by ferm. Ferm scripts can use them
just like any other variable.

=over 8

=item B<$DOMAIN>

The current domain. "ip" or "ip6".

=item B<$TABLE>

The current netfilter table.

=item B<$CHAIN>

The current netfilter chain.

=back

=head2 Functions

Functions are similar to variables, except that they may have
parameters, and they provide ferm commands, not values.

    def &FOO() = proto (tcp udp) dport domain;
    &FOO() ACCEPT;

    def &TCP_TUNNEL($port, $dest) = {
        table filter chain FORWARD interface ppp0 proto tcp dport $port daddr $dest outerface eth0 ACCEPT;
        table nat chain PREROUTING interface ppp0 proto tcp dport $port daddr 1.2.3.4 DNAT to $dest;
    }

    &TCP_TUNNEL(http, 192.168.1.33);
    &TCP_TUNNEL(ftp, 192.168.1.30);
    &TCP_TUNNEL((ssh smtp), 192.168.1.2);

A function call which contains a block (like '{...}') must be the last
command in a ferm rule, i.e. it must be followed by ';'. The '&FOO()'
example does not contain a block, thus you may write 'ACCEPT' after
the call. To circumvent this, you can reorder the keywords:

    def &IPSEC() = { proto (esp ah); proto udp dport 500; }
    ACCEPT &IPSEC();

=head2 Backticks

With backticks, you may use the output of an external command:

    def $DNSSERVERS = `grep nameserver /etc/resolv.conf | awk '{print $2}'`
    chain INPUT proto tcp saddr $DNSSERVERS ACCEPT;

The command is executed with the shell (F</bin/sh>), just like
backticks in perl.  ferm does not do any variable expansion here.

The output is then tokenized, and saved as a ferm list (array). Lines
beginning with '#' are ignored; the other lines may contain any number
of values, separated by whitespace.

=head2 Includes

The B<include> keyword allows you to include external files:

    include 'vars.ferm';

The file name is relative to the calling file, e.g. when including
from F</etc/ferm/ferm.conf>, the above statement includes
F</etc/ferm/vars.ferm>. Variables and functions declared in an
included file are still available in the calling file.

B<include> works within a block:

    chain INPUT {
        include 'input.ferm';
    }

If you specify a directory (with a trailing '/'), all files in this
directory are included, sorted alphabetically:

    include 'ferm.d/';


=head1 RECIPES

The F<./examples/> directory contains numerous ferm configuration
which can be used to begin a new firewall. This sections contains more
samples, recipes and tricks.

=head2 Easy port forwarding

Ferm function make routine tasks quick and easy:

    def &FORWARD_TCP($proto, $port, $dest) = {
        table filter chain FORWARD interface $DEV_WORLD outerface $DEV_DMZ daddr $dest proto $proto dport $port ACCEPT;
        table nat chain PREROUTING interface $DEV_WORLD daddr $HOST_STATIC proto $proto dport $port DNAT to $dest;
    }

    &FORWARD_TCP(tcp, http, 192.168.1.2);
    &FORWARD_TCP(tcp, smtp, 192.168.1.3);
    &FORWARD_TCP((tcp udp), domain, 192.168.1.4);

=head2 Remote B<ferm>

If the target machine is not able to run B<ferm> for some reason
(maybe an embedded device without Perl), you can edit the B<ferm>
configuration file on another computer and let B<ferm> generate a
shell script there.

Example for OpenWRT:

    ferm --remote --shell mywrt/ferm.conf >mywrt/firewall.user
    chmod +x mywrt/firewall.user
    scp mywrt/firewall.user mywrt.local.net:/etc/
    ssh mywrt.local.net /etc/firewall.user

=head1 TRANSITION FROM FERM 1.1

ferm 1.2 aims to be 100% compatible with ferm 1.1, i.e. old
configuration files should work as expected.  For a "clean" ferm 1.2
configuration without warnings, here is a list of the most important
changes:

=over 8

=item I<ipfwadm and ipchains>

Support for these has been removed.

=item I<options B<clearall>, B<flushall>, B<flushchains>, B<createchains>>

All these options are always implied.  There is no option anymore to
disable them.

=item I<option automod>

Automatic module loading is deprecated.  It still works for now, at
least for modules which were already supported by ferm 1.1, but it is
expected to be removed in ferm 1.3.

=item I<option location>

ferm assumes that the iptables utilities are always installed in
/sbin.

=item I<Chain policies>

Chain policies should be written in a dedicated statement; ferm 1.1:

 chain INPUT policy DROP {
   # ...
 }

ferm 1.2:

 chain INPUT {
   policy DROP;
   # ...
 }

=item I<Variables>

The concept of variables has been overhauled in ferm 1.2; you can now
declare functions which take parameters.  Besides that, you should use
the new syntax:

 def $FOO = (http ssh);
 chain INPUT proto tcp dport $FOO ACCEPT;

=item I<Arrays>

Arrays used to be specified with commas separating the items.  In ferm
1.2, you separate array items only by whitespace.

=item I<Misc syntax changes>

Other small syntax changes:

=over

=item *

built-in target names must be upper case; chains are lower case

=item *

MASQUERADE, not MASQ

=item *

A lot of shortcuts are deprecated, since they are polluting the namespace, e.g. "mac", "tosrc".

=item *

"source addr $A port $B" is deprecated, use "sdaddr $A sport $B"
instead.  The same for "destination".

=back

=back

=head1 OPTIONS

=over 12

=item B<--noexec>

Do not execute the iptables(8) commands, but skip instead. This way
you can parse your data, use B<--lines> to view the output.

=item B<--flush>

Clears the firewall rules and sets the policy of all chains to ACCEPT.
B<ferm> needs a configuration file for that to determine which domains
and tables are affected.

=item B<--lines>

Show the firewall lines that were generated from the rules. They
will be shown just before they are executed, so if you get error
messages from iptables(8) etc., you can see which rule caused
the error.

=item B<--interactive>

Apply the firewall rules and ask the user for confirmation.  Reverts
to the previous ruleset if there is no valid user response within 30
seconds.  This is useful for remote firewall administration: you can
test the rules without fearing to lock yourself out.

=item B<--help>

Show a brief list of available commandline options.

=item B<--version>

Shows the version number of the program.

=item B<--fast>

Enable fast mode: ferm generates an iptables-save(8) file, and
installs it with iptables-restore(8). This is much faster, because
ferm calls iptables(8) once for every rule by default.

Watch out for iptables versions older than 1.3, they might not work
with this option due to quoting bugs.

=item B<--shell>

Generate a shell script which calls iptables-restore(8) and prints it.
Implies --fast --lines.

=item B<--remote>

Generate rules for a remote machine.  Implies B<--noexec> and
B<--lines>.  Can be combined with B<--shell>.

=item B<--domain {ip|ip6}>

Handle only the specified domain. B<ferm> output may be empty if the
domain is not configured in the input file.

=back


=head1 SEE ALSO

iptables(8)


=head1 REQUIREMENTS

=head2 Operating system

Linux 2.4 or newer, with netfilter support and all netfilter modules
used by your firewall script

=head2 Software

iptables and perl 5.6

=head1 BUGS

Bugs? What bugs?

If you find a bug, please tell us: ferm@foo-projects.org

=head1 COPYRIGHT

Copyright (C) 2001-2006 Auke Kok <sofar@foo-projects.org>, Max
Kellermann <max@foo-projects.org>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA

=head1 AUTHOR

Auke Kok <sofar@foo-projects.org>, Max Kellermann
<max@foo-projects.org>

=cut