File: ferm.txt

package info (click to toggle)
ferm 1.1-1
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 308 kB
  • ctags: 173
  • sloc: perl: 1,111; makefile: 66
file content (1008 lines) | stat: -rw-r--r-- 35,520 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
NAME
    ferm - a firewall rule parser for linux

SYNOPSYS
    ferm *options* *inputfiles*

DESCRIPTION
    ferm compiles ready to go firewall-rules from a structured rule-setup.
    These rules will be executed by the preferred kernel interface, such as
    ipchains(8) and iptables(8).

    Besides just executing all rules in one command, the obvious gain is the
    possibility to provide a structured description of a firewall. No need
    anymore for tedious typing all firewalls into custom scripts, you can
    now write logically and coherent rules using a C-style nesting
    structure, and let ferm create all rules for you.

    ferm will also aid in modularizing firewalls, because it creates the
    possibility to split up the firewall into several different files, which
    can be reloaded at will, so you can dynamically adjust your rules.

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

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 ferm:

        protocol tcp accept;

    Noticed the ; character? We're getting to that now, because there are
    some special characters in ferm that make life easy.

    Here's a list of the special characters:

    ;       The effectuation character. This character defines the end of a
            rule. Anything defined before this character will be put into
            one or more rules.

            This character *makes* the rule. It gathers all the information,
            all parameters and targets, special things or whatever, that
            currently is 'valid', and tries to make a decent rule out of it.
            ferm will do nothing without this character!

            Example:

                proto tcp ACCEPT;

            THis example shows a single rule, defined by two keys and one
            value.

    {}      The nesting symbol defines a 'block' of rules.

            Anything defined before this block will still be available
            within all rules inside this block. You can nest blocks in
            blocks as far as you like. For every rule defined in this block
            the values defined before this block will apply. Usually you
            would define an often used parameter as the protocol in front of
            this block, and anything special inside it.

            You can put as many rules (using the <;> character) as you like
            insode this block. but there should always be one or more,
            although you will get away with none. Not very usefull except
            for when you frequently edit you config file, and might want to
            leave a chain empty.

            Since the nesting block is left associative, it cannot be bound
            to keys defined after the block.

            Example:

                chain INPUT proto tcp {
                    syn DENY;
                    ACCEPT;
                }

            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 tcp -y -j DENY
                iptables -A INPUT -p tcp -j ACCEPT

    %       Further more, ferm now supports variables, so you can define
            your favorite targets, interfaces etc. before you use them. It
            works like this:

                set IF eth0
                set %IF ACCEPT
                set TARGET %IF

            will result in this:

                %IF = eth0
                %eth0 = ACCEPT
                %TARGET = eth0

            If you want to put multiple arguments into a variable, you
            should do it like this:

                %IFS = "eth0,eth1,ppp0"

            This way, ferm will recognize it being a list of values, and
            split it whenever needed. If you use spaces, ferm won't
            recognize it and think its just a value with spaces. The comma
            tells ferm to split it up when needed.

    ()      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:

                proto ( 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) DENY;

            (which will result in nine rules!)

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

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

    These symbols glue all the keywords into a structure, which allows you
    to specify some keys only a few times, and let them apply to any
    key/value pairs defined within an entire block, for instance:

        proto tcp {
            dport 22 ACCEPT;
            syn DPORT 0:1023 DENY;
            }
        ACCEPT;

    Now here, the 'proto tcp' is valid within the block, but not anymore
    after is, resulting in:

        ... -p tcp --dport 22 -j accept
        ... -p tcp -y --dport 0:1023 -j deny
        ... -j accept # note '-p tcp' is not in here!

    Some important notes:

    - Ferm inserts the rules 'chronologically', so the first rule will be
    inserted before the second one.

    - Anything defined within a block is no longer valid when that block
    ends.

    - Everything defined within the current block that is 'effectuated',
    will be no longer defined immediately after that point.

    - Everything defined before a block is undefined when this block closes.

    If you do not understand this, don't worry, it alle becomes clear by
    itself.

    Two types of keys exist:

  Firewall keys
            Firewall keys define a set of firewall packet matching criteria
            that is supported by the kernel backend. They look like 'name
            value' pairs or like 'switch'. For instance:

                proto tcp

            or:

                syn

            A 'name value' pair lets you fill in a value for a certain
            condition you would like to match packets against, switches are
            like on/off light switches on the wall, if you specify a switch,
            you turn paket matching for whatever the switch stands, on. In
            the latter example, you turn SYN-packet matching on for this
            rule.

            Both types can optionally be preceded by a !. This will be
            handled that you don't want something to be matching it:

                !syn

            or:

                ! syn

            Means you want packets which *don't* have the syn-flag set to be
            matched. Or even:

                proto ! tcp

            Means you want to match *anything but* packets from the tcp
            protocol.

            Read iptables(8) or ipchains(8) to see where the ! can be used.

  Option keys
            Using option keys alter the behaviour of ferm; they can be used
            to e.g. clear chains before use, or turn off certain sanity
            checks.

            Example:

              option verbose

            This option makes ferm show a lot of information about what it
            is doing.

    The syntax is very simple, 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 for ipchains(8):

       ipchains -A input -p tcp ACCEPT
       ipchains -A output -p tcp ACCEPT
       ipchains -A input -p udp ACCEPT
       ipchains -A output -p udp 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 {
           destination 10/8 port ! ftp goto mychain sport :1023 tos 4 settos 8 mark 2;
           destination 10/8 port ftp DENY;
       }

    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 thankfull 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 DENY;
            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;
        }

  keywords
    To make life easy, ferm allows you to use shorthands for most keywords.
    A list of shorthand notations is available at the end of this section.

    What kind of value you provide for a keyword depends on the keyword
    entirely, e.g. 'protocol' expects 'tcp', 'udp' or 'icmp', 'log-prefix'
    expects a value like '"whoops, someone rang the doorbell"' and
    'destination-port' can accept values like 'http', '80' or '0:1023'. Take
    a look at the kernel backend program manual for possible values and how
    they look like.

    Note you may put a value in single quotes or double quotes, if this may
    be required because a value contains spaces:

        log-prefix "Dropped tcp package: "

    Please keep in mind that some characters have special meaning, so it
    might be wise to refrain from using any other character then letters and
    digits and spaces unless you need them and know what you're doing. Take
    a look at VARIABLES and SHELL ESCAPES for more information about that.

    chain [chain-name]
            Specifies a chain that this rule will be inserted to. this is a
            required key for any rule. Chains can be built in, like "input",
            "output" or "forward", or user-defined chains.

    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 "-i" switch in
            ipchains(8) and iptables(8).

    outerface [interface-name]
            Same as interface, only for matching the outgoing interface for
            a packet, as in iptables(8). ipchains(8) hasn't got this
            parameter.

    protocol [protocol-name|protocol-number]
            Currently supported by the kernel are tcp, udp and icmp, or
            their respective numbers.

    port [port-spec]
            Specify a port number, name or range

    addr [address-spec]
            Specify a network address, a hostname or ip-number.

    source|destination
            Specify that the values provided for port and addr above should
            be either source or <destination> ports and addresses. This
            works like a toggle, which can be left on for the entire
            configuration file. So, if you say source once, all occurences
            of port will be source port's, as well as for addresses.

    saddr|daddr [address-spec]
            Specify an address specifically for the source or destination
            side, read it as a shorthand for source address and destination
            address, although it does not 'toggle' the source|destination
            state, which is remembered.

    sport|dport [port-spec]
            Specify a port number, name or range for the source or
            destination side, read it as a shorthand for source port and
            destination port>, although it does not 'toggle' the
            source|destination state, which is remembered. Ports can be
            specified for tcp and udp, as well as icmp, only in that case it
            means 'icmp-type' and only works when you specify the type
            numerically.

            Note that you need to specify a protocol, before you can use
            ports, that is because not all protocols support the ideas of
            ports.

            Here are some examples of valid addresses:

                192.168/8 (identical to the next one:)
                192.168.0.0/255.255.255.0
                my.domain.com

            And some examples of valid ports/ranges:

                80
                http
                ssh:http
                0:1023        which is equivalent to     :1023
                1023:65535    which is equivalent to     1023:65535

    icmptype [type]
            To specify an icmp message type. Can be numbers, but refer to
            the manual of the kernel program to retreive a list, for
            ipchains use "ipchains "-h" icmp". Examples: ping, pong.

    tos [value]
            Matches a packet on the specified TOS-value. See settos for
            values.

    settos [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. Possible values are (look
            in the shorthands for more, and easier values) :

            02 04 08 10

    setftos [value]
            Set TOS field in packet header to value. This value can be in
            decimal (ex: 32) or in hex (ex: 0x20)

    mark [value]
            matches packets based on their mark-value

    setmark [value]
            Sets the mark-value for a packet, use with the MARK target in
            iptables

    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.

    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.

    policy [policy]
            Specifies the default policy for the current chain. Can be
            either of the standard actions (ACCEPT, DENY, REJECT, MASQ and
            REDIRECT). A packet that matches no rules will be treated as
            specified by the policy. You can't specify chain names here.
            Only the predefined (built-in) chains have policies.

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

    log     Log all packets that match this rule in the kernel log. Be
            carefull with log flooding. Note the difference with LOG in
            iptables! See LOG as well. In iptables, this makes a copy of the
            current rule, and inserts it with the LOG target instead of any
            other specified target.

            See also log-[level|prefix|tcp-sequence|tcp-options|ip-options]

    goto [chain]
            Specify that matching packets should jump to this chain, only
            user defined chains are valid jump targets.

    reverse Instructs the kernel to use this rule twice, the second time
            with source and destination swapped. Unfortunately, this doesn't
            work with iptables.

    LOG     Identical to the 'LOG' target in iptables, logs any packet that
            matches, but doesn't do anything else to it. Only valid for
            iptables, otherwise use 'log'. See log and also
            log-[level|prefix|tcp-sequence|tcp-options|ip-options].

    ACCEPT  Accepts matching packets.

    REJECT  Rejects matching packets.

    DENY    Denies matching packets.

    MASQ toports [port|portrange]
            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. Note you need to
            specify the 'to' word here.

    RETURN  Returns to the parent chain where the current chain was called
            if the packet matches.

    REDIRECT [to|toports] [port|portrange]
            Allows transparent proxying when rule matches, the port that is
            redirected to must immediately follow this keyword. The target
            may also be an IP-number in case you are using iptables(8), so
            something like "REDIRECT 192.168.0.5:21" is valid there.

    SNAT|DNAT to [ip-address|ip-range|ip-port-range]
            Allows source/destination address translation, only valid for
            iptables(8), requires an ip-number, range or ip/port value.

    TOS     Changes the packets TOS-field according to the set-tos parameter
            specified, only valid for iptables.

    FTOS    Set TOS field in packet header with setftos parameter.

    TTL     The ttl-target is for changing ttl values

    table [table-name]
            Selects this table for the rule. Valid table names are "filter",
            "nat" and "mangle". If you don't specify any table, the default
            table "filter" is used.

    reject-with [value]
            Rejects a packet with an ICMP value type message.

    limit [value]
            Limits these type of packets to a maximim.

    iplimitabove [value]
            Limits a certain IP list a number of connections.

    iplimitmask [value]
            Specifies the mask to use for iplimitabove.

    psdweightthreshold [value]
            Specifies the port scan weight threshold

    psddelaythreshold [value]
            Specifies the delay weight for port scans

    psdloportsweight [value]
            Specifies the weight for low ports in the port scan detection
            algorithm

    psdhiportsweight [value]
            Specifies the weight for high ports in the port scan detection
            algorithm

    ttl [value]
            Matches the ttl for value

    ttl-[eq|lt|gt] [value]
            Matches the ttl value when equal, smaller or larger than value

    ttl-[set|dec|inc] [value]
            Sets, decreases or increases the ttl value

    length [[value]|[value:value]]
            Specify a certain packet length to match, may be a range of
            lengths

    burst [value]
            Limits bursts of these packets.

    mac [value]
            Matches packets originating from these mac-addresses.

    state [value]
            Matches packets with this state. The value may be specified as a
            normal ferm-list: "(ESTABLISHED,RELATED)" but "NEW:RELATED", and
            single values are also allowed.

    tcp-flags [!] [flagmask] [flagmatch]
            Specify tcp-flags, the ! is optional and has to precede the
            mask, mask and match are mandatory. The list of mask or match
            flags may be specified as a normal ferm-list: "(SYN,ACK,RST)",
            but "SYN:ACK:RST" and single values are also allowed.

    tcp-option [value]
            Specify a tcp-option for this rule.

    log-[level|prefix]
            Specifies several the log level and syslog prefix string.

    log-|tcp-sequence|tcp-options|ip-options]
            Specifies several extra tcp/ip options.

    [u|g|p|s]id-owner [value]
            Matches packets originating from this User, Group, Pid or
            Session ID.

    set [name] [value]
            Set variable "name" to value "value", you can dereference the
            variables by "%name". You may also put variables within set
            statements.

