mirror of
https://github.com/Luzifer/dns.git
synced 2024-12-22 10:51:20 +00:00
Move to bind instead of coredns
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
50b518bc8b
commit
38f960df77
9 changed files with 157 additions and 26 deletions
4
.dockerignore
Normal file
4
.dockerignore
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
zones/db.*
|
||||||
|
zones/named.conf
|
||||||
|
*.pyc
|
||||||
|
.venv
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,2 +1,2 @@
|
||||||
zones/db.*
|
zones/*
|
||||||
*.pyc
|
*.pyc
|
||||||
|
|
10
Corefile
10
Corefile
|
@ -1,10 +0,0 @@
|
||||||
. {
|
|
||||||
auto {
|
|
||||||
directory zones db\.(.*) {1} 10
|
|
||||||
reload 10s
|
|
||||||
upstream 8.8.8.8
|
|
||||||
}
|
|
||||||
|
|
||||||
errors
|
|
||||||
log
|
|
||||||
}
|
|
|
@ -2,13 +2,16 @@ FROM alpine
|
||||||
|
|
||||||
LABEL maintainer Knut Ahlers <knut@ahlers.me>
|
LABEL maintainer Knut Ahlers <knut@ahlers.me>
|
||||||
|
|
||||||
ADD . /src
|
COPY build.sh /src/
|
||||||
WORKDIR /src
|
COPY requirements.txt /src/
|
||||||
|
|
||||||
RUN set -ex \
|
RUN set -ex \
|
||||||
&& apk --no-cache add bash \
|
&& apk --no-cache add bash \
|
||||||
&& /src/build.sh
|
&& /src/build.sh
|
||||||
|
|
||||||
|
COPY . /src
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
EXPOSE 53/udp 53
|
EXPOSE 53/udp 53
|
||||||
|
|
||||||
VOLUME ["/src/zones"]
|
VOLUME ["/src/zones"]
|
||||||
|
@ -17,4 +20,4 @@ HEALTHCHECK --interval=30s --timeout=5s \
|
||||||
CMD dig +short @localhost health.server.test TXT || exit 1
|
CMD dig +short @localhost health.server.test TXT || exit 1
|
||||||
|
|
||||||
ENTRYPOINT ["/src/docker-entrypoint.sh"]
|
ENTRYPOINT ["/src/docker-entrypoint.sh"]
|
||||||
CMD ["coredns"]
|
CMD ["named", "-g"]
|
||||||
|
|
12
build.sh
12
build.sh
|
@ -5,19 +5,14 @@ set -euxo pipefail
|
||||||
apk --no-cache add curl
|
apk --no-cache add curl
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
apk --no-cache add python3 bind-tools
|
apk --no-cache add python3 bind-tools bind
|
||||||
|
|
||||||
# Get latest versions of tools using latestver
|
# Get latest versions of tools using latestver
|
||||||
COREDNS_VERSION=$(curl -sSfL 'https://lv.luzifer.io/catalog-api/coredns/latest.txt?p=version')
|
|
||||||
DUMB_INIT_VERSION=$(curl -sSfL 'https://lv.luzifer.io/catalog-api/dumb-init/latest.txt?p=version')
|
DUMB_INIT_VERSION=$(curl -sSfL 'https://lv.luzifer.io/catalog-api/dumb-init/latest.txt?p=version')
|
||||||
|
|
||||||
[ -z "${COREDNS_VERSION}" ] && { exit 1; }
|
|
||||||
[ -z "${DUMB_INIT_VERSION}" ] && { exit 1; }
|
[ -z "${DUMB_INIT_VERSION}" ] && { exit 1; }
|
||||||
|
|
||||||
# Install tools
|
# Install tools
|
||||||
curl -sSfL https://github.com/coredns/coredns/releases/download/v${COREDNS_VERSION}/coredns_${COREDNS_VERSION}_linux_amd64.tgz | \
|
|
||||||
tar -x -z -C /usr/local/bin
|
|
||||||
|
|
||||||
curl -sSfLo /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v${DUMB_INIT_VERSION}/dumb-init_${DUMB_INIT_VERSION}_amd64
|
curl -sSfLo /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v${DUMB_INIT_VERSION}/dumb-init_${DUMB_INIT_VERSION}_amd64
|
||||||
chmod +x /usr/local/bin/dumb-init
|
chmod +x /usr/local/bin/dumb-init
|
||||||
|
|
||||||
|
@ -25,9 +20,12 @@ chmod +x /usr/local/bin/dumb-init
|
||||||
pip3 install -r /src/requirements.txt
|
pip3 install -r /src/requirements.txt
|
||||||
|
|
||||||
# Create cron to update zones periodically
|
# Create cron to update zones periodically
|
||||||
echo "* * * * * run-parts /etc/periodic/1min" >> /var/spool/cron/crontabs/root
|
echo "* * * * * run-parts /etc/periodic/1min" >>/var/spool/cron/crontabs/root
|
||||||
mkdir -p /etc/periodic/1min
|
mkdir -p /etc/periodic/1min
|
||||||
ln -s /src/zonefile_cron /etc/periodic/1min/zonefile_cron
|
ln -s /src/zonefile_cron /etc/periodic/1min/zonefile_cron
|
||||||
|
|
||||||
|
# Link named.conf
|
||||||
|
ln -sf /src/zones/named.conf /etc/bind/named.conf
|
||||||
|
|
||||||
# Cleanup
|
# Cleanup
|
||||||
apk --no-cache del curl
|
apk --no-cache del curl
|
||||||
|
|
|
@ -1,12 +1,20 @@
|
||||||
#!/usr/local/bin/dumb-init /bin/bash
|
#!/usr/local/bin/dumb-init /bin/bash
|
||||||
set -euxo pipefail
|
set -euxo pipefail
|
||||||
|
|
||||||
if [ "${1:-}" = 'coredns' ]; then
|
# Ensure default config without zones
|
||||||
# Start crond in the background
|
[ -e /src/zones/named.conf ] || {
|
||||||
crond
|
cp /src/named.conf.default /src/zones/named.conf
|
||||||
|
}
|
||||||
|
|
||||||
# Start coredns
|
if [ "${1:-}" = 'named' ]; then
|
||||||
exec "$@"
|
# Generate rndc communication key
|
||||||
|
rndc-confgen -a
|
||||||
|
|
||||||
|
# Start crond in the background
|
||||||
|
crond
|
||||||
|
|
||||||
|
# Start coredns
|
||||||
|
exec "$@"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exec "$@"
|
exec "$@"
|
||||||
|
|
|
@ -5,6 +5,7 @@ import difflib
|
||||||
import hashlib
|
import hashlib
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
@ -20,6 +21,18 @@ import yaml
|
||||||
|
|
||||||
DEFAULT_TTL = 3600
|
DEFAULT_TTL = 3600
|
||||||
|
|
||||||
|
rndc_queue = []
|
||||||
|
|
||||||
|
|
||||||
|
def call_rndc(params):
|
||||||
|
command = ["rndc"]
|
||||||
|
command.extend(params)
|
||||||
|
|
||||||
|
if 'DEBUG' in os.environ and os.environ['DEBUG'] == 'true':
|
||||||
|
print('DBG: Call "{}"'.format(" ".join(command)))
|
||||||
|
else:
|
||||||
|
subprocess.check_call(command, stdout=sys.stdout, stderr=sys.stderr)
|
||||||
|
|
||||||
|
|
||||||
def default(d, key, default=None):
|
def default(d, key, default=None):
|
||||||
if key in d:
|
if key in d:
|
||||||
|
@ -41,6 +54,15 @@ def diff_files(file1, file2):
|
||||||
fromlines, tolines, file1, file2)))
|
fromlines, tolines, file1, file2)))
|
||||||
|
|
||||||
|
|
||||||
|
def exec_rndc_queue():
|
||||||
|
global rndc_queue
|
||||||
|
|
||||||
|
for params in rndc_queue:
|
||||||
|
call_rndc(params)
|
||||||
|
|
||||||
|
rndc_queue = []
|
||||||
|
|
||||||
|
|
||||||
def hash_file(filename):
|
def hash_file(filename):
|
||||||
if not os.path.isfile(filename):
|
if not os.path.isfile(filename):
|
||||||
return ""
|
return ""
|
||||||
|
@ -55,6 +77,12 @@ def hash_file(filename):
|
||||||
return hasher.hexdigest()
|
return hasher.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def queue_rndc_call(params):
|
||||||
|
global rndc_queue
|
||||||
|
|
||||||
|
rndc_queue.append(params)
|
||||||
|
|
||||||
|
|
||||||
def replace_soa_line(line):
|
def replace_soa_line(line):
|
||||||
if 'SOA' in line:
|
if 'SOA' in line:
|
||||||
return '; SOA line replaced'
|
return '; SOA line replaced'
|
||||||
|
@ -108,6 +136,25 @@ def sanitize(entry):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def write_named_conf(zones):
|
||||||
|
tpl = jinja2.Template(open("named.conf").read())
|
||||||
|
zone_content = tpl.render({
|
||||||
|
"zones": zones,
|
||||||
|
})
|
||||||
|
|
||||||
|
with open("zones/named.conf.new", "w") as f:
|
||||||
|
f.write(zone_content)
|
||||||
|
|
||||||
|
if hash_file("zones/named.conf.new") != hash_file("zones/named.conf"):
|
||||||
|
print("Generated and replaced named.conf")
|
||||||
|
diff_files("zones/named.conf", "zones/named.conf.new")
|
||||||
|
os.rename("zones/named.conf.new", "zones/named.conf")
|
||||||
|
|
||||||
|
queue_rndc_call(['reconfig'])
|
||||||
|
else:
|
||||||
|
os.unlink("zones/named.conf.new")
|
||||||
|
|
||||||
|
|
||||||
def write_zone(zone, ttl, soa, nameserver, mailserver, entries):
|
def write_zone(zone, ttl, soa, nameserver, mailserver, entries):
|
||||||
soa['serial'] = int(time.time()) - 946681200 # 2000-01-01
|
soa['serial'] = int(time.time()) - 946681200 # 2000-01-01
|
||||||
|
|
||||||
|
@ -128,6 +175,8 @@ def write_zone(zone, ttl, soa, nameserver, mailserver, entries):
|
||||||
print("Generated and replaced zone file for {}".format(zone))
|
print("Generated and replaced zone file for {}".format(zone))
|
||||||
diff_files("zones/db.{}".format(zone), "zones/tmp.{}".format(zone))
|
diff_files("zones/db.{}".format(zone), "zones/tmp.{}".format(zone))
|
||||||
os.rename("zones/tmp.{}".format(zone), "zones/db.{}".format(zone))
|
os.rename("zones/tmp.{}".format(zone), "zones/db.{}".format(zone))
|
||||||
|
|
||||||
|
queue_rndc_call(['reload', zone])
|
||||||
else:
|
else:
|
||||||
os.unlink("zones/tmp.{}".format(zone))
|
os.unlink("zones/tmp.{}".format(zone))
|
||||||
|
|
||||||
|
@ -143,6 +192,8 @@ def main():
|
||||||
consul_zones = consul.get_zones()
|
consul_zones = consul.get_zones()
|
||||||
zone_data['zones'] = {**consul_zones, **zone_data['zones']}
|
zone_data['zones'] = {**consul_zones, **zone_data['zones']}
|
||||||
|
|
||||||
|
write_named_conf(zone_data['zones'].keys())
|
||||||
|
|
||||||
for zone, config in zone_data['zones'].items():
|
for zone, config in zone_data['zones'].items():
|
||||||
ttl = default(config, "default_ttl", DEFAULT_TTL)
|
ttl = default(config, "default_ttl", DEFAULT_TTL)
|
||||||
|
|
||||||
|
@ -161,6 +212,8 @@ def main():
|
||||||
write_zone(zone, ttl, zone_data['soa'],
|
write_zone(zone, ttl, zone_data['soa'],
|
||||||
zone_data['nameserver'], mailserver, entries)
|
zone_data['nameserver'], mailserver, entries)
|
||||||
|
|
||||||
|
exec_rndc_queue()
|
||||||
|
|
||||||
healthcheck()
|
healthcheck()
|
||||||
|
|
||||||
|
|
||||||
|
|
41
named.conf
Normal file
41
named.conf
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
include "/etc/bind/rndc.key";
|
||||||
|
|
||||||
|
controls {
|
||||||
|
inet 127.0.0.1 port 953
|
||||||
|
allow { 127.0.0.1; } keys { "rndc-key"; };
|
||||||
|
};
|
||||||
|
|
||||||
|
options {
|
||||||
|
directory "/var/bind";
|
||||||
|
|
||||||
|
// Configure the IPs to listen on here.
|
||||||
|
listen-on { any; };
|
||||||
|
listen-on-v6 { none; };
|
||||||
|
|
||||||
|
// Specify a list of IPs/masks to allow zone transfers to here.
|
||||||
|
//
|
||||||
|
// You can override this on a per-zone basis by specifying this inside a zone
|
||||||
|
// block.
|
||||||
|
//
|
||||||
|
// Warning: Removing this block will cause BIND to revert to its default
|
||||||
|
// behaviour of allowing zone transfers to any host (!).
|
||||||
|
allow-transfer {
|
||||||
|
none;
|
||||||
|
};
|
||||||
|
|
||||||
|
// If you have problems and are behind a firewall:
|
||||||
|
//query-source address * port 53;
|
||||||
|
|
||||||
|
pid-file "/var/run/named/named.pid";
|
||||||
|
|
||||||
|
allow-recursion { none; };
|
||||||
|
recursion no;
|
||||||
|
querylog yes;
|
||||||
|
};
|
||||||
|
{% for zone in zones %}
|
||||||
|
zone "{{ zone }}" IN {
|
||||||
|
type master;
|
||||||
|
file "/src/zones/db.{{ zone }}";
|
||||||
|
};
|
||||||
|
{% endfor %}
|
||||||
|
|
34
named.conf.default
Normal file
34
named.conf.default
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
include "/etc/bind/rndc.key";
|
||||||
|
|
||||||
|
controls {
|
||||||
|
inet 127.0.0.1 port 953
|
||||||
|
allow { 127.0.0.1; } keys { "rndc-key"; };
|
||||||
|
};
|
||||||
|
|
||||||
|
options {
|
||||||
|
directory "/var/bind";
|
||||||
|
|
||||||
|
// Configure the IPs to listen on here.
|
||||||
|
listen-on { any; };
|
||||||
|
listen-on-v6 { none; };
|
||||||
|
|
||||||
|
// Specify a list of IPs/masks to allow zone transfers to here.
|
||||||
|
//
|
||||||
|
// You can override this on a per-zone basis by specifying this inside a zone
|
||||||
|
// block.
|
||||||
|
//
|
||||||
|
// Warning: Removing this block will cause BIND to revert to its default
|
||||||
|
// behaviour of allowing zone transfers to any host (!).
|
||||||
|
allow-transfer {
|
||||||
|
none;
|
||||||
|
};
|
||||||
|
|
||||||
|
// If you have problems and are behind a firewall:
|
||||||
|
//query-source address * port 53;
|
||||||
|
|
||||||
|
pid-file "/var/run/named/named.pid";
|
||||||
|
|
||||||
|
allow-recursion { none; };
|
||||||
|
recursion no;
|
||||||
|
querylog yes;
|
||||||
|
};
|
Loading…
Reference in a new issue