]> git.ipfire.org Git - ipfire-2.x.git/blob - src/initscripts/system/unbound
suricata: Change midstream policy to "pass-flow"
[ipfire-2.x.git] / src / initscripts / system / unbound
1 #!/bin/sh
2 ###############################################################################
3 # #
4 # IPFire.org - A linux based firewall #
5 # Copyright (C) 2007-2022 IPFire Team <info@ipfire.org> #
6 # #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
11 # #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
16 # #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
19 # #
20 ###############################################################################
21
22 . /etc/sysconfig/rc
23 . ${rc_functions}
24
25 # Cache any local zones for 60 seconds
26 LOCAL_TTL=60
27
28 # Load configuration
29 eval $(/usr/local/bin/readhash /var/ipfire/dns/settings)
30 eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings)
31
32 ip_address_revptr() {
33 local addr=${1}
34
35 local a1 a2 a3 a4
36 IFS=. read -r a1 a2 a3 a4 <<< ${addr}
37
38 echo "${a4}.${a3}.${a2}.${a1}.in-addr.arpa"
39 }
40
41 read_name_servers() {
42 # Read name servers from ISP
43 if [ "${USE_ISP_NAMESERVERS}" = "on" -a "${PROTO}" != "TLS" ]; then
44 local i
45 for i in 1 2; do
46 echo "$(</var/run/dns${i})"
47 done 2>/dev/null
48 fi
49
50 # Read configured name servers
51 local id address tls_hostname enabled remark
52 while IFS="," read -r id address tls_hostname enabled remark; do
53 [ "${enabled}" != "enabled" ] && continue
54
55 if [ "${PROTO}" = "TLS" ]; then
56 if [ -n "${tls_hostname}" ]; then
57 echo "${address}@853#${tls_hostname}"
58 fi
59 else
60 echo "${address}"
61 fi
62 done < /var/ipfire/dns/servers
63 }
64
65 config_header() {
66 echo "# This file is automatically generated and any changes"
67 echo "# will be overwritten. DO NOT EDIT!"
68 echo
69 }
70
71 write_hosts_conf() {
72 (
73 config_header
74
75 # Make own hostname resolveable
76 # 1.1.1.1 is reserved for unused green, skip this
77 if [ -n "${GREEN_ADDRESS}" -a "${GREEN_ADDRESS}" != "1.1.1.1" ]; then
78 echo "local-data: \"${HOSTNAME} ${LOCAL_TTL} IN A ${GREEN_ADDRESS}\""
79 fi
80
81 local address
82 for address in ${GREEN_ADDRESS} ${BLUE_ADDRESS} ${ORANGE_ADDRESS}; do
83 [ -n "${address}" ] || continue
84 [ "${address}" = "1.1.1.1" ] && continue
85
86 address=$(ip_address_revptr ${address})
87 echo "local-data: \"${address} ${LOCAL_TTL} IN PTR ${HOSTNAME}\""
88 done
89
90 local enabled address hostname domainname generateptr
91
92 # Find all unique domain names
93 while IFS="," read -r enabled address hostname domainname generateptr; do
94 [ "${enabled}" = "on" ] || continue
95
96 # Skip empty domainnames
97 [ "${domainname}" = "" ] && continue
98
99 echo "local-zone: ${domainname} transparent"
100 done < /var/ipfire/main/hosts | sort -u
101
102 # Add all hosts
103 while IFS="," read -r enabled address hostname domainname generateptr; do
104 [ "${enabled}" = "on" ] || continue
105
106 # Build FQDN
107 local fqdn="${hostname}.${domainname}"
108 echo "local-data: \"${fqdn} ${LOCAL_TTL} IN A ${address}\""
109
110 # Skip reverse resolution if the address equals the GREEN address
111 [ "${address}" = "${GREEN_ADDRESS}" ] && continue
112
113 # Skip reverse resolution if user requested not to do so
114 [ "${generateptr}" = "off" ] && continue
115
116 # Add RDNS
117 address=$(ip_address_revptr ${address})
118 echo "local-data: \"${address} ${LOCAL_TTL} IN PTR ${fqdn}\""
119 done < /var/ipfire/main/hosts
120 ) > /etc/unbound/hosts.conf
121 }
122
123 write_forward_conf() {
124 (
125 config_header
126
127 # Enable strict QNAME minimisation
128 if [ "${QNAME_MIN}" = "strict" ]; then
129 echo "server:"
130 echo " qname-minimisation-strict: yes"
131 echo
132 fi
133
134 # Force using TCP for upstream servers only
135 if [ "${PROTO}" = "TCP" ]; then
136 echo "# Force using TCP for upstream servers only"
137 echo "server:"
138 echo " tcp-upstream: yes"
139 echo
140 fi
141
142 local insecure_zones=""
143
144 local enabled zone server servers remark disable_dnssec rest
145 while IFS="," read -r enabled zone servers remark disable_dnssec rest; do
146 # Line must be enabled.
147 [ "${enabled}" = "on" ] || continue
148
149 # Zones that end with .local are commonly used for internal
150 # zones and therefore not signed
151 case "${zone}" in
152 *.local)
153 insecure_zones="${insecure_zones} ${zone}"
154 ;;
155 *)
156 if [ "${disable_dnssec}" = "on" ]; then
157 insecure_zones="${insecure_zones} ${zone}"
158 fi
159 ;;
160 esac
161
162 echo "stub-zone:"
163 echo " name: ${zone}"
164 for server in ${servers//|/ }; do
165 if [[ ${server} =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
166 echo " stub-addr: ${server}"
167 else
168 echo " stub-host: ${server}"
169 fi
170 done
171 echo
172
173 # Make all reverse lookup zones transparent
174 case "${zone}" in
175 *.in-addr.arpa)
176 echo "server:"
177 echo " local-zone: \"${zone}\" transparent"
178 echo
179 ;;
180 esac
181 done < /var/ipfire/dnsforward/config
182
183 if [ -n "${insecure_zones}" ]; then
184 echo "server:"
185
186 for zone in ${insecure_zones}; do
187 echo " domain-insecure: ${zone}"
188 done
189 fi
190
191 # Read name servers.
192 nameservers=$(read_name_servers)
193
194 # Only write forward zones if any nameservers are configured.
195 #
196 # Otherwise fall-back into recursor mode.
197 if [ -n "${nameservers}" ]; then
198
199 echo "forward-zone:"
200 echo " name: \".\""
201
202 # Force using TLS only
203 if [ "${PROTO}" = "TLS" ]; then
204 echo " forward-tls-upstream: yes"
205 fi
206
207 # Add upstream name servers
208 local ns
209 for ns in ${nameservers}; do
210 echo " forward-addr: ${ns}"
211 done
212 fi
213
214 ) > /etc/unbound/forward.conf
215 }
216
217 write_tuning_conf() {
218 # https://www.unbound.net/documentation/howto_optimise.html
219
220 # Determine amount of system memory
221 local mem=$(get_memory_amount)
222
223 # In the worst case scenario, unbound can use double the
224 # amount of memory allocated to a cache due to malloc overhead
225
226 # Even larger systems with more than 8GB of RAM
227 if [ ${mem} -ge 8192 ]; then
228 mem=1024
229
230 # Extra large systems with more than 4GB of RAM
231 elif [ ${mem} -ge 4096 ]; then
232 mem=512
233
234 # Large systems with more than 2GB of RAM
235 elif [ ${mem} -ge 2048 ]; then
236 mem=256
237
238 # Medium systems with more than 1GB of RAM
239 elif [ ${mem} -ge 1024 ]; then
240 mem=128
241
242 # Small systems with less than 256MB of RAM
243 elif [ ${mem} -le 256 ]; then
244 mem=16
245
246 # Everything else
247 else
248 mem=64
249 fi
250
251 (
252 config_header
253
254 # Slice up the cache
255 echo "rrset-cache-size: $(( ${mem} / 2 ))m"
256 echo "msg-cache-size: $(( ${mem} / 4 ))m"
257 echo "key-cache-size: $(( ${mem} / 4 ))m"
258
259 # Increase parallel queries
260 echo "outgoing-range: 8192"
261 echo "num-queries-per-thread: 4096"
262
263 # Use larger send/receive buffers
264 echo "so-sndbuf: 4m"
265 echo "so-rcvbuf: 4m"
266 ) > /etc/unbound/tuning.conf
267 }
268
269 get_memory_amount() {
270 local key val unit
271
272 while read -r key val unit; do
273 case "${key}" in
274 MemTotal:*)
275 # Convert to MB
276 echo "$(( ${val} / 1024 ))"
277 break
278 ;;
279 esac
280 done < /proc/meminfo
281 }
282
283 fix_time_if_dns_fails() {
284 # If DNS is working, everything is fine
285 if resolve "0.ipfire.pool.ntp.org" &>/dev/null || \
286 resolve "1.ipfire.pool.ntp.org" &>/dev/null ; then
287 return 0
288 fi
289
290 # Try to sync time with a known time server
291 boot_mesg "DNS not functioning... Trying to sync time with time.ipfire.org (81.3.27.46)..."
292 loadproc /usr/local/bin/settime 81.3.27.46
293 }
294
295 resolve() {
296 local hostname="${1}"
297 local found=1
298
299 local answer
300 for answer in $(dig +short A "${hostname}"); do
301 # Filter out non-IP addresses
302 if [[ ! "${answer}" =~ \.$ ]]; then
303 found=0
304 echo "${answer}"
305 fi
306 done
307
308 return ${found}
309 }
310
311 # Sets up Safe Search for various search engines
312 update_safe_search() {
313 local google_tlds=(
314 google.ad
315 google.ae
316 google.al
317 google.am
318 google.as
319 google.at
320 google.az
321 google.ba
322 google.be
323 google.bf
324 google.bg
325 google.bi
326 google.bj
327 google.bs
328 google.bt
329 google.by
330 google.ca
331 google.cat
332 google.cd
333 google.cf
334 google.cg
335 google.ch
336 google.ci
337 google.cl
338 google.cm
339 google.cn
340 google.co.ao
341 google.co.bw
342 google.co.ck
343 google.co.cr
344 google.co.id
345 google.co.il
346 google.co.in
347 google.co.jp
348 google.co.ke
349 google.co.kr
350 google.co.ls
351 google.com
352 google.co.ma
353 google.com.af
354 google.com.ag
355 google.com.ai
356 google.com.ar
357 google.com.au
358 google.com.bd
359 google.com.bh
360 google.com.bn
361 google.com.bo
362 google.com.br
363 google.com.bz
364 google.com.co
365 google.com.cu
366 google.com.cy
367 google.com.do
368 google.com.ec
369 google.com.eg
370 google.com.et
371 google.com.fj
372 google.com.gh
373 google.com.gi
374 google.com.gt
375 google.com.hk
376 google.com.jm
377 google.com.kh
378 google.com.kw
379 google.com.lb
380 google.com.ly
381 google.com.mm
382 google.com.mt
383 google.com.mx
384 google.com.my
385 google.com.na
386 google.com.nf
387 google.com.ng
388 google.com.ni
389 google.com.np
390 google.com.om
391 google.com.pa
392 google.com.pe
393 google.com.pg
394 google.com.ph
395 google.com.pk
396 google.com.pr
397 google.com.py
398 google.com.qa
399 google.com.sa
400 google.com.sb
401 google.com.sg
402 google.com.sl
403 google.com.sv
404 google.com.tj
405 google.com.tr
406 google.com.tw
407 google.com.ua
408 google.com.uy
409 google.com.vc
410 google.com.vn
411 google.co.mz
412 google.co.nz
413 google.co.th
414 google.co.tz
415 google.co.ug
416 google.co.uk
417 google.co.uz
418 google.co.ve
419 google.co.vi
420 google.co.za
421 google.co.zm
422 google.co.zw
423 google.cv
424 google.cz
425 google.de
426 google.dj
427 google.dk
428 google.dm
429 google.dz
430 google.ee
431 google.es
432 google.fi
433 google.fm
434 google.fr
435 google.ga
436 google.ge
437 google.gg
438 google.gl
439 google.gm
440 google.gp
441 google.gr
442 google.gy
443 google.hn
444 google.hr
445 google.ht
446 google.hu
447 google.ie
448 google.im
449 google.iq
450 google.is
451 google.it
452 google.je
453 google.jo
454 google.kg
455 google.ki
456 google.kz
457 google.la
458 google.li
459 google.lk
460 google.lt
461 google.lu
462 google.lv
463 google.md
464 google.me
465 google.mg
466 google.mk
467 google.ml
468 google.mn
469 google.ms
470 google.mu
471 google.mv
472 google.mw
473 google.ne
474 google.nl
475 google.no
476 google.nr
477 google.nu
478 google.pl
479 google.pn
480 google.ps
481 google.pt
482 google.ro
483 google.rs
484 google.ru
485 google.rw
486 google.sc
487 google.se
488 google.sh
489 google.si
490 google.sk
491 google.sm
492 google.sn
493 google.so
494 google.sr
495 google.st
496 google.td
497 google.tg
498 google.tk
499 google.tl
500 google.tm
501 google.tn
502 google.to
503 google.tt
504 google.vg
505 google.vu
506 google.ws
507 )
508
509 # Cleanup previous settings
510 unbound-control local_zone_remove "bing.com" >/dev/null
511 unbound-control local_zone_remove "duckduckgo.com" >/dev/null
512 unbound-control local_zone_remove "yandex.com" >/dev/null
513 unbound-control local_zone_remove "yandex.ru" >/dev/null
514 unbound-control local_zone_remove "youtube.com" >/dev/null
515
516 local domain
517 for domain in ${google_tlds[@]}; do
518 unbound-control local_zone_remove "${domain}"
519 done >/dev/null
520
521 if [ "${ENABLE_SAFE_SEARCH}" = "on" ]; then
522 # Bing
523 unbound-control bing.com transparent >/dev/null
524 for address in $(resolve "strict.bing.com"); do
525 unbound-control local_data "www.bing.com ${LOCAL_TTL} IN A ${address}"
526 done >/dev/null
527
528 # DuckDuckGo
529 unbound-control local_zone duckduckgo.com typetransparent >/dev/null
530 for address in $(resolve "safe.duckduckgo.com"); do
531 unbound-control local_data "duckduckgo.com ${LOCAL_TTL} IN A ${address}"
532 done >/dev/null
533
534 # Google
535 local addresses="$(resolve "forcesafesearch.google.com")"
536 for domain in ${google_tlds[@]}; do
537 unbound-control local_zone "${domain}" transparent >/dev/null
538 for address in ${addresses}; do
539 unbound-control local_data "www.${domain} ${LOCAL_TTL} IN A ${address}"
540 done >/dev/null
541 done
542
543 # Yandex
544 for domain in yandex.com yandex.ru; do
545 unbound-control local_zone "${domain}" typetransparent >/dev/null
546 for address in $(resolve "familysearch.${domain}"); do
547 unbound-control local_data "${domain} ${LOCAL_TTL} IN A ${address}"
548 done >/dev/null
549 done
550
551 # YouTube
552 if [ "${ENABLE_SAFE_SEARCH_YOUTUBE}" = "on" ]; then
553 unbound-control local_zone youtube.com transparent >/dev/null
554 for address in $(resolve "restrictmoderate.youtube.com"); do
555 unbound-control local_data "www.youtube.com ${LOCAL_TTL} IN A ${address}"
556 done >/dev/null
557 fi
558 fi
559
560 return 0
561 }
562
563 case "$1" in
564 start)
565 # Print a nicer messagen when unbound is already running
566 if pidofproc -s unbound; then
567 statusproc /usr/sbin/unbound
568 exit 0
569 fi
570
571 # Update configuration files
572 write_tuning_conf
573 write_hosts_conf
574 write_forward_conf
575
576 boot_mesg "Starting Unbound DNS Proxy..."
577 loadproc /usr/sbin/unbound || exit $?
578
579 # Install Safe Search rules when the system is already online
580 if [ -e "/var/ipfire/red/active" ]; then
581 update_safe_search
582 fi
583 ;;
584
585 stop)
586 boot_mesg "Stopping Unbound DNS Proxy..."
587 killproc /usr/sbin/unbound
588 ;;
589
590 restart)
591 $0 stop
592 sleep 1
593 $0 start
594 ;;
595 reload|update-forwarders)
596 # Update configuration files
597 write_forward_conf
598 write_hosts_conf
599
600 # Call unbound-control and perform the reload
601 /usr/sbin/unbound-control -q reload
602
603 # Dummy Resolve to wait for unbound
604 resolve "ping.ipfire.org" &>/dev/null
605
606 if [ "$1" = "update-forwarders" ]; then
607 # Make sure DNS works at this point
608 fix_time_if_dns_fails
609 fi
610
611 # Update Safe Search rules if the system is online.
612 if [ -e "/var/ipfire/red/active" ]; then
613 update_safe_search
614 fi
615 ;;
616
617 status)
618 statusproc /usr/sbin/unbound
619 ;;
620
621 resolve)
622 resolve "${2}" || exit $?
623 ;;
624
625 *)
626 echo "Usage: $0 {start|stop|restart|reload|status|resolve|update-forwarders}"
627 exit 1
628 ;;
629 esac