summaryrefslogtreecommitdiffstats
path: root/docs/uci_firewall.txt
blob: 590aa08d1bba89b23feb34e93ffc2f149842b8d8 (plain)
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
---
---
Firewall configuration
======================

== Firewall Configuration

The firewall configuration located in **'/etc/config/firewall'**.

== Overview

OpenWrt relies on netfilter for packet filtering, NAT and mangling. The UCI Firewall provides a configuration interface that abstracts from the http://www.netfilter.org/[iptables system] to provide a simplified configuration model that is fit for most regular purposes while enabling the user to supply needed iptables rules on their own when needed.

UCI Firewall maps two or more _Interfaces_ together into _Zones_ that are used to describe default rules for a given interface, forwarding rules between interfaces and extra rules. In the config file, default rules come _first_ but they are the last to take effect. The netfilter system is a chained processing filter where packets pass through various rules. The first rule that matches is executed, often leading to another rule-chain until a packet hits either ACCEPT or DROP/REJECT. Such an outcome is final, therefore the default rules take effect last and the most specific rule takes effect first. Zones are also used to configure _masquerading_, also known as NAT (network-address-translation); as well as port forwarding rules, which are more generally known as redirects.

Zones must always be mapped onto one or more Interfaces which ultimately map onto physical devices. Therefore zones cannot be used to specify networks (subnets) and the generated iptables rules operate on interfaces exclusively. The difference is that interfaces can be used to reach destinations not part of their own subnet, when their subnet contains another gateway. Usually however, forwarding is done between lan and wan interfaces, with the router serving as 'edge' gateway to the internet. The default configuration of UCI Firewall provides for such a common setup.

== Requirements

* **'firewall'** (or  **'firewall3'**) and its dependencies (_pre-installed_)
* **'iptables'** (_pre-installed_)
* **'iptables-mod-?'** (_optional_) - depends on what special feature is required

== Sections

Below is an overview of the section types that may be defined in the firewall configuration.
A minimal firewall configuration for a router usually consists of one _defaults_ section, at least two _zones_ ('lan' and 'wan') and one _forwarding_ to allow traffic from 'lan' to 'wan'.

=== Defaults

The 'defaults' section declares global firewall settings which do not belong to specific zones.
The following options are defined within this section:

[cols="4*1,4",options="header"]
|====
| Name | Type | Required | Default | Description
| 'input' | string | no | 'REJECT' | Set policy for the 'INPUT' chain of the 'filter' table.
| 'output' | string | no | 'REJECT' | Set policy for the 'OUTPUT' chain of the 'filter' table.
| 'forward' | string | no | 'REJECT' | Set policy for the 'FORWARD' chain of the 'filter' table.
| 'drop_invalid' | boolean | no | '0' | Drop invalid packets (e.g. not matching any active connection).
| 'synflood_protect' | boolean | no | '0' | Enable SYN flood protection.
| 'synflood_rate' | string | no | '25' | Set rate limit (packets/second) for SYN packets above which the traffic is considered a flood.
| 'synflood_burst' | string | no | '50' | Set burst limit for SYN packets above which the traffic is considered a flood if it exceeds the allowed rate.
| 'tcp_syncookies' | boolean | no | '1' | Enable the use of SYN cookies.
| 'tcp_ecn' | boolean | no | '0' |
| 'tcp_westwood' | boolean | no | '0' |
| 'tcp_window_scaling' | boolean | no | '1' | Enable TCP window scaling.
| 'accept_redirects' | boolean | no | '0' |
| 'accept_source_route' | boolean | no | '0' |
| 'custom_chains' | boolean | no | '1' |
| 'disable_ipv6' | boolean | no | '0' | Disable IPv6 firewall rules.
|====

=== Zones

A 'zone' section groups one or more _interfaces_ and serves as a _source_ or _destination_ for _forwardings_, _rules_ and _redirects_. Masquerading (NAT) of outgoing traffic is controlled on a per-zone basis. Note that masquerading is defined on the _outgoing_ interface.

* INPUT rules for a zone describe what happens to traffic trying to reach the router itself through an interface in that zone.
* OUTPUT rules for a zone describe what happens to traffic originating from the router itself going through an interface in that zone.
* FORWARD rules for a zone describe what happens to traffic passing between different interfaces in that zone.

The options below are defined within 'zone' sections:

[cols="4*1,4",options="header"]
|====
| Name | Type | Required | Default | Description
| 'name' | zone name | yes | _(none)_ | Unique zone name. 11 characters is the maximum working firewall zone name length.
| 'network' | list | no | _(none)_ | List of interfaces attached to this zone. If omitted and neither extra* options, subnets nor devices are given, the value of 'name' is used by default. Alias interfaces defined in the network config cannot be used as valid 'standalone' networks.
| 'masq' | boolean | no | '0' | Specifies whether _outgoing_ zone traffic should be masqueraded. This is typically enabled on the _wan_ zone.
| 'masq_src' | list of subnets | no | '0.0.0.0/0' | Limit masquerading to the given source subnets. Negation is possible by prefixing the subnet with '!'. multiple subnets are allowed.
| 'masq_dest' | list of subnets | no | '0.0.0.0/0' | Limit masquerading to the given destination subnets. Negation is possible by prefixing the subnet with '!'. multiple subnets are allowed.
| 'conntrack' | boolean | no | '1' if masquerading is used, '0' otherwise | Force connection tracking for this zone.
| 'mtu_fix' | boolean | no | '0' | Enable MSS clamping for _outgoing_ zone traffic.
| 'input' | string | no | 'DROP' | Default policy ('ACCEPT', 'REJECT', 'DROP') for _incoming_ zone traffic.
| 'forward' | string | no | 'DROP' | Default policy ('ACCEPT', 'REJECT', 'DROP') for _forwarded_ zone traffic.
| 'output' | string | no | 'DROP' | Default policy ('ACCEPT', 'REJECT', 'DROP') for _outgoing_ zone traffic.
| 'family' | string | no | 'any' | Protocol family ('ipv4', 'ipv6' or 'any') to generate iptables rules for.
| 'log' | boolean | no | '0' | Create log rules for rejected and dropped traffic in this zone.
| 'log_limit' | string | no | '10/minute' | Limits the amount of log messages per interval.
| 'device' | list | no | _(none)_ | List of raw network device names attached to this zone, e.g. 'ppp+' to match any PPP interface.
| 'subnet' | list | no | _(none)_ | List of IP subnets attached to this zone.
| 'extra' | string | no | _(none)_ | Extra arguments passed directly to iptables. Note that these options are passed to both source and destination classification rules, therfore direction-specific options like '--dport' should not be used here - in this case the 'extra_src' and 'extra_dest' options should be used instead.
| 'extra_src' | string | no | _Value of 'extra'_ | Extra arguments passed directly to iptables for source classification rules.
| 'extra_dest' | string | no | _Value of 'extra'_ | Extra arguments passed directly to iptables for destination classification rules.
|====

