Author Topic: [SOLVED] Configuring DNS updates for all DHCP leases (not just domain members)?  (Read 2127 times)

opensesame

  • Zen Apprentice
  • *
  • Posts: 3
  • Karma: +1/-0
    • View Profile
Context: Zentyal 5.0, with the following roles selected during installation:-
 - Domain Controller and File Sharing
 - DNS Server
 - DHCP Server

I have Zentyal running as a domain controller and I am happy with the configuration with the exception that I would like all hosts obtaining an IP address from the DHCP server to trigger a DNS update.

I should note that I have enabled Dynamic DNS and the 'Dynamic domain' and 'Static domain' settings have been configured.

However, it seems that only hosts that have joined the domain are able to trigger a DNS update. Furthermore, it is the host itself that is updating the DNS entries, rather than the DHCP server.

Example of a failed update (representative of both Windows, Linux, Android, other hosts):
Code: [Select]
Aug  8 16:51:29 dc1 dhcpd[1335]: DHCPACK on 192.168.1.10 to aa:bb:cc:dd:ee:ff via eth0
Aug  8 16:51:29 dc1 named[1474]: samba_dlz: starting transaction on zone internal.example.com
Aug  8 16:51:29 dc1 named[1474]: samba_dlz: spnego update failed
Aug  8 16:51:29 dc1 named[1474]: client 127.0.0.1#31281/key internal.example.com: updating zone 'internal.example.com/NONE': update failed: rejected by secure update (REFUSED)
Aug  8 16:51:29 dc1 named[1474]: samba_dlz: cancelling transaction on zone internal.example.com
Aug  8 16:51:29 dc1 dhcpd[1335]: Unable to add forward map from tst-linux.internal.example.com. to 192.168.1.10: REFUSED

Example of a successful update after the Windows host has joined the domain (note that the DHCP server is still trying to perform updates and these are still failing):
Code: [Select]
Aug  8 18:54:26 dc1 named[1474]: client 127.0.0.1#31281/key internal.example.com: updating zone '1.168.192.in-addr.arpa/IN': deleting rrset at '110.1.168.192.in-addr.arpa' PTR
Aug  8 18:54:26 dc1 named[1474]: client 127.0.0.1#31281/key internal.example.com: updating zone '1.168.192.in-addr.arpa/IN': adding an RR at '110.1.168.192.in-addr.arpa' PTR wintst.internal.example.com.
Aug  8 18:54:26 dc1 dhcpd[1335]: DHCPREQUEST for 192.168.1.110 from 11:22:33:44:55:66 (wintst) via eth0
Aug  8 18:54:26 dc1 dhcpd[1335]: DHCPACK on 192.168.1.110 to 11:22:33:44:55:66 (wintst) via eth0
Aug  8 18:54:26 dc1 dhcpd[1335]: Added reverse map from 110.1.168.192.in-addr.arpa. to wintst.internal.example.com
Aug  8 18:54:35 dc1 named[1474]: samba_dlz: starting transaction on zone internal.example.com
Aug  8 18:54:35 dc1 named[1474]: client 192.168.1.110#59072: update 'internal.example.com/IN' denied
Aug  8 18:54:35 dc1 named[1474]: samba_dlz: cancelling transaction on zone internal.example.com
Aug  8 18:54:35 dc1 named[1474]: samba_dlz: starting transaction on zone internal.example.com
Aug  8 18:54:35 dc1 named[1474]: samba_dlz: allowing update of signer=WINTST\$\@INTERNAL.EXAMPLE.COM name=wintst.internal.example.com tcpaddr= type=AAAA key=892-ms-7.1-608e.11111111-2222-3333-4444-555555555555/160/0
Aug  8 18:54:35 dc1 named[1474]: samba_dlz: allowing update of signer=WINTST\$\@INTERNAL.EXAMPLE.COM name=wintst.internal.example.com tcpaddr= type=A key=892-ms-7.1-608e.11111111-2222-3333-4444-555555555555/160/0
Aug  8 18:54:35 dc1 named[1474]: samba_dlz: allowing update of signer=WINTST\$\@INTERNAL.EXAMPLE.COM name=wintst.internal.example.com tcpaddr= type=A key=892-ms-7.1-608e.11111111-2222-3333-4444-555555555555/160/0
Aug  8 18:54:35 dc1 named[1474]: client 192.168.1.110#57633/key WINTST\$\@INTERNAL.EXAMPLE.COM: updating zone 'internal.example.com/NONE': deleting rrset at 'wintst.internal.example.com' AAAA
Aug  8 18:54:35 dc1 named[1474]: client 192.168.1.110#57633/key WINTST\$\@INTERNAL.EXAMPLE.COM: updating zone 'internal.example.com/NONE': deleting rrset at 'wintst.internal.example.com' A
Aug  8 18:54:35 dc1 named[1474]: samba_dlz: subtracted rdataset wintst.internal.example.com 'wintst.internal.example.com.#0111200#011IN#011A#011192.168.1.110'
Aug  8 18:54:35 dc1 named[1474]: client 192.168.1.110#57633/key WINTST\$\@INTERNAL.EXAMPLE.COM: updating zone 'internal.example.com/NONE': adding an RR at 'wintst.internal.example.com' A 192.168.1.110
Aug  8 18:54:35 dc1 named[1474]: samba_dlz: added rdataset wintst.internal.example.com 'wintst.internal.example.com.#0111200#011IN#011A#011192.168.1.110'
Aug  8 18:54:35 dc1 named[1474]: samba_dlz: committed transaction on zone internal.example.com