VARIABLES
    ferm also supports internal variables. This may come in handy if you
    wish to define often used parameters in advance, making the ferm
    configuration files even more easy to understand.

    Setting variables is very easy with the set command. Here's some
    examples:

        set EXTERAL_IP "111.22.33.44"
        set INTERNAL_IP '10.0.0.1'

    Both these statements set the variable to what is in between the quotes,
    you may afterwards refer to them like this:

        chain input daddr ! %EXTERNAL_IP DROP;

    The value of the variable will then be inserted into the rule and passed
    to the firewall program.

    the set command can actally be abused even more, since the following
    statements also work:

        set A "1"
        set B %A
        set %A "2"

    After these statements, variable %A yields value "1", variable %B holds
    the value "1", and the variable %1 holds the value "1" also.

    More importantly, these variables can be used to store arrays or lists
    of values:

        set DNSSERVERS "111.2.33.1,111.2.33.2"

    When this variable is inserted into a configuration file, the rule that
    it applies to will automatically be split up into two different firewall
    rules for each IP number given in the list.

    Here's some even more complicated stuff that works:

        set INTERNALINTERFACES "eth0,eth1,eth2"
        set EXTERNALINTERFACES "ppp0,tunl0"
        set INTERFACES "%INTERNALINTERFACES,%EXTERNALINTERFACES,lo"

    NOTE: Beware of mixing '' string values within new string values,
    because the trailing ' might be concatenated with another one in the
    variable that you are including it. Take a look at this:

        set IF1 'eth0'
        set IF2 'eth1'
        set IFS '%IF1,%IF2'

    Variable IFS will now contain the value ''eth0','eth1'' and that is
    probably not what you want. Better do this:

        set OF1 "eth0"
        set OF2 "eth1"
        set OFS "%OF1,%OF2"

    Which will result in variable OFS holding the value "eth0,eth1", which
    will be split up correctly, namely into "eth0" and "eth1".

