a55ace17c1405a78070a4d85b5928ec1e5df8ba4
[openwrt.git] / package / firewall / files / lib / core_init.sh
1 # Copyright (C) 2009-2010 OpenWrt.org
2 # Copyright (C) 2008 John Crispin <blogic@openwrt.org>
3
4 FW_INITIALIZED=
5
6 FW_ZONES=
7 FW_ZONES4=
8 FW_ZONES6=
9 FW_CONNTRACK_ZONES=
10 FW_NOTRACK_DISABLED=
11
12 FW_DEFAULTS_APPLIED=
13 FW_ADD_CUSTOM_CHAINS=
14 FW_ACCEPT_REDIRECTS=
15 FW_ACCEPT_SRC_ROUTE=
16
17 FW_DEFAULT_INPUT_POLICY=REJECT
18 FW_DEFAULT_OUTPUT_POLICY=REJECT
19 FW_DEFAULT_FORWARD_POLICY=REJECT
20
21 FW_DISABLE_IPV4=0
22 FW_DISABLE_IPV6=0
23
24
25 fw_load_defaults() {
26         fw_config_get_section "$1" defaults { \
27                 string input $FW_DEFAULT_INPUT_POLICY \
28                 string output $FW_DEFAULT_OUTPUT_POLICY \
29                 string forward $FW_DEFAULT_FORWARD_POLICY \
30                 boolean drop_invalid 0 \
31                 boolean syn_flood 0 \
32                 boolean synflood_protect 0 \
33                 string synflood_rate 25 \
34                 string synflood_burst 50 \
35                 boolean tcp_syncookies 1 \
36                 boolean tcp_ecn 0 \
37                 boolean tcp_westwood 0 \
38                 boolean tcp_window_scaling 1 \
39                 boolean accept_redirects 0 \
40                 boolean accept_source_route 0 \
41                 boolean custom_chains 1 \
42                 boolean disable_ipv6 0 \
43         } || return
44         [ -n "$FW_DEFAULTS_APPLIED" ] && {
45                 echo "Error: multiple defaults sections detected"
46                 return 1
47         }
48         FW_DEFAULTS_APPLIED=1
49
50         FW_DEFAULT_INPUT_POLICY=$defaults_input
51         FW_DEFAULT_OUTPUT_POLICY=$defaults_output
52         FW_DEFAULT_FORWARD_POLICY=$defaults_forward
53
54         FW_ADD_CUSTOM_CHAINS=$defaults_custom_chains
55
56         FW_ACCEPT_REDIRECTS=$defaults_accept_redirects
57         FW_ACCEPT_SRC_ROUTE=$defaults_accept_source_route
58
59         FW_DISABLE_IPV6=$defaults_disable_ipv6
60
61         fw_callback pre defaults
62
63         # Seems like there are only one sysctl for both IP versions.
64         for s in syncookies ecn westwood window_scaling; do
65                 eval "sysctl -e -w net.ipv4.tcp_${s}=\$defaults_tcp_${s}" >/dev/null
66         done
67         fw_sysctl_interface all
68
69         [ $defaults_drop_invalid == 1 ] && {
70                 fw add i f INPUT   DROP { -m state --state INVALID }
71                 fw add i f OUTPUT  DROP { -m state --state INVALID }
72                 fw add i f FORWARD DROP { -m state --state INVALID }
73                 FW_NOTRACK_DISABLED=1
74         }
75
76         fw add i f INPUT   ACCEPT { -m state --state RELATED,ESTABLISHED }
77         fw add i f OUTPUT  ACCEPT { -m state --state RELATED,ESTABLISHED }
78         fw add i f FORWARD ACCEPT { -m state --state RELATED,ESTABLISHED }
79
80         fw add i f INPUT  ACCEPT { -i lo }
81         fw add i f OUTPUT ACCEPT { -o lo }
82
83         # Compatibility to old 'syn_flood' parameter
84         [ $defaults_syn_flood == 1 ] && \
85                 defaults_synflood_protect=1
86
87         [ $defaults_synflood_protect == 1 ] && {
88                 echo "Loading synflood protection"
89                 fw_callback pre synflood
90                 fw add i f syn_flood
91                 fw add i f syn_flood RETURN { \
92                         -p tcp --syn \
93                         -m limit --limit "${defaults_synflood_rate}/second" --limit-burst "${defaults_synflood_burst}" \
94                 }
95                 fw add i f syn_flood DROP
96                 fw add i f INPUT syn_flood { -p tcp --syn }
97                 fw_callback post synflood
98         }
99
100         [ $defaults_custom_chains == 1 ] && {
101                 echo "Adding custom chains"
102                 fw add i f input_rule
103                 fw add i f output_rule
104                 fw add i f forwarding_rule
105                 fw add i n prerouting_rule
106                 fw add i n postrouting_rule
107
108                 fw add i f INPUT       input_rule
109                 fw add i f OUTPUT      output_rule
110                 fw add i f FORWARD     forwarding_rule
111                 fw add i n PREROUTING  prerouting_rule
112                 fw add i n POSTROUTING postrouting_rule
113         }
114
115         fw add i f input
116         fw add i f output
117         fw add i f forward
118
119         fw add i f INPUT   input
120         fw add i f OUTPUT  output
121         fw add i f FORWARD forward
122
123         fw add i f reject
124         fw add i f reject REJECT { --reject-with tcp-reset -p tcp }
125         fw add i f reject REJECT { --reject-with port-unreach }
126
127         fw_set_filter_policy
128
129         fw_callback post defaults
130 }
131
132
133 fw_config_get_zone() {
134         [ "${zone_NAME}" != "$1" ] || return
135         fw_config_get_section "$1" zone { \
136                 string name "$1" \
137                 string network "" \
138                 string input "$FW_DEFAULT_INPUT_POLICY" \
139                 string output "$FW_DEFAULT_OUTPUT_POLICY" \
140                 string forward "$FW_DEFAULT_FORWARD_POLICY" \
141                 boolean masq 0 \
142                 boolean conntrack 0 \
143                 boolean mtu_fix 0 \
144                 boolean custom_chains "$FW_ADD_CUSTOM_CHAINS" \
145                 string family "" \
146         } || return
147         [ -n "$zone_name" ] || zone_name=$zone_NAME
148         [ -n "$zone_network" ] || zone_network=$zone_name
149 }
150
151 fw_load_zone() {
152         fw_config_get_zone "$1"
153
154         list_contains FW_ZONES $zone_name && {
155                 fw_die "zone ${zone_name}: duplicated zone"
156         }
157         append FW_ZONES $zone_name
158
159         fw_callback pre zone
160
161         [ $zone_conntrack = 1 -o $zone_masq = 1 ] && \
162                 append FW_CONNTRACK_ZONES "$zone_NAME"
163
164         local mode
165         case "$zone_family" in
166                 *4)
167                         mode=4
168                         append FW_ZONES4 $zone_name
169                         uci_set_state firewall core ${zone_name}_ipv4 1
170                 ;;
171                 *6)
172                         mode=6
173                         append FW_ZONES6 $zone_name
174                         uci_set_state firewall core ${zone_name}_ipv6 1
175                 ;;
176                 *)
177                         mode=i
178                         append FW_ZONES4 $zone_name
179                         append FW_ZONES6 $zone_name
180                         uci_set_state firewall core ${zone_name}_ipv4 1
181                         uci_set_state firewall core ${zone_name}_ipv6 1
182                 ;;
183         esac
184
185         local chain=zone_${zone_name}
186
187         fw add $mode f ${chain}_ACCEPT
188         fw add $mode f ${chain}_DROP
189         fw add $mode f ${chain}_REJECT
190         fw add $mode f ${chain}_MSSFIX
191
192         # TODO: Rename to ${chain}_input
193         fw add $mode f ${chain}
194         fw add $mode f ${chain} ${chain}_${zone_input} $
195
196         fw add $mode f ${chain}_forward
197         fw add $mode f ${chain}_forward ${chain}_${zone_forward} $
198
199         # TODO: add ${chain}_output
200         fw add $mode f output ${chain}_${zone_output} $
201
202         # TODO: Rename to ${chain}_MASQUERADE
203         fw add $mode n ${chain}_nat
204         fw add $mode n ${chain}_prerouting
205
206         fw add $mode r ${chain}_notrack
207         [ $zone_masq == 1 ] && \
208                 fw add $mode n POSTROUTING ${chain}_nat $
209
210         [ $zone_mtu_fix == 1 ] && \
211                 fw add $mode f FORWARD ${chain}_MSSFIX ^
212
213         [ $zone_custom_chains == 1 ] && {
214                 [ $FW_ADD_CUSTOM_CHAINS == 1 ] || \
215                         fw_die "zone ${zone_name}: custom_chains globally disabled"
216
217                 fw add $mode f input_${zone_name}
218                 fw add $mode f ${chain} input_${zone_name} ^
219
220                 fw add $mode f forwarding_${zone_name}
221                 fw add $mode f ${chain}_forward forwarding_${zone_name} ^
222
223                 fw add $mode n prerouting_${zone_name}
224                 fw add $mode n ${chain}_prerouting prerouting_${zone_name} ^
225         }
226
227         fw_callback post zone
228 }
229
230 fw_load_notrack_zone() {
231         fw_config_get_zone "$1"
232         list_contains FW_CONNTRACK_ZONES "${zone_name}" && return
233
234         fw_callback pre notrack
235
236         fw add i r zone_${zone_name}_notrack NOTRACK $
237
238         fw_callback post notrack
239 }
240
241
242 fw_load_include() {
243         local name="$1"
244
245         local path; config_get path ${name} path
246         [ -e $path ] && . $path
247 }
248
249
250 fw_clear() {
251         local policy=$1
252
253         fw_set_filter_policy $policy
254
255         local tab
256         for tab in f n r; do
257                 fw del i $tab
258         done
259 }
260
261 fw_set_filter_policy() {
262         local policy=$1
263
264         local chn tgt
265         for chn in INPUT OUTPUT FORWARD; do
266                 eval "tgt=\${policy:-\${FW_DEFAULT_${chn}_POLICY}}"
267                 [ $tgt == "REJECT" ] && tgt=reject
268                 [ $tgt == "ACCEPT" -o $tgt == "DROP" ] || {
269                         fw add i f $chn $tgt $
270                         tgt=DROP
271                 }
272                 fw policy i f $chn $tgt
273         done
274 }
275
276
277 fw_callback() {
278         local pp=$1
279         local hk=$2
280
281         local libs lib
282         eval "libs=\$FW_CB_${pp}_${hk}"
283         [ -n "$libs" ] || return
284         for lib in $libs; do
285                 ${lib}_${pp}_${hk}_cb
286         done
287 }