PowerDNS
Contents
See Also
Ports
Protocol/Port |
Daemon |
Comment |
apache2 |
redirect to https |
|
apache2 |
serve powerdns-admin over http2s |
|
53 |
dnsdist |
answer queries |
5301 |
pdns-server |
answer authoritive DNS-queries |
5302 |
pdns-recursor |
answer recursive DNS-queries |
pdns-server |
webserver |
|
pdns-recursor |
webserver |
|
dnsdist |
webserver |
About
PowerDNS is a whole ecosystem that consists of multiple parts:
Separation of recursor and authoritative
Rationale
D. J. Bernstein - The importance of separating DNS caches from DNS servers
RFC 7720 DNS Root Name Service Protocol and Deployment Requirements
ICANN RSSAC001 Version 1 Service Expectations of Root Servers
Arguments
- Attacker does not instantly gain control of both components
- Resources are not shared
- Problems with one component don't interfere with the other
- Isolation during upgrades
- Modularity (you may choose different software for caches and authoritative)
Separation and isolation is probably a good idea.
Implementation in PowerDNS
By default pdns-server and pdns-recursor share the same port.
1 Jul 27 16:12:18 hostname pdns_recursor[20006]: Exception: Resolver binding to server socket on port 53 for 127.0.0.1: Address already in use
The statement recursor has been removed from the authoritative server with pdns 4.1.
To get recursion and point to a authoritative server you may configure:
Forwarding zones with a recursor using the statements forward-zones=, forward-zones-recurse= or forward-zones-file=
- You won't get TSIG I/AXFR working through the recursor, so the port of the authoritative needs to be exposed and configured in the requestor.
a #dnsdist load-balancer
After evaluating both, i'd recommend the second option. It's so much more flexible.
PowerDNS authoritative
Installation
PowerDNS packages are more recent than those of Debian. But they don't seem to ship deb-src packages. :-/
Add external repo
/etc/apt/sources.list.d/pdns_buster.list
1 ### AUTHORITATIVE "-auth-"
2 deb [arch=amd64] http://repo.powerdns.com/debian buster-auth-43 main
3 #deb-src [arch=amd64] http://repo.powerdns.com/debian buster-auth-43 main
4
5 ### RECURSOR "-rec-"
6 deb [arch=amd64] http://repo.powerdns.com/debian buster-rec-43 main
7 #deb-src [arch=amd64] http://repo.powerdns.com/debian buster-rec-43 main
8
9 ### DNSDIST
10 deb [arch=amd64] http://repo.powerdns.com/debian buster-dnsdist-15 main
11 #deb-src [arch=amd64] http://repo.powerdns.com/debian buster-dnsdist-15 main
12
13 ### METRONOME
14 #deb [arch=amd64] http://repo.powerdns.com/debian buster-metronome-master main
15 #deb-src [arch=amd64] http://repo.powerdns.com/debian buster-metronome-master main
16
/etc/apt/sources.list.d/pdns_bullseye.list
1 ### AUTHORITATIVE "-auth-"
2 deb [arch=amd64] http://repo.powerdns.com/debian bullseye-auth-46 main
3 #deb-src [arch=amd64] http://repo.powerdns.com/debian bullseye-auth-46 main
4
5 ### RECURSOR "-rec-"
6 deb [arch=amd64] http://repo.powerdns.com/debian bullseye-rec-46 main
7 #deb-src [arch=amd64] http://repo.powerdns.com/debian bullseye-rec-46 main
8
9 ### DNSDIST
10 deb [arch=amd64] http://repo.powerdns.com/debian bullseye-dnsdist-17 main
11 #deb-src [arch=amd64] http://repo.powerdns.com/debian bullseye-dnsdist-17 main
12
Prioritize 3rd-party over distribution packages
/etc/apt/preferences.d/pdns
Create a powerdns keyring
Installation
1 aptitude install pdns-backend-pgsql pdns-tools postgresql
Configure
unattended-upgrades
Please take a look at
Debian#unattended upgrades
Hint:
I tried not to modify /etc/powerdns/pdns.conf or /etc/powerdns/recursor.conf. This allows unattended-upgrades to succeed - sometimes. :-/ Sometimes because, the configuration of the distribution unfortunately contains timestamps of configuration-generation and version strings.
Backends
pdns-backend-bind
Because this backend retrieves its configuration from plain files and not a database, the HTTP API is unable to process changes for this backend. This effectively makes the API read-only for zones hosted by the BIND backend.
Install
1 aptitude install pdns-backend-bind
Postgres
Reasoning
- May be updated by API
- PowerDNS-Admin also uses a postgres backend …
Install
1 aptitude install pdns-backend-bind postgresql
Prepare postgresql
Create user and database for powerdns
1 # su - postgres
2 $ createuser --pwprompt --echo pdns
3 SELECT pg_catalog.set_config('search_path', '', false)
4 CREATE ROLE pdns PASSWORD 'md545b994f35d824c1816b41bcb154d42ef' NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT LOGIN;
5 $ createdb --owner pdns --echo pdns
6 SELECT pg_catalog.set_config('search_path', '', false)
7 CREATE DATABASE pdns OWNER pdns;
Import powerdns schema
Configure pdns-backend-postgres
Launch postgres-backend
/etc/powerdns/pdns.d/_launch.conf
/etc/powerdns/pdns.d/gpqsql.conf
1 #################################
2 #Host (ip address) to connect to. If pgsql-host begins with a slash,
3 #it specifies Unix-domain communication rather than TCP/IP communication;
4 #the value is the name of the directory in which the socket file is stored.
5 #Default: not set.
6 gpgsql-host=localhost
7
8 #################################
9 #The port to connect to on gpgsql-host. Default: not set.
10 gpgsql-port=5432
11
12 #################################
13 #Name of the database to connect to. Default: not set.
14 gpgsql-dbname=pdns
15
16 #################################
17 #User to connect as. Default: not set.
18 gpgsql-user=pdns
19
20 #################################
21 #The password to for gpgsql-user. Default: not set.
22 gpgsql-password=Pah1phai3ahrohshaich0teiH5chu1Ee
23
24 #################################
25 #Enable DNSSEC processing for this backend. Default: no.
26 #gpgsql-dnssec=
27
28 #################################
29 #Extra connection parameters to forward to postgres.
30 #If you want to pin a specific certificate for the connection
31 #you should set this to sslmode=verify-full sslrootcert=<path-to-CA-cert>.
32 #Accepted parameters are documented in the PostgreSQL documentation.
33 #Default: “”.
34 #gpgsql-extra-connection-parameters=
Set correct unix permissions
Local bindings
/etc/powerdns/pdns.d/local.conf
1 #################################
2 # local-address Local IP addresses to which we bind
3 #
4 # local-address=0.0.0.0, ::
5
6 #################################
7 # local-address-nonexist-fail Fail to start if one or more of the local-address's do not exist on this server
8 #
9 # local-address-nonexist-fail=yes
10
11 #################################
12 # local-ipv6 DEPRECATED, will be removed, move your IPs to local-address
13 #
14 # local-ipv6=
15
16 #################################
17 # local-port The port on which we listen
18 #
19 #local-port=53
20 local-port=5301
Default SOA
/etc/powerdns/pdns.d/default-soa.conf
1 #################################
2 # default-soa-edit Default SOA-EDIT value
3 #
4 # default-soa-edit=
5
6 #################################
7 # default-soa-edit-signed Default SOA-EDIT value for signed zones
8 #
9 # default-soa-edit-signed=
10
11 #################################
12 # default-soa-mail mail address to insert in the SOA record if none set in the backend
13 #
14 default-soa-mail=hostmaster@rockstable.it
15
16 #################################
17 # default-soa-name name to insert in the SOA record if none set in the backend
18 #
19 default-soa-name=dyns1.rockstable.it
zone2sql
zone2sql converts Bind zonefiles to sql that can be imported into the powerdns generic sql backends. z2s usualy reads named.conf and follows the pathes to includes and zones files. It won't work in your home-directory, unless you change the pathes in a working copy.
Started easy but ended up in a shell code kata. Convert your zones to compressed sql (postgres). This script does not parse named.conf and assumes your files are named as your zones. It converts comments in the zonefiles to the description column. Finally these commands do all the same.
1 mkdir sql
2
3 ### SEQUENTIAL WHILE FIND
4 while read FILE; do
5 zone2sql --gpgsql --json-comments --verbose \
6 --zone="$FILE" --zone-name="${FILE#./}" \
7 |gzip -c > "sql/${FILE#./}.sql.gz"
8 done <<< "$(find . -type f \
9 -regextype posix-extended \
10 ! -regex '\./.*\.(bak|gz)[0-9]*$' \
11 -a ! -regex '\./\.[^/]+$' \
12 |sort)"
13
14 ### SEQUENTIAL FIND EXEC
15 find . -type f \
16 -regextype posix-extended \
17 ! -regex '\./.*\.(bak|gz)[0-9]*$' \
18 -a ! -regex '\./\.[^/]+$' \
19 -exec bash -c \
20 'zone2sql --gpgsql --json-comments --verbose \
21 --zone="{}" --zone-name="$(sed -r "s#\./##" <<< {})" \
22 |gzip -c > "sql/{}.sql.gz"' \;
23
24 ### PARALLEL FIND XARGS
25 find . -type f \
26 -regextype posix-extended \
27 ! -regex '\./.*\.(bak|gz)[0-9]*$' \
28 -a ! -regex '\./\.[^/]+$' \
29 |sed 's#^./##'\
30 |sort \
31 |xargs -L1 -P2 -d'\n' -I{} -- \
32 bash -c 'zone2sql --gpgsql --json-comments --verbose \
33 --zone="./{}" --zone-name="{}" \
34 |gzip -c > "sql/{}.sql.gz"'
Import it as follows
Zone Transfer
Master
You want your master to send notifies, you have to explicitly enable the master-mode. /etc/powerdns/pdns.d/slave.conf
Slave
When declared a zone as slave to initiate a zone transfer, i got this message in /var/log/daemon.log
1 Apr 1 12:27:52 dyns1 pdns_server[12153]: Received NOTIFY for rockstable.it from 78.47.38.48:53471 but slave support is disabled in the configuration
If you want zone transfers to be working by NOTIFYs, you need to enable slave=yes. This will also make the button button "Update from master" in the powerdns-admin domain view working.
/etc/powerdns/pdns.d/slave.conf
1 #################################
2 # slave Act as a slave
3 #
4 slave=yes
5
6 #################################
7 # slave-cycle-interval Schedule slave freshness checks once every .. seconds
8 #
9 # slave-cycle-interval=60
10
11 #################################
12 # slave-renotify If we should send out notifications for slaved updates
13 #
14 # slave-renotify=no
Import TSIG-Keys
1 pdns=# INSERT INTO tsigkeys (name, algorithm, secret) VALUES ('dns_replicator_external', 'HMAC-SHA512', 'long_tsig_key');
2 INSERT 0 1
3 pdns=# SELECT id FROM domains WHERE name='dyna.rockstable.it';
4 id
5 ----
6 9
7 (1 Zeile)
8
9 -- Generate the SOA Serial like "YYYYMMDD01" (won't increment when not set)
10 #pdns=# INSERT INTO domainmetadata (domain_id, kind, content) VALUES ('9', 'SOA-EDIT-API', 'DEFAULT');
11 -- Notify these nameservers to update the zone from master.
12 #pdns=# INSERT INTO domainmetadata (domain_id, kind, content) VALUES ('9', 'ALSO-NOTIFY', '1P.4D.DR.ESS');
13 -- Use this named key to AXFR this zone from master.
14 #pdns=# INSERT INTO domainmetadata (domain_id, kind, content) VALUES ('9', 'AXFR-MASTER-TSIG', 'dns_replicator_external');
15 -- Allow AXFR this zone from following prefixes.
16 #pdns=# INSERT INTO domainmetadata (domain_id, kind, content) VALUES ('9', 'ALLOW-AXFR-FROM', '1P.4D.DR.ESS/SNM');
17 -- Allow these named TSIG keys to AXFR this zone
18 pdns=# INSERT INTO domainmetadata (domain_id, kind, content) VALUES (9, 'TSIG-ALLOW-AXFR', 'dns_replicator_external');
19 -- Allow these named TSIG keys to perform a dynamic DNS update
20 #pdns=# INSERT INTO domainmetadata (domain_id, kind, content) VALUES (9, 'TSIG-ALLOW-DNSUPDATE', 'dns_replicator_external');
21
22 -- Statement to generate the statements to insert the option.
23 -- Before usage adjust content and master ip.
24 SELECT CONCAT('INSERT INTO domainmetadata (domain_id, kind, content) VALUES (',
25 id,
26 ', ''AXFR-MASTER-TSIG'', ''dns_replicator_external'');')
27 FROM domains
28 WHERE type = 'slave' AND
29 master like '10.0.%'
30 ORDER BY id ASC;
Repeat the procedure for the corresponding reverse zone.
Master
Master support is deactivated by default. To enable sending notifys, you must explicitly enable it.
/etc/powerdns/pdns.d/master.conf
Notifys to the slaves are triggered, when the authoritative finds a new SOA serial in the database. The interval between checks is by default 60s.
https://doc.powerdns.com/authoritative/settings.html#slave-cycle-interval
Trouble Shooting
This log may be acquired from /var/log/daemon.log
1 Sep 15 10:39:41 hostname pdns_server[16717]: 1 domain for which we are master needs notifications
2 Sep 15 10:39:41 hostname pdns_server[16717]: Queued notification of domain 'domain.tld' to IP.ADD.RE.SS:53
3 Sep 15 10:39:42 hostname pdns_server[16717]: Received unsuccessful notification report for 'domain.tld' from IP.ADD.RE.SS:53, error: Server Not Authoritative for zone / Not Authorized
4 Sep 15 10:39:42 hostname pdns_server[16717]: Removed from notification list: 'domain.tld' to IP.ADD.RE.SS:53 Server Not Authoritative for zone / Not Authorized
5 Sep 15 10:39:45 hostname pdns_server[16717]: No master domains need notifications
Try to sniff on the outside interface of your firewall (post NAT) for the packages sent during the notifcation process. A slave may refuse an notify, if the source IP-address does not match the IP-address of the primary master (SOA). Make sure your network address translation works as expected (masquerading vs. static SNAT). The slave may also be configured to not allow the notification from the source:
allow-notify { …; };
PowerDNS authoritative API
/etc/powerdns/pdns.d/api.conf
1 #################################
2 # api Enable/disable the REST API (including HTTP listener)
3 #
4 api=yes
5
6 #################################
7 # api-key Static pre-shared authentication key for access to the REST API
8 #
9 api-key=eengainaivefahkee5eu5lei8oi9eishiuheis4hee7raigho5ohnee6aeh5Auno
PowerDNS authoritative webserver
The webserver itself is also enabled along with the api. Information is displayed only if you set webserver to true. To use the webserver you also have to set a api-key.
/etc/powerdns/pdns.d/webserver.conf
1 #################################
2 # webserver Start a webserver for monitoring (api=yes also enables the HTTP listener)
3 #
4 webserver=yes
5
6 #################################
7 # webserver-address IP Address of webserver/API to listen on
8 #
9 # webserver-address=127.0.0.1
10
11 #################################
12 # webserver-allow-from Webserver/API access is only allowed from these subnets
13 #
14 # webserver-allow-from=127.0.0.1,::1
15
16 #################################
17 # webserver-loglevel Amount of logging in the webserver (none, normal, detailed)
18 #
19 # webserver-loglevel=normal
20
21 #################################
22 # webserver-max-bodysize Webserver/API maximum request/response body size in megabytes
23 #
24 # webserver-max-bodysize=2
25
26 #################################
27 # webserver-password Password required for accessing the webserver
28 #
29 # webserver-password=
30
31 #################################
32 # webserver-port Port of webserver/API to listen on
33 #
34 # webserver-port=8081
35
36 #################################
37 # webserver-print-arguments If the webserver should print arguments
38 #
39 # webserver-print-arguments=no
40
Apache2 reverse proxy
/etc/apache2/sites-available/authoritative_443.conf
1 <IfModule mod_ssl.c>
2 <VirtualHost *:443>
3 Define SERVER_NAME authoritative.hostname.domain.tld
4 ServerName ${SERVER_NAME}
5 ServerAlias authoritative.hostname
6
7 ServerAdmin webmaster@domain.tld
8 DocumentRoot /var/www/html
9
10 # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
11 # error, crit, alert, emerg.
12 # It is also possible to configure the loglevel for particular
13 # modules, e.g.
14 #LogLevel info ssl:warn
15
16 ErrorLog ${APACHE_LOG_DIR}/${SERVER_NAME}_error.log
17 CustomLog ${APACHE_LOG_DIR}/${SERVER_NAME}_access.log combined
18
19 ### SSL-CONFIG
20 # For most configuration files from conf-available/, which are
21 # enabled or disabled at a global level, it is possible to
22 # include a line for only one particular virtual host. For example the
23 # following line enables the CGI configuration for this host only
24 # after it has been globally disabled with "a2disconf".
25 #Include conf-available/serve-cgi-bin.conf
26
27 # SSL Engine Switch:
28 # Enable/Disable SSL for this virtual host.
29 SSLEngine on
30
31 # A self-signed (snakeoil) certificate can be created by installing
32 # the ssl-cert package. See
33 # /usr/share/doc/apache2/README.Debian.gz for more info.
34 # If both key and certificate are stored in the same file, only the
35 # SSLCertificateFile directive is needed.
36 SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
37 SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
38
39 # Server Certificate Chain:
40 # Point SSLCertificateChainFile at a file containing the
41 # concatenation of PEM encoded CA certificates which form the
42 # certificate chain for the server certificate. Alternatively
43 # the referenced file can be the same as SSLCertificateFile
44 # when the CA certificates are directly appended to the server
45 # certificate for convinience.
46 #SSLCertificateChainFile /etc/apache2/ssl.crt/server-ca.crt
47
48 # Certificate Authority (CA):
49 # Set the CA certificate verification path where to find CA
50 # certificates for client authentication or alternatively one
51 # huge file containing all of them (file must be PEM encoded)
52 # Note: Inside SSLCACertificatePath you need hash symlinks
53 # to point to the certificate files. Use the provided
54 # Makefile to update the hash symlinks after changes.
55 #SSLCACertificatePath /etc/ssl/certs/
56 #SSLCACertificateFile /etc/apache2/ssl.crt/ca-bundle.crt
57
58 # Certificate Revocation Lists (CRL):
59 # Set the CA revocation path where to find CA CRLs for client
60 # authentication or alternatively one huge file containing all
61 # of them (file must be PEM encoded)
62 # Note: Inside SSLCARevocationPath you need hash symlinks
63 # to point to the certificate files. Use the provided
64 # Makefile to update the hash symlinks after changes.
65 #SSLCARevocationPath /etc/apache2/ssl.crl/
66 #SSLCARevocationFile /etc/apache2/ssl.crl/ca-bundle.crl
67
68 # Client Authentication (Type):
69 # Client certificate verification type and depth. Types are
70 # none, optional, require and optional_no_ca. Depth is a
71 # number which specifies how deeply to verify the certificate
72 # issuer chain before deciding the certificate is not valid.
73 #SSLVerifyClient require
74 #SSLVerifyDepth 10
75
76 # SSL Engine Options:
77 # Set various options for the SSL engine.
78 # o FakeBasicAuth:
79 # Translate the client X.509 into a Basic Authorisation. This means that
80 # the standard Auth/DBMAuth methods can be used for access control. The
81 # user name is the `one line' version of the client's X.509 certificate.
82 # Note that no password is obtained from the user. Every entry in the user
83 # file needs this password: `xxj31ZMTZzkVA'.
84 # o ExportCertData:
85 # This exports two additional environment variables: SSL_CLIENT_CERT and
86 # SSL_SERVER_CERT. These contain the PEM-encoded certificates of the
87 # server (always existing) and the client (only existing when client
88 # authentication is used). This can be used to import the certificates
89 # into CGI scripts.
90 # o StdEnvVars:
91 # This exports the standard SSL/TLS related `SSL_*' environment variables.
92 # Per default this exportation is switched off for performance reasons,
93 # because the extraction step is an expensive operation and is usually
94 # useless for serving static content. So one usually enables the
95 # exportation for CGI and SSI requests only.
96 # o OptRenegotiate:
97 # This enables optimized SSL connection renegotiation handling when SSL
98 # directives are used in per-directory context.
99 #SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
100
101 <FilesMatch "\.(cgi|shtml|phtml|php)$">
102 SSLOptions +StdEnvVars
103 </FilesMatch>
104 <Directory /usr/lib/cgi-bin>
105 SSLOptions +StdEnvVars
106 </Directory>
107
108 # SSL Protocol Adjustments:
109 # The safe and default but still SSL/TLS standard compliant shutdown
110 # approach is that mod_ssl sends the close notify alert but doesn't wait for
111 # the close notify alert from client. When you need a different shutdown
112 # approach you can use one of the following variables:
113 # o ssl-unclean-shutdown:
114 # This forces an unclean shutdown when the connection is closed, i.e. no
115 # SSL close notify alert is send or allowed to received. This violates
116 # the SSL/TLS standard but is needed for some brain-dead browsers. Use
117 # this when you receive I/O errors because of the standard approach where
118 # mod_ssl sends the close notify alert.
119 # o ssl-accurate-shutdown:
120 # This forces an accurate shutdown when the connection is closed, i.e. a
121 # SSL close notify alert is send and mod_ssl waits for the close notify
122 # alert of the client. This is 100% SSL/TLS standard compliant, but in
123 # practice often causes hanging connections with brain-dead browsers. Use
124 # this only for browsers where you know that their SSL implementation
125 # works correctly.
126 # Notice: Most problems of broken clients are also related to the HTTP
127 # keep-alive facility, so you usually additionally want to disable
128 # keep-alive for those clients, too. Use variable "nokeepalive" for this.
129 # Similarly, one has to force some clients to use HTTP/1.0 to workaround
130 # their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and
131 # "force-response-1.0" for this.
132
133 BrowserMatch "MSIE [2-6]" \
134 nokeepalive ssl-unclean-shutdown \
135 downgrade-1.0 force-response-1.0
136 # MSIE 7 and newer should be able to use keepalive
137 BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
138
139 ### Redirect any request URI to the webserver root URI.
140 #RedirectMatch ^/$ "https://${SERVER_NAME}/webmail"
141
142 RewriteEngine on
143 RewriteCond %{HTTP_HOST} !=${SERVER_NAME}
144 RewriteRule ^/(.*)$ https://${SERVER_NAME}/$1 [R=301,L]
145
146 ### PUT YOUR APPLICATION SPECIFIC CONFIGURATION HERE
147
148 ### Proxy rules
149 ProxyRequests Off
150 ProxyPreserveHost On
151 ProxyPass / http://localhost:8081/
152 ProxyPassReverse / http://localhost:8081/
153 </VirtualHost>
154 </IfModule>
155
156 # vim: syntax=apache ts=4 sw=4 sts=4 sr noet
Enable site and reload apache2
ECS authoritative
PowerDNS recursor
Install
Prior to installation have a look at #Separation of recursor and authoritative
Install
1 aptitude install pdns-recursor dns-root-data
Debian and its derivatives ship the dns-root-data package that contains the DNSSEC root trust anchors in /usr/share/dns/root.key.
Configure
Local bindings
/etc/powerdns/recursor.d/local.conf
1 #################################
2 # local-address IP addresses to listen on, separated by spaces or commas. Also accepts ports.
3 #
4 #local-address=127.0.0.1
5 local-address=0.0.0.0, ::
6
7 #################################
8 # local-port port to listen on
9 #
10 #local-port=53
11 local-port=5302
Forwarding zones
You may use forward-zones-file to omit the boiler plate code in the config
/etc/powerdns/recursor.d/forwards.conf
A leading + would set the recursion flag
/etc/powerdns/recursor.forwards
PowerDNS recursor API
The webserver itself is also enabled along with the api. Information is displayed only if you set webserver to true. To use the webserver you also have to set a api-key.
/etc/powerdns/recursor.d/api.conf
PowerDNS recursor webserver
/etc/powerdns/recursor.d/webserver.conf
1 #################################
2 # webserver Start a webserver (for REST API)
3 #
4 webserver=yes
5
6 #################################
7 # webserver-address IP Address of webserver to listen on
8 #
9 # webserver-address=127.0.0.1
10
11 #################################
12 # webserver-allow-from Webserver access is only allowed from these subnets
13 #
14 # webserver-allow-from=127.0.0.1,::1
15
16 #################################
17 # webserver-loglevel Amount of logging in the webserver (none, normal, detailed)
18 #
19 # webserver-loglevel=normal
20 webserver-loglevel=none
21
22 #################################
23 # webserver-password Password required for accessing the webserver
24 #
25 webserver-password=uqu1ag7SaiNe6ke4Shohk9phie0Chai8
26
27 #################################
28 # webserver-port Port of webserver to listen on
29 #
30 # webserver-port=8082
31
Apache2 reverse proxy
/etc/apache2/sites-available/recursor_443.conf
1 <IfModule mod_ssl.c>
2 <VirtualHost *:443>
3 Define SERVER_NAME recursor.hostname.domain.tld
4 ServerName ${SERVER_NAME}
5 ServerAlias recursor.hostname
6
7 ServerAdmin webmaster@domain.tld
8 DocumentRoot /var/www/html
9
10 # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
11 # error, crit, alert, emerg.
12 # It is also possible to configure the loglevel for particular
13 # modules, e.g.
14 #LogLevel info ssl:warn
15
16 ErrorLog ${APACHE_LOG_DIR}/${SERVER_NAME}_error.log
17 CustomLog ${APACHE_LOG_DIR}/${SERVER_NAME}_access.log combined
18
19 ### SSL-CONFIG
20 # For most configuration files from conf-available/, which are
21 # enabled or disabled at a global level, it is possible to
22 # include a line for only one particular virtual host. For example the
23 # following line enables the CGI configuration for this host only
24 # after it has been globally disabled with "a2disconf".
25 #Include conf-available/serve-cgi-bin.conf
26
27 # SSL Engine Switch:
28 # Enable/Disable SSL for this virtual host.
29 SSLEngine on
30
31 # A self-signed (snakeoil) certificate can be created by installing
32 # the ssl-cert package. See
33 # /usr/share/doc/apache2/README.Debian.gz for more info.
34 # If both key and certificate are stored in the same file, only the
35 # SSLCertificateFile directive is needed.
36 SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
37 SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
38
39 # Server Certificate Chain:
40 # Point SSLCertificateChainFile at a file containing the
41 # concatenation of PEM encoded CA certificates which form the
42 # certificate chain for the server certificate. Alternatively
43 # the referenced file can be the same as SSLCertificateFile
44 # when the CA certificates are directly appended to the server
45 # certificate for convinience.
46 #SSLCertificateChainFile /etc/apache2/ssl.crt/server-ca.crt
47
48 # Certificate Authority (CA):
49 # Set the CA certificate verification path where to find CA
50 # certificates for client authentication or alternatively one
51 # huge file containing all of them (file must be PEM encoded)
52 # Note: Inside SSLCACertificatePath you need hash symlinks
53 # to point to the certificate files. Use the provided
54 # Makefile to update the hash symlinks after changes.
55 #SSLCACertificatePath /etc/ssl/certs/
56 #SSLCACertificateFile /etc/apache2/ssl.crt/ca-bundle.crt
57
58 # Certificate Revocation Lists (CRL):
59 # Set the CA revocation path where to find CA CRLs for client
60 # authentication or alternatively one huge file containing all
61 # of them (file must be PEM encoded)
62 # Note: Inside SSLCARevocationPath you need hash symlinks
63 # to point to the certificate files. Use the provided
64 # Makefile to update the hash symlinks after changes.
65 #SSLCARevocationPath /etc/apache2/ssl.crl/
66 #SSLCARevocationFile /etc/apache2/ssl.crl/ca-bundle.crl
67
68 # Client Authentication (Type):
69 # Client certificate verification type and depth. Types are
70 # none, optional, require and optional_no_ca. Depth is a
71 # number which specifies how deeply to verify the certificate
72 # issuer chain before deciding the certificate is not valid.
73 #SSLVerifyClient require
74 #SSLVerifyDepth 10
75
76 # SSL Engine Options:
77 # Set various options for the SSL engine.
78 # o FakeBasicAuth:
79 # Translate the client X.509 into a Basic Authorisation. This means that
80 # the standard Auth/DBMAuth methods can be used for access control. The
81 # user name is the `one line' version of the client's X.509 certificate.
82 # Note that no password is obtained from the user. Every entry in the user
83 # file needs this password: `xxj31ZMTZzkVA'.
84 # o ExportCertData:
85 # This exports two additional environment variables: SSL_CLIENT_CERT and
86 # SSL_SERVER_CERT. These contain the PEM-encoded certificates of the
87 # server (always existing) and the client (only existing when client
88 # authentication is used). This can be used to import the certificates
89 # into CGI scripts.
90 # o StdEnvVars:
91 # This exports the standard SSL/TLS related `SSL_*' environment variables.
92 # Per default this exportation is switched off for performance reasons,
93 # because the extraction step is an expensive operation and is usually
94 # useless for serving static content. So one usually enables the
95 # exportation for CGI and SSI requests only.
96 # o OptRenegotiate:
97 # This enables optimized SSL connection renegotiation handling when SSL
98 # directives are used in per-directory context.
99 #SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
100
101 <FilesMatch "\.(cgi|shtml|phtml|php)$">
102 SSLOptions +StdEnvVars
103 </FilesMatch>
104 <Directory /usr/lib/cgi-bin>
105 SSLOptions +StdEnvVars
106 </Directory>
107
108 # SSL Protocol Adjustments:
109 # The safe and default but still SSL/TLS standard compliant shutdown
110 # approach is that mod_ssl sends the close notify alert but doesn't wait for
111 # the close notify alert from client. When you need a different shutdown
112 # approach you can use one of the following variables:
113 # o ssl-unclean-shutdown:
114 # This forces an unclean shutdown when the connection is closed, i.e. no
115 # SSL close notify alert is send or allowed to received. This violates
116 # the SSL/TLS standard but is needed for some brain-dead browsers. Use
117 # this when you receive I/O errors because of the standard approach where
118 # mod_ssl sends the close notify alert.
119 # o ssl-accurate-shutdown:
120 # This forces an accurate shutdown when the connection is closed, i.e. a
121 # SSL close notify alert is send and mod_ssl waits for the close notify
122 # alert of the client. This is 100% SSL/TLS standard compliant, but in
123 # practice often causes hanging connections with brain-dead browsers. Use
124 # this only for browsers where you know that their SSL implementation
125 # works correctly.
126 # Notice: Most problems of broken clients are also related to the HTTP
127 # keep-alive facility, so you usually additionally want to disable
128 # keep-alive for those clients, too. Use variable "nokeepalive" for this.
129 # Similarly, one has to force some clients to use HTTP/1.0 to workaround
130 # their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and
131 # "force-response-1.0" for this.
132
133 BrowserMatch "MSIE [2-6]" \
134 nokeepalive ssl-unclean-shutdown \
135 downgrade-1.0 force-response-1.0
136 # MSIE 7 and newer should be able to use keepalive
137 BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
138
139 ### Redirect any request URI to the webserver root URI.
140 #RedirectMatch ^/$ "https://${SERVER_NAME}/webmail"
141
142 RewriteEngine on
143 RewriteCond %{HTTP_HOST} !=${SERVER_NAME}
144 RewriteRule ^/(.*)$ https://${SERVER_NAME}/$1 [R=301,L]
145
146 ### PUT YOUR APPLICATION SPECIFIC CONFIGURATION HERE
147
148 ### Proxy rules
149 ProxyRequests Off
150 ProxyPreserveHost On
151 ProxyPass / http://localhost:8082/
152 ProxyPassReverse / http://localhost:8082/
153 </VirtualHost>
154 </IfModule>
155
156 # vim: syntax=apache ts=4 sw=4 sts=4 sr noet
Enable site and reload apache2
PowerDNS recursor performance
File descriptor limit has already been increased by distribution in
/etc/systemd/system/multi-user.target.wants/pdns-recursor.service
PowerDNS recursor DNSsec
/etc/powerdns/recursor.d/dnssec.conf
=== ECS recursor ====
https://doc.powerdns.com/recursor/settings.html#use-incoming-edns-subnet
https://doc.powerdns.com/recursor/settings.html#edns-subnet-whitelist
PowerDNS Tools
pdns_control
pdns_control is used to send commands to a running PowerDNS nameserver.
rec_control
Command line tool to control a running Recursor.
pdnsutil
pdnsutil (formerly pdnssec) is a powerful command that is the operator-friendly gateway into DNSSEC and zone management for PowerDNS. Behind the scenes,q pdnsutil manipulates a PowerDNS backend database, which also means that for many databases, pdnsutil can be run remotely, and can configure key material on different servers.
pdns_notify
pdns_notify sends a DNS NOTIFY message to IP_ADDRESS or HOSTNAME, by default on port 53, for DOMAIN and prints the remote nameserver's response. If HOSTNAME resolves to multiple IP addresses, each one is notified.
1 pdns_notify IP_ADDRESS/HOSTNAME[:PORT] DOMAIN
PowerDNS-Admin
About
github ngoduykhanh/PowerDNS-Admin Running PowerDNS Admin on Ubuntu or ebian
github ngoduykhanh/PowerDNS-Admin Using-PowerDNS Admin with PostgreSQL
Prepare Postgresql
Create user and database for powerdns-admin
Installation
Clone powerdns-admin from git-repo
Edit /opt/powerdns-admin/requirements.txt to use postgres instead of mysql
1 Flask==1.1.1
2 Flask-Assets==0.12
3 Flask-Login==0.4.1
4 Flask-SQLAlchemy==2.4.1
5 Flask-Migrate==2.5.2
6 SQLAlchemy==1.3.11
7 #mysqlclient==1.4.6
8 psycopg2
9 configobj==5.0.6
10 bcrypt==3.1.4
11 requests==2.20.0
12 python-ldap==3.1.0
13 pyotp==2.2.6
14 qrcode==6.0
15 dnspython==1.15.0
16 gunicorn==20.0.4
17 python3-saml
18 pyOpenSSL>=0.15
19 pytz>=2017.3
20 cssmin==0.2.0
21 jsmin==2.2.2
22 Authlib==0.10
23 Flask-SeaSurf==0.2.2
24 bravado-core==5.13.1
25 lima==0.5
26 pytest==5.0.1
27 pytimeparse==1.1.8
28 PyYAML==5.1.1
29 Flask-SSLify==0.1.5
30 Flask-Mail==0.9.1
Create virtual environment
Configure
powerdns-admin gets config from
docker_config.py,
default_config.py or
environment variable FLASK_CONF
./powerdnsadmin/__init__.py
1 …
2 # Load config from env variables if using docker
3 if os.path.exists(os.path.join(app.root_path, 'docker_config.py')):
4 app.config.from_object('powerdnsadmin.docker_config')
5 else:
6 # Load default configuration
7 app.config.from_object('powerdnsadmin.default_config')
8
9 # Load config file from FLASK_CONF env variable
10 if 'FLASK_CONF' in os.environ:
11 app.config.from_envvar('FLASK_CONF')
12 …
Create system user and group
1 adduser --system --group --home /var/lib/pdns_admin pdns_admin
Change unix-permissions and create a backup of default_config.py
Create SECRET_KEY and SALT e.g. with
bcrypt (12 rounds $2b$12$) like in default_config.py
or with pwgen 32
- or with whatever you like …
Article about hashing with Bcrypt
/opt/powerdns-admin/powerdnsadmin/default_config.py
1 import os
2 basedir = os.path.abspath(os.path.abspath(os.path.dirname(__file__)))
3
4 ### BASIC APP CONFIG
5 SALT = '$2b$12$yLUMTIfl21FKJQpTkRQXCu'
6 SECRET_KEY = 'Rei0zei6iequaich8aibahchahFah9Oociezeed2kie2aeThae9olulaew4jait0'
7 BIND_ADDRESS = '0.0.0.0'
8 PORT = 9191
9 HSTS_ENABLED = False
10
11 ### DATABASE CONFIG
12 SQLA_DB_SCHEMA = 'postgresql'
13 SQLA_DB_USER = 'pdns_admin'
14 SQLA_DB_PASSWORD = 'eixahzaiPhoo0Chiecie9BohK5thong7'
15 SQLA_DB_HOST = '127.0.0.1'
16 SQLA_DB_NAME = 'pdns_admin'
17 SQLALCHEMY_TRACK_MODIFICATIONS = True
18
19 ### DATBASE - PostgreSQL
20 SQLALCHEMY_DATABASE_URI = \
21 SQLA_DB_SCHEMA+'://'+SQLA_DB_USER+':'+SQLA_DB_PASSWORD+ \
22 '@'+SQLA_DB_HOST+'/'+SQLA_DB_NAME
23
24 ### DATABSE - SQLite
25 # SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'pdns.db')
26
27 # SAML Authnetication
28 SAML_ENABLED = False
29
30 PREFERRED_URL_SCHEME = 'https'
31
32 ### SMTP CONFIG
33 MAIL_SERVER = 'localhost'
34 MAIL_PORT = 25
35 # MAIL_DEBUG = False
36 # MAIL_USE_TLS = False
37 # MAIL_USE_SSL = False
38 # MAIL_USERNAME = None
39 # MAIL_PASSWORD = None
40 MAIL_DEFAULT_SENDER = ('Rockstable DNS', 'noreply@dyns1.rockstable.it')
Migrate the database
Install yarnpkg https://classic.yarnpkg.com/en/docs/install#debian-stable
Then generate static assets
Start a development server
1 ./run
If you are running the server remote you can test it via
1 ssh -L 9191:localhost:9191 user@host
and try it in your browser.
http://localhost:9191
Now configure the PowerDNS authoritative API
Webserver
https://github.com/ngoduykhanh/PowerDNS-Admin/wiki/uWSGI-example
https://github.com/ngoduykhanh/PowerDNS-Admin/wiki/WSGI-Apache-example
Apache with gunicorn
For now i decide to Apache webserver in conjunction with gunicorn.
Gunicorn will be used from the virtualenv. It has been installed along with requirements.txt.
Install apache2 from the repository
1 aptitude install apache2
Create a defaults file to be used by the systemd-unit
/etc/default/pdns_admin
/etc/systemd/system/pdns_admin.service
1 [Unit]
2 Description=PowerDNS web administration service
3 Requires=pdns_admin.socket
4 Wants=network.target
5 After=network.target mysqld.service postgresql.service slapd.service mariadb.service
6
7 [Service]
8 PIDFile=/run/powerdns-admin/pid
9 User=pdns_admin
10 Group=pdns_admin
11 WorkingDirectory=/opt/powerdns-admin
12 EnvironmentFile=/etc/default/pdns_admin
13 ExecStart=/opt/powerdns-admin/flask/bin/gunicorn --workers 4 --log-level info \
14 --pid /run/powerdns-admin/pid \
15 "powerdnsadmin:create_app(config='default_config.py')"
16 ExecReload=/bin/kill -s HUP $MAINPID
17 ExecStop=/bin/kill -s TERM $MAINPID
18 PrivateTmp=true
19 Restart=on-failure
20 RestartSec=10
21 StartLimitInterval=0
22
23 [Install]
24 WantedBy=multi-user.target
The .socket file determines which socket the service binds to.
/etc/systemd/system/pdns_admin.socket
/etc/tmpfiles.d/powerdns-admin.conf
Fix unix permissions of .webassets-cache
Enable the systemd-units
Prepare Let's encrypt certificates
/etc/apache2/sites-available/pdns_admin.conf
1 <VirtualHost *:80>
2 Define SERVER_NAME dyns1.rockstable.it
3 ServerName ${SERVER_NAME}
4 DocumentRoot "/opt/powerdns-admin"
5 <Directory "/opt/powerdns-admin">
6 Options Indexes FollowSymLinks MultiViews
7 AllowOverride None
8 Require all granted
9 </Directory>
10 Redirect permanent / https://${SERVER_NAME}/
11
12 ErrorLog ${APACHE_LOG_DIR}/${SERVER_NAME}_error.log
13 CustomLog ${APACHE_LOG_DIR}/${SERVER_NAME}_access.log combined
14 </VirtualHost>
15
16 <VirtualHost *:443>
17 Define SERVER_NAME dyns1.rockstable.it
18 ServerName ${SERVER_NAME}
19 DocumentRoot "/opt/powerdns-admin/powerdnsadmin"
20
21 ### Alias declarations for resources outside the DocumentRoot
22 Alias /static/ "/opt/powerdns-admin/powerdnsadmin/static/"
23 Alias /favicon.ico "/opt/powerdns-admin/powerdnsadmin/static/favicon.ico"
24 <Directory "/opt/powerdns-admin">
25 AllowOverride None
26 Require all granted
27 </Directory>
28
29 ### SSL directives
30 SSLEngine on
31 SSLCertificateFile "/etc/letsencrypt/live/${SERVER_NAME}/fullchain.pem"
32 SSLCertificateKeyFile "/etc/letsencrypt/live/${SERVER_NAME}/privkey.pem"
33
34 ErrorLog ${APACHE_LOG_DIR}/${SERVER_NAME}_error.log
35 CustomLog ${APACHE_LOG_DIR}/${SERVER_NAME}_access.log combined
36
37 ### Proxy rules
38 ProxyRequests Off
39 ProxyPreserveHost On
40 ProxyPass /static/ !
41 ProxyPass /favicon.ico !
42 #ProxyPass / unix:/var/run/powerdns-admin/socket|http://%{HTTP_HOST}/
43 #ProxyPassReverse / unix:/var/run/powerdns-admin/socket|http://%{HTTP_HOST}/
44 ProxyPass / http://127.0.0.1:9191/
45 ProxyPassReverse / http://127.0.0.1:9191/
46 RequestHeader set X-Forwarded-Proto "https"
47 </VirtualHost>
Enable apache2 modules and sites and restart apache2
2 Factor Authentication
The otp secret is only show as a QR code in the frontend, but can be extracted from the database backend.
Query
If necessary encode it in the following format.
otpauth://totp/NAME?&secret=SECRET&counter=0&period=30&digits=6
And create a QR code from it
SMTP server
Configure a SMTP server (like postfix or exim). You'll need it for email confirmations.
Random Bug Fixes
Email Confirmation
There is a bug in the SQL user-model related to PostgreSQL. When clicking the link the UPDATE statement fails and an Internal Server Error occurs. https://github.com/ngoduykhanh/PowerDNS-Admin/issues/787 This is a query to set the user confirmed, if you need it.
To fix the bug confirmation.patch
Apply the patch
Works again. :-D
nsupdate.info
About
List of free Dynamic DNS providers
- FreeDNS
- Securepoint DynDNS
- Dynu
- DynDNS Service
- DNSdynamic
- Afraid.org
- DuckDNS
- No-IP
Install
Clone project
Include six and setuptools>=50 in
/opt/nsupdate-info/requirements.txt
And pin pyscopg2 down to version <2.9
/opt/nsupdate-info/requirements.d/prod.txt
Create virtual environment
Create a system user
1 adduser --system --group --home /var/lib/nsupdate nsupdate
Upgrade
The upgrade process
1 PREFIX="/opt/nsupdate-info"
2 systemctl stop nsupdate.service
3 systemctl stop nsupdate.socket
4 if [ "$PREFIX" ]; then
5 cd "$PREFIX" || exit 1
6 rm -r "$PREFIX/venv_nsupdate"
7 virtualenv -p python3 "$PREFIX"/venv_nsupdate
8 source "$PREFIX"/venv_nsupdate/bin/activate
9 pip install -r "$PREFIX"/requirements.d/prod.txt
10 python setup.py build
11 fi
12 systemctl start nsupdate.socket
13 systemctl start nsupdate.service
Secret key for Django
To have a SECRET_KEY for Django you either:
create a configuration file /opt/nsupdate-info/local_settings.py
OR
export it via environment variables
I decided for the later.
Write this information to a debian defaults file, which may be sourced by the shell and is used by the systemd.unit as EnvironmentFile=. /etc/default/nsupdate
Adjust unix permissions
Configure nsupdate
You can read about the options in /opt/nsupdate-info/venv_nsupdate/lib/python3.7/site-packages/django/conf/global_settings.py
/opt/nsupdate-info/src/nsupdate/settings/prod.py
1 """
2 settings for production
3 """
4
5 # MY LATEST VERSION OF manage.py DOES NO LONGER READ SECRET_KEY FROM ENV…
6 SECRET_KEY = "ooshahTieliat6emahf8jaem7deenaex8eyiaDohYuheikaFieph2Eeghuoth9Oh"
7
8 from .base import *
9
10 DEBUG = False
11
12 WE_HAVE_TLS = True # True if you run a https site also, suggest that site to users if they work on the http site.
13 CSRF_COOKIE_SECURE = WE_HAVE_TLS
14 SESSION_COOKIE_SECURE = WE_HAVE_TLS
15
16 # these are the service host names we deal with
17 BASEDOMAIN = 'nsupdate.rockstable.it'
18 # do NOT just use the BASEDOMAIN for WWW_HOST, or you will run into troubles
19 # when you want to be on publicsuffix.org list and still be able to set cookies
20 WWW_HOST = 'www.' + BASEDOMAIN # a host with a ipv4 and a ipv6 address
21 # hosts to enforce a v4 / v6 connection (to determine the respective ip)
22 WWW_IPV4_HOST = 'ipv4.' + BASEDOMAIN # a host with ONLY a ipv4 address
23 WWW_IPV6_HOST = 'ipv6.' + BASEDOMAIN # a host with ONLY a ipv6 address
24
25 # Hosts/domain names that are valid for this site; required if DEBUG is False
26 # See https://docs.djangoproject.com/en/1.6/ref/settings/#allowed-hosts
27 ALLOWED_HOSTS = [BASEDOMAIN, WWW_HOST, WWW_IPV4_HOST, WWW_IPV6_HOST]
/opt/nsupdate-info/src/nsupdate/settings/base.py
1 """
2 Django settings for nsupdate project
3
4 Note: do not directly use these settings, rather use "dev" or "prod".
5 """
6
7 # Note: django internally first loads its own defaults and then loads the
8 # project's settings on top of that. Due to this, no import * is required here.
9
10 import os
11
12 # To make this work, put a unique, long, random, secret string into your environment.
13 # E.g. in ~/.bashrc: export SECRET_KEY="..."
14 try:
15 SECRET_KEY = os.environ['SECRET_KEY']
16 except KeyError:
17 # if there is no SECRET_KEY in the environment, it will be just undefined and
18 # Django will refuse running - except if you define it somehow else later (e.g. in
19 # a local_settings.py file that imports this file).
20 pass
21
22 # service contact for showing on the "about" page:
23 SERVICE_CONTACT = 'hostmaster@rockstable.it'
24
25 # sender address for e.g. user activation emails
26 DEFAULT_FROM_EMAIL = "nsupdate@rockstable.it"
27
28 # admins will get traceback emails
29 ADMINS = (
30 ('Tobias Stein', 'tobias_stein@rockstable.it'),
31 )
32 MANAGERS = ADMINS
33
34 DATABASES = {
35 'default': {
36 'ENGINE': 'django.db.backends.postgresql_psycopg2', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
37 'NAME': 'nsupdate', # Or path to database file if using sqlite3.
38 # The following settings are not used with sqlite3:
39 'USER': 'nsupdate',
40 'PASSWORD': 'ieQuoo9aiChaChae7eemo1asheeTh6Ch',
41 'HOST': 'localhost', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
42 'PORT': '5432' # Set to empty string for default.
43 }
44 }
45
46 # these useragents are unacceptable for /nic/update service
47 BAD_AGENTS = set([]) # list can have str elements
48
49 # these IPAdresses and/or IPNetworks are unacceptable for /nic/update service
50 # like e.g. IPs of servers related to illegal activities
51 from netaddr import IPSet, IPAddress, IPNetwork
52 BAD_IPS_HOST = IPSet([]) # inner list can have IPAddress and IPNetwork elements
53
54 # when encountering these hostnames (fqdn), block them early/silently from
55 # api usage. avoid any database access, so if someone tries to update
56 # every 5s, the database won't be locked all the time and we can at least
57 # delete the host from django admin.
58 BAD_HOSTS = set([])
59
60 # nameservers used e.g. for MX lookups in the registration email validation.
61 # google / cloudflare DNS IPs are only given as example / fallback -
62 # please configure your own nameservers in your local settings file.
63 NAMESERVERS = ['195.201.246.253', '78.49.38.48', ]
64
65 # registration email validation: disallow specific email domains,
66 # e.g. domains that have a non-working mx / that are frequently abused.
67 # we use a multiline string here with one regex per line (used with re.search).
68 # the domains given below are just examples, please configure your own
69 # regexes in your local settings file.
70 MAILDOMAIN_BLACKLIST = r"""
71 mailcatch\.com$
72 mailspam\.xyz$
73 """
74
75 # Local time zone for this installation. Choices can be found here:
76 # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
77 # although not all choices may be available on all operating systems.
78 # In a Windows environment this must be set to your system time zone.
79 TIME_ZONE = 'Europe/Berlin'
80
81 # Language code for this installation. All choices can be found here:
82 # http://www.i18nguy.com/unicode/language-identifiers.html
83 LANGUAGE_CODE = 'de-de'
84
85 SITE_ID = 1
86
87 # If you set this to False, Django will make some optimizations so as not
88 # to load the internationalization machinery.
89 USE_I18N = True
90
91 # If you set this to False, Django will not format dates, numbers and
92 # calendars according to the current locale.
93 USE_L10N = True
94
95 # If you set this to False, Django will not use timezone-aware datetimes.
96 USE_TZ = True
97
98 # Absolute filesystem path to the directory that will hold user-uploaded files.
99 # Example: "/var/www/example.com/media/"
100 MEDIA_ROOT = ''
101
102 # URL that handles the media served from MEDIA_ROOT. Make sure to use a
103 # trailing slash.
104 # Examples: "http://example.com/media/", "http://media.example.com/"
105 MEDIA_URL = ''
106
107 # URL prefix for static files.
108 # Example: "http://example.com/static/", "http://static.example.com/"
109 STATIC_URL = '/static/'
110
111 # Absolute path to the directory static files should be collected to.
112 # Don't put anything in this directory yourself; store your static files
113 # in apps' "static/" subdirectories and in STATICFILES_DIRS.
114 # Example: "/var/www/example.com/static/"
115 # STATIC_ROOT = "/srv/nsupdate.info/htdocs/static"
116
117 # Additional locations of static files
118 STATICFILES_DIRS = (
119 # Put strings here, like "/home/html/static" or "C:/www/django/static".
120 # Always use forward slashes, even on Windows.
121 # Don't forget to use absolute paths, not relative paths.
122 )
123
124 # List of finder classes that know how to find static files in
125 # various locations.
126 STATICFILES_FINDERS = (
127 'django.contrib.staticfiles.finders.FileSystemFinder',
128 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
129 # 'django.contrib.staticfiles.finders.DefaultStorageFinder',
130 )
131
132 TEMPLATES = [
133 {
134 'BACKEND': 'django.template.backends.django.DjangoTemplates',
135 'DIRS': [
136 # '/where/you/have/additional/templates',
137 ],
138 'OPTIONS': {
139 'context_processors': [
140 # Insert your TEMPLATE_CONTEXT_PROCESSORS here or use this
141 # list if you haven't customized them:
142 # 'django.contrib.auth.context_processors.auth',
143 # 'django.template.context_processors.debug',
144 'django.template.context_processors.i18n',
145 'django.template.context_processors.request',
146 'django.contrib.auth.context_processors.auth',
147 'nsupdate.context_processors.add_settings',
148 'nsupdate.context_processors.update_ips',
149 # 'django.template.context_processors.media',
150 # 'django.template.context_processors.static',
151 # 'django.template.context_processors.tz',
152 'django.contrib.messages.context_processors.messages',
153 'social_django.context_processors.backends',
154 'social_django.context_processors.login_redirect',
155
156 ],
157 'loaders': [
158 'django.template.loaders.filesystem.Loader',
159 'django.template.loaders.app_directories.Loader',
160 ],
161 },
162 },
163 ]
164
165 MIDDLEWARE = (
166 'django.middleware.common.CommonMiddleware',
167 'django.contrib.sessions.middleware.SessionMiddleware',
168 'django.middleware.locale.LocaleMiddleware',
169 'django.middleware.csrf.CsrfViewMiddleware',
170 'django_referrer_policy.middleware.ReferrerPolicyMiddleware',
171 'django.contrib.auth.middleware.AuthenticationMiddleware',
172 'django.contrib.messages.middleware.MessageMiddleware',
173 'social_django.middleware.SocialAuthExceptionMiddleware',
174 'django.middleware.clickjacking.XFrameOptionsMiddleware',
175 'django.middleware.security.SecurityMiddleware',
176 )
177
178 ROOT_URLCONF = 'nsupdate.urls'
179
180 # Python dotted path to the WSGI application used by Django's runserver.
181 WSGI_APPLICATION = 'nsupdate.wsgi.application'
182
183 INSTALLED_APPS = (
184 'django.contrib.auth',
185 'django.contrib.contenttypes',
186 'django.contrib.sessions',
187 'django.contrib.sites',
188 'django.contrib.messages',
189 'django.contrib.staticfiles',
190 'django.contrib.humanize',
191 'social_django',
192 'nsupdate.login',
193 'nsupdate',
194 'nsupdate.accounts',
195 'nsupdate.api',
196 'nsupdate.main',
197 'bootstrapform',
198 'django.contrib.admin',
199 'registration',
200 'django_extensions',
201 )
202
203 # A sample logging configuration.
204 # Sends an email to the site admins on every HTTP 500 error when DEBUG=False.
205 # Do some stderr logging for some views.
206 # See http://docs.djangoproject.com/en/dev/topics/logging for
207 # more details on how to customize your logging configuration.
208 LOGGING = {
209 'version': 1,
210 'disable_existing_loggers': False,
211 'filters': {
212 'require_debug_false': {
213 '()': 'django.utils.log.RequireDebugFalse'
214 }
215 },
216 'handlers': {
217 'mail_admins': {
218 'level': 'ERROR',
219 'filters': ['require_debug_false'],
220 'class': 'django.utils.log.AdminEmailHandler'
221 },
222 'stderr': {
223 'level': 'DEBUG',
224 'class': 'logging.StreamHandler',
225 'formatter': 'stderr'
226 },
227 'stderr_request': {
228 'level': 'DEBUG',
229 'class': 'logging.StreamHandler',
230 'formatter': 'stderr_request'
231 }
232 },
233 'loggers': {
234 'nsupdate.api.views': {
235 'handlers': ['stderr_request', ],
236 'level': 'DEBUG',
237 'propagate': True,
238 },
239 'nsupdate.main.views': {
240 'handlers': ['stderr_request', ],
241 'level': 'DEBUG',
242 'propagate': True,
243 },
244 'nsupdate.main.dnstools': {
245 'handlers': ['stderr', ],
246 'level': 'DEBUG',
247 'propagate': True,
248 },
249 # this is the toplevel handler for all request processing:
250 'django.request': {
251 'handlers': ['mail_admins', 'stderr'],
252 'level': 'ERROR',
253 'propagate': True,
254 },
255 },
256 'formatters': {
257 'stderr': {
258 'format': '[%(asctime)s] %(levelname)s %(message)s',
259 },
260 'stderr_request': {
261 'format': '[%(asctime)s] %(levelname)s %(message)s '
262 '[ip: %(request.META.REMOTE_ADDR)s, ua: "%(request.META.HTTP_USER_AGENT)s"]',
263 },
264 },
265 }
266
267 # Setup support for proxy headers
268 USE_X_FORWARDED_HOST = True
269 SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
270
271 ACCOUNT_ACTIVATION_DAYS = 7
272 REGISTRATION_EMAIL_HTML = False # we override the text, but not the html email template
273 REGISTRATION_FORM = 'nsupdate.accounts.registration_form.RegistrationFormValidateEmail'
274
275 LOGIN_REDIRECT_URL = '/overview/'
276 LOGOUT_REDIRECT_URL = '/'
277
278 X_FRAME_OPTIONS = 'DENY' # for clickjacking middleware
279 SECURE_BROWSER_XSS_FILTER = True
280 SECURE_CONTENT_TYPE_NOSNIFF = True
281 REFERRER_POLICY = 'same-origin'
282
283 CSRF_FAILURE_VIEW = 'nsupdate.main.views.csrf_failure_view'
284
285 # Settings for CSRF cookie.
286 CSRF_COOKIE_NAME = 'csrftoken'
287 CSRF_COOKIE_PATH = '/'
288 CSRF_COOKIE_HTTPONLY = True
289
290 # Settings for session cookie.
291 SESSION_COOKIE_NAME = 'sessionid'
292 SESSION_COOKIE_PATH = '/'
293 SESSION_COOKIE_HTTPONLY = True
294 SESSION_COOKIE_AGE = 10 * 60 * 60 # 10 hours, in seconds (remember_me is True), see #381
295 SESSION_EXPIRE_AT_BROWSER_CLOSE = True # more safe (remember_me is False)
296
297 # Allow SHA1 for host update secrets
298 PASSWORD_HASHERS = [
299 'django.contrib.auth.hashers.PBKDF2PasswordHasher',
300 'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
301 'django.contrib.auth.hashers.Argon2PasswordHasher',
302 'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
303 'django.contrib.auth.hashers.BCryptPasswordHasher',
304 'django.contrib.auth.hashers.SHA1PasswordHasher',
305 ]
306
307 # python-social-auth settings
308 AUTHENTICATION_BACKENDS = (
309 'social_core.backends.amazon.AmazonOAuth2',
310 'social_core.backends.bitbucket.BitbucketOAuth',
311 'social_core.backends.disqus.DisqusOAuth2',
312 'social_core.backends.dropbox.DropboxOAuth',
313 'social_core.backends.github.GithubOAuth2',
314 'social_core.backends.google.GoogleOAuth2',
315 'social_core.backends.reddit.RedditOAuth2',
316 'social_core.backends.soundcloud.SoundcloudOAuth2',
317 'social_core.backends.stackoverflow.StackoverflowOAuth2',
318 'social_core.backends.twitter.TwitterOAuth',
319 'django.contrib.auth.backends.ModelBackend',
320 )
321
322 SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/'
323 # Used to redirect the user once the auth process ended successfully.
324 # The value of ?next=/foo is used if it was present
325
326 SOCIAL_AUTH_LOGIN_ERROR_URL = '/accounts/login/'
327 # URL where the user will be redirected in case of an error
328
329 SOCIAL_AUTH_LOGIN_URL = '/accounts/login/'
330 # Is used as a fallback for LOGIN_ERROR_URL (if it is not defined).
331
332 # SOCIAL_AUTH_NEW_USER_REDIRECT_URL = '/new-users-redirect-url/'
333 # Used to redirect new registered users, will be used in place of SOCIAL_AUTH_LOGIN_REDIRECT_URL if defined.
334
335 SOCIAL_AUTH_NEW_ASSOCIATION_REDIRECT_URL = '/account/profile/'
336 # Like SOCIAL_AUTH_NEW_USER_REDIRECT_URL but for new associated accounts (user is already logged in).
337 # Used in place of SOCIAL_AUTH_LOGIN_REDIRECT_URL.
338
339 SOCIAL_AUTH_DISCONNECT_REDIRECT_URL = '/account/profile'
340 # The user will be redirected to this URL when a social account is disconnected
341
342 SOCIAL_AUTH_INACTIVE_USER_URL = '/'
343 # Inactive users can be redirected to this URL when trying to authenticate.
344
345 # SOCIAL_AUTH_USER_MODEL = 'foo.bar.User'
346 # User model must have a username and email field, these are required.
347 # Also an is_authenticated and is_active boolean flags are recommended, these can be methods if necessary (must
348 # return True or False). If the model lacks them a True value is assumed.
349
350 # SOCIAL_AUTH_UID_LENGTH = <int>
351 # Used to define the max length of the field uid. A value of 223 should work when using MySQL InnoDB which impose
352 # a 767 bytes limit (assuming UTF-8 encoding).
353
354 # SOCIAL_AUTH_NONCE_SERVER_URL_LENGTH = <int>
355 # Nonce model has a unique constraint over ('server_url', 'timestamp', 'salt'), salt has a max length of 40, so
356 # server_url length must be tweaked using this setting.
357
358 # SOCIAL_AUTH_ASSOCIATION_SERVER_URL_LENGTH = <int> or SOCIAL_AUTH_ASSOCIATION_HANDLE_LENGTH = <int>
359 # Association model has a unique constraint over ('server_url', 'handle'), both fields lengths can be tweaked by
360 # these settings.
361
362 SOCIAL_AUTH_DEFAULT_USERNAME = 'user'
363 # Default value to use as username, can be a callable. An UUID will be appended in case of duplicate entries.
364
365 SOCIAL_AUTH_UUID_LENGTH = 16
366 # This controls the length of the UUID appended to usernames.
367
368 SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL = True
369 # If you want to use the full email address as the username, define this setting.
370
371 # SOCIAL_AUTH_SLUGIFY_USERNAMES = False
372 # For those that prefer slugged usernames, the get_username pipeline can apply a slug transformation (code borrowed
373 # from Django project) by defining this setting to True. The feature is disabled by default to to not force this
374 # option to all projects.
375
376 # SOCIAL_AUTH_CLEAN_USERNAMES = True
377 # By default the regex r'[^\w.@+-_]+' is applied over usernames to clean them from usual undesired characters like
378 # spaces. Set this setting to False to disable this behavior.
379
380 # SOCIAL_AUTH_SANITIZE_REDIRECTS = False
381 # The auth process finishes with a redirect, by default it's done to the value of SOCIAL_AUTH_LOGIN_REDIRECT_URL
382 # but can be overridden with next GET argument. If this settings is True, this application will verify the domain of
383 # the final URL and only redirect to it if it's on the same domain.
384
385 # SOCIAL_AUTH_REDIRECT_IS_HTTPS = False
386 # On projects behind a reverse proxy that uses HTTPS, the redirect URIs can became with the wrong schema
387 # (http:// instead of https://) when the request lacks some headers, and might cause errors with the auth process,
388 # to force HTTPS in the final URIs set this setting to True
389
390 # SOCIAL_AUTH_URLOPEN_TIMEOUT = 30
391 # Any urllib2.urlopen call will be performed with the default timeout value, to change it without affecting the
392 # global socket timeout define this setting (the value specifies timeout seconds).
393 # urllib2.urlopen uses socket.getdefaulttimeout() value by default, so setting socket.setdefaulttimeout(...) will
394 # affect urlopen when this setting is not defined, otherwise this setting takes precedence. Also this might affect
395 # other places in Django.
396 # timeout argument was introduced in python 2.6 according to urllib2 documentation
397
398 # SOCIAL_AUTH_<BACKEND_NAME>_WHITELISTED_DOMAINS = ['foo.com', 'bar.com']
399 # Supply a list of domain names to be white-listed. Any user with an email address on any of the allowed domains will
400 # login successfully, otherwise AuthForbidden is raised.
401
402 # SOCIAL_AUTH_<BACKEND_NAME>_WHITELISTED_EMAILS = ['me@foo.com', 'you@bar.com']
403 # Supply a list of email addresses to be white-listed. Any user with an email address in this list will login
404 # successfully, otherwise AuthForbidden is raised.
405
406 # SOCIAL_AUTH_PROTECTED_USER_FIELDS = ['email', ]
407 # The user_details pipeline processor will set certain fields on user objects, such as email. Set this to a list of
408 # fields you only want to set for newly created users and avoid updating on further logins.
409
410 # SOCIAL_AUTH_SESSION_EXPIRATION = True
411 # Some providers return the time that the access token will live, the value is stored in UserSocialAuth.extra_data
412 # under the key expires. By default the current user session is set to expire if this value is present, this
413 # behavior can be disabled by setting.
414
415 # SOCIAL_AUTH_OPENID_PAPE_MAX_AUTH_AGE = <int value>
416 # Enable OpenID PAPE extension support by defining this setting.
417
418 # SOCIAL_AUTH_FIELDS_STORED_IN_SESSION = ['foo', ]
419 # If you want to store extra parameters from POST or GET in session, like it was made for next parameter, define
420 # this setting with the parameter names.
421 # In this case foo field's value will be stored when user follows this link
422 # <a href="{% url socialauth_begin 'github' %}?foo=bar">...</a>.
423
424 # we need slightly different classes for bootstrap3 than the default ones
425 from django.contrib.messages import constants
426 MESSAGE_TAGS = {
427 constants.DEBUG: '',
428 constants.INFO: 'alert-info',
429 constants.SUCCESS: 'alert-success',
430 constants.WARNING: 'alert-warning',
431 constants.ERROR: 'alert-danger',
432 }
433
434 # translations - for details, see:
435 # https://docs.djangoproject.com/en/dev/topics/i18n/translation/#message-files and
436 # https://docs.djangoproject.com/en/dev/topics/i18n/translation/#how-django-discovers-language-preference
437 # By default language is set to english - modify settings.py to set list of languages
438 gettext_noop = lambda s: s
439 LANGUAGES = (
440 ('en', gettext_noop('English')),
441 ('de', gettext_noop('German')),
442 ('el', gettext_noop('Greek')),
443 ('fr', gettext_noop('French')),
444 ('it', gettext_noop('Italian')),
445 # ('es', gettext_noop('Spanish')),
446 # ('zh-cn', gettext_noop('Chinese (China)')),
447 )
448
449 # silences 1_6.W001 warning you get without this:
450 TEST_RUNNER = 'django.test.runner.DiscoverRunner'
Add the following to the settings to enable parsing of some headers. This corrects determination of IP addresses.
Prepare postgresql
Create user and database
manage.py does no longer read PYTHONPATH
/opt/nsupdate-info/manage.py
1 #!/usr/bin/env python
2 import os
3 import sys
4
5 sys.path.append('/opt/nsupdate-info/src')
6
7 if __name__ == "__main__":
8 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "nsupdate.settings.prod")
9 from django.core.management import execute_from_command_line
10 execute_from_command_line(sys.argv)
Migrate database
Create systemd units
/etc/systemd/system/nsupdate.socket
/etc/systemd/system/nsupdate.service
1 [Unit]
2 Description=nsupdate web administration service
3 Requires=nsupdate.socket
4 Wants=network.target
5 After=network.target mysqld.service postgresql.service slapd.service mariadb.service
6
7 [Service]
8 PIDFile=/run/nsupdate/pid
9 User=nsupdate
10 Group=nsupdate
11 WorkingDirectory=/opt/nsupdate-info
12 EnvironmentFile=/etc/default/nsupdate
13 ExecStart=/opt/nsupdate-info/venv_nsupdate/bin/gunicorn \
14 --workers 4 --log-level info \
15 --pid /run/nsupdate/pid \
16 nsupdate.wsgi
17 ExecReload=/bin/kill -s HUP $MAINPID
18 ExecStop=/bin/kill -s TERM $MAINPID
19 PrivateTmp=true
20 Restart=on-failure
21 RestartSec=10
22 StartLimitInterval=0
23
24 [Install]
25 WantedBy=multi-user.target
/etc/tmpfiles.d/nsupdates.conf
Configure webserver
Enable mod_headers
1 a2enmod headers
/etc/apache2/site-available/nsupdate.conf
1 <VirtualHost *:80>
2 Define SERVER_NAME nsupdate.rockstable.it
3 ServerName ${SERVER_NAME}
4 ServerAlias nsupdate.rockstable.it
5 ServerAlias www.nsupdate.rockstable.it
6 ServerAlias ipv4.nsupdate.rockstable.it
7 ServerAlias ipv6.nsupdate.rockstable.it
8
9 DocumentRoot "/opt/nsupdate-info/src/nsupdate"
10
11 ## Alias declarations for resources outside the DocumentRoot
12 Alias /static/ "/opt/nsupdate-info/src/nsupdate/static/"
13 Alias /favicon.ico "/opt/nsupdate-info/src/nsupdate/static/img/favicon.ico"
14 <Directory "/opt/nsupdate-info/src/nsupdate/static/">
15 Options Indexes FollowSymLinks MultiViews
16 AllowOverride None
17 Require all granted
18 </Directory>
19
20 ### ADDITIONAL HEADERS TO mod_proxy DEFAULTS
21 RequestHeader set X-Forwarded-Proto 'http' env=HTTP
22
23 ## Proxy rules
24 ProxyRequests Off
25 ProxyPreserveHost On
26 ProxyPass /static/ !
27 ProxyPass /favicon.ico !
28 #ProxyPass / unix:/var/run/powerdns-admin/socket|http://%{HTTP_HOST}/
29 #ProxyPassReverse / unix:/var/run/powerdns-admin/socket|http://%{HTTP_HOST}/
30 ProxyPass / http://127.0.0.1:8080/
31 ProxyPassReverse / http://127.0.0.1:8080/
32
33 ErrorLog ${APACHE_LOG_DIR}/${SERVER_NAME}_error.log
34 CustomLog ${APACHE_LOG_DIR}/${SERVER_NAME}_access.log combined
35 </VirtualHost>
36
37 <VirtualHost *:443>
38 Define SERVER_NAME nsupdate.rockstable.it
39 ServerName ${SERVER_NAME}
40 ServerAlias nsupdate.rockstable.it
41 ServerAlias www.nsupdate.rockstable.it
42 ServerAlias ipv4.nsupdate.rockstable.it
43 ServerAlias ipv6.nsupdate.rockstable.it
44
45 DocumentRoot "/opt/nsupdate-info/src/nsupdate"
46
47 ## Alias declarations for resources outside the DocumentRoot
48 Alias /static/ "/opt/nsupdate-info/src/nsupdate/static/"
49 Alias /favicon.ico "/opt/nsupdate-info/src/nsupdate/static/img/favicon.ico"
50 <Directory "/opt/nsupdate-info/src/nsupdate/static/">
51 AllowOverride None
52 Require all granted
53 </Directory>
54
55 ### ADDITIONAL HEADERS TO mod_proxy DEFAULTS
56 RequestHeader set X-Forwarded-Proto 'https' env=HTTPS
57
58 ## Proxy rules
59 ProxyRequests Off
60 ProxyPreserveHost On
61 ProxyPass /static/ !
62 ProxyPass /favicon.ico !
63 #ProxyPass / unix:/var/run/powerdns-admin/socket|http://%{HTTP_HOST}/
64 #ProxyPassReverse / unix:/var/run/powerdns-admin/socket|http://%{HTTP_HOST}/
65 ProxyPass / http://127.0.0.1:8080/
66 ProxyPassReverse / http://127.0.0.1:8080/
67
68 ## SSL directives
69 SSLEngine on
70 SSLCertificateFile "/etc/letsencrypt/live/${SERVER_NAME}/fullchain.pem"
71 SSLCertificateKeyFile "/etc/letsencrypt/live/${SERVER_NAME}/privkey.pem"
72
73 ErrorLog ${APACHE_LOG_DIR}/${SERVER_NAME}_error.log
74 CustomLog ${APACHE_LOG_DIR}/${SERVER_NAME}_access.log combined
75 </VirtualHost>
Fix remote ip-address
The IP-address on the landing page was still displayed as "127.0.0.1". Nsupdate uses request.meta.REMOTE_ADDR, which is always the source address of the proxy in between. It simply ignores the HTTP-Header X-FORWARDED-FOR i configured in apache2. So, i patched the code.
I introduced a function from A stackoverflow thread in /opt/nsupdate-info/src/nsupdate/main/iptools.py
In the following files:
context_processors.py
api/views.py
main/views.py
I extended the import statement by the new function
1 from .main.iptools import normalize_ip, get_client_ip
and replaced every occurence of request.META['REMOTE_ADDR'] with get_client_ip(request)
Zone Delegation
Please don't forget to delegate the zone to the nameserver in the parent domain, Like i did for a long time!
Please see DNS#Zone_Delegation
If you are using DNSsec:
- Create a key signing key
- zone signing key
- publish the delegation signer record in the parent zone
- sign the zone
- migrate to NSEC3
Usage
Signup with nsupdate.
Prepare powerdns for dynamic DNS updates with the secret that was provided by nsupdate on domain creation.
1 su - postgres
2 psql pdns
3 pdns=# INSERT INTO tsigkeys (name, algorithm, secret) VALUES ('dyna.rockstable.it', 'HMAC-SHA512', 'MGI0MWM4YmM1MDVhNTE5MmVkOWU1Y2YxYzM0YzNhZDMzZjc4YWFiNThjZDQyYzcyMTNkY2ViZjg3N==');
4 INSERT 0 1
5 pdns=# INSERT INTO domainmetadata (domain_id, kind, content) VALUES (9, 'TSIG-ALLOW-DNSUPDATE', 'dyna.rockstable.it');
6 INSERT 0 1
Get Django-Admin
Fix css
Fix Django domains
1 su - postgres
2 psql nsupdate
3 nsupdate=# select * from django_site;
4 id | domain | name
5 ----+-------------+-------------
6 1 | example.com | example.com
7 (1 Zeile)
8
9 nsupdate=# update django_site SET domain = 'nsupdate.rockstable.it' where id=1;
10 UPDATE 1
11 nsupdate=# update django_site SET name = 'nsupdate.rockstable.it' where id=1;
12 UPDATE 1
13 nsupdate=# select * from django_site
14 ;
15 id | domain | name
16 ----+------------------------+------------------------
17 1 | nsupdate.rockstable.it | nsupdate.rockstable.it
18 (1 Zeile)
MyIP-Address
Add this line to your shell config
1 alias myip='curl https://nsupdate.rockstable.it/myip'
DNSdist
About
Installation
1 aptitude install dnsdist
Configure
Access control
- Access to the recursor is by default restricted to RFC1918 and some other special networks.
- The authoritative should be reachable by anybody.
There is no directive to restrict access like in the recursor allow-from
- dnsdist
With a restricted recursor and an open authoritative it's fine to set setACL({"0.0.0.0/0", "::/0"}) in dnsdist. When dnsdist sends queries to the recursor, the recursor knows nothing about the client itself, the recursor only sees the load-balancer. Without an additional whitelist this creates an open resolver. This can be abused as DDOS-Reflection amplifier. So please make sure, to create a whitelist prefixes that are allowed to use the recursor and/or at least implement a rate limiting.
Create encoded secret
Create an encoded key for the setKey() directive (the port may vary: 53)
Two DNS server pools on same host
/etc/dnsdist/dnsdist.conf
1 -- DNSDIST MAIN CONFIGURATION
2
3 -- RFC5424 "LOG_DAEMON"
4 setSyslogFacility(3)
5
6 -- BIND TO IPV4 and IPV6
7 setLocal("0.0.0.0:53")
8 addLocal("[::]:53")
9 setACL({
10 "0.0.0.0/0",
11 "::/0"
12 })
13 -- DEAFULT ACL
14 -- setACL({
15 -- "127.0.0.0/8",
16 -- "10.0.0.0/8",
17 -- "100.64.0.0/10",
18 -- "169.254.0.0/16",
19 -- "192.168.0.0/16",
20 -- "172.16.0.0/12",
21 -- "::1/128",
22 -- "fc00::/7",
23 -- "fe80::/10"
24 -- })
25
26
27 -- CONTROL SOCKET
28 controlSocket("127.0.0.1:5199")
29 setConsoleACL({
30 "127.0.0.0/8",
31 "::1/128"
32 })
33 setKey("V3Z3RucFDSqqqdRQzX63nFRjSA5TYl+unH1xSUdWTXI=")
34 setConsoleConnectionsLogging(true)
35 setRingBuffersSize(10240, 1)
36
37 -- WEBSERVER
38 webserver("127.0.0.1:8083", "Thoh1deiThu1culoo7taiy7enaeMeeS")
39
40 -- DEFINE POOLS
41 newServer({address="127.0.0.1:5301", pool="authoritative"})
42 newServer({address="127.0.0.1:5302", pool="recursor"})
43
44 -- DEFINE POOLS
45 -- useClientSubnet=true BREAKS TSIG???
46 newServer({
47 address="127.0.0.1:5301",
48 name="localhost4_auth",
49 pool="authoritative"
50 })
51 --newServer({
52 -- address="[::1]:5301",
53 -- name="localhost6_auth",
54 -- pool="authoritative",
55 -- useClientSubnet=true
56 --})
57 newServer({
58 address="127.0.0.1:5302",
59 name="localhost4_rec",
60 pool="recursor"
61 })
62 --newServer({
63 -- address="[::1]:5302",
64 -- name="localhost6_rec",
65 -- pool="recursor",
66 -- useClientSubnet=true
67 --})
68
69 -- EDNS Client Subnet
70 --setECSOverride(false)
71 --setECSSourcePrefixV4(24)
72 --setECSSourcePrefixV6(56)
73
74
75 -- DYNAMIC RULE GENERATION
76
77 local dbr = dynBlockRulesGroup()
78
79 -- DO NOT ADD DYNAMIC BLOCKS FOR
80 dbr:excludeRange({
81 "127.0.0.0/8",
82 "10.0.0.0/8",
83 "100.64.0.0/10",
84 "169.254.0.0/16",
85 "192.168.0.0/16",
86 "172.16.0.0/12",
87 "::1/128",
88 "fc00::/7",
89 "fe80::/10"
90 })
91 -- EXCEPT FOR 192.0.2.1
92 -- dbr:includeRange("192.0.2.1/32")
93
94 dbr:setQueryRate(60, 10, "Exceeded query rate", 60)
95 dbr:setRCodeRate(DNSRCode.NXDOMAIN, 30, 10, "Exceeded NXD rate", 60)
96 dbr:setRCodeRate(DNSRCode.SERVFAIL, 30, 10, "Exceeded ServFail rate", 60)
97 dbr:setQTypeRate(DNSQType.ANY, 15, 10, "Exceeded ANY rate", 60)
98 dbr:setResponseByteRate(10240, 10, "Exceeded resp BW rate", 60)
99
100 function maintenance()
101 dbr:apply()
102 end
103
104 -- ALLOW I/AXFR
105 addAction(
106 AndRule({
107 OrRule({
108 QTypeRule(DNSQType.AXFR),
109 QTypeRule(DNSQType.IXFR)
110 }
111 ),
112 NotRule(
113 makeRule({
114 "ip.add.re.ss1",
115 "ip.add.re.ss2/30"
116 })
117 )
118 }),
119 RCodeAction(DNSRCode.REFUSED)
120 )
121
122 -- ALLOW NOTIFY
123 -- addAction(
124 -- AndRule({
125 -- OpcodeRule(DNSOpcode.Notify),
126 -- NotRule(
127 -- makeRule({
128 -- "ip.add.re.ss3"
129 -- })
130 -- )
131 -- }),
132 -- RCodeAction(DNSRCode.REFUSED)
133 -- )
134
135
136 -- FORWARD DOMAINS TO POOL "authoritative"
137
138 --forwarded_domains = newDNSNameSet()
139 --forwarded_domains:add(newDNSName("domain1.tld"))
140 --forwarded_domains:add(newDNSName("domain2.tld"))
141 -- …
142 --addAction(
143 -- QNameSetRule(forwarded_domains),
144 -- PoolAction("authoritative")
145 --)
146
147 -- addAction("domain3.tld", PoolAction("authoritative"))
148 -- …
149
150 -- OPEN RESOLVER
151 -- ROUTE ANYTHING ELSE TO POOL "recursor"
152 --addAction(AllRule(), PoolAction("recursor"))
153
154 -- RECURSION WHITELIST
155 recursion_allowed = newNMG()
156 recursion_allowed:addMask("127.0.0.0/8")
157 recursion_allowed:addMask("10.0.0.0/8")
158 recursion_allowed:addMask("100.64.0.0/10")
159 recursion_allowed:addMask("169.254.0.0/16")
160 recursion_allowed:addMask("192.168.0.0/16")
161 recursion_allowed:addMask("172.16.0.0/12")
162 recursion_allowed:addMask("::1/128")
163 recursion_allowed:addMask("fc00::/7")
164 recursion_allowed:addMask("fe80::/10")
165
166 addAction(
167 NetmaskGroupRule(recursion_allowed),
168 PoolAction("recursor")
169 )
170
171 -- REFUSE ANYTHING ELSE
172 addAction(AllRule(), RCodeAction(DNSRCode.REFUSED))
173
174 -- PACKET CACHE
175 pc = newPacketCache(
176 1048576,
177 {maxTTL=86400,
178 minTTL=0,
179 temporaryFailureTTL=60,
180 staleTTL=60}
181 )
182 getPool(""):setCache(pc)
Check config!1!!
Restart service
1 systemctl restart dnsdist.service
Access via dnsdist as client over tcp
1 dnsdist -c
Apache2 reverse proxy
/etc/apache2/sites-available/dnsdist_443.conf
1 <IfModule mod_ssl.c>
2 <VirtualHost *:443>
3 Define SERVER_NAME dnsdist.hostname.domain.tld
4 ServerName ${SERVER_NAME}
5 ServerAlias dnsdist.hostname
6
7 ServerAdmin webmaster@domain.tld
8 DocumentRoot /var/www/html
9
10 # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
11 # error, crit, alert, emerg.
12 # It is also possible to configure the loglevel for particular
13 # modules, e.g.
14 #LogLevel info ssl:warn
15
16 ErrorLog ${APACHE_LOG_DIR}/${SERVER_NAME}_error.log
17 CustomLog ${APACHE_LOG_DIR}/${SERVER_NAME}_access.log combined
18
19 ### SSL-CONFIG
20 # For most configuration files from conf-available/, which are
21 # enabled or disabled at a global level, it is possible to
22 # include a line for only one particular virtual host. For example the
23 # following line enables the CGI configuration for this host only
24 # after it has been globally disabled with "a2disconf".
25 #Include conf-available/serve-cgi-bin.conf
26
27 # SSL Engine Switch:
28 # Enable/Disable SSL for this virtual host.
29 SSLEngine on
30
31 # A self-signed (snakeoil) certificate can be created by installing
32 # the ssl-cert package. See
33 # /usr/share/doc/apache2/README.Debian.gz for more info.
34 # If both key and certificate are stored in the same file, only the
35 # SSLCertificateFile directive is needed.
36 SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
37 SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
38
39 # Server Certificate Chain:
40 # Point SSLCertificateChainFile at a file containing the
41 # concatenation of PEM encoded CA certificates which form the
42 # certificate chain for the server certificate. Alternatively
43 # the referenced file can be the same as SSLCertificateFile
44 # when the CA certificates are directly appended to the server
45 # certificate for convinience.
46 #SSLCertificateChainFile /etc/apache2/ssl.crt/server-ca.crt
47
48 # Certificate Authority (CA):
49 # Set the CA certificate verification path where to find CA
50 # certificates for client authentication or alternatively one
51 # huge file containing all of them (file must be PEM encoded)
52 # Note: Inside SSLCACertificatePath you need hash symlinks
53 # to point to the certificate files. Use the provided
54 # Makefile to update the hash symlinks after changes.
55 #SSLCACertificatePath /etc/ssl/certs/
56 #SSLCACertificateFile /etc/apache2/ssl.crt/ca-bundle.crt
57
58 # Certificate Revocation Lists (CRL):
59 # Set the CA revocation path where to find CA CRLs for client
60 # authentication or alternatively one huge file containing all
61 # of them (file must be PEM encoded)
62 # Note: Inside SSLCARevocationPath you need hash symlinks
63 # to point to the certificate files. Use the provided
64 # Makefile to update the hash symlinks after changes.
65 #SSLCARevocationPath /etc/apache2/ssl.crl/
66 #SSLCARevocationFile /etc/apache2/ssl.crl/ca-bundle.crl
67
68 # Client Authentication (Type):
69 # Client certificate verification type and depth. Types are
70 # none, optional, require and optional_no_ca. Depth is a
71 # number which specifies how deeply to verify the certificate
72 # issuer chain before deciding the certificate is not valid.
73 #SSLVerifyClient require
74 #SSLVerifyDepth 10
75
76 # SSL Engine Options:
77 # Set various options for the SSL engine.
78 # o FakeBasicAuth:
79 # Translate the client X.509 into a Basic Authorisation. This means that
80 # the standard Auth/DBMAuth methods can be used for access control. The
81 # user name is the `one line' version of the client's X.509 certificate.
82 # Note that no password is obtained from the user. Every entry in the user
83 # file needs this password: `xxj31ZMTZzkVA'.
84 # o ExportCertData:
85 # This exports two additional environment variables: SSL_CLIENT_CERT and
86 # SSL_SERVER_CERT. These contain the PEM-encoded certificates of the
87 # server (always existing) and the client (only existing when client
88 # authentication is used). This can be used to import the certificates
89 # into CGI scripts.
90 # o StdEnvVars:
91 # This exports the standard SSL/TLS related `SSL_*' environment variables.
92 # Per default this exportation is switched off for performance reasons,
93 # because the extraction step is an expensive operation and is usually
94 # useless for serving static content. So one usually enables the
95 # exportation for CGI and SSI requests only.
96 # o OptRenegotiate:
97 # This enables optimized SSL connection renegotiation handling when SSL
98 # directives are used in per-directory context.
99 #SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
100
101 <FilesMatch "\.(cgi|shtml|phtml|php)$">
102 SSLOptions +StdEnvVars
103 </FilesMatch>
104 <Directory /usr/lib/cgi-bin>
105 SSLOptions +StdEnvVars
106 </Directory>
107
108 # SSL Protocol Adjustments:
109 # The safe and default but still SSL/TLS standard compliant shutdown
110 # approach is that mod_ssl sends the close notify alert but doesn't wait for
111 # the close notify alert from client. When you need a different shutdown
112 # approach you can use one of the following variables:
113 # o ssl-unclean-shutdown:
114 # This forces an unclean shutdown when the connection is closed, i.e. no
115 # SSL close notify alert is send or allowed to received. This violates
116 # the SSL/TLS standard but is needed for some brain-dead browsers. Use
117 # this when you receive I/O errors because of the standard approach where
118 # mod_ssl sends the close notify alert.
119 # o ssl-accurate-shutdown:
120 # This forces an accurate shutdown when the connection is closed, i.e. a
121 # SSL close notify alert is send and mod_ssl waits for the close notify
122 # alert of the client. This is 100% SSL/TLS standard compliant, but in
123 # practice often causes hanging connections with brain-dead browsers. Use
124 # this only for browsers where you know that their SSL implementation
125 # works correctly.
126 # Notice: Most problems of broken clients are also related to the HTTP
127 # keep-alive facility, so you usually additionally want to disable
128 # keep-alive for those clients, too. Use variable "nokeepalive" for this.
129 # Similarly, one has to force some clients to use HTTP/1.0 to workaround
130 # their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and
131 # "force-response-1.0" for this.
132
133 BrowserMatch "MSIE [2-6]" \
134 nokeepalive ssl-unclean-shutdown \
135 downgrade-1.0 force-response-1.0
136 # MSIE 7 and newer should be able to use keepalive
137 BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
138
139 ### Redirect any request URI to the webserver root URI.
140 #RedirectMatch ^/$ "https://${SERVER_NAME}/webmail"
141
142 RewriteEngine on
143 RewriteCond %{HTTP_HOST} !=${SERVER_NAME}
144 RewriteRule ^/(.*)$ https://${SERVER_NAME}/$1 [R=301,L]
145
146 ### PUT YOUR APPLICATION SPECIFIC CONFIGURATION HERE
147
148 ### Proxy rules
149 ProxyRequests Off
150 ProxyPreserveHost On
151 ProxyPass / http://localhost:8083/
152 ProxyPassReverse / http://localhost:8083/
153 </VirtualHost>
154 </IfModule>
155
156 # vim: syntax=apache ts=4 sw=4 sts=4 sr noet
Enable site and reload apache2