=== Forwardings

The 'forwarding' sections control the traffic flow between _zones_ and may enable MSS clamping for specific directions. Only one direction is covered by a 'forwarding' rule. To allow bidirectional traffic flows between two _zones_, two _forwardings_ are required, with 'src' and 'dest' reversed in each.

Below is a listing of allowed option within _forwardings_:

[cols="4*1,4",options="header"]
|====
| Name | Type | Required | Default | Description
| 'src' | zone name | yes | _(none)_ | Specifies the traffic _source zone_. Must refer to one of the defined _zone names_
| 'dest' | zone name | yes | _(none)_ | Specifies the traffic _destination zone_. Must refer to one of the defined _zone names_
| 'family' | string | no | 'any' | Protocol family ('ipv4', 'ipv6' or 'any') to generate iptables rules for
|====

CAUTION: The _iptables_ rules generated for this section rely on the _state match_ which needs connection tracking to work.
At least one of the 'src' or 'dest' zones needs to have _connection tracking_ enabled through either the 'masq' or the 'conntrack' option.

=== Redirects

Port forwardings (DNAT) are defined by 'redirect' sections. All _incoming_ traffic on the specified _source zone_ which matches the given rules will be directed to the specified internal host.

_Redirects are also commonly known as "port forwarding", and "virtual servers"._

Port ranges are specified as 'start:stop', for instance '6666:6670'.  This is similar to the iptables syntax.

The options below are valid for _redirects_:

[cols="4*1,4",options="header"]
|====
| Name | Type | Required | Default | Description
| 'src' | zone name | yes for 'DNAT' target | _(none)_ | Specifies the traffic _source zone_. Must refer to one of the defined _zone names_. For typical port forwards this usually is 'wan'.
| 'src_ip' | ip address | no | _(none)_ | Match incoming traffic from the specified _source ip address_.
| 'src_dip' | ip address | yes for 'SNAT' target | _(none)_ | For _DNAT_, match incoming traffic directed at the given _destination ip address_. For _SNAT_ rewrite the _source address_ to the given address.
| 'src_mac' | mac address | no | _(none)_ | Match incoming traffic from the specified _mac address_.
| 'src_port' | port or range | no | _(none)_ | Match incoming traffic originating from the given _source port or port range_ on the client host.
| 'src_dport' | port or range | no | _(none)_ | For _DNAT_, match incoming traffic directed at the given _destination port or port range_ on this host. For _SNAT_ rewrite the _source ports_ to the given value.
| 'proto' | protocol name or number | yes | _tcpudp_ | Match incoming traffic using the given _protocol_.
| 'dest' | zone name | yes for 'SNAT' target | _(none)_ | Specifies the traffic _destination zone_. Must refer to one of the defined _zone names_.
| 'dest_ip' | ip address | yes for 'DNAT' target | _(none)_ | For _DNAT_, redirect matched incoming traffic to the specified internal host. For _SNAT_, match traffic directed at the given address. For _DNAT_ if the 'dest_ip' value matches the local ip addresses of the router, as shown in the 'ifconfig', then the rule is translated in a DNAT + input 'accept' rule. Otherwise it is a DNAT + forward rule.
| 'dest_port' | port or range | no | _(none)_ | For _DNAT_, redirect matched incoming traffic to the given port on the internal host. For _SNAT_, match traffic directed at the given ports. Only a single port or range can be specified, not disparate ports as with Rules (see below).
| 'ipset' | string | no | _(none)_ | If specified, match traffic against the given ipset. The match can be inverted by prefixing the value with an exclamation mark.
| 'mark' | string | no | _(none)_ | If specified, match traffic against the given firewall mark, e.g. '0xFF' to match mark 255 or '0x0/0x1' to match any even mark value. The match can be inverted by prefixing the value with an exclamation mark, e.g. '!0x10' to match all but mark #16.
| 'start_date' | date ('yyyy-mm-dd') | no | _(always)_ | If specifed, only match traffic after the given date (inclusive).
| 'stop_date' | date ('yyyy-mm-dd') | no | _(always)_ | If specified, only match traffic before the given date (inclusive).
| 'start_time' | time ('hh:mm:ss') | no | _(always)_ | If specified, only match traffic after the given time of day (inclusive).
| 'stop_time' | time ('hh:mm:ss') | no | _(always)_ | If specified, only match traffic before the given time of day (inclusive).
| 'weekdays' | list of weekdays | no | _(always)_ | If specified, only match traffic during the given week days, e.g. 'sun mon thu fri' to only match on sundays, mondays, thursdays and fridays. The list can be inverted by prefixing it with an exclamation mark, e.g. '! sat sun' to always match but on saturdays and sundays.
| 'monthdays' | list of dates | no | _(always)_ | If specified, only match traffic during the given days of the month, e.g. '2 5 30' to only match on every 2nd, 5th and 30rd day of the month. The list can be inverted by prefixing it with an exclamation mark, e.g. '! 31' to always match but on the 31st of the month.
| 'utc_time' | boolean | no | '0' | Treat all given time values as UTC time instead of local time.
| 'target' | string | no | 'DNAT' | NAT target ('DNAT' or 'SNAT') to use when generating the rule.
| 'family' | string | no | 'any' | Protocol family ('ipv4', 'ipv6' or 'any') to generate iptables rules for.
| 'reflection' | boolean | no | '1' | Activate NAT reflection for this redirect - applicable to 'DNAT' targets.
| 'reflection_src' | string | no | 'internal' | The source address to use for NAT-reflected packets if 'reflection' is '1'. This can be 'internal' or 'external', specifying which interface’s address to use. Applicable to 'DNAT' targets.
| 'limit' | string | no | _(none)_ | Maximum average matching rate; specified as a number, with an optional '/second', '/minute', '/hour' or '/day' suffix. Examples: '3/second', '3/sec' or '3/s'.
| 'limit_burst' | integer | no | '5' | Maximum initial number of packets to match, allowing a short-term average above 'limit'.
| 'extra' | string | no | _(none)_ | Extra arguments to pass to iptables. Useful mainly to specify additional match options, such as '-m policy %%--%%dir in' for IPsec.
| 'enabled' | string | no | '1' or 'yes' | Enable the redirect rule or not.
|====

