-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnftables-mode-test.nft
845 lines (674 loc) · 28.7 KB
/
nftables-mode-test.nft
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
#!/sbin/nft -f
# This is not a real ruleset.
# This is just testing Emacs's syntax highlighting.
$foo
@bar
######################################################################
# EXAMPLE RULESETS FROM https://wiki.nftables.org/
######################################################################
table inet filter {
chain input {
type filter hook input priority 0;
# accept any localhost traffic
iif lo accept
# accept traffic originated from us
ct state established,related accept
# accept neighbour discovery otherwise connectivity breaks
ip6 nexthdr icmpv6 icmpv6 type { nd-neighbor-solicit, echo-request, nd-router-advert, nd-neighbor-advert } accept
# count and drop any other traffic
counter drop
}
}
# FLOWTABLE EXAMPLE (NOTE: 0.9 flowtable, not the unrelated 0.8 thing also called flowtable)
table inet x {
flowtable f {
hook ingress priority 0 devices = { eth0, eth1 };
}
chain y {
type filter hook forward priority 0; policy accept;
ip protocol tcp flow offload @f
counter packets 0 bytes 0
}
}
# UPDATING A SET FROM ANOTHER CHAIN (a la iptables -m recent?)
table ip filter {
set myset {
type inet_service
flags timeout
elements = { http expires 9s }
}
chain input {
type filter hook input priority 0; policy accept;
update @myset { tcp dport timeout 1m }
}
}
table ip filter {
set myset {
type ipv4_addr
elements = { 1.1.1.1 }
}
chain input {
type filter hook input priority 0; policy accept;
add @myset { ip saddr }
}
}
add rule bridge filter forward ether type ip tcp dport 22 accept
add rule bridge filter forward ether type arp accept
add rule inet nat prerouting dnat tcp dport map { 1000 : 1.1.1.1, 2000 : 2.2.2.2, 3000 : 3.3.3.3} : tcp dport map { 1000 : 1234, 2000 : 2345, 3000 : 3456 }
add rule inet nat postrouting snat ip saddr map { 192.168.1.1 : 1.1.1.1, 192.168.2.2 : 2.2.2.2, 192.168.3.3 : 3.3.3.3 }
flush ruleset
include "./defines.nft"
table inet filter {
chain global {
ct state established,related accept
ct state invalid drop
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
udp dport 53 accept
}
include "./inet-filter-sets.nft"
include "./inet-filter-forward.nft"
include "./inet-filter-local.nft"
}
# interfaces
define nic_inet = bond0
define nic_dmz = bond1
define nic_lan = bond2
# network ranks
define net_ipv4_dmz = 10.0.1.0/24
define net_ipv6_dmz = fe00:1::/64
define net_ipv4_lan = 10.0.2.0/24
define net_ipv6_lan = fe00:2::/64
# some machines
define server1_ipv4 = 10.0.1.2
define server1_ipv6 = fe00:1::2
define workstation1_ipv4 = 10.0.2.2
define workstation1_ipv6 = fe00:2::2
set myset_ipv4 {
type ipv4_addr;
elements = { $server1_ipv4 , $workstation1_ipv4 }
}
set myset_ipv6 {
type ipv6_addr;
elements = { $server1_ipv6 , $workstation1_ipv6 }
}
chain dmz_in {
# your rules for traffic to your dmz servers
ip saddr @myset_ipv4
ip6 saddr @myset_ipv6
}
chain dmz_out {
# your rules for traffic from the dmz to internet
}
chain lan_in {
# your rules for traffic to your LAN nodes
}
chain lan_out {
# your rules for traffic from the LAN to the internet
}
chain forward {
type filter hook forward priority 0; policy drop;
jump global
oifname vmap { $nic_dmz : jump dmz_in , $nic_lan : jump lan_in }
oifname $nic_inet iifname vmap { $nic_dmz : jump dmz_out , $nic_lan : jump lan_out }
}
chain input {
type filter hook input priority 0 ; policy drop;
jump global
# your rules for traffic to the firewall here
}
chain output {
type filter hook output priority 0 ; policy drop;
jump global
# your rules for traffic originated from the firewall itself here
}
flush ruleset
table ip Inet4 {
set Knocked_1 {
type ipv4_addr
flags timeout, interval
timeout 10s
gc-interval 4s
}
set Knocked_2 {
type ipv4_addr
flags timeout
timeout 10s
gc-interval 4s
}
set Knocked_3 {
type ipv4_addr
flags timeout
timeout 10s
gc-interval 4s
}
set Knocked_4 {
type ipv4_addr
flags timeout
timeout 2m
gc-interval 4s
}
chain Knock_1 {
set add ip saddr @Knocked_1
}
chain Unknock_1 {
set update ip saddr timeout 0s @Knocked_1
}
chain Knock_2 {
set update ip saddr timeout 0s @Knocked_1
set add ip saddr @Knocked_2
}
chain Unknock_2 {
set update ip saddr timeout 0s @Knocked_2
}
chain Knock_3 {
set update ip saddr timeout 0s @Knocked_2
set add ip saddr @Knocked_3
}
chain Unknock_3 {
set update ip saddr timeout 0s @Knocked_3
}
chain Knock_4 {
set update ip saddr timeout 0s @Knocked_3
set add ip saddr @Knocked_4 log prefix "Port-Knock accepted: "
}
chain RefreshKnock {
set update ip saddr timeout 2m @Knocked_4
}
chain PortKnock {
ct state new ip saddr @Knocked_4 goto RefreshKnock
tcp dport 456 ct state new ip saddr @Knocked_3 goto Knock_4
tcp dport 345 ct state new ip saddr @Knocked_3 return
ip saddr @Knocked_3 ct state new goto Unknock_3
tcp dport 345 ct state new ip saddr @Knocked_2 goto Knock_3
tcp dport 234 ct state new ip saddr @Knocked_2 return
ip saddr @Knocked_2 ct state new goto Unknock_2
tcp dport 234 ct state new ip saddr @Knocked_1 goto Knock_2
tcp dport 123 ct state new ip saddr @Knocked_1 return
ip saddr @Knocked_1 ct state new goto Unknock_1
tcp dport 123 ct state new goto Knock_1
}
chain FilterIn {
type filter hook input priority 0
policy drop
# allow established/related connections
ct state established,related accept
# early drop of invalid connections
ct state invalid drop
# allow from loopback
meta iif lo accept
# allow icmp
ip protocol icmp accept
# port-knocking
jump PortKnock
# misc. filtering
# ...
}
chain FilterOut {
type filter hook output priority 0
policy accept
}
}
table ip filter {
map subnet_map {
type ipv4_addr : verdict
flags interval
elements = { 10.20.255.48/29 : goto group_114, 10.20.255.88/29 : goto group_114,
10.20.255.128/29 : goto group_114 }
}
set priority_set {
type ipv4_addr
flags interval
elements = { 8.8.8.8, 8.8.4.4 }
}
map group_114 {
type ipv4_addr : classid
flags interval
elements = { 10.20.255.50 : 1:ffd8, 10.20.255.90 : 1:ffd5,
10.20.255.130 : 1:ffd2 }
}
map group_114_prio {
type ipv4_addr : classid
flags interval
elements = { 10.20.255.50 : 1:ffd9, 10.20.255.90 : 1:ffd6,
10.20.255.130 : 1:ffd3 }
}
chain forward {
type filter hook forward priority filter; policy accept;
meta priority none ip daddr vmap @subnet_map counter packets 0 bytes 0
meta priority none ip saddr vmap @subnet_map counter packets 0 bytes 0
ip daddr 192.168.0.0/16 meta priority none meta priority set 1:ffff counter packets 0 bytes 0 log prefix "total - "
ip saddr 192.168.0.0/16 meta priority none meta priority set 1:ffff counter packets 0 bytes 0 log prefix "total - "
ip daddr 10.0.0.0/8 meta priority none meta priority set 1:ffff counter packets 38931 bytes 2926076 log prefix "total - "
ip saddr 10.0.0.0/8 meta priority none meta priority set 1:ffff counter packets 14 bytes 1064 log prefix "total - "
meta priority none meta priority set 1:2 counter packets 0 bytes 0 log prefix "non_shaped - "
}
chain input {
type filter hook input priority filter; policy accept;
meta priority none meta priority set 1:2 counter packets 419381 bytes 45041195
}
chain output {
type filter hook output priority filter; policy accept;
meta priority none meta priority set 1:2 counter packets 507779 bytes 51809859
}
chain group_114 {
meta priority none ip saddr @priority_set meta priority set ip daddr map @group_114_prio counter packets 0 bytes 0
meta priority none ip daddr @priority_set meta priority set ip saddr map @group_114_prio counter packets 0 bytes 0
meta priority none meta priority set ip daddr map @group_114 counter packets 0 bytes 0
meta priority none meta priority set ip saddr map @group_114 counter packets 0 bytes 0
meta priority none meta priority set 1:ffff counter packets 0 bytes 0 log prefix "group_114 - "
}
}
add table ip filter
add chain ip filter forward { type filter hook forward priority 0; policy accept; }
add map ip filter subnet_map { type ipv4_addr : verdict; flags interval; }
add set ip filter priority_set { type ipv4_addr; flags interval; }
add element ip filter priority_set {8.8.8.8 }
add element ip filter priority_set {8.8.4.4 }
add rule ip filter forward meta priority 0 ip daddr vmap @subnet_map counter
add rule ip filter forward meta priority 0 ip saddr vmap @subnet_map counter
add rule ip filter forward ip daddr 192.168.0.0/16 meta priority 0 meta priority set "1:0xffff" counter log prefix "total - "
add rule ip filter forward ip saddr 192.168.0.0/16 meta priority 0 meta priority set "1:0xffff" counter log prefix "total - "
add rule ip filter forward ip daddr 10.0.0.0/8 meta priority 0 meta priority set "1:0xffff" counter log prefix "total - "
add rule ip filter forward ip saddr 10.0.0.0/8 meta priority 0 meta priority set "1:0xffff" counter log prefix "total - "
add rule ip filter forward meta priority 0 meta priority set "1:0x2" counter log prefix "non_shaped - "
add chain ip filter input { type filter hook input priority 0; policy accept; }
add rule ip filter input meta priority 0 meta priority set "1:0x2" counter
add chain ip filter output { type filter hook output priority 0; policy accept; }
add rule ip filter output meta priority 0 meta priority set "1:0x2" counter
add chain ip filter group_114
add map ip filter group_114 { type ipv4_addr : classid; flags interval; }
add map ip filter group_114_prio { type ipv4_addr : classid; flags interval; }
add rule ip filter group_114 meta priority 0 ip saddr @priority_set meta priority set ip daddr map @group_114_prio counter
add rule ip filter group_114 meta priority 0 ip daddr @priority_set meta priority set ip saddr map @group_114_prio counter
add rule ip filter group_114 meta priority 0 meta priority set ip daddr map @group_114 counter
add rule ip filter group_114 meta priority 0 meta priority set ip saddr map @group_114 counter
add rule ip filter group_114 meta priority 0 meta priority set "1:0xffff" counter log prefix "group_114 - "
add element ip filter subnet_map { 10.20.255.48/29 : goto group_114 }
add element ip filter subnet_map { 10.20.255.88/29 : goto group_114 }
add element ip filter subnet_map { 10.20.255.128/29 : goto group_114 }
add element ip filter group_114_prio { 10.20.255.50/32 : "1:0xffd9" }
add element ip filter group_114 { 10.20.255.50/32 : "1:0xffd8" }
add element ip filter group_114_prio { 10.20.255.90/32 : "1:0xffd6" }
add element ip filter group_114 { 10.20.255.90/32 : "1:0xffd5" }
add element ip filter group_114_prio { 10.20.255.130/32 : "1:0xffd3" }
add element ip filter group_114 { 10.20.255.130/32 : "1:0xffd2" }
# packet passing through server
chain forward {
# hook forward does the magic, not the name of the chain
# priority filter can be used in newer versions of nftables > 0.9.0
type filter hook forward priority filter; policy accept;
# packet is matched against subnet_map - it is verdict map = 10.20.255.48/29 : goto group_114
meta priority none ip daddr vmap @subnet_map counter packets 0 bytes 0 # packet's dst address is looked up
# it contains decision on where to send the packet for further processing when matched - chain group_114
meta priority none ip saddr vmap @subnet_map counter packets 0 bytes 0 # packet's src address is looked up
# private destination subnet without set priority is set to 1:0xffff
ip daddr 192.168.0.0/16 meta priority none meta priority set 1:ffff counter packets 0 bytes 0 log prefix "total - "
# private source subnet without set priority is set to 1:0xffff
ip saddr 192.168.0.0/16 meta priority none meta priority set 1:ffff counter packets 0 bytes 0 log prefix "total - "
ip daddr 10.0.0.0/8 meta priority none meta priority set 1:ffff counter packets 38931 bytes 2926076 log prefix "total - "
ip saddr 10.0.0.0/8 meta priority none meta priority set 1:ffff counter packets 14 bytes 1064 log prefix "total - "
# rest of traffic is sent to separate tc class object
meta priority none meta priority set 1:2 counter packets 0 bytes 0 log prefix "non_shaped - "
}
# subnet_map redirected the packet here
chain group_114 {
# packet's source / destination address is matched against set named priority_set and it can't contain any priority set
meta priority none ip saddr @priority_set meta priority set ip daddr map @group_114_prio counter packets 0 bytes 0
# when matched it compares destination address of the packet against group_114_prio map and sets the priority accordingly - 1:ffd9
meta priority none ip daddr @priority_set meta priority set ip saddr map @group_114_prio counter packets 0 bytes 0
# packets heading / originating to / from non prioritized addresses are matched in next steps
meta priority none meta priority set ip daddr map @group_114 counter packets 0 bytes 0
meta priority none meta priority set ip saddr map @group_114 counter packets 0 bytes 0
# unknown traffic is set to untracked object - 1:0xffff
meta priority none meta priority set 1:ffff counter packets 0 bytes 0 log prefix "group_114 - "
}
map group_114 {
type ipv4_addr : classid
flags interval
elements = { 10.20.255.50 : 1:ffd8, 10.20.255.90 : 1:ffd5,
10.20.255.130 : 1:ffd2 }
}
map group_114_prio {
type ipv4_addr : classid
flags interval
elements = { 10.20.255.50 : 1:ffd9, 10.20.255.90 : 1:ffd6,
10.20.255.130 : 1:ffd3 }
}
######################################################################
# EXAMPLE STATEMENTS FROM THE MANPAGE
######################################################################
list ruleset
flush ruleset
list ruleset ip
flush ruleset ip6
table my_table { ... }
table arp my_table { ... }
add table my_table { ... }
add table arp my_table { ... }
create table my_table { ... }
create table arp my_table { ... }
delete table my_table
delete table arp my_table
list table my_table
list table arp my_table
flush table my_table
flush table arp my_table
list tables
delete table handle 1234
delete table arp handle 1234
create table inet mytable
add chain inet mytable myin { type filter hook input priority 0; }
add rule inet mytable myin counter
add table inet mytable { flags dormant; }
add table inet mytable
chain my_table my_chain { type filter hook input priority filter }
# {add | create} chain [family] table chain [{ type type hook hook [device device] priority priority ; [policy policy ;] }]
# {delete | list | flush} chain [family] table chain
# list chains
# delete chain [family] table handle handle
# rename chain [family] table chain newname
add rule filter output ip daddr 192.168.0.0/24 accept # 'ip filter' is assumed
# same command, slightly more verbose
add rule ip filter output ip daddr 192.168.0.0/24 accept
# nft -a list ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy accept;
ct state established,related accept # handle 4
ip saddr 10.1.1.1 tcp dport ssh accept # handle 5
...
}
}
# delete the rule with handle 5
# nft delete rule inet filter input handle 5
add rule inet filter input ip saddr { 10.0.0.0/8, 192.168.0.0/16 } tcp dport { 22, 443 } accept
add rule inet filter input ip saddr @allowed_hosts tcp dport @allowed_ports accept
# add set [family] table set { type type ; [flags flags ;] [timeout timeout ;] [gc-interval gc-interval ;] [elements = { element[, ...] } ;] [size size ;] [policy policy ;] [auto-merge ;] }
# {delete | list | flush} set [family] table set
# list sets
# delete set [family] table handle handle
# {add | delete} element [family] table set { element[, ...] }
# add map [family] table map { type type [flags flags ;] [elements = { element[, ...] } ;] [size size ;] [policy policy ;] }
# {delete | list | flush} map [family] table map
# list maps
# {add | delete} element [family] table map { elements = { element[, ...] } ; }
# {add | create} flowtable [family] table flowtable { hook hook priority priority ; devices = { device[, ...] } ; }
# {delete | list} flowtable [family] table flowtable
# {add | delete | list | reset} type [family] table object
# delete type [family] table handle handle
# list counters
# list quotas
# ct helper helper { type type protocol protocol ; [l3proto family ;] }
table inet myhelpers {
ct helper ftp-standard {
type "ftp" protocol tcp
}
chain prerouting {
type filter hook prerouting priority 0;
tcp dport 21 ct helper set "ftp-standard"
}
}
# ct timeout name { protocol protocol ; policy = { state: value [, ...] } ; [l3proto family ;] }
table ip filter {
ct timeout customtimeout {
protocol tcp;
l3proto ip
policy = { established: 120, close: 20 }
}
chain output {
type filter hook output priority filter; policy accept;
ct timeout set "customtimeout"
}
}
# counter [packets bytes]
# quota [over | until] [used]
# describe expression
describe tcp flags
# Interface name
filter input iifname eth0
# Weird interface name
filter input iifname "(eth0)"
# Ethernet destination MAC address
filter input ether daddr 20:c9:d0:43:12:d9
# dotted decimal notation
filter output ip daddr 127.0.0.1
# host name
filter output ip daddr localhost
# abbreviated loopback address
filter output ip6 daddr ::1
# without [] the port number (22) would be parsed as part of the
# ipv6 address
ip6 nat prerouting tcp dport 2222 dnat to [1ce::d0]:22
# match if route exists
filter input fib daddr . iif oif exists
# match only non-fragmented packets in IPv6 traffic
filter input exthdr frag missing
# match if TCP timestamp option is present
filter input tcp option timestamp exists
# match ping packets
filter output icmp type { echo-request, echo-reply }
# match ICMPv6 ping packets
filter output icmpv6 type { echo-request, echo-reply }
# meta {length | nfproto | l4proto | protocol | priority}
# [meta] {mark | iif | iifname | iiftype | oif | oifname | oiftype | skuid | skgid | nftrace | rtclassid | ibrname | obrname | pkttype | cpu | iifgroup | oifgroup | cgroup | random | ipsec | iifkind | oifkind}
filter input meta iif "foo"
# qualified meta expression
filter output meta oif eth0
# unqualified meta expression
filter output oif eth0
# packet was subject to ipsec processing
raw prerouting meta ipsec exists accept
# socket {transparent | mark}
# Mark packets that correspond to a transparent socket
table inet x {
chain y {
type filter hook prerouting priority -150; policy accept;
socket transparent 1 mark set 0x00000001 accept
}
}
# Trace packets that corresponds to a socket with a mark value of 15
table inet x {
chain y {
type filter hook prerouting priority -150; policy accept;
socket mark 0x0000000f nftrace set 1
}
}
# Set packet mark to socket mark
table inet x {
chain y {
type filter hook prerouting priority -150; policy accept;
tcp dport 8080 mark set socket mark
}
}
# osf [ttl {loose | skip}] {name | version}
# Accept packets that match the "Linux" OS genre signature without comparing TTL.
table inet x {
chain y {
type filter hook input priority 0; policy accept;
osf ttl skip name "Linux"
}
}
# fib {saddr | daddr | mark | iif | oif} [. ...] {oif | oifname | type}
# drop packets without a reverse path
filter prerouting fib saddr . iif oif missing drop
# drop packets to address not configured on ininterface
filter prerouting fib daddr . iif type != { local, broadcast, multicast } drop
# perform lookup in a specific 'arsehole' table (0xdead, needs ip appropriate ip rule)
filter prerouting meta mark set 0xdead fib daddr . mark type vmap { arsehole : drop, prohibit : jump prohibited, unreachable : drop }
# rt [ip | ip6] {classid | nexthop | mtu | ipsec}
# IP family independent rt expression
filter output rt classid 10
filter output rt ipsec missing
# IP family dependent rt expressions
ip filter output rt nexthop 192.168.0.1
ip6 filter output rt nexthop fd00::1
inet filter output rt ip nexthop 192.168.0.1
inet filter output rt ip6 nexthop fd00::1
# ipsec {in | out} [ spnum NUM ] {reqid | spi}
# ipsec {in | out} [ spnum NUM ] {ip | ip6} {saddr | daddr}
# ether {daddr | saddr | type}
# vlan {id | cfi | pcp | type}
# arp {htype | ptype | hlen | plen | operation | saddr { ip | ether } | daddr { ip | ether }
# ip {version | hdrlength | dscp | ecn | length | id | frag-off | ttl | protocol | checksum | saddr | daddr }
# icmp {type | code | checksum | id | sequence | gateway | mtu}
# igmp {type | mrt | checksum | group}
# ip6 {version | dscp | ecn | flowlabel | length | nexthdr | hoplimit | saddr | daddr}
# matching if first extension header indicates a fragment
ip6 nexthdr ipv6-frag
# icmpv6 {type | code | checksum | parameter-problem | packet-too-big | id | sequence | max-delay}
# tcp {sport | dport | sequence | ackseq | doff | reserved | flags | window | checksum | urgptr}
# udp {sport | dport | length | checksum}
# udplite {sport | dport | checksum}
# sctp {sport | dport | vtag | checksum}
# dccp {sport | dport}
# ah {nexthdr | hdrlength | reserved | spi | sequence}
# esp {spi | sequence}
# comp {nexthdr | flags | cpi}
# @base,offset,length
# Matching destination port of both UDP and TCP.
inet filter input meta l4proto {tcp, udp} @th,16,16 { 53, 80 }
# Rewrite arp packet target hardware address if target protocol address
# matches a given address.
input meta iifname enp2s0 arp ptype 0x0800 arp htype 1 arp hlen 6 arp plen 4 @nh,192,32 0xc0a88f10 @nh,144,48 set 0x112233445566 accept
# hbh {nexthdr | hdrlength}
# frag {nexthdr | frag-off | more-fragments | id}
# rt {nexthdr | hdrlength | type | seg-left}
# dst {nexthdr | hdrlength}
# mh {nexthdr | hdrlength | checksum | type}
# srh {flags | tag | sid | seg-left}
# tcp option {eol | noop | maxseg | window | sack-permitted | sack | sack0 | sack1 | sack2 | sack3 | timestamp} tcp_option_field
# exthdr {hbh | frag | rt | dst | mh}
# tcp option {eol | noop | maxseg | window | sack-permitted | sack | sack0 | sack1 | sack2 | sack3 | timestamp}
filter input tcp option sack-permitted kind 1 counter
ip6 filter input frag more-fragments 1 counter
# ct {state | direction | status | mark | expiration | helper | label}
# ct [original | reply] {l3proto | protocol | bytes | packets | avgpkt | zone}
# ct {original | reply} {proto-src | proto-dst}
# ct {original | reply} {ip | ip6} {saddr | daddr}
# restrict the number of parallel connections to a server.
filter input tcp dport 22 meter test { ip saddr ct count over 2 } reject
# {accept | drop | queue | continue | return}
# {jump | goto} chain
# process packets from eth0 and the internal network in from_lan
# chain, drop all packets from eth0 with different source addresses.
filter input iif eth0 ip saddr 192.168.0.0/24 jump from_lan
filter input iif eth0 drop
# payload_expression set value
# route some packets instead of bridging.
# redirect tcp:http from 192.160.0.0/16 to local machine for routing instead of bridging
# assumes 00:11:22:33:44:55 is local MAC address.
bridge input meta iif eth0 ip saddr 192.168.0.0/16 tcp dport 80 meta pkttype set unicast ether daddr set 00:11:22:33:44:55
# Set IPv4 DSCP header field.
ip forward ip dscp set 42
# extension_header_expression set value
tcp flags syn tcp option maxseg size set 1360
# set a size based on route information:
tcp flags syn tcp option maxseg size set rt mtu
# log the UID which generated the packet and ip options
ip filter output log flags skuid flags ip options
# log the tcp sequence numbers and tcp options from the TCP packet
ip filter output log flags tcp sequence,options
# enable all supported log flags
ip6 filter output log flags all
# counter packets number bytes number
# counter { packets number | bytes number }
# save packet nfmark in conntrack.
ct mark set meta mark
# set zone mapped via interface.
table inet raw {
chain prerouting {
type filter hook prerouting priority -300;
ct zone set iif map { "eth1" : 1, "veth1" : 2 }
}
chain output {
type filter hook output priority -300;
ct zone set oif map { "eth1" : 1, "veth1" : 2 }
}
}
# restrict events reported by ctnetlink.
ct event set new,related,destroy
# meta {mark | priority | pkttype | nftrace} set value
# limit rate [over] packet_number / TIME_UNIT [burst packet_number packets]
# limit rate [over] byte_number BYTE_UNIT / TIME_UNIT [burst byte_number BYTE_UNIT]
# TIME_UNIT := second | minute | hour | day
# BYTE_UNIT := bytes | kbytes | mbytes
# create a suitable table/chain setup for all further examples
add table nat
add chain nat prerouting { type nat hook prerouting priority 0; }
add chain nat postrouting { type nat hook postrouting priority 100; }
# translate source addresses of all packets leaving via eth0 to address 1.2.3.4
add rule nat postrouting oif eth0 snat to 1.2.3.4
# redirect all traffic entering via eth0 to destination address 192.168.1.120
add rule nat prerouting iif eth0 dnat to 192.168.1.120
# translate source addresses of all packets leaving via eth0 to whatever
# locally generated packets would use as source to reach the same destination
add rule nat postrouting oif eth0 masquerade
# redirect incoming TCP traffic for port 22 to port 2222
add rule nat prerouting tcp dport 22 redirect to :2222
# inet family:
# handle ip dnat:
add rule inet nat prerouting dnat ip to 10.0.2.99
# handle ip6 dnat:
add rule inet nat prerouting dnat ip6 to fe80::dead
# this masquerades both ipv4 and ipv6:
add rule inet nat postrouting meta oif ppp0 masquerade
# Example ruleset for tproxy statement.
table ip x {
chain y {
type filter hook prerouting priority -150; policy accept;
tcp dport ntp tproxy to 1.1.1.1
udp dport ssh tproxy to :2222
}
}
table ip6 x {
chain y {
type filter hook prerouting priority -150; policy accept;
tcp dport ntp tproxy to [dead::beef]
udp dport ssh tproxy to :2222
}
}
table inet x {
chain y {
type filter hook prerouting priority -150; policy accept;
tcp dport 321 tproxy to :ssh
tcp dport 99 tproxy ip to 1.1.1.1:999
udp dport 155 tproxy ip6 to [dead::beef]:smux
}
}
flow add @flowtable
# send to machine with ip address 10.2.3.4 on eth0
ip filter forward dup to 10.2.3.4 device "eth0"
# copy raw frame to another interface
netdetv ingress dup to "eth0"
dup to "eth0"
# combine with map dst addr to gateways
dup to ip daddr map { 192.168.7.1 : "eth0", 192.168.7.2 : "eth1" }
fwd to device
# Example for simple shitlist.
# declare a set, bound to table "filter", in family "ip". Timeout and size are mandatory because we will add elements from packet path.
add set ip filter arsehole "{ type ipv4_addr; flags timeout; size 65536; }"
# goodlist internal interface.
add rule ip filter input meta iifname "internal" accept
# drop packets coming from shitlisted ip addresses.
add rule ip filter input ip saddr @arsehole counter drop
# add source ip addresses to the shitlist if more than 10 tcp connection requests occurred per second and ip address.
# entries will timeout after one minute, after which they might be re-added if limit condition persists.
add rule ip filter input tcp flags syn tcp dport ssh meter flood size 128000 { ip saddr timeout 10s limit rate over 10/second} add @arsehole { ip saddr timeout 1m } drop
# inspect state of the rate limit meter:
list meter ip filter flood
# inspect content of arsehole:
list set ip filter arsehole
# manually add two addresses to the set:
add element filter arsehole { 10.2.3.4, 10.23.1.42 }
# select DNAT target based on TCP dport:
# connections to port 80 are redirected to 192.168.1.100,
# connections to port 8888 are redirected to 192.168.1.101
add rule ip nat prerouting dnat tcp dport map { 80 : 192.168.1.100, 8888 : 192.168.1.101 }
# source address based SNAT:
# packets from net 192.168.1.0/24 will appear as originating from 10.0.0.1,
# packets from net 192.168.2.0/24 will appear as originating from 10.0.0.2
add rule ip nat postrouting snat to ip saddr map { 192.168.1.0/24 : 10.0.0.1, 192.168.2.0/24 : 10.0.0.2 }
# jump to different chains depending on layer 4 protocol type:
add rule ip filter input ip protocol vmap { tcp : jump tcp-chain, udp : jump udp-chain , icmp : jump icmp-chain }
monitor ruleset