SHELL ESCAPES
    Ferm supports shell escaping in two ways. First, you may insert a shell
    escaped string into a set command, second, you may insert a shell
    escaped string into any place of a value.

    There is a fundamental difference in this. Ferm will handle shell
    escapes itself when they are used in a set construction, so the variable
    then contains the value that was returned from the shell escape. You may
    later refer to this value again without the command being executed
    again.

    When you use a shell escaped string as a value without it being in a set
    statement, the exact string is just copied in the generated rule, and
    when parsing is finished, ferm will call the shell with the entire rule,
    and thus the shell escaped string. Only at this moment, the shell will
    execute the string and insert the value back into the kernel interface
    program. Thus, ferm will never see the real value of that.

    Examples:

        set DNSSERVERS `grep nameserver /etc/resolv.conf | awk '{print $2}'`
        chain input proto tcp saddr %DNSSERVERS ACCEPT;

    This way, ferm will interpret the value for DSSERVERS itself, put a
    separating comma between multiple values if needed, and store this
    information in the variable DNSSERVERS. The output will be like:

        iptables -t filter -A INPUT -p tcp -s 192.168.0.1 -j ACCEPT
        iptables -t filter -A INPUT -p tcp -s 192.168.0.2 -j ACCEPT

    Otherwise, when you include a shell escape as a regular value in between
    other ferm-statements:

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

    The shell escape is not parsed directly, but passed along with the, e.g.
    iptables command, and subsequently, the shell will insert whatever that
    value may become itself:

        iptables -t filter -A INPUT -p tcp -d `grep nameserver /etc/resolv.conf | awk '{print $2}'` -j ACCEPT

    Note that if the shell escape here yields more lines, something could go
    wrong here easily. You are warned! Better not make ferm SUID too I guess
    ;-)