=== Rules

Sections of the type 'rule' can be used to define basic accept or reject rules to allow or restrict access to specific ports or hosts.

The rules are defined as follows:
* If 'src' and 'dest' are given, the rule matches _forwarded_ traffic
* If only 'src' is given, the rule matches _incoming_ traffic
* If only 'dest' is given, the rule matches _outgoing_ traffic
* If neither 'src' nor 'dest' are given, the rule defaults to an _outgoing_ traffic rule

Port ranges are specified as 'start:stop', for instance '6666:6670'. This is similar to the iptables syntax.

Valid options for this section are:

[cols="4*1,4",options="header"]
|====
| Name | Type | Required | Default | Description
| 'src' | zone name | no | _(none)_ | Specifies the traffic _source zone_. Must refer to one of the defined _zone names_
| 'src_ip' | ip address | no | _(none)_ | Match incoming traffic from the specified _source ip address_
| 'src_mac' | mac address | no | _(none)_ | Match incoming traffic from the specified _mac address_
| 'src_port' | port or range | no | _(none)_ | Match incoming traffic from the specified _source port_ or _port range_, if relevant 'proto' is specified. Multiple ports can be specified like '80 443 465'
| 'proto' | protocol name or number | no | 'tcpudp' | Match incoming traffic using the given _protocol_. Can be one of 'tcp', 'udp', 'tcpudp', 'udplite', 'icmp', 'esp', 'ah', 'sctp', or 'all' or it can be a numeric value. A protocol name from '/etc/protocols' is also allowed. The number 0 is equivalent to 'all'.
| 'icmp_type' | list of type names or numbers | no | any | For _protocol_ 'icmp' select specific icmp types to match. Values can be either exact icmp type numbers or type names (see below).
| 'dest' | zone name | no | _(none)_ | Specifies the traffic _destination zone_. Must refer to one of the defined _zone names_, or * for any zone. If specified, the rule applies to _forwarded_ traffic; otherwise, it is treated as _input_ rule.
| 'dest_ip' | ip address | no | _(none)_ | Match incoming traffic directed to the specified _destination ip address_. With no dest zone, this is treated as an input rule!
| 'dest_port' | port or range | no | _(none)_ | Match incoming traffic directed at the given _destination port or port range_, if relevant 'proto' is specified. Multiple ports can be specified like '80 443 465'
| 'ipset' | string | no | _(none)_ | If specified, match traffic against the given ipset. The match can be inverted by prefixing the value with an exclamation mark
| 'mark' | mark/mask | no | _(none)_ | If specified, match traffic against the given firewall mark, e.g. '0xFF' to match mark 255 or '0x0/0x1' to match any even mark value. The match can be inverted by prefixing the value with an exclamation mark, e.g. '!0x10' to match all but mark #16.
| 'start_date' | date ('yyyy-mm-dd') | no | _(always)_ | If specifed, only match traffic after the given date (inclusive).
| 'stop_date' | date ('yyyy-mm-dd') | no | _(always)_ | If specified, only match traffic before the given date (inclusive).
| 'start_time' | time ('hh:mm:ss') | no | _(always)_ | If specified, only match traffic after the given time of day (inclusive).
| 'stop_time' | time ('hh:mm:ss') | no | _(always)_ | If specified, only match traffic before the given time of day (inclusive).
| 'weekdays' | list of weekdays | no | _(always)_ | If specified, only match traffic during the given week days, e.g. 'sun mon thu fri' to only match on sundays, mondays, thursdays and fridays. The list can be inverted by prefixing it with an exclamation mark, e.g. '! sat sun' to always match but on saturdays and sundays.
| 'monthdays' | list of dates | no | _(always)_ | If specified, only match traffic during the given days of the month, e.g. '2 5 30' to only match on every 2nd, 5th and 30rd day of the month. The list can be inverted by prefixing it with an exclamation mark, e.g. '! 31' to always match but on the 31st of the month.
| 'utc_time' | boolean | no | '0' | Treat all given time values as UTC time instead of local time.
| 'target' | string | yes | 'DROP' | Firewall action ('ACCEPT', 'REJECT', 'DROP', 'MARK', 'NOTRACK') for matched traffic
| 'set_mark' | mark/mask | yes for target 'MARK' | _(none)_ | Zeroes out the bits given by mask and ORs value into the packet mark. If mask is omitted, 0xFFFFFFFF is assumed
| 'set_xmark' | ::: | ::: | ::: | Zeroes out the bits given by mask and XORs value into the packet mark. If mask is omitted, 0xFFFFFFFF is assumed
| 'family' | string | no | 'any' | Protocol family ('ipv4', 'ipv6' or 'any') to generate iptables rules for.
| 'limit' | string | no | _(none)_ | Maximum average matching rate; specified as a number, with an optional '/second', '/minute', '/hour' or '/day' suffix. Examples: '3/minute', '3/min' or '3/m'.
| 'limit_burst' | integer | no | '5' | Maximum initial number of packets to match, allowing a short-term average above 'limit'
| 'extra' | string | no | _(none)_ | Extra arguments to pass to iptables. Useful mainly to specify additional match options, such as '-m policy %%--%%dir in' for IPsec.
| 'enabled' | boolean | no | yes | Enable or disable rule.
|====

