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 2 =========
3 3  
4 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 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 12 GNU License, see [below](#license)
12 13  
13 14  
14 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 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 49 The setup of this solution consists of the following steps:
36 50  
37 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 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 61 cpan CGI Net::DNS
48   - ~~~
  62 + ```
49 63  
50 64 2. Install the file `dyndns.pl` either in your cgi-bin directory or in a
51 65 separate folder
... ... @@ -60,22 +74,27 @@ The setup of this solution consists of the following steps:
60 74 server's cgi-bin directory) add the following line to your Apache virtual
61 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 81 in case you have installed the script in a non-standard folder, you will
66 82 also need the following to make this work on Apache 2.4 (again replacing
67 83 `[INSTALL_DIR]` with the install directory):
68 84  
69   - ~~~
  85 + ```
70 86 <Directory [INSTALL_DIR]/>
71 87 AllowOverride None
72 88 Options +ExecCGI -MultiViews -Indexes
73 89 Require all granted
74 90 </Directory>
75   - ~~~
  91 + ```
76 92  
77 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 99 5. To setup your Bind nameserver, either update `named.conf` direcly or create
81 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 102 (e.g. `include "named.dyndns.conf";`). For a basic dynamic DNS setup a
84 103 configuration like below is required:
85 104  
86   - ~~~
  105 + ```
87 106 // Define the keys for DynDNS
88 107 key "dyndns.mydomain.tld" {
89 108 algorithm hmac-md5; secret "QdDJC7QVYmsCxgWoSAUmBg==";
... ... @@ -106,13 +125,13 @@ The setup of this solution consists of the following steps:
106 125 grant siteuser name site.dyndns.mydomain.tld ANY;
107 126 };
108 127 };
109   - ~~~
  128 + ```
110 129  
111 130 The above defines a domain zone file `dyndns/db.dyndns.mydomain.tld` with
112 131 two signer/keys. *siteuser* only can update `site.dyndns.mydomain.tld`
113 132 while *dyndns.mydomain.tld* can update all entries in the domain (intended
114 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 135 the IP adres to that of your web server.
117 136  
118 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 139  
121 140 * to generate a new key *dyndns.mydomain.tld*:
122 141  
123   - ~~~
  142 + ```
124 143 ddns-confgen -a hmac-md5 -k dyndns.mydomain.tld -z dyndns.mydomain.tld
125   - ~~~
  144 + ```
126 145  
127 146 * generate the required configuration for *siteuser* (or any new user):
128 147  
129   - ~~~
  148 + ```
130 149 ddns-confgen -a hmac-md5 -k siteuser -s site.dyndns.mydomain.tld
131   - ~~~
  150 + ```
132 151  
133 152 6. Generate an initial zone file like the one below for the dyndns domain in
134 153 the location specified in the config file above.
135 154  
136   - ~~~
  155 + ```
137 156 $TTL 3600 ; 1 hour
138 157 @ IN SOA auth.dns.mydomain.tld. hostmaster.mydomain.tld. (
139   - 2015051401 ; serial
  158 + 2019000001 ; serial
140 159 43200 ; refresh (12 hours)
141 160 3600 ; retry (1 hour)
142 161 86400 ; expire (24 hours)
... ... @@ -145,7 +164,7 @@ The setup of this solution consists of the following steps:
145 164 TXT "Dynamic DNS zone for mydomain.tld"
146 165  
147 166 site A 1.2.3.4
148   - ~~~
  167 + ```
149 168  
150 169 Please note that Bind will rewrite this file and you need to be careful
151 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 187  
169 188 * <http://myserver.mydomain.tld/dyndns/list?domain=dyndns.mydomain.tld>
170 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 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 193 to delete (clear) it.
175 194  
176 195 Please read the section below as well on the configuration and different modes
177 196 (operations) available.
178 197  
  198 +
179 199 <a name=configuration>Configuration</a>
180 200 ---------------------------------------
181   -
182 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 207 Parameter | Description
186   -:----------------+:-------------------------------------------------------------
  208 +:----------------|:-------------------------------------------------------------
  209 +`$ConfigFile` | Enable/disable config file support, [see below](config_file)
187 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 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 216 `$StaticSigner` | Static signer ID to be used for AuthMode `static` or `both`
192 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 220 `@ReplaceRR` | List of DNS Record types to remove (clear) as part of update.
196 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 295 The script supports using separate subdomain (e.g. dyndns.mydomain.tld) for
204 296 dynamic DNS and CNAMEs to entries in that subdomain from another zone (e.g.
205 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 304 hostname instead of the provided one. The value of `$ExpandCNAMEs` determines
213 305 the maximum number of CNAME lookups supported (so nesting is allowed and this
214 306 limits the level of nesting to prevent loops).
  307 +
215 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 312 For signing DNS update requests sent to the DNS server the script supports 3
220 313 ways to obtain the signer and key:
221 314  
222 315 AuthMode | Description
223   -:--------+:---------------------------------------------------------------------
  316 +:--------|:---------------------------------------------------------------------
224 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 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 323 --------------------
231 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 336 (`$AuthMode` *remote*) required or optional (`$AuthMode` *both*)
244 337  
245 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 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 371 The script is implemented using the perl CGI module so for testing purposes it
271 372 can be called from the command line with parameters as arguments, i.e.
272 373  
273 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 380 The standard way to use the script is to place it in the cgi-bin folder your
280 381 server, which allows it to be called as:
... ... @@ -295,14 +396,54 @@ When combining the setup would become:
295 396  
296 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 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 442 Name Server Setup Requirements
302 443 ------------------------------
303 444 As the script is only translating requests, depends heavily on the setup of the
304 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 448 * For the modes list and expire to work, the script needs to perform a DNS
308 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 455 used Perl Net::DNS library). The keys setup in the nameservers must
315 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 634 redistribute and/or modify it under the terms of the GNU General Public License
326 635 as published by the Free Software Foundation, either version 3 of the License,
327 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 639 hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
331 640 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
332 641 General Public License for more details.
333 642  
334 643 You should have received a copy of the GNU General Public License along with
335 644 this program. If not, download it from <http://www.gnu.org/licenses/>.
  645 +
... ...