OSDN Git Service

bcm53xx: fix dependency
[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 | 13 +++++-
15  .../firewall4/templates/zone-fullcone.uc      |  4 ++
16  root/usr/share/ucode/fw4.uc                   | 38 ++++++++++++++++++-
17  4 files changed, 53 insertions(+), 3 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 +{%   if (zone.masq6 && !fw4.default_option("fullcone")): %}
62  {%    for (let saddrs in zone.masq6_src_subnets): %}
63  {%     for (let daddrs in zone.masq6_dest_subnets): %}
64                 {%+ include("zone-masq.uc", { fw4, zone, family: 6, saddrs, daddrs }) %}
65  {%     endfor %}
66  {%    endfor %}
67  {%   endif %}
68 +{%   if (fw4.default_option("fullcone")): %}
69 +               {%+ include("zone-fullcone.uc", { fw4, zone, direction: "srcnat" }) %}
70 +{%   endif %}
71 +
72         }
73  
74  {%  endif %}
75 --- /dev/null
76 +++ b/root/usr/share/firewall4/templates/zone-fullcone.uc
77 @@ -0,0 +1,4 @@
78 +{# /usr/share/firewall4/templates/zone-fullcone.uc #}
79 +               fullcone comment "!fw4: Handle {{
80 +               zone.name
81 +}} IPv4/IPv6 fullcone NAT traffic"
82 --- a/root/usr/share/ucode/fw4.uc
83 +++ b/root/usr/share/ucode/fw4.uc
84 @@ -1,3 +1,5 @@
85 +// /usr/share/ucode/fw4.uc
86 +
87  let fs = require("fs");
88  let uci = require("uci");
89  let ubus = require("ubus");
90 @@ -419,6 +421,25 @@ function nft_try_hw_offload(devices) {
91         return (rc == 0);
92  }
93  
94 +function nft_try_fullcone() {
95 +       let nft_test =
96 +               'add table inet fw4-fullcone-test; ' +
97 +               'add chain inet fw4-fullcone-test dstnat { ' +
98 +                       'type nat hook prerouting priority -100; policy accept; ' +
99 +                       'fullcone; ' +
100 +               '}; ' +
101 +               'add chain inet fw4-fullcone-test srcnat { ' +
102 +                       'type nat hook postrouting priority -100; policy accept; ' +
103 +                       'fullcone; ' +
104 +               '}; ';
105 +       let cmd = sprintf("/usr/sbin/nft -c '%s' 2>/dev/null", replace(nft_test, "'", "'\\''"));
106 +       let ok = system(cmd) == 0;
107 +       if (!ok) {
108 +               warn("nft_try_fullcone: cmd "+ cmd + "\n");
109 +       }
110 +       return ok;
111 +}
112 +
113  
114  return {
115         read_kernel_version: function() {
116 @@ -1382,6 +1403,7 @@ return {
117                         "dnat",
118                         "snat",
119                         "masquerade",
120 +                       "fullcone",
121                         "accept",
122                         "reject",
123                         "drop"
124 @@ -1787,6 +1809,7 @@ return {
125                 }
126  
127                 let defs = this.parse_options(data, {
128 +                       fullcone: [ "bool", "0" ],
129                         input: [ "policy", "drop" ],
130                         output: [ "policy", "drop" ],
131                         forward: [ "policy", "drop" ],
132 @@ -1819,6 +1842,14 @@ return {
133  
134                 delete defs.syn_flood;
135  
136 +               if (!nft_try_fullcone()) {
137 +                       delete defs.fullcone;
138 +                       warn("nft_try_fullcone failed, disable fullcone globally\n");
139 +               }
140 +               if (this.state.defaults && !this.state.defaults.fullcone) {
141 +                       this.warn_section(data, "fullcone enabled");
142 +               }
143 +
144                 this.state.defaults = defs;
145         },
146  
147 @@ -2041,10 +2072,15 @@ return {
148                 zone.related_subnets = related_subnets;
149                 zone.related_physdevs = related_physdevs;
150  
151 +               if (this.state.defaults.fullcone) {
152 +                       zone.dflags.snat = true;
153 +                       zone.dflags.dnat = true;
154 +               }
155 +
156                 if (zone.masq || zone.masq6)
157                         zone.dflags.snat = true;
158  
159 -               if ((zone.auto_helper && !(zone.masq || zone.masq6)) || length(zone.helper)) {
160 +               if ((zone.auto_helper && !(zone.masq || zone.masq6 || this.state.defaults.fullcone)) || length(zone.helper)) {
161                         zone.dflags.helper = true;
162  
163                         for (let helper in (length(zone.helper) ? zone.helper : this.state.helpers)) {