Is there a recommended way to have this work with Zentyal?

I have come across the approach described in the following link, which is probably worth investigating further. But I would like to avoid fighting against Zentyal too much if I can avoid it.
https://wiki.samba.org/index.php/Configure_DHCP_to_update_DNS_records_with_BIND9
« Last Edit: August 11, 2017, 07:33:19 am by opensesame »

opensesame

  • Zen Apprentice
  • *
  • Posts: 3
  • Karma: +1/-0
    • View Profile
Re: Configuring DNS updates for all DHCP leases (not just domain members)?
« Reply #1 on: August 11, 2017, 07:32:20 am »
Using the link referenced above I have been able to get this working. I think it should operate without clashing with Zentyal for the most part.

Prepare the user and keytab:
Code: [Select]
$ sudo samba-tool user create dhcpduser --description="Unprivileged user for TSIG-GSSAPI DNS updates via ISC DHCP server" --random-password
$ sudo samba-tool user setexpiry dhcpduser --noexpiry
$ sudo samba-tool group addmembers DnsAdmins dhcpduser

$ sudo samba-tool domain exportkeytab --principal=dhcpduser@INTERNAL.EXAMPLE.COM /etc/dhcp/dhcpduser.keytab
$ sudo chown dhcpd:dhcpd /etc/dhcp/dhcpduser.keytab
$ sudo chmod 400 /etc/dhcp/dhcpduser.keytab

Create the update script:
Code: [Select]
$ sudo mkdir -p /etc/dhcp/bin
$ sudo vi /etc/dhcp/bin/dhcp-dyndns.sh
[REFER TO ATTACHED FILE]
$ sudo chmod 755 /etc/dhcp/bin/dhcp-dyndns.sh

Zentyal recreates configuration files when modules are restarted. To make modifications to these files we need to create a hook script.
This script adds event statements to the dhcpd.conf that will call our update script, as well as AppArmor rules to give the dhcpd process access to everything the update script requires (note: I do not have much experience with AppArmor so these rules are very much just created with a view to just getting things working, and I welcome any suggestions for improvement).
Code: [Select]
$ sudo cp /etc/zentyal/hooks/template.postsetconf /etc/zentyal/hooks/dhcp.postsetconf
$ sudo vi /etc/zentyal/hooks/dhcp.postsetconf
[REFER TO ATTACHED FILE]

Restart the DHCP module from the dashboard.

Forward mapping was working successfully at this point but the adding of reverse map entries was still failing. Example:
Code: [Select]
Aug 10 18:16:51 dc1 named[15482]: client 127.0.0.1#60469/key dhcpduser\@INTERNAL.EXAMPLE.COM: updating zone '1.168.192.in-addr.arpa/IN': update failed: rejected by secure update (REFUSED)
Aug 10 18:16:51 dc1 sh[1307]: update failed: REFUSED
Aug 10 18:16:51 dc1 dhcpd: DHCP-DNS Update failed: 02
Aug 10 18:16:51 dc1 dhcpd[1307]: execute: /etc/dhcp/bin/dhcp-dyndns.sh exit status 512

Add the reverse zone to Samba (it is currently defined in named.conf.local but the named.conf.local.mas file checks if it is in Samba already before adding the definition):
Code: [Select]
$ sudo samba-tool dns zonecreate dc1 1.168.192.in-addr.arpa -k yes

Restart the DNS module from the dashboard.

The dashboard reports that the module restart failed and suggests checking /var/log/zentyal/zentyal.log. However, PTR records are now successfully being created.

From /var/log/zentyal/zentyal.log:
Code: [Select]
2017/08/10 18:20:17 ERROR> RestartService.pm:61 EBox::SysInfo::CGI::RestartService::_process - Restart of DNS from dashboard failed: root command nsupdate -l -t 10 /var/lib/zentyal/tmp/yPKISOiEcj failed.
Error output: update failed: REFUSED

