Commit baef00dddc1d02409c7e3c05fd9e10e2a1906eea

Authored by Frederik Lindenaar
1 parent 885154d3

Updated documentation (closes #1, closes #3 and closes #5)

Showing 1 changed file with 410 additions and 100 deletions
README.md
@@ -2,50 +2,64 @@ dyndns.pl @@ -2,50 +2,64 @@ dyndns.pl
2 ========= 2 =========
3 3
4 Perl CGI-BIN script to handle Dynamic DNS updates through HTTP (e.g. from a 4 Perl CGI-BIN script to handle Dynamic DNS updates through HTTP (e.g. from a
5 -router), updating DNS records through secure DNS update statements. 5 +router), updating DNS records through secure DNS update statements to run your
  6 +own Dynamic DNS Service.
6 7
7 -**Version 1.0**, latest version, documentation and bugtracker available on my 8 +**Version 1.1**, latest version, documentation and bugtracker available on my
8 [GitLab instance](https://gitlab.lindenaar.net/scripts/dyndns) 9 [GitLab instance](https://gitlab.lindenaar.net/scripts/dyndns)
9 10
10 -Copyright (c) 2013 - 2015 Frederik Lindenaar. free for distribution under the 11 +Copyright (c) 2013 - 2019 Frederik Lindenaar. free for distribution under the
11 GNU License, see [below](#license) 12 GNU License, see [below](#license)
12 13
13 14
14 Introduction 15 Introduction
15 ------------ 16 ------------
16 -This script provides a simple interface to allow Dynamic DNS updates for DNS  
17 -zones. It is intended to be used for routers and (aDSL) modems to register their  
18 -IP address by simply opening a URL (this is supported by many modern devices)  
19 -but can also be used by end-users (either directly by using a client). Please  
20 -bear in mind that this script suits my setup and still might have glitches, but  
21 -so far turned out to be a quite stable solution for my needs and I use it in a  
22 -production setup. In case you have any comments / questions or issues, please  
23 -raise them through my  
24 -[GitLab instance](https://gitlab.lindenaar.net/scripts/dyndns) so that all  
25 -users benefit.  
26 -  
27 -Setup  
28 ------ 17 +`dyndns.pl` provides a simple interface to allow Dynamic DNS updates for DNS
  18 +zones through HTTP requests. It is intended for routers and (aDSL) modems to
  19 +register their IP address by simply opening a URL (this is supported by most
  20 +modern devices) but can also be used by end-users (either directly by using a
  21 +client). The script itself uses DNS' `nsupdate` calls to perform the update.
  22 +With this script you can integrate devices not supporting `nsupdate` and
  23 +environments where the master DNS server is not publicly available. The script
  24 +suits my setup/and needs and still might have glitches, but turned out to be a
  25 +very stable solution the last 6 years on both Linux as well as MacOS.
  26 +
  27 +Please [see below](#integration) on how to setup the client side including:
  28 + * [Cisco Routers](#cisco_integration)
  29 + * [AVM Fritz!Box routers](#fritzbox_integration)
  30 + * [Synology DSM](#synology_integration) (NAS)
  31 +
  32 +In case you have any comments / questions or issues, please raise them through
  33 +my [GitLab instance](https://gitlab.lindenaar.net/scripts/dyndns) so that other
  34 +users can benefit and respond. Please also use this to submit setup instructions
  35 +for other devices you have set up for inclusion in this document.
  36 +
  37 +
  38 +Setup of the server side
  39 +========================
29 This script is to be executed as CGI-BIN script by a web server. As it is 40 This script is to be executed as CGI-BIN script by a web server. As it is
30 -written in Perl, it requires that installed (which is pretty standard nowadays  
31 -on all *nix platforms). This description covers the installation on Apache 2.4,  
32 -which should be similar for other web servers, with ISC Bind v9. For performance  
33 -reasons consider using the Apache mod_perl module for highly a volatile domain. 41 +written in Perl, it requires that installed (which is pretty standard on \*nix
  42 +platforms). This description covers the installation on Apache 2.4 and should be
  43 +similar for other web servers, with ISC Bind v9. For performance reasons
  44 +consider using the Apache mod_perl module for highly a volatile domain.
34 45
  46 +
  47 +<a name=installation>Installation</a>
  48 +-------------------------------------
35 The setup of this solution consists of the following steps: 49 The setup of this solution consists of the following steps:
36 50
37 1. Ensure that the Perl modules CGI and Net::DNS are installed. 51 1. Ensure that the Perl modules CGI and Net::DNS are installed.
38 - * on Debian/Ubunto linux this can be done by: 52 + * on Debian/Ubuntu linux this can be done by:
39 53
40 - ~~~~ 54 + ```
41 sudo apt-get install libcgi-pm-perl libnet-dns-perl 55 sudo apt-get install libcgi-pm-perl libnet-dns-perl
42 - ~~~~ 56 + ```
43 57
44 - * or if you have cpan installed: 58 + * or directly from CPAN (assuming that is installed):
45 59
46 - ~~~ 60 + ```
47 cpan CGI Net::DNS 61 cpan CGI Net::DNS
48 - ~~~ 62 + ```
49 63
50 2. Install the file `dyndns.pl` either in your cgi-bin directory or in a 64 2. Install the file `dyndns.pl` either in your cgi-bin directory or in a
51 separate folder 65 separate folder
@@ -60,22 +74,27 @@ The setup of this solution consists of the following steps: @@ -60,22 +74,27 @@ The setup of this solution consists of the following steps:
60 server's cgi-bin directory) add the following line to your Apache virtual 74 server's cgi-bin directory) add the following line to your Apache virtual
61 host configuration (replacing `[INSTALL_DIR]` with the install directory): 75 host configuration (replacing `[INSTALL_DIR]` with the install directory):
62 76
63 - ScriptAlias /dyndns [INSTALL_DIR]/dyndns.pl 77 + ```
  78 + ScriptAlias /dyndns [INSTALL_DIR]/dyndns.pl
  79 + ```
64 80
65 in case you have installed the script in a non-standard folder, you will 81 in case you have installed the script in a non-standard folder, you will
66 also need the following to make this work on Apache 2.4 (again replacing 82 also need the following to make this work on Apache 2.4 (again replacing
67 `[INSTALL_DIR]` with the install directory): 83 `[INSTALL_DIR]` with the install directory):
68 84
69 - ~~~ 85 + ```
70 <Directory [INSTALL_DIR]/> 86 <Directory [INSTALL_DIR]/>
71 AllowOverride None 87 AllowOverride None
72 Options +ExecCGI -MultiViews -Indexes 88 Options +ExecCGI -MultiViews -Indexes
73 Require all granted 89 Require all granted
74 </Directory> 90 </Directory>
75 - ~~~ 91 + ```
76 92
77 reload apache with `/etc/init.d/apache reload` to make the script 93 reload apache with `/etc/init.d/apache reload` to make the script
78 - available at <http://myserver.mydomain.tld/dyndns> 94 + available at <http://myserver.mydomain.tld/dyndns>.
  95 +
  96 + It is also possible to run as a virtual host, [see below](#VirtualHost) for
  97 + an example of that.
79 98
80 5. To setup your Bind nameserver, either update `named.conf` direcly or create 99 5. To setup your Bind nameserver, either update `named.conf` direcly or create
81 a separate file (e.g. `named.dyndns.conf` in the Bind configuration 100 a separate file (e.g. `named.dyndns.conf` in the Bind configuration
@@ -83,7 +102,7 @@ The setup of this solution consists of the following steps: @@ -83,7 +102,7 @@ The setup of this solution consists of the following steps:
83 (e.g. `include "named.dyndns.conf";`). For a basic dynamic DNS setup a 102 (e.g. `include "named.dyndns.conf";`). For a basic dynamic DNS setup a
84 configuration like below is required: 103 configuration like below is required:
85 104
86 - ~~~ 105 + ```
87 // Define the keys for DynDNS 106 // Define the keys for DynDNS
88 key "dyndns.mydomain.tld" { 107 key "dyndns.mydomain.tld" {
89 algorithm hmac-md5; secret "QdDJC7QVYmsCxgWoSAUmBg=="; 108 algorithm hmac-md5; secret "QdDJC7QVYmsCxgWoSAUmBg==";
@@ -106,13 +125,13 @@ The setup of this solution consists of the following steps: @@ -106,13 +125,13 @@ The setup of this solution consists of the following steps:
106 grant siteuser name site.dyndns.mydomain.tld ANY; 125 grant siteuser name site.dyndns.mydomain.tld ANY;
107 }; 126 };
108 }; 127 };
109 - ~~~ 128 + ```
110 129
111 The above defines a domain zone file `dyndns/db.dyndns.mydomain.tld` with 130 The above defines a domain zone file `dyndns/db.dyndns.mydomain.tld` with
112 two signer/keys. *siteuser* only can update `site.dyndns.mydomain.tld` 131 two signer/keys. *siteuser* only can update `site.dyndns.mydomain.tld`
113 while *dyndns.mydomain.tld* can update all entries in the domain (intended 132 while *dyndns.mydomain.tld* can update all entries in the domain (intended
114 for expiry). If you intend to use expiry or want to be able to retrieve a 133 for expiry). If you intend to use expiry or want to be able to retrieve a
115 - list of all entries, comment out the `allow-transfer` statement and update 134 + list of all entries, uncomment the `allow-transfer` statement and update
116 the IP adres to that of your web server. 135 the IP adres to that of your web server.
117 136
118 To seed these entries with fresh keys), use the following 137 To seed these entries with fresh keys), use the following
@@ -120,23 +139,23 @@ The setup of this solution consists of the following steps: @@ -120,23 +139,23 @@ The setup of this solution consists of the following steps:
120 139
121 * to generate a new key *dyndns.mydomain.tld*: 140 * to generate a new key *dyndns.mydomain.tld*:
122 141
123 - ~~~ 142 + ```
124 ddns-confgen -a hmac-md5 -k dyndns.mydomain.tld -z dyndns.mydomain.tld 143 ddns-confgen -a hmac-md5 -k dyndns.mydomain.tld -z dyndns.mydomain.tld
125 - ~~~ 144 + ```
126 145
127 * generate the required configuration for *siteuser* (or any new user): 146 * generate the required configuration for *siteuser* (or any new user):
128 147
129 - ~~~ 148 + ```
130 ddns-confgen -a hmac-md5 -k siteuser -s site.dyndns.mydomain.tld 149 ddns-confgen -a hmac-md5 -k siteuser -s site.dyndns.mydomain.tld
131 - ~~~ 150 + ```
132 151
133 6. Generate an initial zone file like the one below for the dyndns domain in 152 6. Generate an initial zone file like the one below for the dyndns domain in
134 the location specified in the config file above. 153 the location specified in the config file above.
135 154
136 - ~~~ 155 + ```
137 $TTL 3600 ; 1 hour 156 $TTL 3600 ; 1 hour
138 @ IN SOA auth.dns.mydomain.tld. hostmaster.mydomain.tld. ( 157 @ IN SOA auth.dns.mydomain.tld. hostmaster.mydomain.tld. (
139 - 2015051401 ; serial 158 + 2019000001 ; serial
140 43200 ; refresh (12 hours) 159 43200 ; refresh (12 hours)
141 3600 ; retry (1 hour) 160 3600 ; retry (1 hour)
142 86400 ; expire (24 hours) 161 86400 ; expire (24 hours)
@@ -145,7 +164,7 @@ The setup of this solution consists of the following steps: @@ -145,7 +164,7 @@ The setup of this solution consists of the following steps:
145 TXT "Dynamic DNS zone for mydomain.tld" 164 TXT "Dynamic DNS zone for mydomain.tld"
146 165
147 site A 1.2.3.4 166 site A 1.2.3.4
148 - ~~~ 167 + ```
149 168
150 Please note that Bind will rewrite this file and you need to be careful 169 Please note that Bind will rewrite this file and you need to be careful
151 with it. Entries do not need to exist initially, as long as the signer/key 170 with it. Entries do not need to exist initially, as long as the signer/key
@@ -168,38 +187,111 @@ The setup of this solution consists of the following steps: @@ -168,38 +187,111 @@ The setup of this solution consists of the following steps:
168 187
169 * <http://myserver.mydomain.tld/dyndns/list?domain=dyndns.mydomain.tld> 188 * <http://myserver.mydomain.tld/dyndns/list?domain=dyndns.mydomain.tld>
170 to list the entries in the domain (requires zone transfer rights!) 189 to list the entries in the domain (requires zone transfer rights!)
171 - * <http://myserver.mydomain.tld/dyndns/update?host=site.dyndns.mydomain.tld&user=siteuser&key=......> 190 + * <http://myserver.mydomain.tld/dyndns/update?host=site.dyndns.mydomain.tld&user=siteuser&secret=......>
172 to add/update a site and 191 to add/update a site and
173 - * <http://myserver.mydomain.tld/dyndns/delete?host=site.dyndns.mydomain.tld&user=siteuser&key=......> 192 + * <http://myserver.mydomain.tld/dyndns/delete?host=site.dyndns.mydomain.tld&user=siteuser&secret=......>
174 to delete (clear) it. 193 to delete (clear) it.
175 194
176 Please read the section below as well on the configuration and different modes 195 Please read the section below as well on the configuration and different modes
177 (operations) available. 196 (operations) available.
178 197
  198 +
179 <a name=configuration>Configuration</a> 199 <a name=configuration>Configuration</a>
180 --------------------------------------- 200 ---------------------------------------
181 -  
182 At the top of the script is a "Configuration" section, which contains the 201 At the top of the script is a "Configuration" section, which contains the
183 -configurable options of the scripts. 202 +configurable options of the scripts. As of version 1.1 the script also supports
  203 +a [configuration file](#config_file) so that modifying the script is no longer
  204 +required.
  205 +
184 206
185 Parameter | Description 207 Parameter | Description
186 -:----------------+:------------------------------------------------------------- 208 +:----------------|:-------------------------------------------------------------
  209 +`$ConfigFile` | Enable/disable config file support, [see below](config_file)
187 `$DNSServer` | IP address of the DNS Server to send DNS update requests to 210 `$DNSServer` | IP address of the DNS Server to send DNS update requests to
188 -`$ExpandCNAMEs` | Max. CNAME lookups for `$host` (0 to disable), see below 211 +`@DNSDomain` | How to determine the host's domain name, [see below](#conf_dnszone)
  212 +`$DomainListKey` | Secret required to use the list mode, set to '' to always enable and to 'off' to disable this mode
  213 +`$ExpandCNAMEs` | Max. CNAME lookups for `$host` (0 to disable), [see below](#conf_cname)
189 `$AllowDebugKey` | Output debug log after result when `debug` parameter equals this value. Set to '' to always enable and to 'off' to disable debugging 214 `$AllowDebugKey` | Output debug log after result when `debug` parameter equals this value. Set to '' to always enable and to 'off' to disable debugging
190 -`$AuthMode` | Defines how to authenticate DNS update requests, see below 215 +`$AuthMode` | Defines how to authenticate DNS update requests, [see below](#conf_auth)
191 `$StaticSigner` | Static signer ID to be used for AuthMode `static` or `both` 216 `$StaticSigner` | Static signer ID to be used for AuthMode `static` or `both`
192 `$StaticKey` | Static signing key to be used for AuthMode `static` or `both` 217 `$StaticKey` | Static signing key to be used for AuthMode `static` or `both`
193 -`$RequireRR` | Require an existing DNS record of this type to allow updates.  
194 -`$ExpireAfter` | Expire time for registrations in minutes, hours, weeks or seconds. Format is number optionally followed by m, h, w, s (seconds is default). 218 +`$RequireRR` | Require an existing DNS record of this type to allow updates
  219 +`$ExpireAfter` | Expire time for registrations in minutes, hours, weeks or seconds. Format is number optionally followed by m, h, w, s (seconds is default)
195 `@ReplaceRR` | List of DNS Record types to remove (clear) as part of update. 220 `@ReplaceRR` | List of DNS Record types to remove (clear) as part of update.
196 `$UpdateTXT` | Add host TXT record during update with this text followed by a timestamp. Used for expiry (so don't change!), leave empty to not add this 221 `$UpdateTXT` | Add host TXT record during update with this text followed by a timestamp. Used for expiry (so don't change!), leave empty to not add this
197 -`$DeleteTXT` | Set TXT record upon deletion with this text and a timestamp.  
198 -  
199 -Please note that the values must be correctly quoted, etc. not to break the script.  
200 -  
201 -  
202 -#### CNAME Support 222 +`$DeleteTXT` | Set TXT record upon deletion with this text and a timestamp.
  223 +`$RecordTTL` | TTL for created records in minutes, hours, weeks or seconds. Format is number optionally followed by m, h, w, s (seconds is default)
  224 +
  225 +Please note: when changing the script all values must be correctly quoted, etc.
  226 +not to break the script. Therefore as of version 1.1 a config file is supported
  227 +(preferred), [see below](config_file).
  228 +
  229 +
  230 +#### <a name=config_file>Configuration File</a>
  231 +The script can read its settings from a config located in the same directory as
  232 +the script and with the extension `.cfg` (ignoring a `.pl` extension) so the
  233 +default config file would be `dyndns.cfg`. The behavior of how to support the
  234 +config file is configured through the variable `$ConfigFile` and can be one of:
  235 + * `optional` - config file is read if it exists, this is the default
  236 + * `required` - config file is read and must exist (or the script will fail)
  237 + * `ignore` - config file is ignored and not read, configuration in the script
  238 +
  239 +The general format of the config file is `keyword = value`, see the table below
  240 +for a mapping of the parameters to keywords. For lists (variables starting with
  241 +a `@`) the value is comma-separated. The config file supports comments, ignores
  242 +empty lines, starting/trailing spaces and everything following a `#`. Refer to
  243 +`dyndns.cfg.dist` for an example config file. Please note that the script will
  244 +fail if it encounters an error or unknown keyword in the config file.
  245 +
  246 +Parameter | Config Setting | Default value
  247 +:-----------------|:-------------------|:------------------------------
  248 +`$AllowDebugKey` | `allow_debug_key` | `off` (debugging disabled)
  249 +`$AuthMode` | `auth_mode` | `remote` ([see below](#conf_auth))
  250 +`$DeleteTXT` | `delete_txt` | `DynDNS cleared on`
  251 +`$DNSServer` | `dns_server` | `192.168.1.1`
  252 +`@DNSDomain` | `dns_domain` | `?, !, 0` ([see below](#conf_dnszone))
  253 +`$DomainListKey` | `domain_list_key` | `off` (domain list disabled)
  254 +`$ExpandCNAMEs` | `expand_cnames` | `1` (1 level, [see below](#conf_cname))
  255 +`$ExpireAfter` | `expire_after` | `1w` (1 week, [see below](#expire))
  256 +`$RecordTTL` | `record_ttl` | `1h` (1 hour)
  257 +`$RequireRR` | `require_rr` |
  258 +`@ReplaceRR` | `replace_rr` | `A, AAAA, TXT`
  259 +`$StaticKey` | `static_key` |
  260 +`$StaticSigner` | `static_signer` |
  261 +`$UpdateTXT` | `update_txt` | `Last DynDNS update on`
  262 +
  263 +Please note that since `$ConfigFile` determines config file support, it cannot
  264 +be configured in the file. By default the config file is optional not to break
  265 +existing configurations.
  266 +
  267 +
  268 +#### <a name=conf_dnszone>DNS Zone (Domain Name) Selection</a>
  269 +In order to send the right update request to the DNS server, the correct DNS
  270 +zone to update must be determined based on the request's hostname. Most of the
  271 +time an update for `hostname.subdomain.mydomain.tld` is an update of `hostname`
  272 +the DNS zone `subdomain.mydomain.tld` and then the defaults are sufficient.
  273 +However, in some scenarios (e.g. one of my use cases) an update should be sent
  274 +for hostname `hostname.subdomain` in the zone `mydomain.tld` instead. The DNS
  275 +server cannot figure this out itself (at least ISC's Bind9 can not) so it is
  276 +implemented here.
  277 +
  278 +The array `@DNSDomain` contains a list of values matched against the hostname
  279 +to determine the DNS zone to update and can contain:
  280 +
  281 +Value | match hostname ending with
  282 +:----------------|:-------------------------------------------------------
  283 +`"?"` | the domain name from parameter `domain`
  284 +`"!"` | server name the HTTP(S) request was sent to
  285 +`0` | domain from hostname (strip of everythin till first `.`)
  286 +positive number | last # parts from hostname
  287 +negative number | last # parts of server name the HTTP(S) request was sent to
  288 +any other string | use value specified
  289 +
  290 +The first parameter matching the hostname's end will be used. The default is
  291 +`( '?', '!', 0 )`, which should be OK in most cases.
  292 +
  293 +
  294 +#### <a name=conf_cname>CNAME Support</a>
203 The script supports using separate subdomain (e.g. dyndns.mydomain.tld) for 295 The script supports using separate subdomain (e.g. dyndns.mydomain.tld) for
204 dynamic DNS and CNAMEs to entries in that subdomain from another zone (e.g. 296 dynamic DNS and CNAMEs to entries in that subdomain from another zone (e.g.
205 mydomain.tld). The advantage of such a setup is that only one zone (SOA file) 297 mydomain.tld). The advantage of such a setup is that only one zone (SOA file)
@@ -212,17 +304,18 @@ the host provided is a CNAME and if so, performs the request for the actual @@ -212,17 +304,18 @@ the host provided is a CNAME and if so, performs the request for the actual
212 hostname instead of the provided one. The value of `$ExpandCNAMEs` determines 304 hostname instead of the provided one. The value of `$ExpandCNAMEs` determines
213 the maximum number of CNAME lookups supported (so nesting is allowed and this 305 the maximum number of CNAME lookups supported (so nesting is allowed and this
214 limits the level of nesting to prevent loops). 306 limits the level of nesting to prevent loops).
  307 +
215 To disable lookups for CNAME expansion, set `$ExpandCNAMEs` to 0. 308 To disable lookups for CNAME expansion, set `$ExpandCNAMEs` to 0.
216 309
217 310
218 -#### Authentication Modes 311 +#### <a name=conf_auth>Authentication Modes</a>
219 For signing DNS update requests sent to the DNS server the script supports 3 312 For signing DNS update requests sent to the DNS server the script supports 3
220 ways to obtain the signer and key: 313 ways to obtain the signer and key:
221 314
222 AuthMode | Description 315 AuthMode | Description
223 -:--------+:--------------------------------------------------------------------- 316 +:--------|:---------------------------------------------------------------------
224 *static* | use only static authentication information from `$StaticSigner` and`$StaticKey` (and ignore authentication information provided in the request) 317 *static* | use only static authentication information from `$StaticSigner` and`$StaticKey` (and ignore authentication information provided in the request)
225 -*remote* | use only authentication information provided in the request 318 +*remote* | use only authentication information provided in the request
226 *both* | use authentication information provided in the request (fields `user` and `secret`) when provided, otherwise use static values from `$StaticSigner` and `$StaticKey`. Please note that this is checked per parameter 319 *both* | use authentication information provided in the request (fields `user` and `secret`) when provided, otherwise use static values from `$StaticSigner` and `$StaticKey`. Please note that this is checked per parameter
227 320
228 321
@@ -230,51 +323,59 @@ Supported Operations @@ -230,51 +323,59 @@ Supported Operations
230 -------------------- 323 --------------------
231 The script can perform the following operations (modes): 324 The script can perform the following operations (modes):
232 325
233 -Mode | Description | Required Parameters | Optional Parameters  
234 -:------+:-------------------------+:--------------------+:----------------------  
235 -list | Show DDNS domain entries | `domain`__**__ |  
236 -view | Show DDNS hostname entry | `host` |  
237 -update | Update/add a DDNS host | `host` + auth.__*__ | `ipv4addr`, `ipv6addr`  
238 -delete | Remove DDNS registration | `host` + auth.__*__ |  
239 -expire | Expire registrations | `domain`__**__ + auth.__*__ 326 +Mode | Description | Required Parameters | Optional Parameters
  327 +:------|:-----------------------|:--------------------|:----------------------
  328 +list | List zone __***__ | `secret` __***__ | `domain`__**__
  329 +view | Show host's DNS entry | `host` |
  330 +update | Update/add a DDNS host | `host` + auth.__*__ | `ipv4addr`, `ipv6addr`
  331 +delete | Remove registration | `host` + auth.__*__ |
  332 +expire | Expire registrations | `domain`__**__ + auth.__*__
240 333
241 -__*__ Modes that change registrations require authentication, depending on the  
242 - value of `$AuthMode` the parameters `user` and `secret` may be required 334 +__*__ modes that change DNS require authentication, depending on the value of
  335 + `$AuthMode` the parameters `user` and `secret` may be required
243 (`$AuthMode` *remote*) required or optional (`$AuthMode` *both*) 336 (`$AuthMode` *remote*) required or optional (`$AuthMode` *both*)
244 337
245 __**__ in case `domain` is omitted, it will be determined using the `host` 338 __**__ in case `domain` is omitted, it will be determined using the `host`
246 - parameter, if provided  
247 -  
248 -  
249 -#### Parameters  
250 -The script supports the following parameters (please see the table above for which is needed for what mode):  
251 -  
252 -Parameter | Description  
253 -:---------+:--------------------------------------------------------------------  
254 -`mode` | the action to perform (if not provided as part of the path name)  
255 -`domain` | domain for list/expire request, determined from `host` if ommitted  
256 -`host` | hostname to act on, expand CNAMEs max. `$ExpandCNAMEs` levels deep  
257 -`ip` | alias / shortcut for `ipv4addr`  
258 -`ipv4addr`| The IPv4 address to register for the host (update mode only) __*__  
259 -`ipv6addr`| The IPv6 address to register for the host (update mode only) __*__  
260 -`user` | signer of the DNS Update, used for `AuthMode` *remote* and *both*  
261 -`key` | key to sign the DNS Update, used for `AuthMode` *remote* and *both*  
262 -`debug` | debug key, show debug information if this equals `$AllowDebugKey`  
263 -  
264 -__*__ in update mode, if `ipv4addr` or `ipv6addr` is not provided with the 339 + parameter, if provided, or by using the virtualhost the script runs on
  340 + based on the `@DNSDomain` setting
  341 +
  342 +__***__ list mode is only available when `$DomainListKey` is not set to `off`,
  343 + in case `$DomainListKey` is not empty, `secret` is required and must
  344 + equal the key in `$DomainListKey`
  345 +
  346 +
  347 +#### <a name=req_params>Request Parameters</a>
  348 +The script supports (requires) the following parameters (please see the table
  349 +above for which is needed for what mode):
  350 +
  351 +Parameter | Description
  352 +:----------|:-------------------------------------------------------------------
  353 +`mode` | the action to perform (if not provided as part of the path name)
  354 +`domain` | domain for list/expire request, determined from `host` if ommitted
  355 +`host` | hostname to act on, expand CNAMEs max. `$ExpandCNAMEs` levels deep
  356 +`ip` | alias / shortcut for `ipv4addr`
  357 +`ipv4addr` | The IPv4 address to register for the host (update mode only) __*__
  358 +`ipv6` | alias / shortcut for `ipv6addr`
  359 +`ipv6addr` | The IPv6 address to register for the host (update mode only) __*__
  360 +`user` | signer of the DNS Update, used for `AuthMode` *remote* and *both*
  361 +`secret` | key to sign the DNS Update, used for `AuthMode` *remote* and *both*, also used as `$DomainListKey` for list mode.
  362 +`debug` | debug key, show debug information if this equals `$AllowDebugKey`
  363 +
  364 +__*__ in update mode, if `ipv4addr` or `ipv6addr` is set to `auto` in the
265 request, the CGI variable `$REMOTE_ADDR` (the client address), its value 365 request, the CGI variable `$REMOTE_ADDR` (the client address), its value
266 - will be used instead as IPv4/IPv6 address. 366 + will be used instead as IPv4/IPv6 address. __Please Note__ that if both
  367 + are omitted existing addresses will be removed!
267 368
268 369
269 -#### <a name="invoking">Invoking the script</a> 370 +#### <a name=invoking>Invoking the script</a>
270 The script is implemented using the perl CGI module so for testing purposes it 371 The script is implemented using the perl CGI module so for testing purposes it
271 can be called from the command line with parameters as arguments, i.e. 372 can be called from the command line with parameters as arguments, i.e.
272 373
273 ./dyndns.pl mode=expire domain=mydomain.tld debug=.... 374 ./dyndns.pl mode=expire domain=mydomain.tld debug=....
274 375
275 -Which is quite handy for debugging purposes. Please note that the Perl CGI  
276 -library sets `$REMOTE_ADDR` to 127.0.0.1 and that the output will always be  
277 -the HTML-based result. 376 +Which is quite handy for debugging. Please note that the Perl CGI library sets
  377 +`$REMOTE_ADDR` to 127.0.0.1, the server name in this case will be `localhost`
  378 +and that the output is the HTML result.
278 379
279 The standard way to use the script is to place it in the cgi-bin folder your 380 The standard way to use the script is to place it in the cgi-bin folder your
280 server, which allows it to be called as: 381 server, which allows it to be called as:
@@ -295,14 +396,54 @@ When combining the setup would become: @@ -295,14 +396,54 @@ When combining the setup would become:
295 396
296 http://myserver.mydomain.tld/dyndns/list?domain=mydomain.tld&debug=... 397 http://myserver.mydomain.tld/dyndns/list?domain=mydomain.tld&debug=...
297 398
  399 +If using a dedicated virtual host [see below](#VirtualHost) it becomes:
  400 +
  401 + http://myserver.mydomain.tld/list?domain=mydomain.tld&debug=...
  402 +
298 Which is how I use it. 403 Which is how I use it.
299 404
300 405
  406 +### <a name=expire>Expiring Records</a>
  407 +The script can expire registrations after a while. For this, it must add a TXT
  408 +record containing the date of the last change (on by default) and when requested
  409 +it will remove any entry older than the value configured in `$ExpireAfter`.
  410 +
  411 +Please note that:
  412 + * as this is dependent on the value of a TXT record, it may fail if these
  413 + records are updated through another method.
  414 + * there is no security implemented (other than the value of `$ExpireAfter`)
  415 +
  416 +To initiate the expiry, the script must be called with two parameters:
  417 + 1. `mode` should be set to `expire`
  418 + 2. `domain` must be set to the DNS Zone (domain) to run against.
  419 +
  420 +Both can be setup easily in cron with entries like:
  421 +
  422 +~~~
  423 +# Samples to run the expiry every hour
  424 +
  425 +# Cron fields definition:
  426 +#.---------------- minute (0 - 59)
  427 +#| .------------- hour (0 - 23)
  428 +#| | .---------- day of month (1 - 31)
  429 +#| | | .------- month (1 - 12) OR jan,feb,mar,apr ...
  430 +#| | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
  431 +#| | | | |
  432 +#* * * * * user-name command to be executed
  433 +
  434 +# Directly run the script, does not require specific permissions
  435 +15 * * * * www-data [INSTALL_DIR]/dyndns.pl mode=expire domain=mydomain.tld
  436 +
  437 +# example using curl
  438 +15 * * * * www-data curl https://myserver.mydomain.tld/expire?domain=mydomain.tld > /dev/null
  439 +~~~
  440 +
  441 +
301 Name Server Setup Requirements 442 Name Server Setup Requirements
302 ------------------------------ 443 ------------------------------
303 As the script is only translating requests, depends heavily on the setup of the 444 As the script is only translating requests, depends heavily on the setup of the
304 nameserver. The DNS server (obviously) needs to allow DNS updates. In addition 445 nameserver. The DNS server (obviously) needs to allow DNS updates. In addition
305 -to the setup described above, please note that: 446 +to the setup described above, please note that:
306 447
307 * For the modes list and expire to work, the script needs to perform a DNS 448 * For the modes list and expire to work, the script needs to perform a DNS
308 zone transfer (AXFR). This must be allowed for the host running the script. 449 zone transfer (AXFR). This must be allowed for the host running the script.
@@ -314,22 +455,191 @@ to the setup described above, please note that: @@ -314,22 +455,191 @@ to the setup described above, please note that:
314 used Perl Net::DNS library). The keys setup in the nameservers must 455 used Perl Net::DNS library). The keys setup in the nameservers must
315 therefore be of the same time or authentication won't work. 456 therefore be of the same time or authentication won't work.
316 457
317 -The solution scales reasonable well, although adding the keys to the nameserver  
318 -configuration is still manual in my setup (but since it does not happen that  
319 -often, it's no hassle). This setup has been tested against ISC Bind version 9.  
320 - 458 +This setup has been tested against ISC Bind version 9 and scales pretty well.
  459 +Adding the keys to the nameserver configuration is still manual in my setup but
  460 +bit difficult script, if needed.
  461 +
  462 +
  463 +<a name=VirtualHost>Configure as Virtual Host</a>
  464 +-------------------------------------------------
  465 +Running dyndns.pl on a Virtual Host is possible using `mod_rewrite`. This is how
  466 +I use it as it allows the URLs to become even more simple, e.g.:
  467 +
  468 + * to update: `https://dyndns.mydomain.tld/update/hostname.mydomain.tld?secret=...`
  469 + * to delete: `https://dyndns.mydomain.tld/delete/hostname.mydomain.tld?secret=...`
  470 + * to view: `https://dyndns.mydomain.tld/view/hostname.mydomain.tld`
  471 + * to list: `https://dyndns.mydomain.tld/list/mydomain.tld?secret=...`
  472 + * to expire: `https://dyndns.mydomain.tld/expire/mydomain.tld`
  473 +
  474 +An example Apache 2.4 config is shown below (please replace `[INSTALL_DIR]` with
  475 +the install directory and obviously replace the server name as well):
  476 +
  477 +~~~
  478 +<VirtualHost *:80 *:443>
  479 + ServerName dyndns.mydomain.tld
  480 +
  481 + # Enable URL Rewriting
  482 + RewriteEngine On
321 483
322 -<a name="license">License</a>  
323 ------------------------------  
324 -This script, documentation and configration examples are free software: you can 484 + # Enforce HTTPS access
  485 + RewriteCond %{HTTPS} off
  486 + RewriteRule / https://%{HTTP_HOST}%{REQUEST_URI} [R]
  487 +
  488 + # re-route everything to the dyndns script
  489 + RewriteRule (.*) /dyndns/$1 [PT]
  490 +
  491 + ScriptAlias /dyndns [INSTALL_DIR]/dyndns.pl
  492 +
  493 + <Directory [INSTALL_DIR]>
  494 + AllowOverride None
  495 + Options +ExecCGI -MultiViews
  496 + Require all granted
  497 + </Directory>
  498 +
  499 +</VirtualHost>
  500 +~~~
  501 +
  502 +
  503 +<a name=integration>Integration with devices</a>
  504 +================================================
  505 +Integration on routers and other devices is straigtforward, provided do support
  506 +DDNS registrations using a custom URL. The Basic format for the registration
  507 +URL to register is:
  508 +
  509 +~~~
  510 +https://SERVER/cgi-bin/dyndns/update?host=HOSTNAME&ip=IPADDRESS&secret=KEY`
  511 +~~~
  512 +
  513 +Check the [list of parameters supported](req_params) for all available options,
  514 +the above URL contains the absolute minimum where:
  515 +
  516 +Parameter | Value
  517 +:-----------|:---------------------------------------------------------------
  518 +`SERVER` | is the host the script is installed on
  519 +`HOSTNAME` | is the client's hostname as configured in the DNS server
  520 +`SECRET` | is the secret key as configured in the DNS server
  521 +`IPADDRESS` | is the ipv4 address (often dynamic, can also be set to `auto`)
  522 +
  523 +Depending on how you have configured the URL of the script to be, the path
  524 +(`/cgi-bin/dyndns/` may need to be altered as per your setup).
  525 +
  526 +Please note that:
  527 + * The generated secret may contain a `+`, which must be encoded correctly in
  528 + the request or it will fail. I found that not all clients (e.g. a Fritz!Box)
  529 + do this correctly, make sure that your secrets either don't contain a `+`
  530 + or encode it manually (replace any `+` with `%2B` in that case).
  531 + * In case the IP address of the device is behind NAT and you want to have the
  532 + public address register, use the `auto` value for parameters `ip`/`ipv4addr`
  533 + and `ipv6`/`ipv6addr` to have the script auto-detect it (though that this
  534 + can only be used for either an IPv4 or an IPv6 address and will only work
  535 + for devices registering using that protocol!)
  536 + * Some devices have a preference to connect over IPv6 (e.g. Cisco routers).
  537 + This can be used to register the IPv4 and IPv6 addresses together by passing
  538 + the IPv4 address as parameter en setting the IPv6 parameter to `auto`.
  539 + * Some devices (e.g. a Fritz!Box) support a separate URL for IPv4 and IPv6
  540 + registrations. Unfortunately this script cannot handle this yet and will
  541 + unregister a previous registration when the second request comes in. Please
  542 + raise a ticket if you have such a situation to work on a solution together.
  543 +
  544 +To check whether the client's registration was successful (and correct) visit:
  545 +
  546 +~~~
  547 +https://SERVER/cgi-bin/dyndns/view?host
  548 +~~~
  549 +
  550 +
  551 +<a name=cisco_integration>Cisco Routers</a>
  552 +-------------------------------------------
  553 +For Cisco routers add the following config:
  554 +
  555 +```
  556 +ip ddns update method DYNDNS
  557 + HTTP
  558 + add https://SERVER/cgi-bin/dyndns/update?host=<h>&ip=<a>&secret=SECRET
  559 + remove https://SERVER/cgi-bin/dyndns/delete?host=<h>&secret=SECRET
  560 + interval maximum 0 1 0 0
  561 +```
  562 +
  563 +replacing `SERVER` for the host the script is installed on and `SECRET`
  564 +for a DNS key authorized to update the record. The cisco router will replace <a>
  565 +and <h> with the IPv4 address and hostname.
  566 +
  567 +To setup interface `Dialer0` to register as `hostname.dyndns.mydomain.tld` add:
  568 +
  569 +```
  570 +interface Dialer0
  571 + ip ddns update hostname hostname.dyndns.mydomain.tld
  572 + ip ddns update DYNDNS
  573 +```
  574 +
  575 +Which instructs to register using the address of Dialer0 as soon as that is up
  576 +or changes (this also works for non-dialer devices).
  577 +
  578 +Please note that before entering the `?` as part of the URL, a `CTRL`-`V` is
  579 +required to prevent the Cisco CLI to list the available command parameters.
  580 +
  581 +
  582 +<a name=fritzbox_integration>AVM Fritz!Box routers</a>
  583 +------------------------------------------------------
  584 +To setup DynDNS on a Fritz!Box perform the following steps:
  585 + * Login to your Fritz!Box as an admin user
  586 + * Open the 'Internet' menu an go through the 'External Access' page
  587 + * Open the 'DynDNS' tab
  588 + * Enable the 'Use DynDNS' checkbox
  589 + * Select DynDNS Provider: 'User-defined'
  590 + * Enter the following data (replacing `YOURDOMAIN` with your DynDNS domain
  591 + and `SERVER` with your server name - check the rest of the URL as well!)
  592 + - Update URL: `https://SERVER/cgi-bin/dyndns/update?host=<domain>&ip=<ipaddr>&secret=<pass>`
  593 + - Domain name: hostname setup in DNS
  594 + - Username/Email: put here something, not used unless you add it to the URL
  595 + - Password: secret key setup in DNS
  596 + * Click 'Apply' to store and activate the DDNS registrations
  597 +
  598 +Check [this page](https://service.avm.de/help/en/FRITZ-Box-7581/017p2/hilfe_dyndns)
  599 +for the available parameters that can be substituted in the URL.
  600 +
  601 +The status of the DynDNS registrations can be seen in the 'Internet' menu on the
  602 +'Online Monitor' page.
  603 +
  604 +To stop DynDNS registrations, uncheck 'Use DynDNS' from the same screen.
  605 +
  606 +
  607 +<a name=synology_integration>Synology DSM (NAS)</a>
  608 +---------------------------------------------------
  609 +To setup DynDNS on a Synology NAS (DSM 6 or later) perform the following steps:
  610 + * Login to your Synology NAS DSM as an admin user
  611 + * Open the Control Panel and go to 'External Access'
  612 + * Click 'Customize' to add a new DDNS provider
  613 + * Enter the following data (replacing `YOURDOMAIN` with your DynDNS domain
  614 + and `SERVER` with your server name - check the rest of the URL as well!)
  615 + - Service Provider: `YOURDOMAIN`
  616 + - Query URL `https://SERVER/cgi-bin/dyndns/update?host=__HOSTNAME__&ip=__MYIP__&secret=__PASSWORD__`
  617 + * Click Save to store the custom DDNS provider
  618 + * Click Add to register the DDNS registration and enter:
  619 + - Service Provider: select the name you have just added (`*YOURDOMAIN`)
  620 + - Hostname: hostname setup in DNS
  621 + - Username/Email: put here something, not used unless you add it to the URL
  622 + - Password/Key: secret key setup in DNS
  623 + * Click 'OK' to store and activate the DDNS registrations
  624 +
  625 +After a while the screen should display that the status is Normal and when the
  626 +last update occurred.
  627 +
  628 +To stop DDNS registrations, 'Delete' the registration from the same screen.
  629 +
  630 +
  631 +<a name=license>License</a>
  632 +=============================
  633 +This script, documentation and configuration examples are free software: you can
325 redistribute and/or modify it under the terms of the GNU General Public License 634 redistribute and/or modify it under the terms of the GNU General Public License
326 as published by the Free Software Foundation, either version 3 of the License, 635 as published by the Free Software Foundation, either version 3 of the License,
327 or (at your option) any later version. 636 or (at your option) any later version.
328 637
329 -This script, documenatation and configuration examples are distributed in the 638 +This script, documentation and configuration examples are distributed in the
330 hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied 639 hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
331 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 640 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
332 General Public License for more details. 641 General Public License for more details.
333 642
334 You should have received a copy of the GNU General Public License along with 643 You should have received a copy of the GNU General Public License along with
335 this program. If not, download it from <http://www.gnu.org/licenses/>. 644 this program. If not, download it from <http://www.gnu.org/licenses/>.
  645 +