OSDN Git Service

firewall4: disable ipv6 fullcone nat
[immortalwrt/immortalwrt.git] / package / network / config / firewall4 / patches / 001-firewall4-add-support-for-fullcone-nat.patch
1 From 980594ee7bcb0bcded95731bb12cf118d7f48951 Mon Sep 17 00:00:00 2001
2 From: Syrone Wong <wong.syrone@gmail.com>
3 Date: Sat, 9 Apr 2022 13:24:19 +0800
4 Subject: [PATCH] firewall4: add fullcone support
5
6 fullcone is drop-in replacement of masq for non-udp traffic
7
8 add runtime fullcone rule check, disable it globally if fullcone expr is
9 invalid
10
11 Renew: ZiMing Mo <msylgj@immortalwrt.org>
12 ---
13  root/etc/config/firewall                      |  1 +
14  root/usr/share/firewall4/templates/ruleset.uc | 11 +++++-
15  .../firewall4/templates/zone-fullcone.uc      |  4 ++
16  root/usr/share/ucode/fw4.uc                   | 38 ++++++++++++++++++-
17  4 files changed, 52 insertions(+), 2 deletions(-)
18  create mode 100644 root/usr/share/firewall4/templates/zone-fullcone.uc
19
20 --- a/root/etc/config/firewall
21 +++ b/root/etc/config/firewall
22 @@ -5,6 +5,7 @@ config defaults
23         option forward          REJECT
24  # Uncomment this line to disable ipv6 rules
25  #      option disable_ipv6     1
26 +       option fullcone '1'
27  
28  config zone
29         option name             lan
30 --- a/root/usr/share/firewall4/templates/ruleset.uc
31 +++ b/root/usr/share/firewall4/templates/ruleset.uc
32 @@ -1,3 +1,4 @@
33 +{# /usr/share/firewall4/templates/ruleset.uc #}
34  {% let flowtable_devices = fw4.resolve_offload_devices(); -%}
35  
36  table inet fw4
37 @@ -238,6 +239,10 @@ table inet fw4 {
38  {%   for (let redirect in fw4.redirects("dstnat_"+zone.name)): %}
39                 {%+ include("redirect.uc", { fw4, redirect }) %}
40  {%   endfor %}
41 +{%   if (fw4.default_option("fullcone")): %}
42 +               {%+ include("zone-fullcone.uc", { fw4, zone, direction: "dstnat" }) %}
43 +{%   endif %}
44 +
45         }
46  
47  {%  endif %}
48 @@ -246,20 +251,24 @@ table inet fw4 {
49  {%   for (let redirect in fw4.redirects("srcnat_"+zone.name)): %}
50                 {%+ include("redirect.uc", { fw4, redirect }) %}
51  {%   endfor %}
52 -{%   if (zone.masq): %}
53 +{%   if (zone.masq && !fw4.default_option("fullcone")): %}
54  {%    for (let saddrs in zone.masq4_src_subnets): %}
55  {%     for (let daddrs in zone.masq4_dest_subnets): %}
56                 {%+ include("zone-masq.uc", { fw4, zone, family: 4, saddrs, daddrs }) %}
57  {%     endfor %}
58  {%    endfor %}
59  {%   endif %}
60  {%   if (zone.masq6): %}
61  {%    for (let saddrs in zone.masq6_src_subnets): %}
62  {%     for (let daddrs in zone.masq6_dest_subnets): %}
63                 {%+ include("zone-masq.uc", { fw4, zone, family: 6, saddrs, daddrs }) %}
64  {%     endfor %}
65  {%    endfor %}
66  {%   endif %}
67 +{%   if (fw4.default_option("fullcone")): %}
68 +               {%+ include("zone-fullcone.uc", { fw4, zone, direction: "srcnat" }) %}
69 +{%   endif %}
70 +
71         }
72  
73  {%  endif %}
74 --- /dev/null
75 +++ b/root/usr/share/firewall4/templates/zone-fullcone.uc
76 @@ -0,0 +1,4 @@
77 +{# /usr/share/firewall4/templates/zone-fullcone.uc #}
78 +               meta nfproto ipv4 fullcone comment "!fw4: Handle {{
79 +               zone.name
80 +}} IPv4 fullcone NAT traffic"
81 --- a/root/usr/share/ucode/fw4.uc
82 +++ b/root/usr/share/ucode/fw4.uc
83 @@ -1,3 +1,5 @@
84 +// /usr/share/ucode/fw4.uc
85 +
86  let fs = require("fs");
87  let uci = require("uci");
88  let ubus = require("ubus");
89 @@ -419,6 +421,25 @@ function nft_try_hw_offload(devices) {
90         return (rc == 0);
91  }
92  
93 +function nft_try_fullcone() {
94 +       let nft_test =
95 +               'add table inet fw4-fullcone-test; ' +
96 +               'add chain inet fw4-fullcone-test dstnat { ' +
97 +                       'type nat hook prerouting priority -100; policy accept; ' +
98 +                       'fullcone; ' +
99 +               '}; ' +
100 +               'add chain inet fw4-fullcone-test srcnat { ' +
101 +                       'type nat hook postrouting priority -100; policy accept; ' +
102 +                       'fullcone; ' +
103 +               '}; ';
104 +       let cmd = sprintf("/usr/sbin/nft -c '%s' 2>/dev/null", replace(nft_test, "'", "'\\''"));
105 +       let ok = system(cmd) == 0;
106 +       if (!ok) {
107 +               warn("nft_try_fullcone: cmd "+ cmd + "\n");
108 +       }
109 +       return ok;
110 +}
111 +
112  
113  return {
114         read_kernel_version: function() {
115 @@ -1382,6 +1403,7 @@ return {
116                         "dnat",
117                         "snat",
118                         "masquerade",
119 +                       "fullcone",
120                         "accept",
121                         "reject",
122                         "drop"
123 @@ -1787,6 +1809,7 @@ return {
124                 }
125  
126                 let defs = this.parse_options(data, {
127 +                       fullcone: [ "bool", "0" ],
128                         input: [ "policy", "drop" ],
129                         output: [ "policy", "drop" ],
130                         forward: [ "policy", "drop" ],
131 @@ -1819,6 +1842,14 @@ return {
132  
133                 delete defs.syn_flood;
134  
135 +               if (!nft_try_fullcone()) {
136 +                       delete defs.fullcone;
137 +                       warn("nft_try_fullcone failed, disable fullcone globally\n");
138 +               }
139 +               if (this.state.defaults && !this.state.defaults.fullcone) {
140 +                       this.warn_section(data, "fullcone enabled");
141 +               }
142 +
143                 this.state.defaults = defs;
144         },
145  
146 @@ -2041,10 +2072,15 @@ return {
147                 zone.related_subnets = related_subnets;
148                 zone.related_physdevs = related_physdevs;
149  
150 +               if (this.state.defaults.fullcone) {
151 +                       zone.dflags.snat = true;
152 +                       zone.dflags.dnat = true;
153 +               }
154 +
155                 if (zone.masq || zone.masq6)
156                         zone.dflags.snat = true;
157  
158 -               if ((zone.auto_helper && !(zone.masq || zone.masq6)) || length(zone.helper)) {
159 +               if ((zone.auto_helper && !(zone.masq || zone.masq6 || this.state.defaults.fullcone)) || length(zone.helper)) {
160                         zone.dflags.helper = true;
161  
162                         for (let helper in (length(zone.helper) ? zone.helper : this.state.helpers)) {