It is failing when trying to create PTR records for the static host entries defined in the DNS section of the web interface (eg. for dc1 itself).

This change is a bit of a hack and is likely to be overwritten by Zentyal at some point.
Code: [Select]
$ sudo cp -a /usr/share/perl5/EBox/DNS.pm /usr/share/perl5/EBox/DNS.pm.orig
$ sudo vi /usr/share/perl5/EBox/DNS.pm
$ diff -u /usr/share/perl5/EBox/DNS.pm.orig /usr/share/perl5/EBox/DNS.pm
--- /usr/share/perl5/EBox/DNS.pm.orig   2017-07-21 21:06:40.000000000 +1000
+++ /usr/share/perl5/EBox/DNS.pm        2017-08-11 14:15:33.022140698 +1000
@@ -1520,7 +1520,7 @@
     my ($self, $fh, $reverse) = @_;

     my $auth = $reverse ? '-l' : '-g';
-    my $cmd = NS_UPDATE_CMD . " $auth -t 10 " . $fh->filename();
+    my $cmd = NS_UPDATE_CMD . " -g -t 10 " . $fh->filename();
     $self->{nsupdateCmds} = [] unless exists $self->{nsupdateCmds};
     push (@{$self->{nsupdateCmds}}, $cmd);
     $fh->unlink_on_destroy(0);

Restarting the DNS module from the dashboard continues to fail, but it works after restarting the server. Reverse lookups for static DNS entries will now work.

TODO: the /var/log/zentyal/zentyal.log file is full of parser warnings from where it encounters the dhcpd event statements while looking for dhcp lease definitions.

halsbox

  • Zen Apprentice
  • *
  • Posts: 1
  • Karma: +0/-0
    • View Profile
Thank you so much, opensesame!

Had same problem on fresh install of 5.0.10. Solved it with your instructions except for not creating a new "dhcpduser", but using the already present "dns-{MYDC_HOSTNAME}" user. Also did not have problems with restarting the DNS module from the dashboard (and no errors in log), thus no need to apply DNS.pm patch.

Here is a quick dirty patch for /usr/share/perl5/Text/DHCPLeases/Object.pm to get rid of dhcp leases file parsing warnings in log:
Code: [Select]
--- /usr/share/perl5/Text/DHCPLeases/Object.pm.orig 2012-12-07 22:35:44.000000000 +0400
+++ //usr/share/perl5/Text/DHCPLeases/Object.pm 2017-12-04 03:04:38.702611203 +0300
@@ -156,9 +156,14 @@
 sub parse{
     my ($self, $lines) = @_;
     my %obj;
+    my $event_block = 0;
     for ( @$lines ){
  $_ =~ s/^\s+//o;
  $_ =~ s/\s+$//o;
+ if ($event_block){
+     $event_block = 0 if ( /\}/);
+     next;
+ }
  next if ( /^#|^$|\}$/o );
  if ( /^lease ($IPV4) /o ){
      $obj{type} = 'lease';
@@ -211,13 +216,11 @@
      $obj{'option_agent_remote_id'} = $1;
  }elsif ( /set (\w+) = (.*);/o ){
      $obj{set}{$1} = $2;
- }elsif ( /on (.*) \{(.*)\};/o ){
+ }elsif ( /on\s+(.*)\s+\{/ ){
      my $events     = $1;
      my @events = split /\|/, $events;
-     my $statements = $2;
-     my @statements = split /\n;/, $statements;
      $obj{on}{events}     = @events;
-     $obj{on}{statements} = @statements;
+     $event_block = 1;
  }elsif ( /bootp;/o ){
      $obj{bootp} = 1;
  }elsif ( /reserved;/o ){
@@ -238,6 +241,8 @@
      $obj{ddns_fwd_name} = $1;
  }elsif (/set ddns-txt = \"(.*)\";/o){
      $obj{ddns_txt} = $1;
+ }elsif (/set vendor-class-identifier = \"(.*)\";/){
+            $obj{ddns_txt} = $1;
  }else{
      carp "Text::DHCPLeases::Object::parse Error: Statement not recognized: '$_'\n";
  }

BerT666

  • Zen Warrior
  • ***
  • Posts: 198
  • Karma: +5/-0
    • View Profile
INFO for Zentyal 6.0:

I tested it and it works under 6.0, too ;-)

Regards

Thomas

Neustradamus

  • Zen Monk
  • **
  • Posts: 63
  • Karma: +0/-2
    • View Profile
It is possible to add this directly in the module?

 

mailcat