Available icmp type names for _icmp_type_:

[options="header"]
|====
| 'address-mask-reply' | 'host-redirect' | 'pong' | 'time-exceeded'
| 'address-mask-request' | 'host-unknown' | 'port-unreachable' | 'timestamp-reply'
| 'any' | 'host-unreachable' | 'precedence-cutoff' | 'timestamp-request'
| 'communication-prohibited' | 'ip-header-bad' | 'protocol-unreachable' | 'TOS-host-redirect'
| 'destination-unreachable' | 'network-prohibited' | 'redirect' | 'TOS-host-unreachable'
| 'echo-reply' | 'network-redirect' | 'required-option-missing' | 'TOS-network-redirect'
| 'echo-request' | 'network-unknown' | 'router-advertisement' | 'TOS-network-unreachable'
| 'fragmentation-needed' | 'network-unreachable' | 'router-solicitation' | 'ttl-exceeded'
| 'host-precedence-violation' | 'parameter-problem' | 'source-quench' | 'ttl-zero-during-reassembly'
| 'host-prohibited' | 'ping' | 'source-route-failed' | 'ttl-zero-during-transit'
|====

=== Includes

It is possible to include custom firewall scripts by specifying one or more 'include' sections in the firewall configuration.

There is only one possible parameter for _includes_:

[cols="4*1,4",options="header"]
|====
| Name | Type | Required | Default | Description
| 'enabled' | boolean | no | '1' | Allows to disable the corresponding include without having to delete the section
| 'type' | string | no | 'script' | Specifies the type of the include, can be 'script' for traditional shell script includes or 'restore' for plain files in _iptables-restore_ format
| 'path' | file name | yes | '/etc/firewall.user' | Specifies a shell script to execute on boot or firewall restarts
| 'family' | string | no | 'any' | Specifies the address family ('ipv4', 'ipv6' or 'any') for which the include is called
| 'reload' | boolean | no | '0' | Specifies whether the include should be called on reload - this is only needed if the include injects rules into internal chains
|====

Includes of type 'script' may contain arbitary commands, for example advanced iptables rules or tc commands required for traffic shaping.

CAUTION: Since custom iptables rules are meant to be more specific than the generic ones, you must make sure to use '-I' (insert) instead of '-A' (append) so that the rules appear **before** the default rules.


=== IP Sets

The UCI firewall version 3 supports referencing or creating http://ipset.netfilter.org/[ipsets] to simplify matching of
huge address or port lists without the need for creating one rule per item to match.

The following options are defined for _ipsets_:

[cols="4*1,4",options="header"]
|====
| Name | Type | Required | Default | Description
| 'enabled' | boolean | no | '1' | Allows to disable the declaration fo the ipset without the need to delete the section
| 'external' | string | no | _(none)_ | If the 'external' option is set to a name, the firewall will simply reference an already existing ipset pointed to by the name. If the 'external' option is unset, the firewall will create the ipset on start and destroy it on stop
| 'name' | string | yes if 'external' is unset \\ no if 'external' is set | _(none)_ if 'external' is unset \\ value of 'external' if 'external' is set | Specifies the firewall internal name of the ipset which is used to reference the set in rules or redirects
| 'family' | string | no | 'ipv4' | Protocol family ('ipv4' or 'ipv6') to create ipset for. Only applicable to storage types 'hash' and 'list', the 'bitmap' type implies 'ipv4'.
| 'storage' | string | no | _varies_ | Specifies the storage method ('bitmap', 'hash' or 'list') used by the ipset, the default varies depending on the used datatypes (see 'match' option below). In most cases the storage method can be automatically inferred from the datatype combination but in some cases multiple choices are possible (e.g. 'bitmap:ip' vs. 'hash:ip').
| 'match' | list of direction/type tuples | yes | _(none)_ | Specifies the matched data types ('ip', 'port', 'mac', 'net' or 'set') and their direction ('src' or 'dest'). The direction is joined with the datatype by an underscore to form a tuple, e.g. 'src_port' to match source ports or 'dest_net' to match destination CIDR ranges.

