Add dns, dyndns services
This commit is contained in:
parent
e346c558ea
commit
d1b0579a41
6 changed files with 716 additions and 0 deletions
91
dns.yml
Normal file
91
dns.yml
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
- name: Setup subdomain A records pointing to wendelstein
|
||||
inwx:
|
||||
domain: "{{item.partition('.')[2]}}"
|
||||
record: "{{item.partition('.')[0]}}"
|
||||
type: A
|
||||
value: "{{ hostvars['wendelstein']['ansible_default_ipv4']['address'] }}"
|
||||
loop: "{{subdomains}}"
|
||||
|
||||
- name: Setup dyndns A record
|
||||
inwx:
|
||||
domain: jaseg.de
|
||||
record: ns
|
||||
type: A
|
||||
value: "{{ hostvars['wendelstein']['ansible_default_ipv4']['address'] }}"
|
||||
|
||||
- name: Setup dyndns NS record
|
||||
inwx:
|
||||
domain: jaseg.de
|
||||
record: dyn
|
||||
type: NS
|
||||
value: 'ns.jaseg.de'
|
||||
|
||||
- name: Setup subdomain AAAA records pointing to wendelstein
|
||||
inwx:
|
||||
domain: "{{item.partition('.')[2]}}"
|
||||
record: "{{item.partition('.')[0]}}"
|
||||
type: AAAA
|
||||
value: "{{ hostvars['wendelstein']['ansible_default_ipv6']['address'] }}"
|
||||
loop: "{{subdomains}}"
|
||||
|
||||
- name: Setup jaseg.net subdomain MX records pointing to fastmail
|
||||
inwx:
|
||||
domain: "{{item.partition('.')[2]}}"
|
||||
record: "{{item.partition('.')[0]}}"
|
||||
type: MX
|
||||
priority: 10
|
||||
value: in1-smtp.messagingengine.com
|
||||
loop: "{{subdomains}}"
|
||||
|
||||
- name: Setup jaseg.net subdomain MX records pointing to fastmail
|
||||
inwx:
|
||||
domain: "{{item.partition('.')[2]}}"
|
||||
record: "{{item.partition('.')[0]}}"
|
||||
type: MX
|
||||
priority: 20
|
||||
value: in2-smtp.messagingengine.com
|
||||
loop: "{{subdomains}}"
|
||||
|
||||
- name: Setup sendgrid gateway
|
||||
inwx:
|
||||
domain: jaseg.de
|
||||
type: CNAME
|
||||
record: "{{item.split(' ')[0]}}"
|
||||
value: "{{item.split(' ')[1]}}"
|
||||
loop:
|
||||
- em6100.automation u14518136.wl137.sendgrid.net
|
||||
- s1._domainkey.automation s1.domainkey.u14518136.wl137.sendgrid.net
|
||||
- s2._domainkey.automation s2.domainkey.u14518136.wl137.sendgrid.net
|
||||
|
||||
- name: Set fastmail DNS entry template
|
||||
set_fact:
|
||||
fastmail_dns_entries:
|
||||
- {rtype: MX, record: ".", prio: 10, value: in1-smtp.messagingengine.com}
|
||||
- {rtype: MX, record: ".", prio: 20, value: in2-smtp.messagingengine.com}
|
||||
- {rtype: MX, record: "*", prio: 10, value: in1-smtp.messagingengine.com}
|
||||
- {rtype: MX, record: "*", prio: 20, value: in2-smtp.messagingengine.com}
|
||||
- {rtype: TXT, record: ".", value: "v=spf1 include:spf.messagingengine.com ?all"}
|
||||
- {rtype: CNAME, record: mesmtp._domainkey, value: mesmtp.jaseg.de.dkim.fmhosted.com}
|
||||
- {rtype: CNAME, record: fm1._domainkey, value: fm1.jaseg.de.dkim.fmhosted.com}
|
||||
- {rtype: CNAME, record: fm2._domainkey, value: fm2.jaseg.de.dkim.fmhosted.com}
|
||||
- {rtype: CNAME, record: fm3._domainkey, value: fm3.jaseg.de.dkim.fmhosted.com}
|
||||
- {rtype: SRV, record: _submission._tcp, prio: 0, weight: 1, port: 587, value: smtp.fastmail.com}
|
||||
- {rtype: SRV, record: _imap._tcp, prio: 0, weight: 0, port: 0, value: "."}
|
||||
- {rtype: SRV, record: _imaps._tcp, prio: 0, weight: 1, port: 993, value: imap.fastmail.com}
|
||||
- {rtype: SRV, record: _pop3._tcp, prio: 0, weight: 0, port: 0, value: "."}
|
||||
- {rtype: SRV, record: _pop3s._tcp, prio: 10, weight: 1, port: 995, value: pop.fastmail.com}
|
||||
- {rtype: SRV, record: _jmap._tcp, prio: 0, weight: 1, port: 443, value: jmap.fastmail.com}
|
||||
- {rtype: SRV, record: _carddav._tcp, prio: 0, weight: 0, port: 0, value: "."}
|
||||
- {rtype: SRV, record: _carddavs._tcp, prio: 0, weight: 1, port: 443, value: carddav.fastmail.com}
|
||||
|
||||
- name: Setup fastmail DNS entries
|
||||
inwx:
|
||||
domain: "{{ item[1] }}"
|
||||
type: "{{ item[0]['rtype'] }}"
|
||||
record: "{{ item[0]['record'] | regex_replace('\\.*$', '') }}"
|
||||
priority: "{{ item[0].get('prio') | int }}"
|
||||
port: "{{ item[0].get('port') | int}}"
|
||||
weight: "{{ item[0].get('weight') | int }}"
|
||||
value: "{{ item[0]['value'] }}"
|
||||
loop: "{{ fastmail_dns_entries | product(fastmail_domains) | list }}"
|
||||
|
||||
149
dyndns.py
Normal file
149
dyndns.py
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import time
|
||||
from contextlib import contextmanager
|
||||
import re
|
||||
import os
|
||||
import os.path
|
||||
import random
|
||||
import string
|
||||
import subprocess
|
||||
import sqlite3
|
||||
import hmac
|
||||
from ipaddress import IPv4Address, IPv6Address
|
||||
|
||||
from flask import Flask, request, abort
|
||||
import uwsgidecorators
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config.update(dict(
|
||||
RECORD_EXPIRY_S = 86400,
|
||||
NSD_CONTROL = 'nsd-control'
|
||||
))
|
||||
app.config.from_pyfile('config.py')
|
||||
|
||||
|
||||
ZONEFILE_TEMPLATE = '''\
|
||||
; #################################################### ;
|
||||
; THIS FILE IS AUTOMATICALLY GENERATED! DO NOT MODIFY! ;
|
||||
; #################################################### ;
|
||||
|
||||
$ORIGIN {zone}.
|
||||
$TTL 1800
|
||||
@ IN SOA {ns}. {mail}. (
|
||||
{serial} ; serial number
|
||||
60 ; refresh
|
||||
60 ; retry
|
||||
{expire} ; expire
|
||||
60 ; ttl
|
||||
)
|
||||
; Name servers
|
||||
IN NS {ns}.
|
||||
|
||||
; Additional A records from template
|
||||
; @ IN A 192.0.2.3
|
||||
; www IN A 192.0.2.3
|
||||
|
||||
; Dynamically generated records
|
||||
{dynamic_records}
|
||||
'''
|
||||
|
||||
db = sqlite3.connect(app.config['SQLITE_DB'], check_same_thread=False)
|
||||
with db as conn:
|
||||
conn.execute('''CREATE TABLE IF NOT EXISTS zone_versions (date TEXT)''')
|
||||
conn.execute('''CREATE TABLE IF NOT EXISTS records
|
||||
(name TEXT PRIMARY KEY, ipv4 TEXT, ipv6 TEXT, last_update INTEGER)''')
|
||||
|
||||
def purge_expired_records():
|
||||
with db as conn:
|
||||
conn.execute('DELETE FROM records WHERE last_update < ?',
|
||||
(int(time.time()) - app.config['RECORD_EXPIRY_S'],))
|
||||
|
||||
def update_record(record, ipv4=None, ipv6=None):
|
||||
with db as conn:
|
||||
old_v4, old_v6 = conn.execute('SELECT ipv4, ipv6 FROM records WHERE name=?', (record,)).fetchone() or (None, None)
|
||||
conn.execute('INSERT OR REPLACE INTO records VALUES (?, ?, ?, ?)', (record, ipv4, ipv6, int(time.time())))
|
||||
return ipv4 != old_v4 or ipv6 != old_v6
|
||||
|
||||
@contextmanager
|
||||
def inplace_rewrite(filename, cleanup=True):
|
||||
print('Writing', filename)
|
||||
filename = os.path.abspath(filename)
|
||||
if cleanup:
|
||||
basename = os.path.basename(filename)
|
||||
for entry in os.scandir(os.path.dirname(filename)):
|
||||
if entry.name.startswith(basename) and re.match(r'\.tmp-[a-zA-Z0-9]{8}', entry.name[len(basename):]):
|
||||
os.remove(entry.path)
|
||||
|
||||
tmp_fn = filename + f'.tmp-' + ''.join(random.choices(string.ascii_letters + string.digits, k=8))
|
||||
with open(tmp_fn, 'w') as tmp_f:
|
||||
yield tmp_f
|
||||
tmp_f.flush()
|
||||
os.fsync(tmp_f.fileno())
|
||||
os.rename(tmp_fn, filename)
|
||||
|
||||
def write_zonefile():
|
||||
# Find the next free zonefile version number
|
||||
with db as conn:
|
||||
conn.execute('INSERT INTO zone_versions VALUES (DATE())')
|
||||
date, version_num, = conn.execute('SELECT zone_versions.date, COUNT(*) FROM zone_versions WHERE zone_versions.date = DATE()').fetchone()
|
||||
zone_version = f'{date.replace("-", "")}{version_num:02d}'
|
||||
|
||||
# Generate dynamic record block
|
||||
with db as conn:
|
||||
records = db.execute('SELECT name, "A", ipv4 FROM records UNION SELECT name, "AAAA", ipv6 FROM records')
|
||||
dynamic_records = '\n'.join(f'{name:<20} IN {rtype:<4} {value}' for name, rtype, value in records if value is not None)
|
||||
|
||||
# Template zone file content
|
||||
content = ZONEFILE_TEMPLATE.format(
|
||||
zone = app.config['ZONE'],
|
||||
ns = app.config['NAMESERVER'],
|
||||
mail = app.config['NAMESERVER_MAIL'].replace('@', '.'),
|
||||
serial = zone_version,
|
||||
dynamic_records = dynamic_records,
|
||||
expire = app.config['RECORD_EXPIRY_S']
|
||||
)
|
||||
|
||||
with inplace_rewrite(app.config['ZONEFILE'], cleanup=True) as f:
|
||||
f.write(content)
|
||||
|
||||
def kick_nsd():
|
||||
prog = app.config['NSD_CONTROL']
|
||||
if isinstance(prog, str):
|
||||
prog = [prog]
|
||||
subprocess.run([*prog, 'reload', app.config['ZONE']], check=True)
|
||||
|
||||
@app.before_first_request
|
||||
@uwsgidecorators.timer(300)
|
||||
def update_zonefile():
|
||||
purge_expired_records()
|
||||
write_zonefile()
|
||||
kick_nsd()
|
||||
|
||||
@app.route('/update', methods=['POST'])
|
||||
def route_update():
|
||||
if request.authorization is None:
|
||||
abort(403)
|
||||
|
||||
record = request.authorization['username']
|
||||
record_config = app.config['DYNAMIC_RECORDS'].get(record)
|
||||
if record_config is None:
|
||||
abort(403)
|
||||
|
||||
*supported_formats, password = record_config
|
||||
if not hmac.compare_digest(request.authorization['password'], password):
|
||||
abort(403)
|
||||
|
||||
ipv4 = request.args.get('ipv4', '127.0.0.1')
|
||||
ipv6 = request.args.get('ipv6', '::1')
|
||||
ipv4 = str(IPv4Address(ipv4)) if 'v4' in supported_formats else None
|
||||
ipv6 = str(IPv6Address(ipv6)) if 'v6' in supported_formats else None
|
||||
if update_record(record, ipv4=ipv4, ipv6=ipv6):
|
||||
update_zonefile()
|
||||
|
||||
return 'success'
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
||||
|
||||
14
dyndns_config.py.j2
Normal file
14
dyndns_config.py.j2
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
SQLITE_DB = '{{dyndns_sqlite_dbfile}}'
|
||||
|
||||
NAMESERVER = 'ns.jaseg.de'
|
||||
NAMESERVER_MAIL = 'dns@jaseg.de'
|
||||
ZONEFILE = 'dyn.jaseg.de.zone'
|
||||
ZONE = 'dyn.jaseg.de'
|
||||
NSD_CONTROL = 'sudo -u nsd nsd-control'.split()
|
||||
|
||||
DYNAMIC_RECORDS = {
|
||||
'bigdata': ('v6', '{{ lookup('password', 'dyndns_secret_bigdata.txt length=32') }}'),
|
||||
'raspi': ('v6', '{{ lookup('password', 'dyndns_secret_raspi.txt length=32') }}'),
|
||||
}
|
||||
|
||||
372
nsd.conf
Normal file
372
nsd.conf
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
#
|
||||
# nsd.conf -- the NSD(8) configuration file, nsd.conf(5).
|
||||
#
|
||||
# Copyright (c) 2001-2011, NLnet Labs. All rights reserved.
|
||||
#
|
||||
# See LICENSE for the license.
|
||||
#
|
||||
|
||||
# This is a comment.
|
||||
# Sample configuration file
|
||||
# include: "file" # include that file's text over here. Globbed, "*.conf"
|
||||
|
||||
# options for the nsd server
|
||||
server:
|
||||
# Number of NSD servers to fork. Put the number of CPUs to use here.
|
||||
server-count: 1
|
||||
|
||||
# uncomment to specify specific interfaces to bind (default are the
|
||||
# wildcard interfaces 0.0.0.0 and ::0).
|
||||
# For servers with multiple IP addresses, list them one by one,
|
||||
# or the source address of replies could be wrong.
|
||||
# Use ip-transparent to be able to list addresses that turn on later.
|
||||
# ip-address: 1.2.3.4
|
||||
# ip-address: 1.2.3.4@5678
|
||||
# ip-address: 12fe::8ef0
|
||||
|
||||
# Allow binding to non local addresses. Default no.
|
||||
# ip-transparent: no
|
||||
|
||||
# Allow binding to addresses that are down. Default no.
|
||||
# ip-freebind: no
|
||||
|
||||
# use the reuseport socket option for performance. Default no.
|
||||
reuseport: yes
|
||||
|
||||
# override maximum socket send buffer size. Default of 0 results in
|
||||
# send buffer size being set to 1048576 (bytes).
|
||||
# send-buffer-size: 1048576
|
||||
|
||||
# override maximum socket receive buffer size. Default of 0 results in
|
||||
# receive buffer size being set to 1048576 (bytes).
|
||||
# receive-buffer-size: 1048576
|
||||
|
||||
# enable debug mode, does not fork daemon process into the background.
|
||||
# debug-mode: no
|
||||
|
||||
# listen on IPv4 connections
|
||||
# do-ip4: yes
|
||||
|
||||
# listen on IPv6 connections
|
||||
# do-ip6: yes
|
||||
|
||||
# port to answer queries on. default is 53.
|
||||
# port: 53
|
||||
|
||||
# Verbosity level.
|
||||
# verbosity: 0
|
||||
|
||||
# After binding socket, drop user privileges.
|
||||
# can be a username, id or id.gid.
|
||||
# username: nsd
|
||||
|
||||
# Run NSD in a chroot-jail.
|
||||
# make sure to have pidfile and database reachable from there.
|
||||
# by default, no chroot-jail is used.
|
||||
# chroot: "/etc/nsd"
|
||||
|
||||
# The directory for zonefile: files. The daemon chdirs here.
|
||||
zonesdir: "/etc/nsd"
|
||||
|
||||
# the list of dynamically added zones.
|
||||
# zonelistfile: "/var/lib/nsd/zone.list"
|
||||
|
||||
# the database to use
|
||||
# if set to "" then no disk-database is used, less memory usage.
|
||||
database: ""
|
||||
|
||||
# log messages to file. Default to stderr and syslog (with
|
||||
# facility LOG_DAEMON). stderr disappears when daemon goes to bg.
|
||||
# logfile: "/var/log/nsd.log"
|
||||
|
||||
# File to store pid for nsd in.
|
||||
# pidfile: "/run/nsd/nsd.pid"
|
||||
|
||||
# The file where secondary zone refresh and expire timeouts are kept.
|
||||
# If you delete this file, all secondary zones are forced to be
|
||||
# 'refreshing' (as if nsd got a notify). Set to "" to disable.
|
||||
# xfrdfile: "/var/lib/nsd/ixfr.state"
|
||||
|
||||
# The directory where zone transfers are stored, in a subdir of it.
|
||||
# xfrdir: "/tmp"
|
||||
|
||||
# don't answer VERSION.BIND and VERSION.SERVER CHAOS class queries
|
||||
hide-version: yes
|
||||
|
||||
# don't answer HOSTNAME.BIND and ID.SERVER CHAOS class queries
|
||||
hide-identity: yes
|
||||
|
||||
# version string the server responds with for chaos queries.
|
||||
# default is 'NSD x.y.z' with the server's version number.
|
||||
# version: "NSD"
|
||||
|
||||
# identify the server (CH TXT ID.SERVER entry).
|
||||
# identity: "unidentified server"
|
||||
|
||||
# NSID identity (hex string, or "ascii_somestring"). default disabled.
|
||||
# nsid: "aabbccdd"
|
||||
|
||||
# Maximum number of concurrent TCP connections per server.
|
||||
# tcp-count: 100
|
||||
|
||||
# Accept (and immediately close) TCP connections after maximum number
|
||||
# of connections is reached to prevent kernel connection queue from
|
||||
# growing.
|
||||
# tcp-reject-overflow: no
|
||||
|
||||
# Maximum number of queries served on a single TCP connection.
|
||||
# By default 0, which means no maximum.
|
||||
# tcp-query-count: 0
|
||||
|
||||
# Override the default (120 seconds) TCP timeout.
|
||||
# tcp-timeout: 120
|
||||
|
||||
# Maximum segment size (MSS) of TCP socket on which the server
|
||||
# responds to queries. Default is 0, system default MSS.
|
||||
# tcp-mss: 0
|
||||
|
||||
# Maximum segment size (MSS) of TCP socket for outgoing AXFR request.
|
||||
# Default is 0, system default MSS.
|
||||
# outgoing-tcp-mss: 0
|
||||
|
||||
# Preferred EDNS buffer size for IPv4.
|
||||
# ipv4-edns-size: 4096
|
||||
|
||||
# Preferred EDNS buffer size for IPv6.
|
||||
# ipv6-edns-size: 4096
|
||||
|
||||
# statistics are produced every number of seconds. Prints to log.
|
||||
# Default is 0, meaning no statistics are produced.
|
||||
# statistics: 3600
|
||||
|
||||
# Number of seconds between reloads triggered by xfrd.
|
||||
# xfrd-reload-timeout: 1
|
||||
|
||||
# log timestamp in ascii (y-m-d h:m:s.msec), yes is default.
|
||||
# log-time-ascii: yes
|
||||
|
||||
# round robin rotation of records in the answer.
|
||||
round-robin: yes
|
||||
|
||||
# minimal-responses only emits extra data for referrals.
|
||||
minimal-responses: yes
|
||||
|
||||
# Do not return additional information if the apex zone of the
|
||||
# additional information is configured but does not match the apex zone
|
||||
# of the initial query.
|
||||
# confine-to-zone: no
|
||||
|
||||
# refuse queries of type ANY. For stopping floods.
|
||||
refuse-any: yes
|
||||
|
||||
# check mtime of all zone files on start and sighup
|
||||
# zonefiles-check: yes
|
||||
|
||||
# write changed zonefiles to disk, every N seconds.
|
||||
# default is 0(disabled) or 3600(if database is "").
|
||||
# zonefiles-write: 3600
|
||||
|
||||
# RRLconfig
|
||||
# Response Rate Limiting, size of the hashtable. Default 1000000.
|
||||
# rrl-size: 1000000
|
||||
|
||||
# Response Rate Limiting, maximum QPS allowed (from one query source).
|
||||
# If set to 0, ratelimiting is disabled. Also set
|
||||
# rrl-whitelist-ratelimit to 0 to disable ratelimit processing.
|
||||
# Default is on.
|
||||
# rrl-ratelimit: 200
|
||||
|
||||
# Response Rate Limiting, number of packets to discard before
|
||||
# sending a SLIP response (a truncated one, allowing an honest
|
||||
# resolver to retry with TCP). Default is 2 (one half of the
|
||||
# queries will receive a SLIP response, 0 disables SLIP (all
|
||||
# packets are discarded), 1 means every request will get a
|
||||
# SLIP response. When the ratelimit is hit the traffic is
|
||||
# divided by the rrl-slip value.
|
||||
# rrl-slip: 2
|
||||
|
||||
# Response Rate Limiting, IPv4 prefix length. Addresses are
|
||||
# grouped by netblock.
|
||||
# rrl-ipv4-prefix-length: 24
|
||||
|
||||
# Response Rate Limiting, IPv6 prefix length. Addresses are
|
||||
# grouped by netblock.
|
||||
# rrl-ipv6-prefix-length: 64
|
||||
|
||||
# Response Rate Limiting, maximum QPS allowed (from one query source)
|
||||
# for whitelisted types. Default is on.
|
||||
# rrl-whitelist-ratelimit: 2000
|
||||
# RRLend
|
||||
|
||||
# Optional local server config
|
||||
include: "/etc/nsd/server.d/*.conf"
|
||||
|
||||
# Include optional local configs.
|
||||
include: "/etc/nsd/conf.d/*.conf"
|
||||
|
||||
# Fedora: DNSTAP not yet enabled
|
||||
# dnstap:
|
||||
# set this to yes and set one or more of dnstap-log-..-messages to yes.
|
||||
# dnstap-enable: no
|
||||
# dnstap-socket-path: "/var/run/dnstap.sock"
|
||||
# dnstap-send-identity: no
|
||||
# dnstap-send-version: no
|
||||
# dnstap-identity: ""
|
||||
# dnstap-version: ""
|
||||
# dnstap-log-auth-query-messages: no
|
||||
# dnstap-log-auth-response-messages: no
|
||||
|
||||
# Service clients over TLS (on the TCP sockets), with plain DNS inside
|
||||
# the TLS stream. Give the certificate to use and private key.
|
||||
# Default is "" (disabled). Requires restart to take effect.
|
||||
# tls-service-key: "path/to/privatekeyfile.key"
|
||||
# tls-service-pem: "path/to/publiccertfile.pem"
|
||||
# tls-service-ocsp: "path/to/ocsp.pem"
|
||||
# tls-port: 853
|
||||
|
||||
# Remote control config section.
|
||||
remote-control:
|
||||
# Enable remote control with nsd-control(8) here.
|
||||
# set up the keys and certificates with nsd-control-setup.
|
||||
control-enable: yes
|
||||
|
||||
# what interfaces are listened to for control, default is on localhost.
|
||||
# with an absolute path, a unix local named pipe is used for control
|
||||
# (and key and cert files are not needed, use directory permissions).
|
||||
# control-interface: 127.0.0.1
|
||||
# control-interface: ::1
|
||||
control-interface: /run/nsd/nsd.ctl
|
||||
|
||||
# port number for remote control operations (uses TLS over TCP).
|
||||
# control-port: 8952
|
||||
|
||||
# nsd server key file for remote control.
|
||||
# server-key-file: "/etc/nsd/nsd_server.key"
|
||||
|
||||
# nsd server certificate file for remote control.
|
||||
# server-cert-file: "/etc/nsd/nsd_server.pem"
|
||||
|
||||
# nsd-control key file.
|
||||
# control-key-file: "/etc/nsd/nsd_control.key"
|
||||
|
||||
# nsd-control certificate file.
|
||||
# control-cert-file: "/etc/nsd/nsd_control.pem"
|
||||
|
||||
|
||||
# Secret keys for TSIGs that secure zone transfers.
|
||||
# You could include: "secret.keys" and put the 'key:' statements in there,
|
||||
# and give that file special access control permissions.
|
||||
#
|
||||
# key:
|
||||
# The key name is sent to the other party, it must be the same
|
||||
#name: "keyname"
|
||||
# algorithm hmac-md5, or sha1, sha256, sha224, sha384, sha512
|
||||
#algorithm: sha256
|
||||
# secret material, must be the same as the other party uses.
|
||||
# base64 encoded random number.
|
||||
# e.g. from dd if=/dev/random of=/dev/stdout count=1 bs=32 | base64
|
||||
#secret: "K2tf3TRjvQkVCmJF3/Z9vA=="
|
||||
|
||||
|
||||
# Patterns have zone configuration and they are shared by one or more zones.
|
||||
#
|
||||
# pattern:
|
||||
# name by which the pattern is referred to
|
||||
#name: "myzones"
|
||||
# the zonefile for the zones that use this pattern.
|
||||
# if relative then from the zonesdir (inside the chroot).
|
||||
# the name is processed: %s - zone name (as appears in zone:name).
|
||||
# %1 - first character of zone name, %2 second, %3 third.
|
||||
# %z - topleveldomain label of zone, %y, %x next labels in name.
|
||||
# if label or character does not exist you get a dot '.'.
|
||||
# for example "%s.zone" or "zones/%1/%2/%3/%s" or "secondary/%z/%s"
|
||||
#zonefile: "%s.zone"
|
||||
|
||||
# If no master and slave access control elements are provided,
|
||||
# this zone will not be served to/from other servers.
|
||||
|
||||
# A master zone needs notify: and provide-xfr: lists. A slave
|
||||
# may also allow zone transfer (for debug or other secondaries).
|
||||
# notify these slaves when the master zone changes, address TSIG|NOKEY
|
||||
# IP can be ipv4 and ipv6, with @port for a nondefault port number.
|
||||
#notify: 192.0.2.1 NOKEY
|
||||
# allow these IPs and TSIG to transfer zones, addr TSIG|NOKEY|BLOCKED
|
||||
# address range 192.0.2.0/24, 1.2.3.4&255.255.0.0, 3.0.2.20-3.0.2.40
|
||||
#provide-xfr: 192.0.2.0/24 my_tsig_key_name
|
||||
# set the number of retries for notify.
|
||||
#notify-retry: 5
|
||||
|
||||
# uncomment to provide AXFR to all the world
|
||||
# provide-xfr: 0.0.0.0/0 NOKEY
|
||||
# provide-xfr: ::0/0 NOKEY
|
||||
|
||||
# A slave zone needs allow-notify: and request-xfr: lists.
|
||||
#allow-notify: 2001:db8::0/64 my_tsig_key_name
|
||||
# By default, a slave will request a zone transfer with IXFR/TCP.
|
||||
# If you want to make use of IXFR/UDP use: UDP addr tsigkey
|
||||
# for a master that only speaks AXFR (like NSD) use AXFR addr tsigkey
|
||||
#request-xfr: 192.0.2.2 the_tsig_key_name
|
||||
# Attention: You cannot use UDP and AXFR together. AXFR is always over
|
||||
# TCP. If you use UDP, we higly recommend you to deploy TSIG.
|
||||
# Allow AXFR fallback if the master does not support IXFR. Default
|
||||
# is yes.
|
||||
#allow-axfr-fallback: yes
|
||||
# set local interface for sending zone transfer requests.
|
||||
# default is let the OS choose.
|
||||
#outgoing-interface: 10.0.0.10
|
||||
# limit the refresh and retry interval in seconds.
|
||||
#max-refresh-time: 2419200
|
||||
#min-refresh-time: 0
|
||||
#max-retry-time: 1209600
|
||||
#min-retry-time: 0
|
||||
|
||||
# Slave server tries zone transfer to all masters and picks highest
|
||||
# zone version available, for when masters have different versions.
|
||||
#multi-master-check: no
|
||||
|
||||
# limit the zone transfer size (in bytes), stops very large transfers
|
||||
# 0 is no limits enforced.
|
||||
# size-limit-xfr: 0
|
||||
|
||||
# if compiled with --enable-zone-stats, give name of stat block for
|
||||
# this zone (or group of zones). Output from nsd-control stats.
|
||||
# zonestats: "%s"
|
||||
|
||||
# if you give another pattern name here, at this point the settings
|
||||
# from that pattern are inserted into this one (as if it were a
|
||||
# macro). The statement can be given in between other statements,
|
||||
# because the order of access control elements can make a difference
|
||||
# (which master to request from first, which slave to notify first).
|
||||
#include-pattern: "common-masters"
|
||||
|
||||
|
||||
# Fixed zone entries. Here you can config zones that cannot be deleted.
|
||||
# Zones that are dynamically added and deleted are put in the zonelist file.
|
||||
#
|
||||
# zone:
|
||||
# name: "example.com"
|
||||
# you can give a pattern here, all the settings from that pattern
|
||||
# are then inserted at this point
|
||||
# include-pattern: "master"
|
||||
# You can also specify (additional) options directly for this zone.
|
||||
# zonefile: "example.com.zone"
|
||||
# request-xfr: 192.0.2.1 example.com.key
|
||||
|
||||
# RRLconfig
|
||||
# Response Rate Limiting, whitelist types
|
||||
# rrl-whitelist: nxdomain
|
||||
# rrl-whitelist: error
|
||||
# rrl-whitelist: referral
|
||||
# rrl-whitelist: any
|
||||
# rrl-whitelist: rrsig
|
||||
# rrl-whitelist: wildcard
|
||||
# rrl-whitelist: nodata
|
||||
# rrl-whitelist: dnskey
|
||||
# rrl-whitelist: positive
|
||||
# rrl-whitelist: all
|
||||
# RRLend
|
||||
|
||||
zone:
|
||||
name: "dyn.jaseg.de"
|
||||
zonefile: "/var/lib/dyndns/dyn.jaseg.de.zone"
|
||||
|
||||
80
setup_dyndns.yml
Normal file
80
setup_dyndns.yml
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
---
|
||||
- name: Set local facts
|
||||
set_fact:
|
||||
dyndns_sqlite_dbfile: /var/lib/dyndns/db.sqlite3
|
||||
|
||||
- name: Copy nsd config
|
||||
copy:
|
||||
src: nsd.conf
|
||||
dest: /etc/nsd/nsd.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0644
|
||||
|
||||
- name: Enable and launch nsd systemd service
|
||||
systemd:
|
||||
name: nsd.service
|
||||
enabled: yes
|
||||
state: restarted
|
||||
|
||||
- name: Create dyndns worker user and group
|
||||
user:
|
||||
name: uwsgi-dyndns
|
||||
create_home: no
|
||||
group: uwsgi
|
||||
password: '!'
|
||||
shell: /sbin/nologin
|
||||
system: yes
|
||||
|
||||
- name: Allow dyndns app to kick nsd
|
||||
lineinfile:
|
||||
path: /etc/sudoers
|
||||
line: 'uwsgi-dyndns ALL=(nsd) NOPASSWD: /usr/sbin/nsd-control reload dyn.jaseg.de'
|
||||
|
||||
- name: Create webapp dir
|
||||
file:
|
||||
path: /var/lib/dyndns
|
||||
state: directory
|
||||
owner: uwsgi-dyndns
|
||||
group: nsd
|
||||
mode: 0750
|
||||
|
||||
- name: Copy webapp sources
|
||||
copy:
|
||||
src: dyndns.py
|
||||
dest: /var/lib/dyndns/
|
||||
owner: uwsgi-dyndns
|
||||
group: uwsgi
|
||||
mode: 0440
|
||||
|
||||
- name: Template webapp config
|
||||
template:
|
||||
src: dyndns_config.py.j2
|
||||
dest: /var/lib/dyndns/config.py
|
||||
owner: uwsgi-dyndns
|
||||
group: root
|
||||
mode: 0660
|
||||
|
||||
- name: Copy uwsgi config
|
||||
copy:
|
||||
src: uwsgi-dyndns.ini
|
||||
dest: /etc/uwsgi.d/dyndns.ini
|
||||
owner: uwsgi-dyndns
|
||||
group: uwsgi
|
||||
mode: 0440
|
||||
|
||||
- name: Enable uwsgi systemd socket
|
||||
systemd:
|
||||
daemon-reload: yes
|
||||
name: uwsgi-app@dyndns.socket
|
||||
enabled: yes
|
||||
|
||||
- name: Create sqlite db file
|
||||
file:
|
||||
path: "{{dyndns_sqlite_dbfile}}"
|
||||
owner: uwsgi-dyndns
|
||||
group: uwsgi
|
||||
mode: 0660
|
||||
state: touch
|
||||
|
||||
|
||||
10
uwsgi-dyndns.ini
Normal file
10
uwsgi-dyndns.ini
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[uwsgi]
|
||||
master = True
|
||||
cheap = True
|
||||
die-on-idle = False
|
||||
manage-script-name = True
|
||||
log-format = [pid: %(pid)|app: -|req: -/-] %(addr) (%(user)) {%(vars) vars in %(pktsize) bytes} [%(ctime)] %(method) [URI hidden] => generated %(rsize) bytes in %(msecs) msecs (%(proto) %(status)) %(headers) headers in %(hsize) bytes (%(switches) switches on core %(core))
|
||||
plugins = python3
|
||||
chdir = /var/lib/dyndns
|
||||
mount = /=dyndns:app
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue