initial commit

This commit is contained in:
Daniel Sommer 2023-10-20 13:06:49 +02:00
commit 9cd32903bc
13 changed files with 522 additions and 0 deletions

2
.dockerignore Normal file
View file

@ -0,0 +1,2 @@
build
docker-compose.yml

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
build
unbound/src/*

28
Dockerfile Normal file
View file

@ -0,0 +1,28 @@
FROM alpine:latest
LABEL version="1.0.0" \
author="Daniel Sommer <daniel.sommer@velvettear.de>" \
license="MIT"
MAINTAINER Daniel Sommer <daniel.sommer@nux.de>
ENV VERSION=
COPY [ "unbound", "/tmp/unbound" ]
RUN apk upgrade --no-cache --progress \
&& apk add --no-cache --progress \
alpine-sdk \
dnssec-root \
expat-dev \
libevent-dev \
linux-headers \
openssl-dev \
protobuf-c-dev \
python3-dev \
swig \
hiredis-dev \
bind-tools \
ldns-tools
ENTRYPOINT ["/tmp/unbound/build.sh"]

20
LICENSE.md Normal file
View file

@ -0,0 +1,20 @@
# MIT License
**Copyright (c) 2022 Daniel Sommer \<daniel.sommer@velvettear.de\>**
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
**THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.**

6
README.md Normal file
View file

@ -0,0 +1,6 @@
# unbound-redis-apk
build .apk files for [unbound](https://nlnetlabs.nl/projects/unbound) with support for as cache backend [redis](https://redis.io) for [alpine linux](https://alpinelinux.org/).
**installation on alpine linux:**
`apk add --no-cache --allow-untrusted <package>.apk`

11
docker-compose.yml Normal file
View file

@ -0,0 +1,11 @@
version: "3"
services:
builder:
container_name: "unbound-redis-apk-builder"
build: "."
environment:
- VERSION=
volumes:
- /etc/resolv.conf:/etc/resolv.conf:ro
- ./build:/build

116
unbound/APKBUILD Normal file
View file

@ -0,0 +1,116 @@
# Contributor: Sören Tempel <soeren+alpine@soeren-tempel.net>
# Contributor: Carlo Landmeter <clandmeter@alpinelinux.org>
# Contributor: Natanael Copa <ncopa@alpinelinux.org>
# Maintainer: Jakub Jirutka <jakub@jirutka.cz>
pkgname=unbound
pkgver=0.0.0
pkgrel=0
pkgdesc="Unbound is a validating, recursive, and caching DNS resolver"
url="https://nlnetlabs.nl/projects/unbound/about/"
arch="all"
license="BSD-3-Clause"
depends="dnssec-root"
depends_dev="expat-dev"
_depends_migrate="
/bin/sh
apk-tools
openrc
"
makedepends="$depends_dev
libevent-dev
linux-headers
openssl-dev>3
protobuf-c-dev
python3-dev
swig
"
checkdepends="
bind-tools
ldns-tools
"
install="$pkgname.pre-install"
pkgusers="unbound"
pkggroups="unbound"
subpackages="
$pkgname-dbg
$pkgname-dev
$pkgname-doc
$pkgname-libs
$pkgname-openrc
py-unbound:py
$pkgname-migrate::noarch
"
source="https://unbound.net/downloads/unbound-$pkgver.tar.gz
conf.patch
migrate-dnscache-to-unbound
$pkgname.initd
$pkgname.confd
"
build() {
export CFLAGS="$CFLAGS -flto=auto"
PYTHON_VERSION=3 ./configure \
--build="$CBUILD" \
--host="$CHOST" \
--prefix=/usr \
--sysconfdir=/etc \
--mandir=/usr/share/man \
--localstatedir=/var \
--with-username=unbound \
--with-run-dir="" \
--with-pidfile="" \
--with-rootkey-file=/usr/share/dnssec-root/trusted-key.key \
--with-libevent \
--with-pthreads \
--disable-static \
--disable-rpath \
--enable-dnstap \
--with-ssl \
--without-pythonmodule \
--with-pyunbound \
--with-libhiredis \
--enable-cachedb
# do not link to libpython
sed -i -e '/^LIBS=/s/-lpython.*[[:space:]]/ /' Makefile
make
}
check() {
make test
}
package() {
make DESTDIR="$pkgdir" install
make DESTDIR="$pkgdir" unbound-event-install
install -Dm755 contrib/update-anchor.sh \
"$pkgdir"/usr/share/$pkgname/update-anchor.sh
install -D -m644 doc/CREDITS doc/Changelog doc/FEATURES \
doc/README doc/TODO -t "$pkgdir"/usr/share/doc/$pkgname/
cd "$pkgdir"
install -Dm755 "$srcdir"/unbound.initd ./etc/init.d/unbound
install -Dm644 "$srcdir"/unbound.confd ./etc/conf.d/unbound
}
py() {
pkgdesc="Python bindings to libunbound"
depends="$depends_py"
amove usr/lib/python*
}
migrate() {
pkgdesc="Simple tool to migrate from dnscache to unbound"
depends="$_depends_migrate"
install -m755 -D "$srcdir"/migrate-dnscache-to-unbound \
"$subpkgdir"/usr/bin/migrate-dnscache-to-unbound
}
sha512sums=""

78
unbound/build.sh Executable file
View file

@ -0,0 +1,78 @@
#!/usr/bin/env sh
# exit on error
set -e
# variables
unbound_dir="/tmp/unbound"
src_dir="$unbound_dir/src"
# functions
function checkEnvironment() {
[[ -n "$VERSION" ]] && return
printf "environment variable 'VERSION' is unset, defaulting to 'latest'...\n"
VERSION="latest"
}
function checkAndExtractArchive() {
cd "$src_dir"
archive="$(find "$src_dir" -type f -iname 'unbound*.tar.gz' -exec basename {} \;)"
[[ -n "$archive" ]] && tar -xzf "$archive" && rm -f "$archive" && return
archive="$(find "$src_dir" -type f -iname 'unbound*.zip' -exec basename {} \;)"
[[ -z "$archive" ]] && return
unzip -q "$archive" -d "$(basename -s ".zip" $archive)" && rm -f "$archive"
}
function getPkgVersion() {
pkgver="$(find "$src_dir" -type d -iname 'unbound*' -exec sh -c "realpath {} | cut -d "-" -f2" \;)"
}
function downloadSources() {
mkdir -p "$src_dir"
cd "$src_dir"
wget "https://nlnetlabs.nl/downloads/unbound/unbound-$VERSION.tar.gz"
tar -xzf "unbound-$VERSION.tar.gz"
rm -f "unbound-$VERSION.tar.gz"
}
# main routine
printf "starting build process for unbound with redis support...\n"
# check if an archive is in "$src_dir" present and extract it
checkAndExtractArchive
# check if a valid version has been copied to "$src_dir"
getPkgVersion
# if no valid version could be found, start a download
if [[ -z "$pkgver" ]]; then
checkEnvironment
downloadSources
getPkgVersion
fi
# exit if no unbound version could be determined
[[ -z "$pkgver" ]] && printf "error: could not determine unbound version\n" && exit 1
# replace version in APKBUILD file
sed -i "s/pkgver=0.0.0/pkgver=$pkgver/" "$unbound_dir/APKBUILD"
# generate key pairs
printf "\n" | abuild-keygen -a
# generate checksums and start the build
cd "$unbound_dir"
abuild -F checksum
abuild -F -r
# move the built packages
[[ ! -d "/build" ]] && mkdir -p "/build"
rm -rf "/build/"*
find $HOME/packages -type f -iname '*.apk' -exec mv {} /build \;
# clean up
rm -rf "$unbound_dir"
printf ".apk files can be found at '/build'\n"
cd "/build"
ls -1

46
unbound/conf.patch Normal file
View file

@ -0,0 +1,46 @@
diff -upr unbound-1.13.0.orig/doc/example.conf.in unbound-1.13.0/doc/example.conf.in
--- unbound-1.13.0.orig/doc/example.conf.in 2020-12-21 09:58:04.154390497 +0100
+++ unbound-1.13.0/doc/example.conf.in 2020-12-21 09:58:53.094583255 +0100
@@ -355,9 +355,6 @@ server:
# print log lines that say why queries return SERVFAIL to clients.
# log-servfail: no
- # the pid file. Can be an absolute path outside of chroot/work dir.
- # pidfile: "@UNBOUND_PIDFILE@"
-
# file to read root hints from.
# get one from https://www.internic.net/domain/named.cache
# root-hints: ""
@@ -507,7 +504,7 @@ server:
# you start unbound (i.e. in the system boot scripts). And enable:
# Please note usage of unbound-anchor root anchor is at your own risk
# and under the terms of our LICENSE (see that file in the source).
- # auto-trust-anchor-file: "@UNBOUND_ROOTKEY_FILE@"
+ # auto-trust-anchor-file: ""
# trust anchor signaling sends a RFC8145 key tag query after priming.
# trust-anchor-signaling: yes
@@ -519,7 +516,7 @@ server:
# with several entries, one file per entry.
# Zone file format, with DS and DNSKEY entries.
# Note this gets out of date, use auto-trust-anchor-file please.
- # trust-anchor-file: ""
+ trust-anchor-file: "@UNBOUND_ROOTKEY_FILE@"
# Trusted key for validation. DS or DNSKEY. specify the RR on a
# single line, surrounded by "". TTL is ignored. class is IN default.
@@ -900,12 +897,13 @@ dynlib:
remote-control:
# Enable remote control with unbound-control(8) here.
# set up the keys and certificates with unbound-control-setup.
- # control-enable: no
+ control-enable: yes
# what interfaces are listened to for remote control.
# give 0.0.0.0 and ::0 to listen to all interfaces.
# set to an absolute path to use a unix local name pipe, certificates
# are not used for that, so key and cert files need not be present.
+ control-interface: /run/unbound.control.sock
# control-interface: 127.0.0.1
# control-interface: ::1

View file

@ -0,0 +1,147 @@
#!/bin/sh
to_subnet() {
pref=$1
case "$pref" in
*.*.*.*) echo $pref/32;;
*.*.*) echo $pref.0/24;;
*.*) echo $pref.0.0/16;;
*) echo $pref.0.0.0/8;;
esac
}
gen_config() {
echo "# Config generated by $0, $(date)"
echo "server:"
[ -n "$IP" ] && echo -e "\tinterface: $IP\n"
[ -n "$IPSEND" ] && echo -e "\toutgoing-interface: $IPSEND\n"
for i in $access_control; do
echo -e "\taccess-control: $i allow"
done
echo ""
# stub zones
local zonefile ip
local fwdtype="stub"
if [ -n "$FORWARDONLY" ]; then
fwdtype="forward"
fi
for zonefile in "$root"/etc/dnscache/servers/*; do
local zone=${zonefile##*/}
case "$zone" in
'@'|'*'|*.apk-new) continue;;
esac
echo "${fwdtype}-zone:"
echo -e "\tname: ${zone}"
for ip in $(cat $zonefile); do
echo -e "\t${fwdtype}-addr: $ip"
done
echo ""
done
}
usage() {
cat >&2 <<EOF
usage: $0 [-h] [-r ROOT]
Migrate dnscache configuration to unbound
This tool will install unbound, migrate the configuration, stop dnscache
and start unbound and remove traces of dnscache.
Options:
-c Only dump the config to stdout and exit
-h Show this help
-k Keep unbound.conf.backup and keep dnscache config
-r Look for dnscache config in ROOT/etc/dnscache
EOF
}
root=${ROOT:-/}
dump_config=false
quiet=false
keep_backup=false
while getopts "chr:" opt; do
case "$opt" in
'c') dump_config=true;;
'h') usage; exit;;
'k') keep_backup=true;;
'r') root="$OPTARG";;
'q') quiet=true; quiet_opt=--quiet;;
esac
done
unbound_conf=${UNBOUND_CONF:-${root%/}/etc/unbound/unbound.conf}
# read dnscache config
if ! [ -f "$root"/etc/conf.d/dnscache ] && ! [ -d "$root"/etc/dnscache ]; then
echo "No dnscache config found"
exit 1
fi
confd="$root"/etc/conf.d/dnscache
if [ -r "$confd" ]; then
. "$confd"
fi
interface="$IP"
outgoing_interface="$IPSEND"
for i in "$root"/etc/dnscache/ip/*; do
[ -f "$i" ] || continue
access_control="$access_control $(to_subnet ${i##*/})"
done
if $dump_config; then
gen_config
exit 0
fi
# install unbound if needed
if ! apk info -e unbound; then
apk add $quiet_opt unbound
fi
# generate config
if [ -f "$unbound_conf" ]; then
$quiet || echo "Backing up $unbound_conf" >&2
mv "$unbound_conf" "${unbound_conf}".backup
fi
$quiet || echo "Generating $unbound_conf" >&2
gen_config > "$unbound_conf"
# stop dnscache and start unbound
if /etc/init.d/dnscache --quiet status 2>/dev/null; then
/etc/init.d/dnscache $quiet_opt stop
if ! /etc/init.d/unbound $quiet_opt start; then
echo "Failed to start unbound. Starting up dnscache again"
/etc/init.d/dnscache $quiet_opt start
exit 1
fi
fi
# update runlevels
errors=0
if rc-update | grep -q -w dnscache; then
runlevels=$(rc-update | awk '$1 == "dnscache" { FS="|"; $0 = $0; print $2 }')
for level in $runlevels; do
rc-update $quiet_opt add unbound $level \
|| errors=$(($errors + 1))
rc-update $quiet_opt del dnscache $level \
|| errors=$(($errors + 1))
done
fi
# cleanup if requested
if [ $errors -eq 0 ] && ! $keep_backup ; then
$quiet || echo "Purging dnscache and dnscache config" >&2
apk del --purge $quiet_opt dnscache
rm -rf $root/etc/dnscache $root/etc/conf.d/dnscache
$quiet || echo "Purging ${unbound_conf}.backup" >&2
rm -rf ${unbound_conf}.backup
fi
exit $errors