When using ipsets matching on multiple elements, e.g. 'hash:ip,port', specify the packet fields to match on in quotes or comma-separated (i.e. "match dest_ip dest_port").
| 'iprange' | IP range | yes for storage type 'bitmap' with datatype 'ip' | _(none)_ | Specifies the IP range to cover, see ipset. Only applicable to the 'hash' storage type.
| 'portrange' | Port range | yes for storage type 'bitmap' with datatype 'port' | _(none)_ | Specifies the port range to cover, see ipset. Only applicable to the 'hash' storage type.
| 'netmask' | integer | no | '32' | If specified, network addresses will be stored in the set instead of IP host addresses. Value must be between '1' and '32', see ipset. Only applicable to the 'bitmap' storage type with match 'ip' or the 'hash' storage type with match 'ip'.
| 'maxelem' | integer | no | '65536' | Limits the number of items that can be added to the set, only applicable to the 'hash' and 'list' storage types.
| 'hashsize' | integer | no | '1024' | Specifies the initial hash size of the set, only applicable to the 'hash' storage type.
| 'timeout' | integer | no | '0' | Specifies the default timeout for entries added to the set. A value of '0' means no timeout.
|====

=== Possible Storage / Match Combinations ===

The table below outlines the possible combinations of storage methods and matched datatypes as well as the usable IP address family.
The order of the datatype matches is significant.

[options="header"]
|====
| Family | Storage | Match | Notes
| 'ipv4' | 'bitmap' | 'ip' | Requries 'iprange' option
| 'ipv4' | 'bitmap' | 'ip mac' | Requires 'iprange' option
| 'ipv4' | 'bitmap' | 'port' | Requires 'portrange' option
| _any_ | 'hash' | 'ip' | -
| _any_ | 'hash' | 'net' | -
| _any_ | 'hash' | 'ip port' | -
| _any_ | 'hash' | 'net port' | -
| _any_ | 'hash' | 'ip port ip' | -
| _any_ | 'hash' | 'ip port net' | -
| - | 'list' | 'set' | Meta type to create a set-of-sets
|====

== IPv6 notes

As described above, the option 'family' is used for distinguishing between IPv4, IPv6 and both protocols. However the family is inferred automatically if IPv6 addresses are used, the following is automatically treated as an IPv6 only rule.

----
config rule
	option src wan
	option src_ip fdca:f00:ba3::/64
	option target ACCEPT
----


Similar, such a rule is detected as IPv4 only.

----
config rule
	option src wan
	option dest_ip 88.77.66.55
	option target REJECT
----

Rules without IP addresses are automatically added to iptables and ip6tables, unless overridden by the family option.
Redirect rules (portforwards) are always IPv4 (for now) since there is no IPv6 DNAT support (yet).

== Examples

=== Opening ports

The default configuration accepts all LAN traffic, but blocks all incoming WAN traffic on ports not currently used for connections or NAT. To open a port for a service, add a 'rule' section:
----
config rule
	option src              wan
	option dest_port        22
	option target           ACCEPT
	option proto            tcp
----

This example enables machines on the internet to use SSH to access your router.

=== Opening ports for selected subnet/host

If you want to permit access to one host or subnet you should describe _src_ip_ field:
----
config rule
	option src              wan
	option src_ip           '12.34.56.64/28'
	option dest_port        22
	option target           ACCEPT
	option proto            tcp
----

This example enables ssh access to the host from the entire _12.34.56.64/28_ subnet.

=== Port forwarding for IPv4 (Destination NAT/DNAT)

This example forwards http (but not HTTPS) traffic to the webserver running on 192.168.1.10:

----
config redirect
	option src       wan
	option src_dport 80
	option proto     tcp
	option dest      lan
	option dest_ip   192.168.1.10
----

This other example forwards one arbitrary port that you define to a box running ssh.

----
config redirect
	option src       wan
	option src_dport 5555
	option proto     tcp
	option dest      lan
	option dest_ip   192.168.1.100
	option dest_port 22
----

=== Stateful firewall without NAT

If your LAN is running with public IP addresses, then you definitely don't want NAT (masquerading). But you may still want to run a stateful firewall on the router, so that machines on the LAN are not reachable from the Internet.

To do this, add the `conntrack` option to the WAN zone:

----
config zone
	option name             wan
	list   network          'wan'
	list   network          'wan6'
	option input            REJECT
	option output           ACCEPT
	option forward          REJECT
	option masq             0
	option mtu_fix          1
	option conntrack        1
----

=== DNAT/SNAT redirects and forwarding combination

Given a couple of redirect (DNAT and SNAT, like to redirect the traffic from an host to and from a specific ip address) such as:

----
config redirect
	option name     'icmp DNAT'
	option src      'wan'
	option src_dip   '1.2.3.4'
	option proto    'icmp'
	option dest     'dmz'
	option dest_ip  '192.168.1.79'
	option target   'DNAT'

config redirect
	option name     'icmp SNAT'
	option src      'dmz'
	option src_ip   '192.168.1.79'
	option src_dip  '1.2.3.4'
	option proto    'icmp'
	option dest     'wan'
	option target   'SNAT'
----

Someone could ask "_Ok, the packet source or destination is changed, but still has to be forwarded towards the right network interface to reach the endpoint_". So the administrator of the device could wonder if adding additional forwarding rules is required; but no, it is not needed. The forwarding rules are added by the firewall appliance itself.

The same applies to the masquerading, the rules are applied _before_ the global masquerading (if a masquerading is set), therefore they will not be overridden (at least the SNAT) by the masquerading mechanism.

=== Port accept for IPv6

To open port 80 so that a local webserver at '2001:db8:42::1337' can be reached from the Internet:

----
config rule
	option src       wan
	option proto     tcp
	option dest      lan
	option dest_ip   2001:db8:42::1337
	option dest_port 80
	option family    ipv6
	option target    ACCEPT
----

To open SSH access to all IPv6 hosts in the local network:

----
config rule
	option src       wan
	option proto     tcp
	option dest      lan
	option dest_port 22
	option family    ipv6
	option target    ACCEPT
