aboutsummaryrefslogtreecommitdiffstats
path: root/config/shione/nftables/files/etc/nftables.conf
blob: 516718d3475ce6d6698804edde8ced8bf8415d22 (plain) (blame)
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
#!/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
                                                                                 
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,
    } 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.
}