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
|
#!/usr/sbin/nft -f
flush ruleset
define eth_iface = enp1s0
define wg_iface = wg0
define wg_port = 51820
define dns_port = 53
define srt_input_udp_port = 60001
define srt_output_port = 60000
define srb2kart_port = 5029
table inet filter {
chain input_ipv4 {
# accepting ping (icmp-echo-request) for diagnostic purposes.
# However, it also lets probes discover this host is alive.
# This sample accepts them within a certain rate limit:
icmp type echo-request limit rate 5/second accept
}
chain input_ipv6 {
# accept neighbour discovery otherwise connectivity breaks
icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept
# accepting ping (icmpv6-echo-request) for diagnostic purposes.
# However, it also lets probes discover this host is alive.
# This sample accepts them within a certain rate limit:
icmpv6 type echo-request limit rate 5/second accept
}
chain input_world {
udp dport {
$wg_port
} accept
}
chain input_vpn {
# TODO: Should we limit source address space?
#
# ip saddr 10.8.0.0/32
# Allow VPN to use DNS.
tcp dport { $dns_port } accept
udp dport {
$dns_port,
$srt_input_udp_port,
} accept
}
chain input {
# By default, drop all traffic unless it meets a filter
# criteria specified by the rules that follow below.
type filter hook input priority 0; policy drop;
# Allow traffic from established and related packets, drop invalid
ct state vmap { established : accept, related : accept, invalid : drop }
# Jump to chain according to layer 3 protocol using a verdict map
meta protocol vmap { ip : jump input_ipv4, ip6 : jump input_ipv6 }
# Allow traffic for/from both the world and VPN.
tcp dport {
ssh,
http,
https,
} accept
udp dport {
$srt_output_port,
$srb2kart_port,
} accept
# allow loopback traffic, anything else jump to chain for further evaluation
iifname vmap { lo : accept, $eth_iface : jump input_world, $wg_iface : jump input_vpn }
# Uncomment to enable logging of denied input traffic
# log prefix "[nftables] input Denied: " counter drop
# Reject with polite "port unreachable" icmp response
reject
}
chain forward {
# Drop everything (assumes this device is not a router)
# type filter hook forward priority filter;
type filter hook forward priority 0; policy drop;
# Forward all icmp/icmpv6 packets
meta l4proto { icmp, ipv6-icmp } accept
# Allow traffic from established and related packets, drop invalid
ct state vmap { established : accept, related : accept, invalid : drop }
# Forward traffic within the VPN and between it and the outside world.
iifname $wg_iface oifname $wg_iface counter accept;
iifname $wg_iface oifname $eth_iface counter accept;
iifname $eth_iface oifname $eth_iface counter accept;
# Reject with polite "host unreachable" icmp response
reject with icmpx type host-unreachable
}
chain prerouting {
type nat hook prerouting priority 0;
}
chain postrouting {
type nat hook postrouting priority 100; policy accept;
# Masquerade all packets from WireGuard VPN to the outside world.
iifname $wg_iface oifname $eth_iface masquerade
}
# no need to define output chain, default policy is accept if undefined.
}
|