----

To open all TCP/UDP port between 1024 and 65535 towards the local IPv6 network:

----
config rule
	option src       wan
	option proto     tcpudp
	option dest      lan
	option dest_port 1024:65535
	option family    ipv6
	option target    ACCEPT
----

=== Source NAT (SNAT)

Source NAT changes an outgoing packet so that it looks as though the OpenWrt system is the source of the packet.

Define source NAT for UDP and TCP traffic directed to port 123 originating from the host with the IP address 10.55.34.85.
The source address is rewritten to 63.240.161.99:

----
config redirect
	option src              lan
	option dest             wan
	option src_ip           10.55.34.85
	option src_dip          63.240.161.99
	option dest_port        123
	option target           SNAT
----

When used alone, Source NAT is used to restrict a computer's access to the internet, but allow it to access a few services by forwarding what appear to be a few local services, e.g. NTP, to the internet.  While DNAT hides the local network from the internet, SNAT hides the internet from the local network.

Source NAT and destination NAT are combined and used dynamically in IP masquerading to make computers with private (192.168.x.x, etc.) IP address appear on the internet with the OpenWrt router's public WAN ip address.

=== Block access to the Internet using MAC

The following rule blocks all connection attempts from the client to the Internet.

----
config rule
	option src              lan
	option dest             wan
	option src_mac          00:00:00:00:00:00
	option target           REJECT
----

=== Block access to the Internet for specific IP on certain times

The following rule blocks all connection attempts to the internet from 192.168.1.27 on weekdays between 21:00pm and 09:00am (times are specified in UTC unless the --kerneltz switch is used).

CAUTION: The package 'iptables-mod-ipopt' must be installed to provide 'xt_time'.

----
config rule
	option src              lan
	option dest             wan
	option src_ip           192.168.1.27
	option proto            all
	option start_time       21:00
	option stop_time        09:00
	option weekdays         'mon tue wed thu fri'
	option target           REJECT
----

=== Restricted forwarding rule

The example below creates a _forward_ rule rejecting traffic from lan to wan on the ports 1000-1100.

----
config rule
	option src              lan
	option dest             wan
	option dest_port        1000-1100
	option proto            tcpudp
	option target           REJECT
----

=== Simple output rule

The example below creates an _output_ rule which prevents the router from pinging the address '8.8.8.8'.

----
config rule
	option dest             wan
	option dest_ip          8.8.8.8
	option proto            icmp
	option target           REJECT
----

=== Transparent proxy rule (same host)

The rule below redirects all outgoing HTTP traffic from _lan_ through a proxy server listening at port 3128 on the router itself.

----
config redirect
	option src              lan
	option proto            tcp
	option src_dport        80
	option dest_port        3128
	option dest_ip          192.168.1.1
----

=== Transparent proxy rule (external)

The following rule redirects all outgoing HTTP traffic from _lan_ through an external proxy at 192.168.1.100 listening on port 3128.
It assumes the _lan_ address to be 192.168.1.1 - this is needed to masquerade redirected traffic towards the proxy.

----
config redirect
	option src              lan
	option proto            tcp
	option src_ip           !192.168.1.100
	option src_dport        80
	option dest_ip          192.168.1.100
	option dest_port        3128
	option target           DNAT

config redirect
	option dest             lan
	option proto            tcp
	option src_dip          192.168.1.1
	option dest_ip          192.168.1.100
	option dest_port        3128
	option target           SNAT
----

=== IPSec passthrough

This example enables proper forwarding of IPSec traffic through the wan.

----
# AH protocol
config rule
	option src              wan
	option dest             lan
	option proto            ah
	option target           ACCEPT

# ESP protocol
config rule
	option src              wan
	option dest             lan
	option proto            esp
	option target           ACCEPT
----

For some configurations you also have to open port 500/UDP.

----
# ISAKMP protocol
config rule
	option src              wan
	option dest             lan
	option proto            udp
	option src_port         500
	option dest_port        500
	option target           ACCEPT
----

=== Using ipsets

This example shows how to block traffic to ipset of online game IP/port combinations. Creation/update of the ipset can be done in '/etc/rc.local' or using crontab.

----
config ipset
	option external         games_blacklist
	option match            'dest_ip dest_port'
	option family           ipv4
	option storage          hash
----

----
config rule
	option name             Drop-games-blacklist
	option src              lan
	option ipset            games_blacklist
	option proto            tcpudp
	option target           DROP
----

=== Zone declaration for semi non-UCI interfaces, manually listed in the network config, and forwardings

Scenario: having one or more vpn tunnels using openvpn,
with the need of defining a zone to forward the traffic between the
vpn interfaces and the lan.

First list the interfaces in **/etc/config/network**,
for example in written below. Be careful on the limits of interface naming in terms of name length.

----
config interface 'tun0'
	option ifname 'tun0'
	option proto 'none'

config interface 'tun1'
	option ifname 'tun1'
	option proto 'none'
----

Then create the zone in **/etc/config/firewall**, for example one zone for all the vpn interfaces.

----
config zone
	option name             vpn_tunnel
	list   network          'tun0'
	list   network          'tun1'
	option input            ACCEPT
#the traffic towards the router from the interface will be accepted
#(as for the lan communications)
	option output           ACCEPT
#the traffic from the router to the interface will be accepted
	option forward          REJECT
#traffic from this zone to other zones is normally rejected
----

Then we want to communicate with the "lan" zone, therefore we need forwardings in both ways
(from lan to wan and viceversa)

----
config forwarding
	option src              lan
	option dest             vpn_tunnel
#if a packet from lan wants to go to the vpn_tunnel zone
#let it pass

config forwarding
	option src              vpn_tunnel
	option dest             lan