SHORTHANDS
    Here's a complete list of possible shorthands, just to reduce the amount
    of typing:

    interface:
        if

    outerface:
        of

    protocol:
        proto

    source:
        src

    destination:
        dest

    fragment:
        frag

    ACCEPT:
        accept

    DENY:
        deny, DROP, drop

    REJECT:
        reject

    MASQ:
        masq

    RETURN:
        return

    REDIRECT:
        redirect, PROXY, proxy

    MARK:
        mark

    QUEUE:
        queue

    SNAT:
        snat

    DNAT:
        dnat

    goto:
        to, jump

    icmptype
        icmp-type

    reverse:
        bidirectional, swap

    tcp-option:
        tcpoption

    mac:
        mac-source, macsource

    iplimitabove:
        ip-limit-above

    iplimitmask
        ip-limit-mask

    burst:
        limit-burst, limitburst

    uid-owner:
        uidowner, uid

    gid-owner:
        gidowner, gid

    pid-owner:
        pidowner, pid

    sid-owner:
        sidowner, sid

    psdweightthreshold:
        psd-weight-threshold

    psddelaythreshold:
        psd-delay-threshold

    psdloportsweight:
        psd-lo-ports-weight

    psdhiportsweight:
        psd-hi-ports-weight

    log-level:
        loglev

    log-prefix:
        logprefix

    log-tcp-sequence:
        logseq

    log-tcp-options:
        logtcpopt

    log-ip-options:
        logipopt

    reject-with:
        rejectwith

    setmark
        set-mark

    tos/settos-values:
        The following Type Of Services values may be given:

            mincost min-cost 2 02 0x02

            reliability reliable 4 04 0x04

            max-throughput maxthroughput 8 08 0x08

            lowdelay interactive min-delay 10 0x10

            clear 0 00 0x00

    setftos
        set-ftos