11
unbound/unbound.confd Normal file
View file

@ -0,0 +1,11 @@
# Configuration for /etc/init.d/unbound
# Path of the configuration file.
#cfgfile="/etc/unbound/$RC_SVCNAME.conf"
# Additional arguments for the unbound command.
# Add "-v" to enable verbose logging (more times to increase verbosity).
#command_args=""
# Uncomment to use process supervisor.
#supervisor=supervise-daemon

48
unbound/unbound.initd Normal file
View file

@ -0,0 +1,48 @@
#!/sbin/openrc-run
extra_commands="checkconfig"
extra_started_commands="reload"
name="unbound daemon"
description="unbound is a Domain Name Server (DNS) that is used to resolve host names to IP address."
description_checkconfig="Run syntax tests for configuration files only."
description_reload="Kills all children and reloads the configuration."
# Upper case variables are here only for backward compatibility.
: ${cfgfile:=${UNBOUND_CONFFILE:-/etc/unbound/$RC_SVCNAME.conf}}
command=/usr/sbin/unbound
command_args="-d $command_args"
command_background=yes
pidfile="/run/$RC_SVCNAME.pid"
required_files="$cfgfile"
depend() {
need net
use logger
provide dns
after auth-dns entropy
}
checkconfig() {
ebegin "Checking $cfgfile"
/usr/sbin/unbound-checkconf -f "$cfgfile" >/dev/null
eend $?
}
start_pre() {
checkconfig
}
reload() {
start_pre || return $?
ebegin "Reloading $name"
if [ "$supervisor" ]; then
$supervisor "$RC_SVCNAME" --signal HUP
else
start-stop-daemon --signal HUP --pidfile "$pidfile"
fi
eend $?
}

View file

@ -0,0 +1,7 @@
#!/bin/sh
addgroup -S unbound 2>/dev/null
adduser -S -D -H -h /etc/unbound -s /sbin/nologin -G unbound \
-g "Unbound user" unbound 2>/dev/null
exit 0