#if a packet from vpn_tunnel wants to go to the lan zone
#let it pass
----

This will create a lot of "automatic" iptables rules (because automatic scripting is not
as efficient as raw iptable commands in /etc/firewall.user) but those rules will be more clear in the luci webinterface and also more readable for
less expert users.

In general remember that forwardings are relying how routing rules are defined, and afterwards which zones are
defined on which interfaces.

=== Zone declaration for non-UCI interfaces

This example declares a zone which maches any Linux network device whose name begins with "ppp".

----
config zone
	option name             example
	option input            ACCEPT
	option output           ACCEPT
	option forward          REJECT
	option device           'ppp+'
----

=== Zone declaration for a specific subnet and protocol

This example declares a zone which maches any TCP stream in the '10.21.0.0/16' subnet.

----
config zone
	option name             example
	option input            ACCEPT
	option output           ACCEPT
	option forward          REJECT
	option subnet           '10.21.0.0/16'
	option extra            '-p tcp'
----


=== Zone declaration for a specific protocol and port

This example declares a zone which maches any TCP stream from and to port '22'.

----
config zone
	option name             example
	option input            ACCEPT
	option output           ACCEPT
	option forward          REJECT
	option extra_src        '-p tcp --sport 22'
	option extra_dest       '-p tcp --dport 22'
----

=== Manual iptables rules

Traditional iptables rules, in the standard iptables unix command form, can be specified in an external file and included in the firewall config file. It is possible to include multiple files this way.
----
config include
	option path /etc/firewall.user

config include
	option path /etc/firewall.vpn
----

NOTE: The syntax for the includes is standard http://www.netfilter.org/[iptables], and therefore different from the syntax supported by UCI.

== Firewall management

After a configuration change, firewall rules are rebuilt by executing '/etc/init.d/firewall restart'; calling '/etc/init.d/firewall stop' will flush all rules and set the policies to ACCEPT on all standard chains. To manually start the firewall, call '/etc/init.d/firewall start'.

The firewall can be permananently disabled by executing '/etc/init.d/firewall disable'.
Note that 'disable' does not flush the rules, so it might be required to issue a 'stop' before.
Use 'enable' to activate the firewall again.

=== Temporarily disable firewall

Run '/etc/init.d/firewall stop' to flush all rules and set the policies to ACCEPT.
To restart the firewall, run '/etc/init.d/firewall start'.

== Hotplug hooks

In addition to _includes_ it is possible to let the firewall execute _hotplug handlers_ when interfaces are added to a zone or removed from it. This is useful to create rules for interfaces with dynamic ip configurations (dhcp, pppoe) on the fly.

Each time an interface is added or removed from a zone, all scripts in the '/etc/hotplug.d/firewall/' directory are executed. Scripts must be named in the form 'NN-name' with 'NN' being a numeric index between '00' and '99'. The 'name' can be freely choosen.

Once a handler script is invoked, the information about the event is passed through the environment. The table below lists defined variables and their meaning.

[options="header"]
|====
| Variable | Description
| ACTION | Type of the event: 'add' if an interface was added, 'remove' if it was removed
| ZONE | Name of the firewall zone the interface was added to
| INTERFACE | OpenWrt name of the interface, for example "lan" or "wan" - corresponds to the interfaces defined in '/etc/config/network'
| DEVICE | The physical interface involved, for example "eth0" or "ppp0"
|====

== Implications of DROP vs. REJECT

The decision whether to _drop_ or to _reject_ traffic should be done on a case-by-case basis. Many people see dropping traffic as a security advantage over rejecting it because it exposes less information to a potential attacker. While dropping slightly increases security, it can also complicate the debugging of network issues or cause unwanted side-effects on client programs.

If traffic is _rejected_, the router will respond with an ICMP error message ("destination port unreachable") causing the connection attempt to fail immediately. This also means that for each connection attempt a certain amount of response traffic is generated. This can cause harm if the firewall is "attacked" with many simultaneous connection attempts; the resulting "backfire" of ICMP responses can clog up all available bandwidth and make the connection unusable (DoS).

When connection attempts are _dropped_ the client is not aware of the blocking and will continue to re-transmit its packets until the connection eventually times out. Depending on the way the client software is implemented, this could result in frozen or hanging programs that need to wait until a timeout occurs before they're able to continue.

Also there is an interesting article which that claims dropping connections doesnt make you any safer - link:http://www.chiark.greenend.org.uk/~peterb/network/drop-vs-reject[Drop versus Reject]

**DROP**

* less information is exposed
* less attack surface
* client software may not cope well with it (hangs until connection times out)
* may complicate network debugging (where was traffic dropped and why)

**REJECT**

* may expose information (like the ip at which traffic was actually blocked)
* client software can recover faster from rejected connection attempts
* network debugging easier (routing and firewall issues clearly distinguishable)


== Notes on connection tracking

=== NOTRACK

By default, the firewall will disable connection tracking for a zone if no masquerading is enabled. This is achieved by generating _NOTRACK_ firewall rules matching all traffic passing via interfaces referenced by the firewall zone. The purpose of _NOTRACK_ is to speed up routing and save memory by circumventing resource intensive connection tracking in cases where it is not needed. You can check if connection tracking is disabled by issuing 'iptables -t raw -vnL', it will list all rules, check for _NOTRACK_ target.

CAUTION: _NOTRACK_ will render certain ipables extensions unusable, for example the _MASQUERADE_ target or the _state_ match will not work!

If connection tracking is required, for example by custom rules in '/etc/firewall.user', the 'conntrack' option must be enabled in the corresponding zone to disable _NOTRACK_. It should appear as 'option conntrack 1' in the right zone in '/etc/config/firewall'. For further information see http://security.maruhn.com/iptables-tutorial/x4772.html .