OPTIONS
    Options can be specified with the "option" keyword, which can be defined
    anywhere within the document. Although that may be fine, you almost
    allways want to define them at the beginning of your document, because
    the behaviour changes at the moment they are specified.

    All options can also be specified on the command line, which has a few
    more available. The equivalent for the commandline options that are also
    available in the firewall file is mentioned in the firewall file options
    section.

  Command line options
    --noexec    Do not execute the ipchains(8) or iptables(8) commands, but
                skip instead. This way you can parse your data, use --lines
                to view the output.

    --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 ipchains(8) etc., you can see which
                rule caused the error.

    --verbose   Shows some more details of the stages of execution of the
                program.

    --debug     Shows even more details of what ferm is doing while parsing
                the rules. The debug info is put between the output for
                clearity and commented.

    --help      Show a brief list of available commandline options.

    --version   Shows the version number of the program.

    --use [ipchains|iptables|ipfwadm]
                Use this kernel program to implement the rules into the
                kernel. Also available as firewall file option "option
                [...]". This option must be set, either on the commandline
                or in a ferm config file.

    --location [/path/to/filename]
                Explicitly define the exact name and location of the kernel
                backend program, for the paranoid people out there.

    --automod   Automatically insert the correct module parameter when using
                iptables, making the module parameter unnecessary

  Firewall file options
    option clearall
            Clears the entire firewall, deletes all user chains and flushes
            the built in chains. Does not alter policies.

    option flushall
            Flushes all chains but does not delete them.

    option flushchains
            Flushes any chain which is defined in the setup, even built-in
            chains are flushed when referred.

    option createchains
            Creates any chain which is referred to, even when no rule is
            specified for the chain, but is only referred by with a "goto"
            keyword.

    option automod
            Automatically insert the correct module parameter when using
            iptables, making the module parameter unnecessary

    option [iptables|ipchains|ipfwadm]
            Define which kernel program you have to use to install rules.
            This one is required, since on some systems, they can both be
            present, or you want to use a wrapper for an older version.
            Currently defaults to ipchains.

