Hi,
i have build Unbound 1.5.9 as addon for IPFire. Later this can completly replace dnsmaqs on IPFire. I myself run unbound over 6 weeks on more than 8 IPfire installations wihtout any problems! (x86 and x64). In this time i optimizing the config and the scripts. Now i think it's time to push my work to the mailing list... :)
Addon Description: Unbound is a validating, recursive, and caching DNS resolver. It is designed as a set of modular components that incorporate modern features, such as enhanced security (DNSSEC) validation, Internet Protocol Version 6 (IPv6), and a client resolver library API as an integral part of the architecture.
https://www.unbound.net/ http://www.linuxfromscratch.org/blfs/view/svn/server/unbound.html
Configuration: The main config file is the "/etc/unbound/unbound.conf" (default). I created a cleared config file with no descriptions and with all necessary and useful settings. (The original unbound.conf was renamed to unbound_org.conf). Unbound runs with this config in chroot mode under a separate user ("unbound" created while installing the addon). The config file is prepared for IPv6, but is disabled with "do-ip6: no". The logfile is located at /etc/unbound/log/. In chroot mode the only working location! The logrotate script moves the log daily to /var/log/unbound/. Nice statistcis are possible for IPFire's WebIF. Take a look to https://www.unbound.net/documentation/howto_statistics.html. I have written two addintional scripts and the init scripts to integrate Unbound into IPFire.
The second deamon is a watcher for the dhcpd lease file. It is only started if the DNS-Update (RFC2136) in WebIF is enabled. The unbound init script checks the WebIf valve and stats the watcher daemon automatically. I need a working solution to start a deamon from Webif with nobody rights when click "save" on dhcp server section.
New folders: /etc/unbound - main config folder /etc/unbound/blocklists - for block lists, named as "*.conf" /etc/unbound/log - contains undbound.log /etc/unbound/zones - for extra zone files, named as "*.conf" and contains local.conf /var/log/unbound - contains the older logfiles
The /etc/unbound/forward.conf can be edit for extra DNS-Server independently from IPFire setup. More than 2 servers are possible.
Needed scripts: /usr/sbin/unbound-switch Switching between dnsmasq and unbound. Creates and removes the autostart links for unbound und dnsmasq and switches the network init script
/usr/sbin/unbound-zone Reading current IPFire's network, domain and static hosts config and create IPFire's DNS-Zone file (/etc/unbound/zones/local.conf)
/src/initscripts/init.d/unbound The init script for unbound under IPFire. This Srcipt creates the needed interface.conf and dnssec.conf under /etc/unbound/. These values are read from the files /var/ipfire/ethernet/settings and /var/ipfire/red/resolv.conf
/src/initscripts/init.d/network-unbound A copy from /src/initscripts/init.d/network with removed workarounds for dnsmasq. It's not a perfect solution, but i have no better idea to remove error messages in boot log.
/src/initscripts/init.d/unbound-dhcpd The init script for python written dhcp watcher daemon
/usr/sbin/watcherdhcpd.py This script and the additional python files comes from the OPNsense Firewall disribution. I modified the watcher script to work with universal standard times in the IPFire's dhcp lease file (/var/state/dhcp/dhcpd.leases)
Additional python files under /usr/lib/python2.7/site-packages daemonize.py for demonizing the python watcher script dhcpd.py needed file for watcherdhcpd.py (read the lease file) params.py needed file for watcherdhcpd.py (procces python daemon args)
Special init scipt options (default settings): CONTROL_INTERFACE_FILE=1 - enable or disable creation/updating of /etc/unbound/interfaces.conf CONTROL_ACCESS_FILE=1 - enable or disable creation/updating of /etc/unbound/access.conf USE_CUSTOM_FORWARDS=0 - enable or disable the unsing of custom DNS forwards file /etc/unbound/forward.conf ENABLE_DNSSEC=1 - enable or disable DNSSEC (deactivates unbounds validator module) /etc/unbound/dnssec.conf
As an goodie, my patch include a block list for microsoft (skynet) windows telemetry hosts to disable phone home. The /etc/unbound/blocklists/ms-telemetry.conf file can be removed or renamed if not needed.
The second goodie: the /etc/fcron.weekly/update_unbound_anchor script downloads an ad-server block list zone file for unbound from http://pgl.yoyo.org/adservers/#unbound. This is a very nice block list for ads. If not needed remove the line: "curl -sS -L --compressed "http://pgl.yoyo.org/adservers/serverlist.php?hostformat=unbound&showintr..." > /etc/unbound/blocklists/ad-servers.conf" from the file.
I hope this small description is useful for all. Hints and suggestions are welcome.
Greetings, Marcel
Unbound is a validating, recursive, and caching DNS resolver. https://www.unbound.net
Signed-off-by: Marcel Lorenz marcel.lorenz@ipfire.org
--- config/rootfiles/packages/unbound | 70 ++++++++ config/unbound/blocklists/ms-telemetry.conf | 49 ++++++ config/unbound/forward.conf | 6 + config/unbound/root.hints | 90 ++++++++++ config/unbound/root.key | 9 + config/unbound/site-packages/daemonize.py | 247 +++++++++++++++++++++++++++ config/unbound/site-packages/dhcpd.py | 108 ++++++++++++ config/unbound/site-packages/params.py | 46 +++++ config/unbound/site-packages/watcherdhcpd.py | 107 ++++++++++++ config/unbound/unbound-dhcpd.py | 145 ++++++++++++++++ config/unbound/unbound-switch | 80 +++++++++ config/unbound/unbound-zone | 78 +++++++++ config/unbound/unbound.conf | 123 +++++++++++++ lfs/unbound | 103 +++++++++++ make.sh | 1 + src/initscripts/init.d/network-unbound | 114 +++++++++++++ src/initscripts/init.d/unbound | 178 +++++++++++++++++++ src/initscripts/init.d/unbound-dhcpd | 61 +++++++ src/paks/unbound/install.sh | 70 ++++++++ src/paks/unbound/uninstall.sh | 27 +++ src/paks/unbound/update.sh | 26 +++ 21 files changed, 1738 insertions(+) create mode 100644 config/rootfiles/packages/unbound create mode 100644 config/unbound/blocklists/ms-telemetry.conf create mode 100644 config/unbound/forward.conf create mode 100644 config/unbound/root.hints create mode 100644 config/unbound/root.key create mode 100644 config/unbound/site-packages/daemonize.py create mode 100644 config/unbound/site-packages/dhcpd.py create mode 100644 config/unbound/site-packages/params.py create mode 100644 config/unbound/site-packages/watcherdhcpd.py create mode 100644 config/unbound/unbound-dhcpd.py create mode 100755 config/unbound/unbound-switch create mode 100644 config/unbound/unbound-zone create mode 100644 config/unbound/unbound.conf create mode 100644 lfs/unbound create mode 100644 src/initscripts/init.d/network-unbound create mode 100644 src/initscripts/init.d/unbound create mode 100644 src/initscripts/init.d/unbound-dhcpd create mode 100644 src/paks/unbound/install.sh create mode 100644 src/paks/unbound/uninstall.sh create mode 100644 src/paks/unbound/update.sh
diff --git a/config/rootfiles/packages/unbound b/config/rootfiles/packages/unbound new file mode 100644 index 0000000..c468167 --- /dev/null +++ b/config/rootfiles/packages/unbound @@ -0,0 +1,70 @@ +etc/rc.d/init.d/network-unbound +etc/rc.d/init.d/unbound +etc/rc.d/init.d/unbound-dhcpd +#etc/unbound +#etc/unbound/blocklists +etc/unbound/blocklists/ms-telemetry.conf +etc/unbound/forward.conf +etc/unbound/root.hints +etc/unbound/root.key +etc/unbound/unbound.conf +etc/unbound/unbound_org.conf +usr/bin/unbound-host +#usr/include/unbound.h +#usr/lib/libunbound.la +usr/lib/libunbound.so +usr/lib/libunbound.so.2 +usr/lib/libunbound.so.2.4.1 +#usr/lib/python2.7/site-packages/_unbound.la +usr/lib/python2.7/site-packages/_unbound.so +usr/lib/python2.7/site-packages/daemonize.py +usr/lib/python2.7/site-packages/dhcpd.py +usr/lib/python2.7/site-packages/params.py +usr/lib/python2.7/site-packages/unbound.py +usr/lib/python2.7/site-packages/watcherdhcpd.py +usr/sbin/unbound +usr/sbin/unbound-anchor +usr/sbin/unbound-checkconf +usr/sbin/unbound-dhcpd.py +usr/sbin/unbound-control +usr/sbin/unbound-control-setup +usr/sbin/unbound-switch +usr/sbin/unbound-zone +#usr/share/man/man1/unbound-host.1 +#usr/share/man/man3/libunbound.3 +#usr/share/man/man3/ub_cancel.3 +#usr/share/man/man3/ub_ctx.3 +#usr/share/man/man3/ub_ctx_add_ta.3 +#usr/share/man/man3/ub_ctx_add_ta_file.3 +#usr/share/man/man3/ub_ctx_async.3 +#usr/share/man/man3/ub_ctx_config.3 +#usr/share/man/man3/ub_ctx_create.3 +#usr/share/man/man3/ub_ctx_data_add.3 +#usr/share/man/man3/ub_ctx_data_remove.3 +#usr/share/man/man3/ub_ctx_debuglevel.3 +#usr/share/man/man3/ub_ctx_debugout.3 +#usr/share/man/man3/ub_ctx_delete.3 +#usr/share/man/man3/ub_ctx_get_option.3 +#usr/share/man/man3/ub_ctx_hosts.3 +#usr/share/man/man3/ub_ctx_print_local_zones.3 +#usr/share/man/man3/ub_ctx_resolvconf.3 +#usr/share/man/man3/ub_ctx_set_fwd.3 +#usr/share/man/man3/ub_ctx_set_option.3 +#usr/share/man/man3/ub_ctx_trustedkeys.3 +#usr/share/man/man3/ub_ctx_zone_add.3 +#usr/share/man/man3/ub_ctx_zone_remove.3 +#usr/share/man/man3/ub_fd.3 +#usr/share/man/man3/ub_poll.3 +#usr/share/man/man3/ub_process.3 +#usr/share/man/man3/ub_resolve.3 +#usr/share/man/man3/ub_resolve_async.3 +#usr/share/man/man3/ub_resolve_free.3 +#usr/share/man/man3/ub_result.3 +#usr/share/man/man3/ub_strerror.3 +#usr/share/man/man3/ub_wait.3 +#usr/share/man/man5/unbound.conf.5 +#usr/share/man/man8/unbound-anchor.8 +#usr/share/man/man8/unbound-checkconf.8 +#usr/share/man/man8/unbound-control-setup.8 +#usr/share/man/man8/unbound-control.8 +#usr/share/man/man8/unbound.8 diff --git a/config/unbound/blocklists/ms-telemetry.conf b/config/unbound/blocklists/ms-telemetry.conf new file mode 100644 index 0000000..7801e76 --- /dev/null +++ b/config/unbound/blocklists/ms-telemetry.conf @@ -0,0 +1,49 @@ +# Windows telemetry +local-data: "a-0001.a-msedge.net A 127.0.0.1" +local-data: "asimov-win.settings.data.microsoft.com.akadns.net. A 127.0.0.1" +local-data: "asimov-win.vortex.data.microsoft.com.akadns.net. A 127.0.0.1" +local-data: "choice.microsoft.com A 127.0.0.1" +local-data: "choice.microsoft.com.nsatc.net A 127.0.0.1" +local-data: "compatexchange.cloudapp.net A 127.0.0.1" +local-data: "corpext.msitadfs.glbdns2.microsoft.com A 127.0.0.1" +local-data: "corp.sts.microsoft.com A 127.0.0.1" +local-data: "cs1.wpc.v0cdn.net A 127.0.0.1" +local-data: "df.telemetry.microsoft.com A 127.0.0.1" +local-data: "diagnostics.support.microsoft.com A 127.0.0.1" +local-data: "fe2.update.microsoft.com.akadns.net A 127.0.0.1" +local-data: "feedback.microsoft-hohm.com A 127.0.0.1" +local-data: "feedback.search.microsoft.com A 127.0.0.1" +local-data: "feedback.windows.com A 127.0.0.1" +local-data: "i1.services.social.microsoft.com A 127.0.0.1" +local-data: "i1.services.social.microsoft.com.nsatc.net A 127.0.0.1" +local-data: "nexus.officeapps.live.com A 127.0.0.1" +local-data: "oca.telemetry.microsoft.com A 127.0.0.1" +local-data: "oca.telemetry.microsoft.com.nsatc.net A 127.0.0.1" +local-data: "pre.footprintpredict.com A 127.0.0.1" +local-data: "redir.metaservices.microsoft.com A 127.0.0.1" +local-data: "reports.wes.df.telemetry.microsoft.com A 127.0.0.1" +local-data: "services.wes.df.telemetry.microsoft.com A 127.0.0.1" +local-data: "settings-sandbox.data.microsoft.com A 127.0.0.1" +local-data: "settings-win.data.microsoft.com A 127.0.0.1" +local-data: "sls.update.microsoft.com.akadns.net A 127.0.0.1" +local-data: "sqm.df.telemetry.microsoft.com A 127.0.0.1" +local-data: "sqm.telemetry.microsoft.com A 127.0.0.1" +local-data: "sqm.telemetry.microsoft.com.nsatc.net A 127.0.0.1" +local-data: "statsfe1.ws.microsoft.com A 127.0.0.1" +local-data: "statsfe2.update.microsoft.com.akadns.net A 127.0.0.1" +local-data: "statsfe2.ws.microsoft.com A 127.0.0.1" +local-data: "survey.watson.microsoft.com A 127.0.0.1" +local-data: "telecommand.telemetry.microsoft.com A 127.0.0.1" +local-data: "telecommand.telemetry.microsoft.com.nsatc.net A 127.0.0.1" +local-data: "telemetry.appex.bing.net A 127.0.0.1" +local-data: "telemetry.microsoft.com A 127.0.0.1" +local-data: "telemetry.urs.microsoft.com A 127.0.0.1" +local-data: "vortex.data.microsoft.com A 127.0.0.1" +local-data: "vortex-sandbox.data.microsoft.com A 127.0.0.1" +local-data: "vortex-win.data.microsoft.com A 127.0.0.1" +local-data: "watson.live.com A 127.0.0.1" +local-data: "watson.microsoft.com A 127.0.0.1" +local-data: "watson.ppe.telemetry.microsoft.com A 127.0.0.1" +local-data: "watson.telemetry.microsoft.com A 127.0.0.1" +local-data: "watson.telemetry.microsoft.com.nsatc.net A 127.0.0.1" +local-data: "wes.df.telemetry.microsoft.com A 127.0.0.1" diff --git a/config/unbound/forward.conf b/config/unbound/forward.conf new file mode 100644 index 0000000..5784f9f --- /dev/null +++ b/config/unbound/forward.conf @@ -0,0 +1,6 @@ +forward-zone: + name: "." + forward-addr: 85.214.20.141 + forward-addr: 194.150.168.168 + forward-addr: 208.67.222.222 + forward-addr: 208.67.220.220 diff --git a/config/unbound/root.hints b/config/unbound/root.hints new file mode 100644 index 0000000..3c82146 --- /dev/null +++ b/config/unbound/root.hints @@ -0,0 +1,90 @@ +; This file holds the information on root name servers needed to +; initialize cache of Internet domain name servers +; (e.g. reference this file in the "cache . <file>" +; configuration file of BIND domain name servers). +; +; This file is made available by InterNIC +; under anonymous FTP as +; file /domain/named.cache +; on server FTP.INTERNIC.NET +; -OR- RS.INTERNIC.NET +; +; last update: March 23, 2016 +; related version of root zone: 2016032301 +; +; formerly NS.INTERNIC.NET +; +. 3600000 NS A.ROOT-SERVERS.NET. +A.ROOT-SERVERS.NET. 3600000 A 198.41.0.4 +A.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:ba3e::2:30 +; +; FORMERLY NS1.ISI.EDU +; +. 3600000 NS B.ROOT-SERVERS.NET. +B.ROOT-SERVERS.NET. 3600000 A 192.228.79.201 +B.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:84::b +; +; FORMERLY C.PSI.NET +; +. 3600000 NS C.ROOT-SERVERS.NET. +C.ROOT-SERVERS.NET. 3600000 A 192.33.4.12 +C.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2::c +; +; FORMERLY TERP.UMD.EDU +; +. 3600000 NS D.ROOT-SERVERS.NET. +D.ROOT-SERVERS.NET. 3600000 A 199.7.91.13 +D.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2d::d +; +; FORMERLY NS.NASA.GOV +; +. 3600000 NS E.ROOT-SERVERS.NET. +E.ROOT-SERVERS.NET. 3600000 A 192.203.230.10 +; +; FORMERLY NS.ISC.ORG +; +. 3600000 NS F.ROOT-SERVERS.NET. +F.ROOT-SERVERS.NET. 3600000 A 192.5.5.241 +F.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2f::f +; +; FORMERLY NS.NIC.DDN.MIL +; +. 3600000 NS G.ROOT-SERVERS.NET. +G.ROOT-SERVERS.NET. 3600000 A 192.112.36.4 +; +; FORMERLY AOS.ARL.ARMY.MIL +; +. 3600000 NS H.ROOT-SERVERS.NET. +H.ROOT-SERVERS.NET. 3600000 A 198.97.190.53 +H.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:1::53 +; +; FORMERLY NIC.NORDU.NET +; +. 3600000 NS I.ROOT-SERVERS.NET. +I.ROOT-SERVERS.NET. 3600000 A 192.36.148.17 +I.ROOT-SERVERS.NET. 3600000 AAAA 2001:7fe::53 +; +; OPERATED BY VERISIGN, INC. +; +. 3600000 NS J.ROOT-SERVERS.NET. +J.ROOT-SERVERS.NET. 3600000 A 192.58.128.30 +J.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:c27::2:30 +; +; OPERATED BY RIPE NCC +; +. 3600000 NS K.ROOT-SERVERS.NET. +K.ROOT-SERVERS.NET. 3600000 A 193.0.14.129 +K.ROOT-SERVERS.NET. 3600000 AAAA 2001:7fd::1 +; +; OPERATED BY ICANN +; +. 3600000 NS L.ROOT-SERVERS.NET. +L.ROOT-SERVERS.NET. 3600000 A 199.7.83.42 +L.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:9f::42 +; +; OPERATED BY WIDE +; +. 3600000 NS M.ROOT-SERVERS.NET. +M.ROOT-SERVERS.NET. 3600000 A 202.12.27.33 +M.ROOT-SERVERS.NET. 3600000 AAAA 2001:dc3::35 +; End of file diff --git a/config/unbound/root.key b/config/unbound/root.key new file mode 100644 index 0000000..fb540e3 --- /dev/null +++ b/config/unbound/root.key @@ -0,0 +1,9 @@ +; autotrust trust anchor file +;;id: . 1 +;;last_queried: 1467576595 ;;Sun Jul 3 22:09:55 2016 +;;last_success: 1467576595 ;;Sun Jul 3 22:09:55 2016 +;;next_probe_time: 1467616562 ;;Mon Jul 4 09:16:02 2016 +;;query_failed: 0 +;;query_interval: 43200 +;;retry_time: 8640 +. 172800 IN DNSKEY 257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjFFVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaDX6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpzW5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relSQageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulqQxA+Uk1ihz0= ;{id = 19036 (ksk), size = 2048b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1467575383 ;;Sun Jul 3 21:49:43 2016 diff --git a/config/unbound/site-packages/daemonize.py b/config/unbound/site-packages/daemonize.py new file mode 100644 index 0000000..e083feb --- /dev/null +++ b/config/unbound/site-packages/daemonize.py @@ -0,0 +1,247 @@ +# #!/usr/bin/python + +import fcntl +import os +import pwd +import grp +import sys +import signal +import resource +import logging +import atexit +from logging import handlers +import traceback + + +__version__ = "2.4.6" + + +class Daemonize(object): + """ + Daemonize object. + + Object constructor expects three arguments. + + :param app: contains the application name which will be sent to syslog. + :param pid: path to the pidfile. + :param action: your custom function which will be executed after daemonization. + :param keep_fds: optional list of fds which should not be closed. + :param auto_close_fds: optional parameter to not close opened fds. + :param privileged_action: action that will be executed before drop privileges if user or + group parameter is provided. + If you want to transfer anything from privileged_action to action, such as + opened privileged file descriptor, you should return it from + privileged_action function and catch it inside action function. + :param user: drop privileges to this user if provided. + :param group: drop privileges to this group if provided. + :param verbose: send debug messages to logger if provided. + :param logger: use this logger object instead of creating new one, if provided. + :param foreground: stay in foreground; do not fork (for debugging) + :param chdir: change working directory if provided or / + """ + def __init__(self, app, pid, action, + keep_fds=None, auto_close_fds=True, privileged_action=None, + user=None, group=None, verbose=False, logger=None, + foreground=False, chdir="/"): + self.app = app + self.pid = os.path.abspath(pid) + self.action = action + self.keep_fds = keep_fds or [] + self.privileged_action = privileged_action or (lambda: ()) + self.user = user + self.group = group + self.logger = logger + self.verbose = verbose + self.auto_close_fds = auto_close_fds + self.foreground = foreground + self.chdir = chdir + + def sigterm(self, signum, frame): + """ + These actions will be done after SIGTERM. + """ + self.logger.warn("Caught signal %s. Stopping daemon." % signum) + sys.exit(0) + + def exit(self): + """ + Cleanup pid file at exit. + """ + self.logger.warn("Stopping daemon.") + os.remove(self.pid) + sys.exit(0) + + def start(self): + """ + Start daemonization process. + """ + # If pidfile already exists, we should read pid from there; to overwrite it, if locking + # will fail, because locking attempt somehow purges the file contents. + if os.path.isfile(self.pid): + with open(self.pid, "r") as old_pidfile: + old_pid = old_pidfile.read() + # Create a lockfile so that only one instance of this daemon is running at any time. + try: + lockfile = open(self.pid, "w") + except IOError: + print("Unable to create the pidfile.") + sys.exit(1) + try: + # Try to get an exclusive lock on the file. This will fail if another process has the file + # locked. + fcntl.flock(lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB) + except IOError: + print("Unable to lock on the pidfile.") + # We need to overwrite the pidfile if we got here. + with open(self.pid, "w") as pidfile: + pidfile.write(old_pid) + sys.exit(1) + + # skip fork if foreground is specified + if not self.foreground: + # Fork, creating a new process for the child. + try: + process_id = os.fork() + except OSError as e: + self.logger.error("Unable to fork, errno: {0}".format(e.errno)) + sys.exit(1) + if process_id != 0: + # This is the parent process. Exit without cleanup, + # see https://github.com/thesharp/daemonize/issues/46 + os._exit(0) + # This is the child process. Continue. + + # Stop listening for signals that the parent process receives. + # This is done by getting a new process id. + # setpgrp() is an alternative to setsid(). + # setsid puts the process in a new parent group and detaches its controlling terminal. + process_id = os.setsid() + if process_id == -1: + # Uh oh, there was a problem. + sys.exit(1) + + # Add lockfile to self.keep_fds. + self.keep_fds.append(lockfile.fileno()) + + # Close all file descriptors, except the ones mentioned in self.keep_fds. + devnull = "/dev/null" + if hasattr(os, "devnull"): + # Python has set os.devnull on this system, use it instead as it might be different + # than /dev/null. + devnull = os.devnull + + if self.auto_close_fds: + for fd in range(3, resource.getrlimit(resource.RLIMIT_NOFILE)[0]): + if fd not in self.keep_fds: + try: + os.close(fd) + except OSError: + pass + + devnull_fd = os.open(devnull, os.O_RDWR) + os.dup2(devnull_fd, 0) + os.dup2(devnull_fd, 1) + os.dup2(devnull_fd, 2) + + if self.logger is None: + # Initialize logging. + self.logger = logging.getLogger(self.app) + self.logger.setLevel(logging.DEBUG) + # Display log messages only on defined handlers. + self.logger.propagate = False + + # Initialize syslog. + # It will correctly work on OS X, Linux and FreeBSD. + if sys.platform == "darwin": + syslog_address = "/var/run/syslog" + else: + syslog_address = "/dev/log" + + # We will continue with syslog initialization only if actually have such capabilities + # on the machine we are running this. + if os.path.exists(syslog_address): + syslog = handlers.SysLogHandler(syslog_address) + if self.verbose: + syslog.setLevel(logging.DEBUG) + else: + syslog.setLevel(logging.INFO) + # Try to mimic to normal syslog messages. + formatter = logging.Formatter("%(asctime)s %(name)s: %(message)s", + "%b %e %H:%M:%S") + syslog.setFormatter(formatter) + + self.logger.addHandler(syslog) + + # Set umask to default to safe file permissions when running as a root daemon. 027 is an + # octal number which we are typing as 0o27 for Python3 compatibility. + os.umask(0o27) + + # Change to a known directory. If this isn't done, starting a daemon in a subdirectory that + # needs to be deleted results in "directory busy" errors. + os.chdir(self.chdir) + + # Execute privileged action + privileged_action_result = self.privileged_action() + if not privileged_action_result: + privileged_action_result = [] + + # Change owner of pid file, it's required because pid file will be removed at exit. + uid, gid = -1, -1 + + if self.group: + try: + gid = grp.getgrnam(self.group).gr_gid + except KeyError: + self.logger.error("Group {0} not found".format(self.group)) + sys.exit(1) + + if self.user: + try: + uid = pwd.getpwnam(self.user).pw_uid + except KeyError: + self.logger.error("User {0} not found.".format(self.user)) + sys.exit(1) + + if uid != -1 or gid != -1: + os.chown(self.pid, uid, gid) + + # Change gid + if self.group: + try: + os.setgid(gid) + except OSError: + self.logger.error("Unable to change gid.") + sys.exit(1) + + # Change uid + if self.user: + try: + uid = pwd.getpwnam(self.user).pw_uid + except KeyError: + self.logger.error("User {0} not found.".format(self.user)) + sys.exit(1) + try: + os.setuid(uid) + except OSError: + self.logger.error("Unable to change uid.") + sys.exit(1) + + try: + lockfile.write("%s" % (os.getpid())) + lockfile.flush() + except IOError: + self.logger.error("Unable to write pid to the pidfile.") + print("Unable to write pid to the pidfile.") + sys.exit(1) + + # Set custom action on SIGTERM. + signal.signal(signal.SIGTERM, self.sigterm) + atexit.register(self.exit) + + self.logger.warn("Starting daemon.") + + try: + self.action(*privileged_action_result) + except Exception as e: + for line in traceback.format_exc(e).split("\n"): + self.logger.error(line) diff --git a/config/unbound/site-packages/dhcpd.py b/config/unbound/site-packages/dhcpd.py new file mode 100644 index 0000000..6d586c7 --- /dev/null +++ b/config/unbound/site-packages/dhcpd.py @@ -0,0 +1,108 @@ +""" + Copyright (c) 2016 Ad Schellevis + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +""" +import os +import time +import datetime + +class DHCPDLease(object): + watch_file = '/var/dhcpd/var/db/dhcpd.leases' + + def __init__(self): + """ init watcher + :return: watcher object + """ + self._section_data = [] + self._fhandle = None + self._last_pos = None + self._open() + + def _open(self): + """ (re)open watched file + :return: watcher object + """ + try: + self._fhandle = open(self.watch_file, 'r') + self._last_pos = None + self._section_data = [] + return True + except IOError: + self._fhandle = None + return False + + @staticmethod + def parse_lease(lines): + """ parse dhcp lease + :param lines: lease section as list item + :return: dictionary + """ + lease = dict() + lease['address'] = lines[0].split()[1] + for line in lines: + parts = line.split() + field_name = parts[0] + field_value = None + if field_name in ('starts', 'ends', 'tstp', 'tsfp', 'atsfp', 'cltt') and len(parts) >= 3: + dt = '%s %s'%(parts[2], parts[3]) + try: + field_value = time.mktime(datetime.datetime.strptime(dt, "%Y/%m/%d %H:%M:%S;").timetuple()) + except ValueError: + field_value = None + elif field_name == 'hardware' and len(parts) >= 3: + field_value = {'hardware-type': parts[1], 'mac-address': parts[2]} + elif field_name in('uid', 'client-hostname') and len(parts) >= 2 and parts[1].find('"') > -1: + field_value = parts[1].split('"')[1] + + if field_value is not None: + lease[field_name] = field_value + + return lease + + def watch(self): + """ watch file, return lease dictionaries + :return: iterator for leases + """ + if self._fhandle is None or os.fstat(self._fhandle.fileno()).st_nlink == 0: + # nothing to watch, try to (re)open return when failed + if not self._open(): + return + elif self._last_pos is not None: + self._fhandle.seek(self._last_pos) + + while True: + line = self._fhandle.readline() + if line: + if len(line) > 5 and line[0:5] == 'lease': + self._section_data.append(line) + elif len(line) > 1 and line[0] == '}': + self._section_data.append(line) + yield self.parse_lease(self._section_data) + self._section_data = [] + elif len(self._section_data) > 0: + self._section_data.append(line) + else: + break + + self._last_pos = self._fhandle.tell() diff --git a/config/unbound/site-packages/params.py b/config/unbound/site-packages/params.py new file mode 100644 index 0000000..6be3244 --- /dev/null +++ b/config/unbound/site-packages/params.py @@ -0,0 +1,46 @@ +""" + Copyright (c) 2015-2016 Ad Schellevis + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +""" + +import sys + + +def update_params(parameters): + """ update predefined parameters with given list from shell (as switches) + for example /a valA /b valB + converts to + {'a':'valA','b':'valB'} + (assuming parameters contains both a and b) + :param parameters: parameter dictionary + :return: + """ + cmd = None + for arg in sys.argv[1:]: + if cmd is None: + cmd = arg[1:] + else: + if cmd in parameters and arg.strip() != '': + parameters[cmd] = arg.strip() + cmd = None diff --git a/config/unbound/site-packages/watcherdhcpd.py b/config/unbound/site-packages/watcherdhcpd.py new file mode 100644 index 0000000..c726d5c --- /dev/null +++ b/config/unbound/site-packages/watcherdhcpd.py @@ -0,0 +1,107 @@ +""" + Copyright (c) 2016 Ad Schellevis + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +""" +import os +import time +import datetime + +class DHCPDLease(object): + watch_file = '/var/state/dhcp/dhcpd.leases' + + def __init__(self): + """ init watcher + :return: watcher object + """ + self._section_data = [] + self._fhandle = None + self._last_pos = None + self._open() + + def _open(self): + """ (re)open watched file + :return: watcher object + """ + try: + self._fhandle = open(self.watch_file, 'r') + self._last_pos = None + self._section_data = [] + return True + except IOError: + self._fhandle = None + return False + + @staticmethod + def parse_lease(lines): + """ parse dhcp lease + :param lines: lease section as list item + :return: dictionary + """ + lease = dict() + lease['address'] = lines[0].split()[1] + for line in lines: + parts = line.split() + field_name = parts[0] + field_value = None + if field_name in ('starts', 'ends', 'tstp', 'tsfp', 'atsfp', 'cltt') and len(parts) >= 3: + dt = '%s %s'%(parts[2], parts[3]) + try: + field_value = time.mktime(datetime.datetime.strptime(dt, "%Y/%m/%d %H:%M:%S;").timetuple()) + except ValueError: + field_value = None + elif field_name == 'hardware' and len(parts) >= 3: + field_value = {'hardware-type': parts[1], 'mac-address': parts[2]} + elif field_name in('uid', 'client-hostname') and len(parts) >= 2 and parts[1].find('"') > -1: + field_value = parts[1].split('"')[1] + + if field_value is not None: + lease[field_name] = field_value + return lease + + def watch(self): + """ watch file, return lease dictionaries + :return: iterator for leases + """ + if self._fhandle is None or os.fstat(self._fhandle.fileno()).st_nlink == 0: + # nothing to watch, try to (re)open return when failed + if not self._open(): + return + elif self._last_pos is not None: + self._fhandle.seek(self._last_pos) + + while True: + line = self._fhandle.readline() + if line: + if len(line) > 5 and line[0:5] == 'lease': + self._section_data.append(line) + elif len(line) > 1 and line[0] == '}': + self._section_data.append(line) + yield self.parse_lease(self._section_data) + self._section_data = [] + elif len(self._section_data) > 0: + self._section_data.append(line) + else: + break + + self._last_pos = self._fhandle.tell() diff --git a/config/unbound/unbound-dhcpd.py b/config/unbound/unbound-dhcpd.py new file mode 100644 index 0000000..0afedc9 --- /dev/null +++ b/config/unbound/unbound-dhcpd.py @@ -0,0 +1,145 @@ +#!/usr/bin/python2.7 + +""" + Copyright (c) 2016 Ad Schellevis + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + -------------------------------------------------------------------------------------- + watch dhcp lease file and build include file for unbound +""" +import os +import sys + +sys.path.insert(0, "/usr/lib/python2.7/site-packages") +import subprocess +import time +import tempfile +from daemonize import Daemonize +import watcherdhcpd +import params + + +def unbound_control(commands, output_stream=None): + """ execute (chrooted) unbound-control command + :param commands: command list (parameters) + :param output_stream: (optional)output stream + :return: None + """ + output_stream = open(os.devnull, 'w') + subprocess.check_call(['/usr/sbin/chroot', '--userspec=unbound:unbound', '/', + '/usr/sbin/unbound-control', '-c', '/etc/unbound/unbound.conf'] + commands, + stdout=output_stream, stderr=subprocess.STDOUT) + output_stream.seek(0) + + +def unbound_known_addresses(): + """ fetch known addresses + :return: list + """ + result = list() + with tempfile.NamedTemporaryFile() as output_stream: + unbound_control(['list_local_data'], output_stream) + for line in output_stream.read().split('\n'): + parts = line.split() + if len(parts) > 4 and parts[3] == 'A': + result.append(parts[4]) + print result + return result + + +# parse input params +app_params = {'pid': '/var/run/unbound_dhcpd.pid', + 'domain': 'local', + 'target': '/etc/unbound/dhcpleases.conf', + 'background': '1'} +params.update_params(app_params) + + +def main(): + # cleanup interval (seconds) + cleanup_interval = 60 + + # All times in the lease database are in Coordinated Universal Time (UTC), not local time! + tzone = 0 + if app_params['background'] <> 1: + print "Add leases for domian:",app_params['domain'] + + # initiate lease watcher and setup cache + dhcpdleases = watcherdhcpd.DHCPDLease() + cached_leases = dict() + known_addresses = unbound_known_addresses() + + # start watching dhcp leases + last_cleanup = time.time() + while True: + dhcpd_changed = False + if time.daylight <> 0: + utctime = time.time() + time.altzone + else: + utctime = time.time() + time.timezone + + for lease in dhcpdleases.watch(): + if 'ends' in lease and lease['ends'] > utctime and 'client-hostname' in lease and 'address' in lease: + cached_leases[lease['address']] = lease + dhcpd_changed = True + if app_params['background'] <> 1: + print "IP:",lease['address'],"Hostname:",lease['client-hostname'],"Start:",lease['starts'],"End:",lease['ends'] + + if time.time() - last_cleanup > cleanup_interval: + # cleanup every x seconds + last_cleanup = time.time() + addresses = cached_leases.keys() + for address in addresses: + if cached_leases[address]['ends'] < time.time(): + del cached_leases[address] + dhcpd_changed = True + + if dhcpd_changed: + # dump dns output to target + with open(app_params['target'], 'w') as unbound_conf: + for address in cached_leases: + unbound_conf.write('local-data-ptr: "%s %s.%s"\n' % (address, + cached_leases[address]['client-hostname'], + app_params['domain'])) + + unbound_conf.write('local-data: "%s.%s IN A %s"\n' % (cached_leases[address]['client-hostname'], + app_params['domain'], + address)) + # signal unbound + for address in cached_leases: + if address not in known_addresses: + fqdn = '%s.%s' % (cached_leases[address]['client-hostname'], app_params['domain']) + unbound_control(['local_data', address, 'PTR', fqdn]) + unbound_control(['local_data', fqdn, 'IN A', address]) + known_addresses.append(address) + # wait for next cycle + time.sleep(5) + + +# startup +if app_params['background'] == '1': + daemon = Daemonize(app="unbound_dhcpd", pid=app_params['pid'], action=main) + daemon.start() +else: + main() diff --git a/config/unbound/unbound-switch b/config/unbound/unbound-switch new file mode 100755 index 0000000..60eeb89 --- /dev/null +++ b/config/unbound/unbound-switch @@ -0,0 +1,80 @@ +#!/bin/bash +############################################################################### +# # +# IPFire.org - A linux based firewall # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see http://www.gnu.org/licenses/. # +# # +# Description : script to switch the DNS server/proxy in IPfire # +# rerun to easy go back to dnsmasq # +# # +# Author : Marcel Lorenz marcel.lorenz@ipfire.org # +# # +############################################################################### + +CGIFILE="/srv/web/ipfire/cgi-bin/services.cgi" + +install_cron_jobs() { +cat > /etc/fcron.weekly/update_unbound_anchor << "EOF" +#!/bin/bash +# allow max all 30 minutes to update files +if [[ $(( (`date +%s` - `stat -L --format %Y /etc/unbound/root.key`) > (30*60) )) != 0 ]]; then + wget -q ftp://ftp.internic.net/domain/named.cache -O /etc/unbound/root.hints + curl -sS -L --compressed "http://pgl.yoyo.org/adservers/serverlist.php?hostformat=unbound&showintr..." > /etc/unbound/blocklists/ad-servers.conf + unbound-anchor +fi +exit 0 +EOF +chmod +x /etc/fcron.weekly/update_unbound_anchor +cat > /etc/fcron.hourly/update_unbound_zone << "EOF" +#!/bin/bash +unbound-zone +EOF +chmod +x /etc/fcron.hourly/update_unbound_zone +} + +# main switch +if [[ -e /etc/rc.d/init.d/networking/red.up/05-RS-dnsmasq ]]; then + echo -e "\033[32mActivate Unbound DNS-proxy at start...\033[0m"; + # autostart symlinks + rm -f /etc/rc.d/init.d/networking/red.up/05-RS-dnsmasq /etc/rc.d/init.d/networking/red.down/05-RS-dnsmasq + mv -f /etc/init.d/network /etc/init.d/network-dnsmasq + mv -f /etc/init.d/network-unbound /etc/init.d/network + # WebIF services.cgi + sed -i "s|$Lang::tr{'dns proxy server'} => 'dnsmasq',.*|$Lang::tr{'dns proxy server'} => 'unbound',|" ${CGIFILE} + install_cron_jobs + /etc/fcron.weekly/update_unbound_anchor + # Stop and start services + /etc/rc.d/init.d/dnsmasq stop + sleep 1 + /etc/rc.d/init.d/unbound start + +else + echo -e "\033[32mActivate dnsmasq DNS-proxy at start...\033[0m"; + # autostart symlinks + ln -sf /etc/rc.d/init.d/dnsmasq /etc/rc.d/init.d/networking/red.up/05-RS-dnsmasq + ln -sf /etc/rc.d/init.d/dnsmasq /etc/rc.d/init.d/networking/red.down/05-RS-dnsmasq + mv -f /etc/init.d/network /etc/init.d/network-unbound + mv -f /etc/init.d/network-dnsmasq /etc/init.d/network + # WebIF services.cgi + sed -i "s|$Lang::tr{'dns proxy server'} => 'unbound',.*|$Lang::tr{'dns proxy server'} => 'dnsmasq',|" ${CGIFILE} + # Stop and start services + /etc/rc.d/init.d/unbound stop + sleep 1 + /etc/rc.d/init.d/dnsmasq start + rm -f /etc/fcron.weekly/update_unbound_anchor /etc/fcron.hourly/update_unbound_zone; +fi +unset CGIFILE +echo -e "\033[32mdone...\033[0m"; +exit 0 +# end of unbound-proxy diff --git a/config/unbound/unbound-zone b/config/unbound/unbound-zone new file mode 100644 index 0000000..9a0de1f --- /dev/null +++ b/config/unbound/unbound-zone @@ -0,0 +1,78 @@ +#!/bin/bash +############################################################################### +# # +# IPFire.org - A linux based firewall # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see http://www.gnu.org/licenses/. # +# # +# Description : small script to create the zone file for ipfire's # +# internal domain (for example ipfire.local) # +# # +# Author : Marcel Lorenz marcel.lorenz@ipfire.org # +# # +############################################################################### + +ZONEFILE="/etc/unbound/zones/local.conf" +HOSTSFILE="/var/ipfire/main/hosts" + +eval $(/usr/local/bin/readhash /var/ipfire/main/settings) +eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings) +REV_GREEN=$(echo ${GREEN_ADDRESS} |awk -F. '{print $4"."$3"."$2"."$1}') + +# overwrite existing file +cat > ${ZONEFILE} << "EOF" +# This is the automatically created zone file for unbound +# please do not edit this file, use the webinterface to add or remove hosts +# if need more zones, create a new zone file and restart unbound +# +EOF + +# create zone header +echo "# Zone file created at $(date)" >> ${ZONEFILE} +echo "">> ${ZONEFILE} +echo "# zone definition " >> ${ZONEFILE} +echo "private-domain: "${DOMAINNAME}"" >> ${ZONEFILE} +echo "local-zone: "${DOMAINNAME}." static" >> ${ZONEFILE} +echo "local-data: "${HOSTNAME}.${DOMAINNAME}. IN A ${GREEN_ADDRESS}"" >> ${ZONEFILE} +echo "local-data: "wpad.${DOMAINNAME}. IN A ${GREEN_ADDRESS}"" >> ${ZONEFILE} +echo "local-data: "${REV_GREEN}.in-addr.arpa. 10800 IN PTR ${HOSTNAME}.${DOMAINNAME}."" >> ${ZONEFILE} + +# write forward entrys to zone file +echo "" >> ${ZONEFILE} +echo "# Hosts from /var/ipfire/main/hosts" >> ${ZONEFILE} + +while read line +do + if [[ $(echo ${line}|awk -F, '{print $1}') = on ]]; then + IP=$(echo ${line}|awk -F, '{print $2}') + HOST=$(echo ${line}|awk -F, '{print $3}') + DOMAIN=$(echo ${line}|awk -F, '{print $4}') + echo "local-data: "${HOST}.${DOMAIN}. IN A ${IP}"" >> ${ZONEFILE} + fi +done < ${HOSTSFILE} + +# write reverse entrys to zone file +echo "" >> ${ZONEFILE} +echo "# reverse entrys" >> ${ZONEFILE} +while read line +do + if [[ $(echo ${line}|awk -F, '{print $1}') = on ]]; then + IP=$(echo ${line}|awk -F, '{print $2}'|awk -F. '{print $4"."$3"."$2"."$1}') + HOST=$(echo ${line}|awk -F, '{print $3}') + DOMAIN=$(echo ${line}|awk -F, '{print $4}') + echo "local-data: "${IP}.in-addr.arpa. 10800 IN PTR ${HOST}.${DOMAIN}"" >> ${ZONEFILE} + fi +done < ${HOSTSFILE} +unset IP HOST DOMAIN REV_GREEN; +exit 0 +# end of unbound-zone diff --git a/config/unbound/unbound.conf b/config/unbound/unbound.conf new file mode 100644 index 0000000..8dc72e6 --- /dev/null +++ b/config/unbound/unbound.conf @@ -0,0 +1,123 @@ +# +# Unbound configuration file for IPFire +# +# The full documentation is available at: +# https://www.unbound.net/documentation/unbound.conf.html +# + +server: + # common server options + chroot: "/etc/unbound" + username: "unbound" + pidfile: "/var/run/unbound.pid" + num-threads: 2 + port: 53 + do-ip4: yes + do-ip6: no + do-udp: yes + do-tcp: yes + prefetch: yes + so-reuseport: yes + cache-min-ttl: 3600 + cache-max-ttl: 86400 + unwanted-reply-threshold: 10000 + do-not-query-localhost: yes + + # logging options + logfile: "log/unbound.log" + use-syslog: no + verbosity: 1 + log-queries: no + log-time-ascii: yes + + # Unbound Statistics + statistics-interval: 3600 + statistics-cumulative: yes + extended-statistics: yes + + # privacy options + hide-identity: yes + hide-version: yes + qname-minimisation: yes + minimal-responses: yes + + # hardening options (some experimental) + harden-glue: yes + harden-large-queries: yes + harden-dnssec-stripped: yes + harden-short-bufsize: no + harden-below-nxdomain: no + harden-referral-path: no + harden-algo-downgrade: no + use-caps-for-id: yes + + # listen on localhost interface + interface: 127.0.0.1 + + # file with ipfire interfaces + include: "/etc/unbound/interfaces.conf" + + # control which clients are allowed to make (recursive) queries + access-control: 0.0.0.0/0 refuse + access-control: 127.0.0.0/8 allow + access-control: ::0/0 refuse + access-control: ::1 allow + access-control: ::ffff:127.0.0.1 allow + + # file with ipfire networks + include: "/etc/unbound/access.conf" + + # dnssec main options + val-clean-additional: yes + val-log-level: 1 + # file with ipfire dnssec configuration + include: "/etc/unbound/dnssec.conf" + + # DNS Rebinding + # For DNS Rebinding prevention + # + # All these addresses are either private or should not be routable in the global IPv4 or IPv6 internet. + # IPv4 Addresses + private-address: 0.0.0.0/8 # Broadcast address + private-address: 10.0.0.0/8 + private-address: 127.0.0.0/8 # Loopback Localhost + private-address: 172.16.0.0/12 + private-address: 192.168.0.0/16 + private-address: 169.254.0.0/16 + private-address: 198.18.0.0/15 # Used for testing inter-network communications + private-address: 198.51.100.0/24 # Documentation network TEST-NET-2 + private-address: 203.0.113.0/24 # Documentation network TEST-NET-3 + private-address: 233.252.0.0/24 # Documentation network MCAST-TEST-NET + # IPv6 Addresses + private-address: ::1/128 # Loopback Localhost + private-address: 2001:db8::/32 # Documentation network IPv6 + private-address: fc00::/8 # Unique local address (ULA) part of "fc00::/7", not defined yet + private-address: fd00::/8 # Unique local address (ULA) part of "fc00::/7", "/48" prefix group + private-address: fe80::/10 # Link-local address (LLA) + + # file with root servers + root-hints: "/etc/unbound/root.hints" + + # custom DNS zone files + include: "/etc/unbound/zones/*.conf" + + # DHCP leases (if configured) + include: /etc/unbound/dhcpleases.conf + + # Blocklists + include: "/etc/unbound/blocklists/*.conf" +# end server config + +# enable remote control only on localhost +remote-control: + control-enable: yes + control-use-cert: yes + control-interface: 127.0.0.1 + server-key-file: "/etc/unbound/unbound_server.key" + server-cert-file: "/etc/unbound/unbound_server.pem" + control-key-file: "/etc/unbound/unbound_control.key" + control-cert-file: "/etc/unbound/unbound_control.pem" +# end remote control config + +# custom DNS forward config +include: "/etc/unbound/forward.conf" diff --git a/lfs/unbound b/lfs/unbound new file mode 100644 index 0000000..d91c0f9 --- /dev/null +++ b/lfs/unbound @@ -0,0 +1,103 @@ +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2007 Michael Tremer & Christian Schmidt # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see http://www.gnu.org/licenses/. # +# # +############################################################################### + +############################################################################### +# Definitions +############################################################################### + +include Config + +VER = 1.5.9 +THISAPP = unbound-$(VER) +DL_FILE = $(THISAPP).tar.gz +DL_FROM = $(URL_IPFIRE) +DIR_APP = $(DIR_SRC)/$(THISAPP) +TARGET = $(DIR_INFO)/$(THISAPP) +PROG = unbound +PAK_VER = 1 +DEPS = "" + +############################################################################### +# Top-level Rules +############################################################################### + +objects = $(DL_FILE) + +$(DL_FILE) = $(DL_FROM)/$(DL_FILE) + +$(DL_FILE)_MD5 = 0cefa62c1690b4db18583db84bff00e3 + +install : $(TARGET) + +check : $(patsubst %,$(DIR_CHK)/%,$(objects)) + +download :$(patsubst %,$(DIR_DL)/%,$(objects)) + +md5 : $(subst %,%_MD5,$(objects)) + +dist: + $(PAK) + +############################################################################### +# Downloading, checking, md5sum +############################################################################### + +$(patsubst %,$(DIR_CHK)/%,$(objects)) : + @$(CHECK) + +$(patsubst %,$(DIR_DL)/%,$(objects)) : + @$(LOAD) + +$(subst %,%_MD5,$(objects)) : + @$(MD5) + +############################################################################### +# Installation Details +############################################################################### + +$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) + @$(PREBUILD) + @rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE) + cd $(DIR_APP) && ./configure \ + --prefix=/usr \ + --sysconfdir=/etc \ + --disable-static \ + --with-libevent \ + --with-pyunbound \ + --with-pidfile=/var/run/unbound.pid + cd $(DIR_APP) && make $(MAKETUNING) + cd $(DIR_APP) && make install + mv -v /usr/sbin/unbound-host /usr/bin/ + # add ipfire config + mkdir -pv /etc/unbound/blocklists + mv -v /etc/unbound/unbound.conf /etc/unbound/unbound_org.conf + install -v -m 644 $(DIR_SRC)/config/unbound/*.conf /etc/unbound/ + install -v -m 644 $(DIR_SRC)/config/unbound/root.hints /etc/unbound/ + install -v -m 644 $(DIR_SRC)/config/unbound/root.key /etc/unbound/ + install -v -m 644 $(DIR_SRC)/config/unbound/blocklists/*.conf /etc/unbound/blocklists/ + install -v -m 644 $(DIR_SRC)/config/unbound/site-packages/* /usr/lib/python2.7/site-packages/ + install -v -m 754 $(DIR_SRC)/config/unbound/unbound-switch /usr/sbin/ + install -v -m 754 $(DIR_SRC)/config/unbound/unbound-zone /usr/sbin/ + install -v -m 754 $(DIR_SRC)/config/unbound/unbound-dhcpd.py /usr/sbin/ + install -v -m 754 $(DIR_SRC)/src/initscripts/init.d/unbound /etc/rc.d/init.d/ + install -v -m 754 $(DIR_SRC)/src/initscripts/init.d/unbound-dhcpd /etc/rc.d/init.d/ + install -v -m 754 $(DIR_SRC)/src/initscripts/init.d/network-unbound /etc/rc.d/init.d/ + @rm -rf $(DIR_APP) + @$(POSTBUILD) diff --git a/make.sh b/make.sh index a9fac52..74bc06a 100755 --- a/make.sh +++ b/make.sh @@ -870,6 +870,7 @@ buildipfire() { ipfiremake libpciaccess ipfiremake libyajl ipfiremake libvirt + ipfiremake unbound }
buildinstaller() { diff --git a/src/initscripts/init.d/network-unbound b/src/initscripts/init.d/network-unbound new file mode 100644 index 0000000..31fe173 --- /dev/null +++ b/src/initscripts/init.d/network-unbound @@ -0,0 +1,114 @@ +#!/bin/sh +######################################################################## +# Begin $rc_base/init.d/network +# +# Description : Network Control Script +# +# Authors : Michael Tremer - mitch@ipfire.org +# +# Version : 01.00 +# +# Notes : Written for IPFire by its team +# +######################################################################## + +. /etc/sysconfig/rc +. ${rc_functions} +eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings) + + +DO="${1}" +shift + +if [ -n "${1}" ]; then + ALL=0 + for i in green red blue orange; do + eval "${i}=0" + done +else + ALL=1 + for i in green red blue orange; do + eval "${i}=1" + done +fi + +while [ ! $# = 0 ]; do + for i in green red blue orange; do + if [ "${i}" == "${1}" ]; then + eval "${i}=1" + shift + fi + done +done + +case "${DO}" in + start) + + # Starting interfaces... + # GREEN + [ "$green" == "1" ] && /etc/rc.d/init.d/networking/green start + + # BLUE + [ "$blue" == "1" ] && [ "$CONFIG_TYPE" = "3" -o "$CONFIG_TYPE" = "4" ] && \ + /etc/rc.d/init.d/networking/blue start + + # ORANGE + [ "$orange" == "1" ] && [ "$CONFIG_TYPE" = "2" -o "$CONFIG_TYPE" = "4" ] && \ + /etc/rc.d/init.d/networking/orange start + + # RED + if [ "$red" == "1" ]; then + if [ "$CONFIG_TYPE" = "1" -o "$CONFIG_TYPE" = "2" -o "$CONFIG_TYPE" = "3" -o "$CONFIG_TYPE" = "4" ]; then + # Remove possible leftover files + rm -f /var/ipfire/red/{active,device,dial-on-demand,dns1,dns2,local-ipaddress,remote-ipaddress,resolv.conf} + [ "$AUTOCONNECT" == "off" ] || /etc/rc.d/init.d/networking/red start + fi + fi + + /etc/rc.d/init.d/static-routes start + [ "${ALL}" == "1" ] && /etc/rc.d/init.d/unbound start + ;; + + stop) + + [ "${ALL}" == "1" ] && /etc/rc.d/init.d/unbound stop + # Stopping interfaces... + # GREEN + [ "$green" == "1" ] && /etc/rc.d/init.d/networking/green stop + + # BLUE + [ "$blue" == "1" ] && [ "$CONFIG_TYPE" = "3" -o "$CONFIG_TYPE" = "4" ] && \ + /etc/rc.d/init.d/networking/blue stop + + # ORANGE + [ "$orange" == "1" ] && [ "$CONFIG_TYPE" = "2" -o "$CONFIG_TYPE" = "4" ] && \ + /etc/rc.d/init.d/networking/orange stop + + # RED + if [ "$red" == "1" ]; then + if [ "$CONFIG_TYPE" = "1" -o "$CONFIG_TYPE" = "2" -o "$CONFIG_TYPE" = "3" -o "$CONFIG_TYPE" = "4" ]; then + /etc/rc.d/init.d/networking/red stop + fi + fi + + exit 0 + ;; + + restart) + for i in green red blue orange; do + if [ "${!i}" == "1" ]; then + ARGS+=" ${i}" + fi + done + ${0} stop ${ARGS} + sleep 1 + ${0} start ${ARGS} + ;; + + *) + echo "Usage: ${0} {start|stop|restart} [device(s)]" + exit 1 + ;; +esac + +# End /etc/rc.d/init.d/network diff --git a/src/initscripts/init.d/unbound b/src/initscripts/init.d/unbound new file mode 100644 index 0000000..8e6881e --- /dev/null +++ b/src/initscripts/init.d/unbound @@ -0,0 +1,178 @@ +#!/bin/sh +# Begin $rc_base/init.d/unbound + +# Description : Unbound DNS resolver boot script for IPfire +# Author : Marcel Lorenz marcel.lorenz@ipfire.org +# +# Comment : This init script additional starts the dhcpd watcher daemon +# if DNS-Update (RFC2136) in web interface enabled + +. /etc/sysconfig/rc +. ${rc_functions} + +if [[ ! -d /run/var ]]; then mkdir /run/var; fi; + +CONTROL_INTERFACE_FILE=1 +CONTROL_ACCESS_FILE=1 +USE_CUSTOM_FORWARDS=0 +ENABLE_DNSSEC=1 + +# Unbound daemon pid file +PIDFILE=/var/run/unbound.pid + +# Watcher deamon pid file must be the same in unbound main init script +WAPIDFILE=/var/run/unbound_dhcpd.pid + +function cidr() { + local cidr nbits IFS; + IFS=. read -r i1 i2 i3 i4 <<< ${1} + IFS=. read -r m1 m2 m3 m4 <<< ${2} + cidr=$(printf "%d.%d.%d.%d\n" "$((i1 & m1))" "$((i2 & m2))" "$((i3 & m3))" "$((i4 & m4))") + nbits=0 + IFS=. + for dec in $2 ; do + case $dec in + 255) let nbits+=8;; + 254) let nbits+=7;; + 252) let nbits+=6;; + 248) let nbits+=5;; + 240) let nbits+=4;; + 224) let nbits+=3;; + 192) let nbits+=2;; + 128) let nbits+=1;; + 0);; + *) echo "Error: $dec is not recognised"; exit 1 + esac + done + echo "${cidr}/${nbits}" +} + +case "$1" in + start) + + if [[ -f ${PIDFILE} ]]; then + log_warning_msg "Unbound daemon is running with Process ID $(cat ${PIDFILE})" + else + eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings) + #ARGS="$CUSTOM_ARGS" + #[ "$DOMAIN_NAME_GREEN" != "" ] && ARGS="$ARGS -s $DOMAIN_NAME_GREEN" + + echo > /var/ipfire/red/resolv.conf # Clear it + if [ -e "/var/ipfire/red/dns1" ]; then + DNS1=$(cat /var/ipfire/red/dns1 2>/dev/null) + if [ ! -z ${DNS1} ]; then + echo "nameserver ${DNS1}" >> /var/ipfire/red/resolv.conf + NAMESERVERS="${DNS1} " + fi + fi + if [ -e "/var/ipfire/red/dns2" ]; then + DNS2=$(cat /var/ipfire/red/dns2 2>/dev/null) + if [ ! -z ${DNS2} ]; then + echo "nameserver ${DNS2}" >> /var/ipfire/red/resolv.conf + NAMESERVERS+="${DNS2} " + fi + fi + + # create unbound interfaces.conf + if [ ${CONTROL_INTERFACE_FILE} = 1 ]; then + echo -n > /etc/unbound/interfaces.conf # Clear it + if [ ! -z ${GREEN_ADDRESS} ]; then + echo "interface: ${GREEN_ADDRESS}" >> /etc/unbound/interfaces.conf + fi + if [ ! -z ${BLUE_ADDRESS} ]; then + echo "interface: ${BLUE_ADDRESS}" >> /etc/unbound/interfaces.conf + fi + if [ ! -z ${ORANGE_ADDRESS} ]; then + echo "interface: ${ORANGE_ADDRESS}" >> /etc/unbound/interfaces.conf + fi + fi + + # create unbound access.conf + if [ ${CONTROL_ACCESS_FILE} = 1 ]; then + echo -n > /etc/unbound/access.conf # Clear it + if [ ! -z ${GREEN_ADDRESS} ]; then + echo "access-control: $(cidr ${GREEN_ADDRESS} ${GREEN_NETMASK}) allow" >> /etc/unbound/access.conf + fi + if [ ! -z ${BLUE_ADDRESS} ]; then + echo "access-control: $(cidr ${BLUE_ADDRESS} ${BLUE_NETMASK}) allow" >> /etc/unbound/access.conf + fi + if [ ! -z ${ORANGE_ADDRESS} ]; then + echo "access-control: $(cidr ${ORANGE_ADDRESS} ${ORANGE_NETMASK}) allow" >> /etc/unbound/access.conf + fi + fi + + # create unbound dnssec.conf + echo -n > /etc/unbound/dnssec.conf # Clear it + if [ ${ENABLE_DNSSEC} = 1 ]; then + echo " # dessec enabled per default" >> /etc/unbound/dnssec.conf + echo " # no necessary config options in this file" >> /etc/unbound/dnssec.conf + else + echo " # dnssec now disabled" >> /etc/unbound/dnssec.conf + echo " module-config: iterator" >> /etc/unbound/dnssec.conf + echo " val-permissive-mode: yes" >> /etc/unbound/dnssec.conf + fi + + # create zone file for internal ipfire domain + unbound-zone + + boot_mesg "Starting Unbound DNS proxy..." + unbound-anchor + loadproc /usr/sbin/unbound + + # start dhcpd watcher daemon if DNS-Update (RFC2136) activated + eval $(/usr/local/bin/readhash /var/ipfire/dhcp/settings) + if [[ ${DNS_UPDATE_ENABLED} = on && ! -f ${WAPIDFILE} ]]; then + /etc/rc.d/init.d/unbound-dhcpd start + fi + + # use setup configured DNS servers + if [ "${USE_CUSTOM_FORWARDS}" -eq 0 ]; then + unbound-control forward_add +i . ${NAMESERVERS} &> /dev/null + fi; + + FORWADRS=$(unbound-control list_forwards |sed 's|. IN forward ||g'|sed 's|+i ||g') + if [ "${USE_CUSTOM_FORWARDS}" -eq 0 ]; then + boot_mesg "Using DNS server(s): ${FORWADRS}" + else + boot_mesg "Using custom DNS server(s): ${FORWADRS}" + fi + if [ ${ENABLE_DNSSEC} = 1 ]; then + boot_mesg "DNSSEC is enabled!" + else + boot_mesg "DNSSEC is disabled!" + fi + fi + ;; + + stop) + + if [[ -f ${PIDFILE} ]]; then + # stop dhcpd watcher daemon if activted + if [[ -f ${WAPIDFILE} ]]; then + /etc/rc.d/init.d/unbound-dhcpd stop + fi + # stop Unbound daemon + boot_mesg "Stopping Unbound DNS proxy..." + killproc -p "/var/run/unbound.pid" /usr/sbin/unbound + else + log_warning_msg "Unbound daemon is not running..." + fi + ;; + + restart) + $0 stop + sleep 1 + $0 start + ;; + + status) + statusproc /usr/sbin/unbound + ;; + + *) + echo "Usage: $0 {start|stop|restart|status}" + exit 1 + ;; +esac + +# End $rc_base/init.d/unbound diff --git a/src/initscripts/init.d/unbound-dhcpd b/src/initscripts/init.d/unbound-dhcpd new file mode 100644 index 0000000..4c24a3c --- /dev/null +++ b/src/initscripts/init.d/unbound-dhcpd @@ -0,0 +1,61 @@ +#!/bin/sh +# Begin $rc_base/init.d/unbound-dhcpd + +# Description : Unbound dhcpd lease file wachter daemon boot script for IPFire +# Author : Marcel Lorenz marcel.lorenz@ipfire.org + +. /etc/sysconfig/rc +. $rc_functions + +PIDFILE=/var/run/unbound_dhcpd.pid +SETFILE=/var/ipfire/main/settings + +case "$1" in + start) + if [[ -f ${PIDFILE} ]]; then + log_warning_msg "Unbound dhcpd watcher daemon is running with Process ID $(cat ${PIDFILE})" + else + eval $(/usr/local/bin/readhash ${SETFILE}) + boot_mesg "Starting Unbound dhcpd watcher deamon..." + loadproc /usr/bin/python /usr/sbin/unbound-dhcpd.py /domain ${DOMAINNAME} /pid ${PIDFILE} + fi + ;; + + stop) + if [[ -f ${PIDFILE} ]]; then + boot_mesg "Stopping Unbound dhcpd watcher deamon..." + kill $(/bin/cat ${PIDFILE}) + sleep 1 + if [[ -f ${PIDFILE} ]]; then + echo_failure + else + echo_ok + fi + else + log_warning_msg "Unbound dhcpd watcher daemon is not running..." + fi + ;; + + restart) + $0 stop + sleep 1 + $0 start + ;; + + status) + if [[ -f "$PIDFILE" ]]; then + echo -e "\033[1;36mUnbound dhcpd watcher daemon is running with Process ID $(cat ${PIDFILE})\033[0;39m" + exit 0 + else + echo -e "\033[1;36mUnbound dhcpd watcher daemon is not running...\033[0;39m" + exit 0 + fi + ;; + + *) + echo "Usage: $0 {start|stop|restart|status}" + exit 1 + ;; +esac + +# End $rc_base/init.d/unbound-dhcpd \ No newline at end of file diff --git a/src/paks/unbound/install.sh b/src/paks/unbound/install.sh new file mode 100644 index 0000000..84c93f3 --- /dev/null +++ b/src/paks/unbound/install.sh @@ -0,0 +1,70 @@ +#!/bin/bash +############################################################################ +# # +# This file is part of the IPFire Firewall. # +# # +# IPFire is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +# IPFire is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with IPFire; if not, write to the Free Software # +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +# # +# Copyright (C) 2016 IPFire-Team info@ipfire.org. # +# # +############################################################################ +# +. /opt/pakfire/lib/functions.sh +extract_files +restore_backup ${NAME} + +# add unbound user and group +groupadd -g 85 unbound +useradd -c "Unbound DNS resolver" -d /var/lib/unbound -u 85 -g unbound -s /bin/false unbound + +# create config subdir's +mkdir -pv /etc/unbound/log /etc/unbound/zones /var/log/unbound +chown unbound:unbound -R /var/log/unbound/ /etc/unbound/log/; + +echo "Add logrotate config for unbound now..." +LOGROTATE=$(grep -A 1 '/var/log/unbound/unbound.log' /etc/logrotate.conf) +if [[ ! "${LOGROTATE}" ]]; then +cat >> /etc/logrotate.conf << "EOF" +# Unbound +/var/log/unbound/unbound.log { + daily + rotate 30 + copytruncate + compress + missingok + prerotate + /bin/mv -f /etc/unbound/log/unbound.log /var/log/unbound/unbound.log + /usr/sbin/unbound-control log_reopen &> /dev/null + endscript +} + +EOF +touch /etc/unbound/dhcpleases.conf +touch /var/log/unbound/unbound.log +chown unbound:unbound /var/log/unbound/unbound.log +fi + +# create link to current logfile +ln -svf /etc/unbound/log/unbound.log /var/log/unbound/current.log + +# create remote control key files and set rights +/usr/sbin/unbound-control-setup &> /dev/null +chown unbound:unbound /etc/unbound/{unbound_control.*,unbound_server.*,root.key,root.hints} + +# at last switch the DNS-Resolver to unbound +/usr/sbin/unbound-switch + +unset LOGROTATE +exit 0 diff --git a/src/paks/unbound/uninstall.sh b/src/paks/unbound/uninstall.sh new file mode 100644 index 0000000..fc39f9f --- /dev/null +++ b/src/paks/unbound/uninstall.sh @@ -0,0 +1,27 @@ +#!/bin/bash +############################################################################ +# # +# This file is part of the IPFire Firewall. # +# # +# IPFire is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +# IPFire is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with IPFire; if not, write to the Free Software # +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +# # +# Copyright (C) 2007 IPFire-Team info@ipfire.org. # +# # +############################################################################ +# +. /opt/pakfire/lib/functions.sh +/usr/sbin/resolver.sh +make_backup ${NAME} +remove_files diff --git a/src/paks/unbound/update.sh b/src/paks/unbound/update.sh new file mode 100644 index 0000000..89c40d0 --- /dev/null +++ b/src/paks/unbound/update.sh @@ -0,0 +1,26 @@ +#!/bin/bash +############################################################################ +# # +# This file is part of the IPFire Firewall. # +# # +# IPFire is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +# IPFire is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with IPFire; if not, write to the Free Software # +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +# # +# Copyright (C) 2007 IPFire-Team info@ipfire.org. # +# # +############################################################################ +# +. /opt/pakfire/lib/functions.sh +./uninstall.sh +./install.sh
Hi,
so I have been working on this for a bit over the weekend and started a branch with those changes.
http://cgit.ipfire.org/people/ms/ipfire-2.x.git/log/?h=unbound
I rewrote the Python code which I didn't find clean enough and good enough for our standards. My solution is lacking some minor things (the domain is always .local) but those should be easily fixable. I am just running out of time here.
However I wanted to share my changes for you to review and test because despite these small things and some other issues for which I created bug reports on Bugzilla, I think this is rather close to be finished.
https://bugzilla.ipfire.org/showdependencytree.cgi?id=11163&hide_resolve...
So, please have a look and test. I won't be able to work much on this over the next few weeks, hence I would be happy if some people take over a small part and get that fixed. I will be responding to emails though.
Best, -Michael
On Tue, 2016-08-02 at 20:48 +0200, Marcel Lorenz wrote:
Unbound is a validating, recursive, and caching DNS resolver. https://www.unbound.net
Signed-off-by: Marcel Lorenz marcel.lorenz@ipfire.org
config/rootfiles/packages/unbound | 70 ++++++++ config/unbound/blocklists/ms-telemetry.conf | 49 ++++++ config/unbound/forward.conf | 6 + config/unbound/root.hints | 90 ++++++++++ config/unbound/root.key | 9 + config/unbound/site-packages/daemonize.py | 247 +++++++++++++++++++++++++++ config/unbound/site-packages/dhcpd.py | 108 ++++++++++++ config/unbound/site-packages/params.py | 46 +++++ config/unbound/site-packages/watcherdhcpd.py | 107 ++++++++++++ config/unbound/unbound-dhcpd.py | 145 ++++++++++++++++ config/unbound/unbound-switch | 80 +++++++++ config/unbound/unbound-zone | 78 +++++++++ config/unbound/unbound.conf | 123 +++++++++++++ lfs/unbound | 103 +++++++++++ make.sh | 1 + src/initscripts/init.d/network-unbound | 114 +++++++++++++ src/initscripts/init.d/unbound | 178 +++++++++++++++++++ src/initscripts/init.d/unbound-dhcpd | 61 +++++++ src/paks/unbound/install.sh | 70 ++++++++ src/paks/unbound/uninstall.sh | 27 +++ src/paks/unbound/update.sh | 26 +++ 21 files changed, 1738 insertions(+) create mode 100644 config/rootfiles/packages/unbound create mode 100644 config/unbound/blocklists/ms-telemetry.conf create mode 100644 config/unbound/forward.conf create mode 100644 config/unbound/root.hints create mode 100644 config/unbound/root.key create mode 100644 config/unbound/site-packages/daemonize.py create mode 100644 config/unbound/site-packages/dhcpd.py create mode 100644 config/unbound/site-packages/params.py create mode 100644 config/unbound/site-packages/watcherdhcpd.py create mode 100644 config/unbound/unbound-dhcpd.py create mode 100755 config/unbound/unbound-switch create mode 100644 config/unbound/unbound-zone create mode 100644 config/unbound/unbound.conf create mode 100644 lfs/unbound create mode 100644 src/initscripts/init.d/network-unbound create mode 100644 src/initscripts/init.d/unbound create mode 100644 src/initscripts/init.d/unbound-dhcpd create mode 100644 src/paks/unbound/install.sh create mode 100644 src/paks/unbound/uninstall.sh create mode 100644 src/paks/unbound/update.sh
diff --git a/config/rootfiles/packages/unbound b/config/rootfiles/packages/unbound new file mode 100644 index 0000000..c468167 --- /dev/null +++ b/config/rootfiles/packages/unbound @@ -0,0 +1,70 @@ +etc/rc.d/init.d/network-unbound +etc/rc.d/init.d/unbound +etc/rc.d/init.d/unbound-dhcpd +#etc/unbound +#etc/unbound/blocklists +etc/unbound/blocklists/ms-telemetry.conf +etc/unbound/forward.conf +etc/unbound/root.hints +etc/unbound/root.key +etc/unbound/unbound.conf +etc/unbound/unbound_org.conf +usr/bin/unbound-host +#usr/include/unbound.h +#usr/lib/libunbound.la +usr/lib/libunbound.so +usr/lib/libunbound.so.2 +usr/lib/libunbound.so.2.4.1 +#usr/lib/python2.7/site-packages/_unbound.la +usr/lib/python2.7/site-packages/_unbound.so +usr/lib/python2.7/site-packages/daemonize.py +usr/lib/python2.7/site-packages/dhcpd.py +usr/lib/python2.7/site-packages/params.py +usr/lib/python2.7/site-packages/unbound.py +usr/lib/python2.7/site-packages/watcherdhcpd.py +usr/sbin/unbound +usr/sbin/unbound-anchor +usr/sbin/unbound-checkconf +usr/sbin/unbound-dhcpd.py +usr/sbin/unbound-control +usr/sbin/unbound-control-setup +usr/sbin/unbound-switch +usr/sbin/unbound-zone +#usr/share/man/man1/unbound-host.1 +#usr/share/man/man3/libunbound.3 +#usr/share/man/man3/ub_cancel.3 +#usr/share/man/man3/ub_ctx.3 +#usr/share/man/man3/ub_ctx_add_ta.3 +#usr/share/man/man3/ub_ctx_add_ta_file.3 +#usr/share/man/man3/ub_ctx_async.3 +#usr/share/man/man3/ub_ctx_config.3 +#usr/share/man/man3/ub_ctx_create.3 +#usr/share/man/man3/ub_ctx_data_add.3 +#usr/share/man/man3/ub_ctx_data_remove.3 +#usr/share/man/man3/ub_ctx_debuglevel.3 +#usr/share/man/man3/ub_ctx_debugout.3 +#usr/share/man/man3/ub_ctx_delete.3 +#usr/share/man/man3/ub_ctx_get_option.3 +#usr/share/man/man3/ub_ctx_hosts.3 +#usr/share/man/man3/ub_ctx_print_local_zones.3 +#usr/share/man/man3/ub_ctx_resolvconf.3 +#usr/share/man/man3/ub_ctx_set_fwd.3 +#usr/share/man/man3/ub_ctx_set_option.3 +#usr/share/man/man3/ub_ctx_trustedkeys.3 +#usr/share/man/man3/ub_ctx_zone_add.3 +#usr/share/man/man3/ub_ctx_zone_remove.3 +#usr/share/man/man3/ub_fd.3 +#usr/share/man/man3/ub_poll.3 +#usr/share/man/man3/ub_process.3 +#usr/share/man/man3/ub_resolve.3 +#usr/share/man/man3/ub_resolve_async.3 +#usr/share/man/man3/ub_resolve_free.3 +#usr/share/man/man3/ub_result.3 +#usr/share/man/man3/ub_strerror.3 +#usr/share/man/man3/ub_wait.3 +#usr/share/man/man5/unbound.conf.5 +#usr/share/man/man8/unbound-anchor.8 +#usr/share/man/man8/unbound-checkconf.8 +#usr/share/man/man8/unbound-control-setup.8 +#usr/share/man/man8/unbound-control.8 +#usr/share/man/man8/unbound.8 diff --git a/config/unbound/blocklists/ms-telemetry.conf b/config/unbound/blocklists/ms-telemetry.conf new file mode 100644 index 0000000..7801e76 --- /dev/null +++ b/config/unbound/blocklists/ms-telemetry.conf @@ -0,0 +1,49 @@ +# Windows telemetry +local-data: "a-0001.a-msedge.net A 127.0.0.1" +local-data: "asimov-win.settings.data.microsoft.com.akadns.net. A 127.0.0.1" +local-data: "asimov-win.vortex.data.microsoft.com.akadns.net. A 127.0.0.1" +local-data: "choice.microsoft.com A 127.0.0.1" +local-data: "choice.microsoft.com.nsatc.net A 127.0.0.1" +local-data: "compatexchange.cloudapp.net A 127.0.0.1" +local-data: "corpext.msitadfs.glbdns2.microsoft.com A 127.0.0.1" +local-data: "corp.sts.microsoft.com A 127.0.0.1" +local-data: "cs1.wpc.v0cdn.net A 127.0.0.1" +local-data: "df.telemetry.microsoft.com A 127.0.0.1" +local-data: "diagnostics.support.microsoft.com A 127.0.0.1" +local-data: "fe2.update.microsoft.com.akadns.net A 127.0.0.1" +local-data: "feedback.microsoft-hohm.com A 127.0.0.1" +local-data: "feedback.search.microsoft.com A 127.0.0.1" +local-data: "feedback.windows.com A 127.0.0.1" +local-data: "i1.services.social.microsoft.com A 127.0.0.1" +local-data: "i1.services.social.microsoft.com.nsatc.net A 127.0.0.1" +local-data: "nexus.officeapps.live.com A 127.0.0.1" +local-data: "oca.telemetry.microsoft.com A 127.0.0.1" +local-data: "oca.telemetry.microsoft.com.nsatc.net A 127.0.0.1" +local-data: "pre.footprintpredict.com A 127.0.0.1" +local-data: "redir.metaservices.microsoft.com A 127.0.0.1" +local-data: "reports.wes.df.telemetry.microsoft.com A 127.0.0.1" +local-data: "services.wes.df.telemetry.microsoft.com A 127.0.0.1" +local-data: "settings-sandbox.data.microsoft.com A 127.0.0.1" +local-data: "settings-win.data.microsoft.com A 127.0.0.1" +local-data: "sls.update.microsoft.com.akadns.net A 127.0.0.1" +local-data: "sqm.df.telemetry.microsoft.com A 127.0.0.1" +local-data: "sqm.telemetry.microsoft.com A 127.0.0.1" +local-data: "sqm.telemetry.microsoft.com.nsatc.net A 127.0.0.1" +local-data: "statsfe1.ws.microsoft.com A 127.0.0.1" +local-data: "statsfe2.update.microsoft.com.akadns.net A 127.0.0.1" +local-data: "statsfe2.ws.microsoft.com A 127.0.0.1" +local-data: "survey.watson.microsoft.com A 127.0.0.1" +local-data: "telecommand.telemetry.microsoft.com A 127.0.0.1" +local-data: "telecommand.telemetry.microsoft.com.nsatc.net A 127.0.0.1" +local-data: "telemetry.appex.bing.net A 127.0.0.1" +local-data: "telemetry.microsoft.com A 127.0.0.1" +local-data: "telemetry.urs.microsoft.com A 127.0.0.1" +local-data: "vortex.data.microsoft.com A 127.0.0.1" +local-data: "vortex-sandbox.data.microsoft.com A 127.0.0.1" +local-data: "vortex-win.data.microsoft.com A 127.0.0.1" +local-data: "watson.live.com A 127.0.0.1" +local-data: "watson.microsoft.com A 127.0.0.1" +local-data: "watson.ppe.telemetry.microsoft.com A 127.0.0.1" +local-data: "watson.telemetry.microsoft.com A 127.0.0.1" +local-data: "watson.telemetry.microsoft.com.nsatc.net A 127.0.0.1" +local-data: "wes.df.telemetry.microsoft.com A 127.0.0.1" diff --git a/config/unbound/forward.conf b/config/unbound/forward.conf new file mode 100644 index 0000000..5784f9f --- /dev/null +++ b/config/unbound/forward.conf @@ -0,0 +1,6 @@ +forward-zone: + name: "." + forward-addr: 85.214.20.141 + forward-addr: 194.150.168.168 + forward-addr: 208.67.222.222 + forward-addr: 208.67.220.220 diff --git a/config/unbound/root.hints b/config/unbound/root.hints new file mode 100644 index 0000000..3c82146 --- /dev/null +++ b/config/unbound/root.hints @@ -0,0 +1,90 @@ +; This file holds the information on root name servers needed to +; initialize cache of Internet domain name servers +; (e.g. reference this file in the "cache . <file>" +; configuration file of BIND domain name servers). +; +; This file is made available by InterNIC +; under anonymous FTP as +; file /domain/named.cache +; on server FTP.INTERNIC.NET +; -OR- RS.INTERNIC.NET +; +; last update: March 23, 2016 +; related version of root zone: 2016032301 +; +; formerly NS.INTERNIC.NET +; +. 3600000 NS A.ROOT-SERVERS.NET. +A.ROOT-SERVERS.NET. 3600000 A 198.41.0.4 +A.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:ba3e::2:30 +; +; FORMERLY NS1.ISI.EDU +; +. 3600000 NS B.ROOT-SERVERS.NET. +B.ROOT-SERVERS.NET. 3600000 A 192.228.79.201 +B.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:84::b +; +; FORMERLY C.PSI.NET +; +. 3600000 NS C.ROOT-SERVERS.NET. +C.ROOT-SERVERS.NET. 3600000 A 192.33.4.12 +C.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2::c +; +; FORMERLY TERP.UMD.EDU +; +. 3600000 NS D.ROOT-SERVERS.NET. +D.ROOT-SERVERS.NET. 3600000 A 199.7.91.13 +D.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2d::d +; +; FORMERLY NS.NASA.GOV +; +. 3600000 NS E.ROOT-SERVERS.NET. +E.ROOT-SERVERS.NET. 3600000 A 192.203.230.10 +; +; FORMERLY NS.ISC.ORG +; +. 3600000 NS F.ROOT-SERVERS.NET. +F.ROOT-SERVERS.NET. 3600000 A 192.5.5.241 +F.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2f::f +; +; FORMERLY NS.NIC.DDN.MIL +; +. 3600000 NS G.ROOT-SERVERS.NET. +G.ROOT-SERVERS.NET. 3600000 A 192.112.36.4 +; +; FORMERLY AOS.ARL.ARMY.MIL +; +. 3600000 NS H.ROOT-SERVERS.NET. +H.ROOT-SERVERS.NET. 3600000 A 198.97.190.53 +H.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:1::53 +; +; FORMERLY NIC.NORDU.NET +; +. 3600000 NS I.ROOT-SERVERS.NET. +I.ROOT-SERVERS.NET. 3600000 A 192.36.148.17 +I.ROOT-SERVERS.NET. 3600000 AAAA 2001:7fe::53 +; +; OPERATED BY VERISIGN, INC. +; +. 3600000 NS J.ROOT-SERVERS.NET. +J.ROOT-SERVERS.NET. 3600000 A 192.58.128.30 +J.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:c27::2:30 +; +; OPERATED BY RIPE NCC +; +. 3600000 NS K.ROOT-SERVERS.NET. +K.ROOT-SERVERS.NET. 3600000 A 193.0.14.129 +K.ROOT-SERVERS.NET. 3600000 AAAA 2001:7fd::1 +; +; OPERATED BY ICANN +; +. 3600000 NS L.ROOT-SERVERS.NET. +L.ROOT-SERVERS.NET. 3600000 A 199.7.83.42 +L.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:9f::42 +; +; OPERATED BY WIDE +; +. 3600000 NS M.ROOT-SERVERS.NET. +M.ROOT-SERVERS.NET. 3600000 A 202.12.27.33 +M.ROOT-SERVERS.NET. 3600000 AAAA 2001:dc3::35 +; End of file diff --git a/config/unbound/root.key b/config/unbound/root.key new file mode 100644 index 0000000..fb540e3 --- /dev/null +++ b/config/unbound/root.key @@ -0,0 +1,9 @@ +; autotrust trust anchor file +;;id: . 1 +;;last_queried: 1467576595 ;;Sun Jul 3 22:09:55 2016 +;;last_success: 1467576595 ;;Sun Jul 3 22:09:55 2016 +;;next_probe_time: 1467616562 ;;Mon Jul 4 09:16:02 2016 +;;query_failed: 0 +;;query_interval: 43200 +;;retry_time: 8640 +. 172800 IN DNSKEY 257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjFFVQUTf6v58fLjwBd0YI0Ez rAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkj f5/Efucp2gaDX6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpzW5hOA2hzCT MjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relSQageu+ipAdTTJ25AsRTAoub8ONGcLmqr AmRLKBP1dfwhYB4N7knNnulqQxA+Uk1ihz0= ;{id = 19036 (ksk), size = 2048b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1467575383 ;;Sun Jul 3 21:49:43 2016 diff --git a/config/unbound/site-packages/daemonize.py b/config/unbound/site- packages/daemonize.py new file mode 100644 index 0000000..e083feb --- /dev/null +++ b/config/unbound/site-packages/daemonize.py @@ -0,0 +1,247 @@ +# #!/usr/bin/python
+import fcntl +import os +import pwd +import grp +import sys +import signal +import resource +import logging +import atexit +from logging import handlers +import traceback
+__version__ = "2.4.6"
+class Daemonize(object): + """ + Daemonize object.
+ Object constructor expects three arguments.
+ :param app: contains the application name which will be sent to syslog. + :param pid: path to the pidfile. + :param action: your custom function which will be executed after daemonization. + :param keep_fds: optional list of fds which should not be closed. + :param auto_close_fds: optional parameter to not close opened fds. + :param privileged_action: action that will be executed before drop privileges if user or + group parameter is provided. + If you want to transfer anything from privileged_action to action, such as + opened privileged file descriptor, you should return it from + privileged_action function and catch it inside action function. + :param user: drop privileges to this user if provided. + :param group: drop privileges to this group if provided. + :param verbose: send debug messages to logger if provided. + :param logger: use this logger object instead of creating new one, if provided. + :param foreground: stay in foreground; do not fork (for debugging) + :param chdir: change working directory if provided or / + """ + def __init__(self, app, pid, action, + keep_fds=None, auto_close_fds=True, privileged_action=None, + user=None, group=None, verbose=False, logger=None, + foreground=False, chdir="/"): + self.app = app + self.pid = os.path.abspath(pid) + self.action = action + self.keep_fds = keep_fds or [] + self.privileged_action = privileged_action or (lambda: ()) + self.user = user + self.group = group + self.logger = logger + self.verbose = verbose + self.auto_close_fds = auto_close_fds + self.foreground = foreground + self.chdir = chdir
+ def sigterm(self, signum, frame): + """ + These actions will be done after SIGTERM. + """ + self.logger.warn("Caught signal %s. Stopping daemon." % signum) + sys.exit(0)
+ def exit(self): + """ + Cleanup pid file at exit. + """ + self.logger.warn("Stopping daemon.") + os.remove(self.pid) + sys.exit(0)
+ def start(self): + """ + Start daemonization process. + """ + # If pidfile already exists, we should read pid from there; to overwrite it, if locking + # will fail, because locking attempt somehow purges the file contents. + if os.path.isfile(self.pid): + with open(self.pid, "r") as old_pidfile: + old_pid = old_pidfile.read() + # Create a lockfile so that only one instance of this daemon is running at any time. + try: + lockfile = open(self.pid, "w") + except IOError: + print("Unable to create the pidfile.") + sys.exit(1) + try: + # Try to get an exclusive lock on the file. This will fail if another process has the file + # locked. + fcntl.flock(lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB) + except IOError: + print("Unable to lock on the pidfile.") + # We need to overwrite the pidfile if we got here. + with open(self.pid, "w") as pidfile: + pidfile.write(old_pid) + sys.exit(1)
+ # skip fork if foreground is specified + if not self.foreground: + # Fork, creating a new process for the child. + try: + process_id = os.fork() + except OSError as e: + self.logger.error("Unable to fork, errno: {0}".format(e.errno)) + sys.exit(1) + if process_id != 0: + # This is the parent process. Exit without cleanup, + # see https://github.com/thesharp/daemonize/issues/46 + os._exit(0) + # This is the child process. Continue.
+ # Stop listening for signals that the parent process receives. + # This is done by getting a new process id. + # setpgrp() is an alternative to setsid(). + # setsid puts the process in a new parent group and detaches its controlling terminal. + process_id = os.setsid() + if process_id == -1: + # Uh oh, there was a problem. + sys.exit(1)
+ # Add lockfile to self.keep_fds. + self.keep_fds.append(lockfile.fileno())
+ # Close all file descriptors, except the ones mentioned in self.keep_fds. + devnull = "/dev/null" + if hasattr(os, "devnull"): + # Python has set os.devnull on this system, use it instead as it might be different + # than /dev/null. + devnull = os.devnull
+ if self.auto_close_fds: + for fd in range(3, resource.getrlimit(resource.RLIMIT_NOFILE)[0]): + if fd not in self.keep_fds: + try: + os.close(fd) + except OSError: + pass
+ devnull_fd = os.open(devnull, os.O_RDWR) + os.dup2(devnull_fd, 0) + os.dup2(devnull_fd, 1) + os.dup2(devnull_fd, 2)
+ if self.logger is None: + # Initialize logging. + self.logger = logging.getLogger(self.app) + self.logger.setLevel(logging.DEBUG) + # Display log messages only on defined handlers. + self.logger.propagate = False
+ # Initialize syslog. + # It will correctly work on OS X, Linux and FreeBSD. + if sys.platform == "darwin": + syslog_address = "/var/run/syslog" + else: + syslog_address = "/dev/log"
+ # We will continue with syslog initialization only if actually have such capabilities + # on the machine we are running this. + if os.path.exists(syslog_address): + syslog = handlers.SysLogHandler(syslog_address) + if self.verbose: + syslog.setLevel(logging.DEBUG) + else: + syslog.setLevel(logging.INFO) + # Try to mimic to normal syslog messages. + formatter = logging.Formatter("%(asctime)s %(name)s: %(message)s", + "%b %e %H:%M:%S") + syslog.setFormatter(formatter)
+ self.logger.addHandler(syslog)
+ # Set umask to default to safe file permissions when running as a root daemon. 027 is an + # octal number which we are typing as 0o27 for Python3 compatibility. + os.umask(0o27)
+ # Change to a known directory. If this isn't done, starting a daemon in a subdirectory that + # needs to be deleted results in "directory busy" errors. + os.chdir(self.chdir)
+ # Execute privileged action + privileged_action_result = self.privileged_action() + if not privileged_action_result: + privileged_action_result = []
+ # Change owner of pid file, it's required because pid file will be removed at exit. + uid, gid = -1, -1
+ if self.group: + try: + gid = grp.getgrnam(self.group).gr_gid + except KeyError: + self.logger.error("Group {0} not found".format(self.group)) + sys.exit(1)
+ if self.user: + try: + uid = pwd.getpwnam(self.user).pw_uid + except KeyError: + self.logger.error("User {0} not found.".format(self.user)) + sys.exit(1)
+ if uid != -1 or gid != -1: + os.chown(self.pid, uid, gid)
+ # Change gid + if self.group: + try: + os.setgid(gid) + except OSError: + self.logger.error("Unable to change gid.") + sys.exit(1)
+ # Change uid + if self.user: + try: + uid = pwd.getpwnam(self.user).pw_uid + except KeyError: + self.logger.error("User {0} not found.".format(self.user)) + sys.exit(1) + try: + os.setuid(uid) + except OSError: + self.logger.error("Unable to change uid.") + sys.exit(1)
+ try: + lockfile.write("%s" % (os.getpid())) + lockfile.flush() + except IOError: + self.logger.error("Unable to write pid to the pidfile.") + print("Unable to write pid to the pidfile.") + sys.exit(1)
+ # Set custom action on SIGTERM. + signal.signal(signal.SIGTERM, self.sigterm) + atexit.register(self.exit)
+ self.logger.warn("Starting daemon.")
+ try: + self.action(*privileged_action_result) + except Exception as e: + for line in traceback.format_exc(e).split("\n"): + self.logger.error(line) diff --git a/config/unbound/site-packages/dhcpd.py b/config/unbound/site- packages/dhcpd.py new file mode 100644 index 0000000..6d586c7 --- /dev/null +++ b/config/unbound/site-packages/dhcpd.py @@ -0,0 +1,108 @@ +""" + Copyright (c) 2016 Ad Schellevis + All rights reserved.
+ Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution.
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +""" +import os +import time +import datetime
+class DHCPDLease(object): + watch_file = '/var/dhcpd/var/db/dhcpd.leases'
+ def __init__(self): + """ init watcher + :return: watcher object + """ + self._section_data = [] + self._fhandle = None + self._last_pos = None + self._open()
+ def _open(self): + """ (re)open watched file + :return: watcher object + """ + try: + self._fhandle = open(self.watch_file, 'r') + self._last_pos = None + self._section_data = [] + return True + except IOError: + self._fhandle = None + return False
+ @staticmethod + def parse_lease(lines): + """ parse dhcp lease + :param lines: lease section as list item + :return: dictionary + """ + lease = dict() + lease['address'] = lines[0].split()[1] + for line in lines: + parts = line.split() + field_name = parts[0] + field_value = None + if field_name in ('starts', 'ends', 'tstp', 'tsfp', 'atsfp', 'cltt') and len(parts) >= 3: + dt = '%s %s'%(parts[2], parts[3]) + try: + field_value = time.mktime(datetime.datetime.strptime(dt, "%Y/%m/%d %H:%M:%S;").timetuple()) + except ValueError: + field_value = None + elif field_name == 'hardware' and len(parts) >= 3: + field_value = {'hardware-type': parts[1], 'mac-address': parts[2]} + elif field_name in('uid', 'client-hostname') and len(parts) >= 2 and parts[1].find('"') > -1: + field_value = parts[1].split('"')[1]
+ if field_value is not None: + lease[field_name] = field_value
+ return lease
+ def watch(self): + """ watch file, return lease dictionaries + :return: iterator for leases + """ + if self._fhandle is None or os.fstat(self._fhandle.fileno()).st_nlink == 0: + # nothing to watch, try to (re)open return when failed + if not self._open(): + return + elif self._last_pos is not None: + self._fhandle.seek(self._last_pos)
+ while True: + line = self._fhandle.readline() + if line: + if len(line) > 5 and line[0:5] == 'lease': + self._section_data.append(line) + elif len(line) > 1 and line[0] == '}': + self._section_data.append(line) + yield self.parse_lease(self._section_data) + self._section_data = [] + elif len(self._section_data) > 0: + self._section_data.append(line) + else: + break
+ self._last_pos = self._fhandle.tell() diff --git a/config/unbound/site-packages/params.py b/config/unbound/site- packages/params.py new file mode 100644 index 0000000..6be3244 --- /dev/null +++ b/config/unbound/site-packages/params.py @@ -0,0 +1,46 @@ +""" + Copyright (c) 2015-2016 Ad Schellevis + All rights reserved.
+ Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution.
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +"""
+import sys
+def update_params(parameters): + """ update predefined parameters with given list from shell (as switches) + for example /a valA /b valB + converts to + {'a':'valA','b':'valB'} + (assuming parameters contains both a and b) + :param parameters: parameter dictionary + :return: + """ + cmd = None + for arg in sys.argv[1:]: + if cmd is None: + cmd = arg[1:] + else: + if cmd in parameters and arg.strip() != '': + parameters[cmd] = arg.strip() + cmd = None diff --git a/config/unbound/site-packages/watcherdhcpd.py b/config/unbound/site-packages/watcherdhcpd.py new file mode 100644 index 0000000..c726d5c --- /dev/null +++ b/config/unbound/site-packages/watcherdhcpd.py @@ -0,0 +1,107 @@ +""" + Copyright (c) 2016 Ad Schellevis + All rights reserved.
+ Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution.
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +""" +import os +import time +import datetime
+class DHCPDLease(object): + watch_file = '/var/state/dhcp/dhcpd.leases'
+ def __init__(self): + """ init watcher + :return: watcher object + """ + self._section_data = [] + self._fhandle = None + self._last_pos = None + self._open()
+ def _open(self): + """ (re)open watched file + :return: watcher object + """ + try: + self._fhandle = open(self.watch_file, 'r') + self._last_pos = None + self._section_data = [] + return True + except IOError: + self._fhandle = None + return False
+ @staticmethod + def parse_lease(lines): + """ parse dhcp lease + :param lines: lease section as list item + :return: dictionary + """ + lease = dict() + lease['address'] = lines[0].split()[1] + for line in lines: + parts = line.split() + field_name = parts[0] + field_value = None + if field_name in ('starts', 'ends', 'tstp', 'tsfp', 'atsfp', 'cltt') and len(parts) >= 3: + dt = '%s %s'%(parts[2], parts[3]) + try: + field_value = time.mktime(datetime.datetime.strptime(dt, "%Y/%m/%d %H:%M:%S;").timetuple()) + except ValueError: + field_value = None + elif field_name == 'hardware' and len(parts) >= 3: + field_value = {'hardware-type': parts[1], 'mac-address': parts[2]} + elif field_name in('uid', 'client-hostname') and len(parts) >= 2 and parts[1].find('"') > -1: + field_value = parts[1].split('"')[1]
+ if field_value is not None: + lease[field_name] = field_value + return lease
+ def watch(self): + """ watch file, return lease dictionaries + :return: iterator for leases + """ + if self._fhandle is None or os.fstat(self._fhandle.fileno()).st_nlink == 0: + # nothing to watch, try to (re)open return when failed + if not self._open(): + return + elif self._last_pos is not None: + self._fhandle.seek(self._last_pos)
+ while True: + line = self._fhandle.readline() + if line: + if len(line) > 5 and line[0:5] == 'lease': + self._section_data.append(line) + elif len(line) > 1 and line[0] == '}': + self._section_data.append(line) + yield self.parse_lease(self._section_data) + self._section_data = [] + elif len(self._section_data) > 0: + self._section_data.append(line) + else: + break
+ self._last_pos = self._fhandle.tell() diff --git a/config/unbound/unbound-dhcpd.py b/config/unbound/unbound-dhcpd.py new file mode 100644 index 0000000..0afedc9 --- /dev/null +++ b/config/unbound/unbound-dhcpd.py @@ -0,0 +1,145 @@ +#!/usr/bin/python2.7
+""" + Copyright (c) 2016 Ad Schellevis + All rights reserved.
+ Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution.
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE.
+ -------------------------------------------------------------------------
+ watch dhcp lease file and build include file for unbound +""" +import os +import sys
+sys.path.insert(0, "/usr/lib/python2.7/site-packages") +import subprocess +import time +import tempfile +from daemonize import Daemonize +import watcherdhcpd +import params
+def unbound_control(commands, output_stream=None): + """ execute (chrooted) unbound-control command + :param commands: command list (parameters) + :param output_stream: (optional)output stream + :return: None + """ + output_stream = open(os.devnull, 'w') + subprocess.check_call(['/usr/sbin/chroot', '--userspec=unbound:unbound', '/', + '/usr/sbin/unbound-control', '-c', '/etc/unbound/unbound.conf'] + commands, + stdout=output_stream, stderr=subprocess.STDOUT) + output_stream.seek(0)
+def unbound_known_addresses(): + """ fetch known addresses + :return: list + """ + result = list() + with tempfile.NamedTemporaryFile() as output_stream: + unbound_control(['list_local_data'], output_stream) + for line in output_stream.read().split('\n'): + parts = line.split() + if len(parts) > 4 and parts[3] == 'A': + result.append(parts[4]) + print result + return result
+# parse input params +app_params = {'pid': '/var/run/unbound_dhcpd.pid', + 'domain': 'local', + 'target': '/etc/unbound/dhcpleases.conf', + 'background': '1'} +params.update_params(app_params)
+def main(): + # cleanup interval (seconds) + cleanup_interval = 60
+ # All times in the lease database are in Coordinated Universal Time (UTC), not local time! + tzone = 0 + if app_params['background'] <> 1: + print "Add leases for domian:",app_params['domain']
+ # initiate lease watcher and setup cache + dhcpdleases = watcherdhcpd.DHCPDLease() + cached_leases = dict() + known_addresses = unbound_known_addresses()
+ # start watching dhcp leases + last_cleanup = time.time() + while True: + dhcpd_changed = False + if time.daylight <> 0: + utctime = time.time() + time.altzone + else: + utctime = time.time() + time.timezone
+ for lease in dhcpdleases.watch(): + if 'ends' in lease and lease['ends'] > utctime and 'client- hostname' in lease and 'address' in lease: + cached_leases[lease['address']] = lease + dhcpd_changed = True + if app_params['background'] <> 1: + print "IP:",lease['address'],"Hostname:",lease['client- hostname'],"Start:",lease['starts'],"End:",lease['ends']
+ if time.time() - last_cleanup > cleanup_interval: + # cleanup every x seconds + last_cleanup = time.time() + addresses = cached_leases.keys() + for address in addresses: + if cached_leases[address]['ends'] < time.time(): + del cached_leases[address] + dhcpd_changed = True
+ if dhcpd_changed: + # dump dns output to target + with open(app_params['target'], 'w') as unbound_conf: + for address in cached_leases: + unbound_conf.write('local-data-ptr: "%s %s.%s"\n' % (address, + cach ed_leases[address]['client-hostname'], + app_ params['domain']))
+ unbound_conf.write('local-data: "%s.%s IN A %s"\n' % (cached_leases[address]['client-hostname'], + app _params['domain'], + add ress)) + # signal unbound + for address in cached_leases: + if address not in known_addresses: + fqdn = '%s.%s' % (cached_leases[address]['client- hostname'], app_params['domain']) + unbound_control(['local_data', address, 'PTR', fqdn]) + unbound_control(['local_data', fqdn, 'IN A', address]) + known_addresses.append(address) + # wait for next cycle + time.sleep(5)
+# startup +if app_params['background'] == '1': + daemon = Daemonize(app="unbound_dhcpd", pid=app_params['pid'], action=main) + daemon.start() +else: + main() diff --git a/config/unbound/unbound-switch b/config/unbound/unbound-switch new file mode 100755 index 0000000..60eeb89 --- /dev/null +++ b/config/unbound/unbound-switch @@ -0,0 +1,80 @@ +#!/bin/bash +############################################################################# ## +# # +# IPFire.org - A linux based firewall # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see http://www.gnu.org/licenses/. # +# # +# Description : script to switch the DNS server/proxy in IPfire # +# rerun to easy go back to dnsmasq # +# # +# Author : Marcel Lorenz marcel.lorenz@ipfire.org # +# # +############################################################################# ##
+CGIFILE="/srv/web/ipfire/cgi-bin/services.cgi"
+install_cron_jobs() { +cat > /etc/fcron.weekly/update_unbound_anchor << "EOF" +#!/bin/bash +# allow max all 30 minutes to update files +if [[ $(( (`date +%s` - `stat -L --format %Y /etc/unbound/root.key`) > (30*60) )) != 0 ]]; then + wget -q ftp://ftp.internic.net/domain/named.cache -O /etc/unbound/root.hints + curl -sS -L --compressed "http://pgl.yoyo.org/adservers/serverlist.php?host format=unbound&showintro=0&mimetype=plaintext" > /etc/unbound/blocklists/ad- servers.conf + unbound-anchor +fi +exit 0 +EOF +chmod +x /etc/fcron.weekly/update_unbound_anchor +cat > /etc/fcron.hourly/update_unbound_zone << "EOF" +#!/bin/bash +unbound-zone +EOF +chmod +x /etc/fcron.hourly/update_unbound_zone +}
+# main switch +if [[ -e /etc/rc.d/init.d/networking/red.up/05-RS-dnsmasq ]]; then + echo -e "\033[32mActivate Unbound DNS-proxy at start...\033[0m"; + # autostart symlinks + rm -f /etc/rc.d/init.d/networking/red.up/05-RS-dnsmasq /etc/rc.d/init.d/networking/red.down/05-RS-dnsmasq + mv -f /etc/init.d/network /etc/init.d/network-dnsmasq + mv -f /etc/init.d/network-unbound /etc/init.d/network + # WebIF services.cgi + sed -i "s|$Lang::tr{'dns proxy server'} => 'dnsmasq',.*|$Lang::tr{'dns proxy server'} => 'unbound',|" ${CGIFILE} + install_cron_jobs + /etc/fcron.weekly/update_unbound_anchor + # Stop and start services + /etc/rc.d/init.d/dnsmasq stop + sleep 1 + /etc/rc.d/init.d/unbound start
+else + echo -e "\033[32mActivate dnsmasq DNS-proxy at start...\033[0m"; + # autostart symlinks + ln -sf /etc/rc.d/init.d/dnsmasq /etc/rc.d/init.d/networking/red.up/05-RS- dnsmasq + ln -sf /etc/rc.d/init.d/dnsmasq /etc/rc.d/init.d/networking/red.down/05-RS- dnsmasq + mv -f /etc/init.d/network /etc/init.d/network-unbound + mv -f /etc/init.d/network-dnsmasq /etc/init.d/network + # WebIF services.cgi + sed -i "s|$Lang::tr{'dns proxy server'} => 'unbound',.*|$Lang::tr{'dns proxy server'} => 'dnsmasq',|" ${CGIFILE} + # Stop and start services + /etc/rc.d/init.d/unbound stop + sleep 1 + /etc/rc.d/init.d/dnsmasq start + rm -f /etc/fcron.weekly/update_unbound_anchor /etc/fcron.hourly/update_unbound_zone; +fi +unset CGIFILE +echo -e "\033[32mdone...\033[0m"; +exit 0 +# end of unbound-proxy diff --git a/config/unbound/unbound-zone b/config/unbound/unbound-zone new file mode 100644 index 0000000..9a0de1f --- /dev/null +++ b/config/unbound/unbound-zone @@ -0,0 +1,78 @@ +#!/bin/bash +############################################################################# ## +# # +# IPFire.org - A linux based firewall # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see http://www.gnu.org/licenses/. # +# # +# Description : small script to create the zone file for ipfire's # +# internal domain (for example ipfire.local) # +# # +# Author : Marcel Lorenz marcel.lorenz@ipfire.org # +# # +############################################################################# ##
+ZONEFILE="/etc/unbound/zones/local.conf" +HOSTSFILE="/var/ipfire/main/hosts"
+eval $(/usr/local/bin/readhash /var/ipfire/main/settings) +eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings) +REV_GREEN=$(echo ${GREEN_ADDRESS} |awk -F. '{print $4"."$3"."$2"."$1}')
+# overwrite existing file +cat > ${ZONEFILE} << "EOF" +# This is the automatically created zone file for unbound +# please do not edit this file, use the webinterface to add or remove hosts +# if need more zones, create a new zone file and restart unbound +# +EOF
+# create zone header +echo "# Zone file created at $(date)" >> ${ZONEFILE} +echo "">> ${ZONEFILE} +echo "# zone definition " >> ${ZONEFILE} +echo "private-domain: "${DOMAINNAME}"" >> ${ZONEFILE} +echo "local-zone: "${DOMAINNAME}." static" >> ${ZONEFILE} +echo "local-data: "${HOSTNAME}.${DOMAINNAME}. IN A ${GREEN_ADDRESS}"" >> ${ZONEFILE} +echo "local-data: "wpad.${DOMAINNAME}. IN A ${GREEN_ADDRESS}"" >> ${ZONEFILE} +echo "local-data: "${REV_GREEN}.in-addr.arpa. 10800 IN PTR ${HOSTNAME}.${DOMAINNAME}."" >> ${ZONEFILE}
+# write forward entrys to zone file +echo "" >> ${ZONEFILE} +echo "# Hosts from /var/ipfire/main/hosts" >> ${ZONEFILE}
+while read line +do + if [[ $(echo ${line}|awk -F, '{print $1}') = on ]]; then + IP=$(echo ${line}|awk -F, '{print $2}') + HOST=$(echo ${line}|awk -F, '{print $3}') + DOMAIN=$(echo ${line}|awk -F, '{print $4}') + echo "local-data: "${HOST}.${DOMAIN}. IN A ${IP}"" >> ${ZONEFILE} + fi +done < ${HOSTSFILE}
+# write reverse entrys to zone file +echo "" >> ${ZONEFILE} +echo "# reverse entrys" >> ${ZONEFILE} +while read line +do + if [[ $(echo ${line}|awk -F, '{print $1}') = on ]]; then + IP=$(echo ${line}|awk -F, '{print $2}'|awk -F. '{print $4"."$3"."$2"."$1}') + HOST=$(echo ${line}|awk -F, '{print $3}') + DOMAIN=$(echo ${line}|awk -F, '{print $4}') + echo "local-data: "${IP}.in-addr.arpa. 10800 IN PTR ${HOST}.${DOMAIN}""
${ZONEFILE}
+ fi +done < ${HOSTSFILE} +unset IP HOST DOMAIN REV_GREEN; +exit 0 +# end of unbound-zone diff --git a/config/unbound/unbound.conf b/config/unbound/unbound.conf new file mode 100644 index 0000000..8dc72e6 --- /dev/null +++ b/config/unbound/unbound.conf @@ -0,0 +1,123 @@ +# +# Unbound configuration file for IPFire +# +# The full documentation is available at: +# https://www.unbound.net/documentation/unbound.conf.html +#
+server:
- # common server options
- chroot: "/etc/unbound"
- username: "unbound"
- pidfile: "/var/run/unbound.pid"
- num-threads: 2
- port: 53
- do-ip4: yes
- do-ip6: no
- do-udp: yes
- do-tcp: yes
- prefetch: yes
- so-reuseport: yes
- cache-min-ttl: 3600
- cache-max-ttl: 86400
- unwanted-reply-threshold: 10000
- do-not-query-localhost: yes
- # logging options
- logfile: "log/unbound.log"
- use-syslog: no
- verbosity: 1
- log-queries: no
- log-time-ascii: yes
- # Unbound Statistics
- statistics-interval: 3600
- statistics-cumulative: yes
- extended-statistics: yes
- # privacy options
- hide-identity: yes
- hide-version: yes
- qname-minimisation: yes
- minimal-responses: yes
- # hardening options (some experimental)
- harden-glue: yes
- harden-large-queries: yes
- harden-dnssec-stripped: yes
- harden-short-bufsize: no
- harden-below-nxdomain: no
- harden-referral-path: no
- harden-algo-downgrade: no
- use-caps-for-id: yes
- # listen on localhost interface
- interface: 127.0.0.1
- # file with ipfire interfaces
- include: "/etc/unbound/interfaces.conf"
- # control which clients are allowed to make (recursive) queries
- access-control: 0.0.0.0/0 refuse
- access-control: 127.0.0.0/8 allow
- access-control: ::0/0 refuse
- access-control: ::1 allow
- access-control: ::ffff:127.0.0.1 allow
- # file with ipfire networks
- include: "/etc/unbound/access.conf"
- # dnssec main options
- val-clean-additional: yes
- val-log-level: 1
- # file with ipfire dnssec configuration
- include: "/etc/unbound/dnssec.conf"
- # DNS Rebinding
- # For DNS Rebinding prevention
- #
- # All these addresses are either private or should not be routable in
the global IPv4 or IPv6 internet.
- # IPv4 Addresses
- private-address: 0.0.0.0/8 # Broadcast address
- private-address: 10.0.0.0/8
- private-address: 127.0.0.0/8 # Loopback Localhost
- private-address: 172.16.0.0/12
- private-address: 192.168.0.0/16
- private-address: 169.254.0.0/16
- private-address: 198.18.0.0/15 # Used for testing inter-network
communications
- private-address: 198.51.100.0/24 # Documentation network TEST-NET-2
- private-address: 203.0.113.0/24 # Documentation network TEST-NET-3
- private-address: 233.252.0.0/24 # Documentation network MCAST-TEST-
NET
- # IPv6 Addresses
- private-address: ::1/128 # Loopback Localhost
- private-address: 2001:db8::/32 # Documentation network IPv6
- private-address: fc00::/8 # Unique local address (ULA) part of
"fc00::/7", not defined yet
- private-address: fd00::/8 # Unique local address (ULA) part of
"fc00::/7", "/48" prefix group
- private-address: fe80::/10 # Link-local address (LLA)
- # file with root servers
- root-hints: "/etc/unbound/root.hints"
- # custom DNS zone files
- include: "/etc/unbound/zones/*.conf"
- # DHCP leases (if configured)
- include: /etc/unbound/dhcpleases.conf
- # Blocklists
- include: "/etc/unbound/blocklists/*.conf"
+# end server config
+# enable remote control only on localhost +remote-control:
- control-enable: yes
- control-use-cert: yes
- control-interface: 127.0.0.1
- server-key-file: "/etc/unbound/unbound_server.key"
- server-cert-file: "/etc/unbound/unbound_server.pem"
- control-key-file: "/etc/unbound/unbound_control.key"
- control-cert-file: "/etc/unbound/unbound_control.pem"
+# end remote control config
+# custom DNS forward config +include: "/etc/unbound/forward.conf" diff --git a/lfs/unbound b/lfs/unbound new file mode 100644 index 0000000..d91c0f9 --- /dev/null +++ b/lfs/unbound @@ -0,0 +1,103 @@ +############################################################################# ## +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2007 Michael Tremer & Christian Schmidt # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see http://www.gnu.org/licenses/. # +# # +############################################################################# ##
+############################################################################# ## +# Definitions +############################################################################# ##
+include Config
+VER = 1.5.9 +THISAPP = unbound-$(VER) +DL_FILE = $(THISAPP).tar.gz +DL_FROM = $(URL_IPFIRE) +DIR_APP = $(DIR_SRC)/$(THISAPP) +TARGET = $(DIR_INFO)/$(THISAPP) +PROG = unbound +PAK_VER = 1 +DEPS = ""
+############################################################################# ## +# Top-level Rules +############################################################################# ##
+objects = $(DL_FILE)
+$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
+$(DL_FILE)_MD5 = 0cefa62c1690b4db18583db84bff00e3
+install : $(TARGET)
+check : $(patsubst %,$(DIR_CHK)/%,$(objects))
+download :$(patsubst %,$(DIR_DL)/%,$(objects))
+md5 : $(subst %,%_MD5,$(objects))
+dist:
- $(PAK)
+############################################################################# ## +# Downloading, checking, md5sum +############################################################################# ##
+$(patsubst %,$(DIR_CHK)/%,$(objects)) :
- @$(CHECK)
+$(patsubst %,$(DIR_DL)/%,$(objects)) :
- @$(LOAD)
+$(subst %,%_MD5,$(objects)) :
- @$(MD5)
+############################################################################# ## +# Installation Details +############################################################################# ##
+$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
- @$(PREBUILD)
- @rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE)
- cd $(DIR_APP) && ./configure \
--prefix=/usr \
--sysconfdir=/etc \
--disable-static \
--with-libevent \
--with-pyunbound \
--with-pidfile=/var/run/unbound.pid
- cd $(DIR_APP) && make $(MAKETUNING)
- cd $(DIR_APP) && make install
- mv -v /usr/sbin/unbound-host /usr/bin/
- # add ipfire config
- mkdir -pv /etc/unbound/blocklists
- mv -v /etc/unbound/unbound.conf /etc/unbound/unbound_org.conf
- install -v -m 644 $(DIR_SRC)/config/unbound/*.conf /etc/unbound/
- install -v -m 644 $(DIR_SRC)/config/unbound/root.hints /etc/unbound/
- install -v -m 644 $(DIR_SRC)/config/unbound/root.key /etc/unbound/
- install -v -m 644 $(DIR_SRC)/config/unbound/blocklists/*.conf
/etc/unbound/blocklists/
- install -v -m 644 $(DIR_SRC)/config/unbound/site-packages/*
/usr/lib/python2.7/site-packages/
- install -v -m 754 $(DIR_SRC)/config/unbound/unbound-switch /usr/sbin/
- install -v -m 754 $(DIR_SRC)/config/unbound/unbound-zone /usr/sbin/
- install -v -m 754 $(DIR_SRC)/config/unbound/unbound-dhcpd.py
/usr/sbin/
- install -v -m 754 $(DIR_SRC)/src/initscripts/init.d/unbound
/etc/rc.d/init.d/
- install -v -m 754 $(DIR_SRC)/src/initscripts/init.d/unbound-dhcpd
/etc/rc.d/init.d/
- install -v -m 754 $(DIR_SRC)/src/initscripts/init.d/network-unbound
/etc/rc.d/init.d/
- @rm -rf $(DIR_APP)
- @$(POSTBUILD)
diff --git a/make.sh b/make.sh index a9fac52..74bc06a 100755 --- a/make.sh +++ b/make.sh @@ -870,6 +870,7 @@ buildipfire() { ipfiremake libpciaccess ipfiremake libyajl ipfiremake libvirt + ipfiremake unbound } buildinstaller() { diff --git a/src/initscripts/init.d/network-unbound b/src/initscripts/init.d/network-unbound new file mode 100644 index 0000000..31fe173 --- /dev/null +++ b/src/initscripts/init.d/network-unbound @@ -0,0 +1,114 @@ +#!/bin/sh +######################################################################## +# Begin $rc_base/init.d/network +# +# Description : Network Control Script +# +# Authors : Michael Tremer - mitch@ipfire.org +# +# Version : 01.00 +# +# Notes : Written for IPFire by its team +# +########################################################################
+. /etc/sysconfig/rc +. ${rc_functions} +eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings)
+DO="${1}" +shift
+if [ -n "${1}" ]; then
- ALL=0
- for i in green red blue orange; do
eval "${i}=0"
- done
+else
- ALL=1
- for i in green red blue orange; do
eval "${i}=1"
- done
+fi
+while [ ! $# = 0 ]; do
- for i in green red blue orange; do
if [ "${i}" == "${1}" ]; then
eval "${i}=1"
shift
fi
- done
+done
+case "${DO}" in
- start)
# Starting interfaces...
# GREEN
[ "$green" == "1" ] && /etc/rc.d/init.d/networking/green
start
# BLUE
[ "$blue" == "1" ] && [ "$CONFIG_TYPE" = "3" -o
"$CONFIG_TYPE" = "4" ] && \
/etc/rc.d/init.d/networking/blue start
# ORANGE
[ "$orange" == "1" ] && [ "$CONFIG_TYPE" = "2" -o
"$CONFIG_TYPE" = "4" ] && \
/etc/rc.d/init.d/networking/orange start
# RED
if [ "$red" == "1" ]; then
if [ "$CONFIG_TYPE" = "1" -o "$CONFIG_TYPE" = "2" -o
"$CONFIG_TYPE" = "3" -o "$CONFIG_TYPE" = "4" ]; then
# Remove possible leftover files
rm -f /var/ipfire/red/{active,device,dial-on-
demand,dns1,dns2,local-ipaddress,remote-ipaddress,resolv.conf}
[ "$AUTOCONNECT" == "off" ] ||
/etc/rc.d/init.d/networking/red start
fi
fi
/etc/rc.d/init.d/static-routes start
[ "${ALL}" == "1" ] && /etc/rc.d/init.d/unbound start
;;
- stop)
[ "${ALL}" == "1" ] && /etc/rc.d/init.d/unbound stop
# Stopping interfaces...
# GREEN
[ "$green" == "1" ] && /etc/rc.d/init.d/networking/green stop
# BLUE
[ "$blue" == "1" ] && [ "$CONFIG_TYPE" = "3" -o
"$CONFIG_TYPE" = "4" ] && \
/etc/rc.d/init.d/networking/blue stop
# ORANGE
[ "$orange" == "1" ] && [ "$CONFIG_TYPE" = "2" -o
"$CONFIG_TYPE" = "4" ] && \
/etc/rc.d/init.d/networking/orange stop
# RED
if [ "$red" == "1" ]; then
if [ "$CONFIG_TYPE" = "1" -o "$CONFIG_TYPE" = "2" -o
"$CONFIG_TYPE" = "3" -o "$CONFIG_TYPE" = "4" ]; then
/etc/rc.d/init.d/networking/red stop
fi
fi
exit 0
;;
- restart)
for i in green red blue orange; do
if [ "${!i}" == "1" ]; then
ARGS+=" ${i}"
fi
done
${0} stop ${ARGS}
sleep 1
${0} start ${ARGS}
;;
- *)
echo "Usage: ${0} {start|stop|restart} [device(s)]"
exit 1
;;
+esac
+# End /etc/rc.d/init.d/network diff --git a/src/initscripts/init.d/unbound b/src/initscripts/init.d/unbound new file mode 100644 index 0000000..8e6881e --- /dev/null +++ b/src/initscripts/init.d/unbound @@ -0,0 +1,178 @@ +#!/bin/sh +# Begin $rc_base/init.d/unbound
+# Description : Unbound DNS resolver boot script for IPfire +# Author : Marcel Lorenz marcel.lorenz@ipfire.org +# +# Comment : This init script additional starts the dhcpd watcher daemon +# if DNS-Update (RFC2136) in web interface enabled
+. /etc/sysconfig/rc +. ${rc_functions}
+if [[ ! -d /run/var ]]; then mkdir /run/var; fi;
+CONTROL_INTERFACE_FILE=1 +CONTROL_ACCESS_FILE=1 +USE_CUSTOM_FORWARDS=0 +ENABLE_DNSSEC=1
+# Unbound daemon pid file +PIDFILE=/var/run/unbound.pid
+# Watcher deamon pid file must be the same in unbound main init script +WAPIDFILE=/var/run/unbound_dhcpd.pid
+function cidr() { + local cidr nbits IFS; + IFS=. read -r i1 i2 i3 i4 <<< ${1} + IFS=. read -r m1 m2 m3 m4 <<< ${2} + cidr=$(printf "%d.%d.%d.%d\n" "$((i1 & m1))" "$((i2 & m2))" "$((i3 & m3))" "$((i4 & m4))") + nbits=0 + IFS=. + for dec in $2 ; do + case $dec in + 255) let nbits+=8;; + 254) let nbits+=7;; + 252) let nbits+=6;; + 248) let nbits+=5;; + 240) let nbits+=4;; + 224) let nbits+=3;; + 192) let nbits+=2;; + 128) let nbits+=1;; + 0);; + *) echo "Error: $dec is not recognised"; exit 1 + esac + done + echo "${cidr}/${nbits}" +}
+case "$1" in
- start)
- if [[ -f ${PIDFILE} ]]; then
- log_warning_msg "Unbound daemon is running with Process ID $(cat
${PIDFILE})"
- else
- eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings)
- #ARGS="$CUSTOM_ARGS"
- #[ "$DOMAIN_NAME_GREEN" != "" ] && ARGS="$ARGS -s
$DOMAIN_NAME_GREEN"
- echo > /var/ipfire/red/resolv.conf # Clear it
- if [ -e "/var/ipfire/red/dns1" ]; then
- DNS1=$(cat /var/ipfire/red/dns1 2>/dev/null)
- if [ ! -z ${DNS1} ]; then
echo "nameserver ${DNS1}" >> /var/ipfire/red/resolv.conf
NAMESERVERS="${DNS1} "
- fi
- fi
- if [ -e "/var/ipfire/red/dns2" ]; then
- DNS2=$(cat /var/ipfire/red/dns2 2>/dev/null)
- if [ ! -z ${DNS2} ]; then
echo "nameserver ${DNS2}" >> /var/ipfire/red/resolv.conf
NAMESERVERS+="${DNS2} "
- fi
- fi
- # create unbound interfaces.conf
- if [ ${CONTROL_INTERFACE_FILE} = 1 ]; then
echo -n > /etc/unbound/interfaces.conf # Clear it
- if [ ! -z ${GREEN_ADDRESS} ]; then
echo "interface: ${GREEN_ADDRESS}" >>
/etc/unbound/interfaces.conf
- fi
- if [ ! -z ${BLUE_ADDRESS} ]; then
echo "interface: ${BLUE_ADDRESS}" >>
/etc/unbound/interfaces.conf
- fi
if [ ! -z ${ORANGE_ADDRESS} ]; then
echo "interface: ${ORANGE_ADDRESS}" >>
/etc/unbound/interfaces.conf
- fi
- fi
- # create unbound access.conf
- if [ ${CONTROL_ACCESS_FILE} = 1 ]; then
- echo -n > /etc/unbound/access.conf # Clear it
- if [ ! -z ${GREEN_ADDRESS} ]; then
echo "access-control: $(cidr ${GREEN_ADDRESS}
${GREEN_NETMASK}) allow" >> /etc/unbound/access.conf
- fi
- if [ ! -z ${BLUE_ADDRESS} ]; then
echo "access-control: $(cidr ${BLUE_ADDRESS} ${BLUE_NETMASK})
allow" >> /etc/unbound/access.conf
- fi
- if [ ! -z ${ORANGE_ADDRESS} ]; then
echo "access-control: $(cidr ${ORANGE_ADDRESS}
${ORANGE_NETMASK}) allow" >> /etc/unbound/access.conf
- fi
- fi
- # create unbound dnssec.conf
- echo -n > /etc/unbound/dnssec.conf # Clear it
- if [ ${ENABLE_DNSSEC} = 1 ]; then
- echo " # dessec enabled per default" >>
/etc/unbound/dnssec.conf
- echo " # no necessary config options in this file" >>
/etc/unbound/dnssec.conf
- else
- echo " # dnssec now disabled" >>
/etc/unbound/dnssec.conf
- echo " module-config: iterator" >>
/etc/unbound/dnssec.conf
- echo " val-permissive-mode: yes" >>
/etc/unbound/dnssec.conf
- fi
- # create zone file for internal ipfire domain
- unbound-zone
- boot_mesg "Starting Unbound DNS proxy..."
- unbound-anchor
- loadproc /usr/sbin/unbound
- # start dhcpd watcher daemon if DNS-Update (RFC2136) activated
- eval $(/usr/local/bin/readhash /var/ipfire/dhcp/settings)
- if [[ ${DNS_UPDATE_ENABLED} = on && ! -f ${WAPIDFILE} ]]; then
- /etc/rc.d/init.d/unbound-dhcpd start
- fi
- # use setup configured DNS servers
- if [ "${USE_CUSTOM_FORWARDS}" -eq 0 ]; then
- unbound-control forward_add +i . ${NAMESERVERS} &> /dev/null
- fi;
- FORWADRS=$(unbound-control list_forwards |sed 's|. IN forward
||g'|sed 's|+i ||g')
- if [ "${USE_CUSTOM_FORWARDS}" -eq 0 ]; then
- boot_mesg "Using DNS server(s): ${FORWADRS}"
- else
- boot_mesg "Using custom DNS server(s): ${FORWADRS}"
- fi
- if [ ${ENABLE_DNSSEC} = 1 ]; then
- boot_mesg "DNSSEC is enabled!"
- else
- boot_mesg "DNSSEC is disabled!"
- fi
- fi
- ;;
- stop)
- if [[ -f ${PIDFILE} ]]; then
- # stop dhcpd watcher daemon if activted
- if [[ -f ${WAPIDFILE} ]]; then
- /etc/rc.d/init.d/unbound-dhcpd stop
- fi
- # stop Unbound daemon
- boot_mesg "Stopping Unbound DNS proxy..."
- killproc -p "/var/run/unbound.pid" /usr/sbin/unbound
- else
- log_warning_msg "Unbound daemon is not running..."
- fi
- ;;
- restart)
- $0 stop
- sleep 1
- $0 start
- ;;
- status)
- statusproc /usr/sbin/unbound
- ;;
- *)
- echo "Usage: $0 {start|stop|restart|status}"
- exit 1
- ;;
+esac
+# End $rc_base/init.d/unbound diff --git a/src/initscripts/init.d/unbound-dhcpd b/src/initscripts/init.d/unbound-dhcpd new file mode 100644 index 0000000..4c24a3c --- /dev/null +++ b/src/initscripts/init.d/unbound-dhcpd @@ -0,0 +1,61 @@ +#!/bin/sh +# Begin $rc_base/init.d/unbound-dhcpd
+# Description : Unbound dhcpd lease file wachter daemon boot script for IPFire +# Author : Marcel Lorenz marcel.lorenz@ipfire.org
+. /etc/sysconfig/rc +. $rc_functions
+PIDFILE=/var/run/unbound_dhcpd.pid +SETFILE=/var/ipfire/main/settings
+case "$1" in
- start)
if [[ -f ${PIDFILE} ]]; then
log_warning_msg "Unbound dhcpd watcher daemon is running
with Process ID $(cat ${PIDFILE})"
else
eval $(/usr/local/bin/readhash ${SETFILE})
boot_mesg "Starting Unbound dhcpd watcher deamon..."
loadproc /usr/bin/python /usr/sbin/unbound-dhcpd.py /domain
${DOMAINNAME} /pid ${PIDFILE}
fi
;;
- stop)
if [[ -f ${PIDFILE} ]]; then
boot_mesg "Stopping Unbound dhcpd watcher deamon..."
kill $(/bin/cat ${PIDFILE})
sleep 1
if [[ -f ${PIDFILE} ]]; then
echo_failure
else
echo_ok
fi
else
log_warning_msg "Unbound dhcpd watcher daemon is not
running..."
fi
;;
- restart)
$0 stop
sleep 1
$0 start
;;
- status)
if [[ -f "$PIDFILE" ]]; then
echo -e "\\033[1;36mUnbound dhcpd watcher daemon is running
with Process ID $(cat ${PIDFILE})\033[0;39m"
exit 0
else
echo -e "\\033[1;36mUnbound dhcpd watcher daemon is not
running...\033[0;39m"
exit 0
fi
;;
- *)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
;;
+esac
+# End $rc_base/init.d/unbound-dhcpd \ No newline at end of file diff --git a/src/paks/unbound/install.sh b/src/paks/unbound/install.sh new file mode 100644 index 0000000..84c93f3 --- /dev/null +++ b/src/paks/unbound/install.sh @@ -0,0 +1,70 @@ +#!/bin/bash +############################################################################ +# # +# This file is part of the IPFire Firewall. # +# # +# IPFire is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +# IPFire is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with IPFire; if not, write to the Free Software # +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +# # +# Copyright (C) 2016 IPFire-Team info@ipfire.org. # +# # +############################################################################ +# +. /opt/pakfire/lib/functions.sh +extract_files +restore_backup ${NAME}
+# add unbound user and group +groupadd -g 85 unbound +useradd -c "Unbound DNS resolver" -d /var/lib/unbound -u 85 -g unbound -s /bin/false unbound
+# create config subdir's +mkdir -pv /etc/unbound/log /etc/unbound/zones /var/log/unbound +chown unbound:unbound -R /var/log/unbound/ /etc/unbound/log/;
+echo "Add logrotate config for unbound now..." +LOGROTATE=$(grep -A 1 '/var/log/unbound/unbound.log' /etc/logrotate.conf) +if [[ ! "${LOGROTATE}" ]]; then +cat >> /etc/logrotate.conf << "EOF" +# Unbound +/var/log/unbound/unbound.log { + daily + rotate 30 + copytruncate + compress + missingok + prerotate + /bin/mv -f /etc/unbound/log/unbound.log /var/log/unbound/unbound.log + /usr/sbin/unbound-control log_reopen &> /dev/null + endscript +}
+EOF +touch /etc/unbound/dhcpleases.conf +touch /var/log/unbound/unbound.log +chown unbound:unbound /var/log/unbound/unbound.log +fi
+# create link to current logfile +ln -svf /etc/unbound/log/unbound.log /var/log/unbound/current.log
+# create remote control key files and set rights +/usr/sbin/unbound-control-setup &> /dev/null +chown unbound:unbound /etc/unbound/{unbound_control.*,unbound_server.*,root.key,root.hints}
+# at last switch the DNS-Resolver to unbound +/usr/sbin/unbound-switch
+unset LOGROTATE +exit 0 diff --git a/src/paks/unbound/uninstall.sh b/src/paks/unbound/uninstall.sh new file mode 100644 index 0000000..fc39f9f --- /dev/null +++ b/src/paks/unbound/uninstall.sh @@ -0,0 +1,27 @@ +#!/bin/bash +############################################################################ +# # +# This file is part of the IPFire Firewall. # +# # +# IPFire is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +# IPFire is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with IPFire; if not, write to the Free Software # +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +# # +# Copyright (C) 2007 IPFire-Team info@ipfire.org. # +# # +############################################################################ +# +. /opt/pakfire/lib/functions.sh +/usr/sbin/resolver.sh +make_backup ${NAME} +remove_files diff --git a/src/paks/unbound/update.sh b/src/paks/unbound/update.sh new file mode 100644 index 0000000..89c40d0 --- /dev/null +++ b/src/paks/unbound/update.sh @@ -0,0 +1,26 @@ +#!/bin/bash +############################################################################ +# # +# This file is part of the IPFire Firewall. # +# # +# IPFire is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +# IPFire is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with IPFire; if not, write to the Free Software # +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +# # +# Copyright (C) 2007 IPFire-Team info@ipfire.org. # +# # +############################################################################ +# +. /opt/pakfire/lib/functions.sh +./uninstall.sh +./install.sh