== Debug generated rule set

It is possible to observe the iptables commands generated by the firewall program,
this is useful to track down iptables errors during firewall restarts or to verify
the outcome of certain uci rules.

You can enable debug mode using the '-d' switch:
----
# fw3 -d reload 2>/tmp/iptables.log
----

Furthermore it is also possible to print the to-be generated ruleset using the 'print' command in conjunction with the '-4' and '-6' switches:
----
# fw3 -4 print > /tmp/ipv4.rules
# fw3 -6 print > /tmp/ipv6.rules
----

== Packet flow

=== INPUT (destined to router)

[options="header"]
|====
| Table  | Chain                       | Type     | Description
| raw    | 'PREROUTING'                | system   |
| :::    | 'notrack'                   | internal | Internal chain for NOTRACK rules
| mangle | 'PREROUTING'                | system   |
| :::    | 'fwmark'                    | internal | Internal chain for MARK rules
| nat    | 'PREROUTING'                | system   |
| :::    | 'delegate_prerouting'       | internal | Internal chain to hold toplevel prerouting rules, dispatches traffic to the corresponding 'zone__name__prerouting' chains
| :::    | 'prerouting_rule'           | user     | Container chain for custom user prerouting rules (firewall.user)
| :::    | 'zone__name__prerouting'    | internal | Per-zone container chains for DNAT (port forwarding) rules
| :::    | 'prerouting__name__rule'    | user     | Per-zone container chains for custom user prerouting rules (firewall.user)
| mangle | 'INPUT'                     | system   |
| filter | 'INPUT'                     | system   |
| :::    | 'delegate_input'            | internal | Internal chain to hold toplevel input rules, dispatches traffic to the corresponding 'zone__name__input' chains
| :::    | 'input_rule'                | user     | Container chain for custom user input rules (firewall.user)
| :::    | 'syn_flood'                 | internal | Internal chain to match and drop syn flood attempts
| :::    | 'zone__name__input'         | internal | Per-zone container chains for input rules
| :::    | 'input__name__rule'         | user     | Per-zone container chains for custom user input rules (firewall.user)
|====

=== OUTPUT (originating from router)

[options="header"]
|====
| Table  | Chain                       | Type     | Description
| raw    | 'OUTPUT'                    | system   |
| mangle | 'OUTPUT'                    | system   |
| nat    | 'OUTPUT'                    | system   |
| filter | 'OUTPUT'                    | system   |
| :::    | 'delegate_output'           | internal | Internal chain to hold toplevel output rules, dispatches traffic to the corresponding 'zone__name__output' chains
| :::    | 'output_rule'               | user     | Container chain for custom user output rules (firewall.user)
| :::    | 'zone__name__output'        | internal | Per-zone container chains for output rules
| :::    | 'output__name__rule'        | user     | Per-zone container chains for custom user output rules (firewall.user)
| mangle | 'POSTROUTING'               | system   |
| nat    | 'POSTROUTING'               | system   |
| :::    | 'delegate_postrouting'      | internal | Internal chain to hold toplevel postrouting rules, dispatches traffic to the corresponding 'zone__name__postrouting' chains
| :::    | 'postrouting_rule'          | user     | Container chain for custom user postrouting rules (firewall.user)
| :::    | 'zone__name__postrouting'   | internal | Per-zone container chains for postrouting rules (masq, snat)
| :::    | 'postrouting__name__rule'   | user     | Per-zone container chains for custom user postrouting rules (firewall.user)
|====

=== FORWARD (relayed through router)

[options="header"]
|====
| Table  | Chain                       | Type     | Description
| raw    | 'PREROUTING'                | system   |
| :::    | 'notrack'                   | internal | Internal chain for NOTRACK rules
| mangle | 'PREROUTING'                | system   |
| :::    | 'fwmark'                    | internal | Internal chain for MARK rules
| nat    | 'PREROUTING'                | system   |
| :::    | 'delegate_prerouting'       | internal | Internal chain to hold toplevel prerouting rules, dispatches traffic to the corresponding 'zone__name__prerouting' chains
| :::    | 'prerouting_rule'           | user     | Container chain for custom user prerouting rules (firewall.user)
| :::    | 'zone__name__prerouting'    | internal | Per-zone container chains for DNAT (port forwarding) rules
| :::    | 'prerouting__name__rule'    | user     | Per-zone container chains for custom user prerouting rules (firewall.user)
| mangle | 'FORWARD'                   | system   |
| :::    | 'mssfix'                    | internal | Internal chain to hold for TCPMSS rules (mtu_fix)
| filter | 'FORWARD'                   | system   |
| :::    | 'delegate_forward'          | internal | Internal chain to hold toplevel forward rules, dispatches traffic to the corresponding 'zone__name__forward' chains
| :::    | 'forwarding_rule'           | user     | Container chain for custom user forward rules (firewall.user)
| :::    | 'zone__name__forward'       | internal | Per-zone container chains for output rules
| :::    | 'forwarding__name__rule'    | user     | Per-zone container chains for custom user forward rules (firewall.user)
| mangle | 'POSTROUTING'               | system   |
| nat    | 'POSTROUTING'               | system   |
| :::    | 'delegate_postrouting'      | internal | Internal chain to hold toplevel postrouting rules, dispatches traffic to the corresponding 'zone__name__postrouting' chains
| :::    | 'postrouting_rule'          | user     | Container chain for custom user postrouting rules (firewall.user)
| :::    | 'zone__name__postrouting'   | internal | Per-zone container chains for postrouting rules (masq, snat)
| :::    | 'postrouting__name__rule'   | user     | Per-zone container chains for custom user postrouting rules (firewall.user)
|====