SEE ALSO
    ipchains(8), ipfwadm(8), iptables(8)

NOTES
    A good firewall is not the only step in security, even the firewall may
    be insecure, or someone breaks into your house and steals the hard disk
    out of your PC. Do not rely on this firewall tool for the use of mission
    critical or confidential data. It is not fit for such a purpose!

    Instead, use this tool to expand your current use of ipchains(8) and
    routing, create a flexible firewall and look out for anything
    suspicious. Be carefull with open ports and servers, always get the
    latest, patched versions. Read more about firewalls before
    experimenting, you are warned! You might also read the COPYING file
    provided with the package or visit www.gnu.org to find more about the
    license.

EXAMPLES
    The package comes with a directory full of goodies (examples) that you
    can try, adjust for your system or just read if you want to understand
    the syntax and it's possibilities. Look in the "examples" directory.

REQUIREMENTS
  Operating system
    The Operating system currently supported is only linux, although it may
    be possible to port this program to support FreeBSD or SOLARIS firewall
    systems, provided they supply a similar firewalling scheme. (Does
    anybody known about that?)

  Software/packages
    Required are 2 packages: Perl5, under which this ferm runs, and one of
    the kernel firewall programs, suited for your system and kernel version.

  Kernel
    The respective required kernel versions for each of the kernel firewall
    programs (ipchains(8), ipfwadm(8) or iptables(8)) is also needed. This
    means you have to have a kernel which can use the firewalling thing,
    something you might have to compile a kernel for, or set some switches
    in /proc. Look at the man pages of those kernel programs for more
    information.

RESTRICTIONS
    ferm allows almost anything the used firewall program allows, so go
    ahead and specify complex port ranges, icmp by number or worse. Just be
    warned.

    Although quite sophisticated, the kernel interface programs ipchains(8)
    and iptables(8) are very limited in some respects. ferm is only an
    interface to improve the handling of these programs, and is therefore
    limited by the possibilities of these programs.

    Ipfwadm(8) is extremely limited in rule-building, upgrade or succomb in
    it. Nothing ferm can do about it.

BUGS
    The ipfwadm(8) interface is really limited due to being unable to test
    it and having no experience with it at all. I'll be concentration on
    iptables(8), which supports much more options and will be quite more
    flexible.

    Several nasty cleanups are not done well, which may result in surviving
    data. Tried to remove all of them but suspect more of them to occur.

    The --log-prefix construct does not allow certain characters to be put
    between "". Make sure you don't use the bracket {} and [] characters,
    the ! and , are also not correctly parsed.

TODO
    * Improve ipfwadm(8) handling or removing it altogether

    * Add more examples, with modularized snipplets (include option)

    * Make rpm's for RH and SuSE, or better: get you to do that!

    * Review the second half of the manual page

    * Make ferm bug you more about errors, i.e. increase validity checking
    to high levels

COPYRIGHT
    Copyright (C) 2001-2003, Auke Kok <auke.kok@planet.nl>

LICENSE
    ferm is released under the Gnu Public License, see the COPYING file that
    came with the package or visit www.gnu.org.

    This is free software; see the source for copying conditions. There is
    NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
    PURPOSE.

AUTHOR
    Auke Kok (auke.kok@planet.nl)