1. Introduction

There are many situations in which we want to refer to our servers by their names instead of their IP addresses. Server names are more intuitive and much more easily remembered by users. Also, we can have multiple virtual hostnames pointing to a single server so it can have multiple uses and applications.

In most cases, we’ll use static IP allocations registered directly in our DNS (Domain Name System) zones. That’s the standard and the most commendable setting. However, there are some special cases when we might need to create DNS entries on the fly, dynamically. For instance, when we deploy new services to a containerized environment, it can be nice to have all the resource handling embedded into the automated pipeline, including the DNS registering.

In this tutorial, we’ll discuss how to register Linux servers with Windows DNS servers.

2. Dynamic DNS Registrations

Let’s begin by defining what DNS (Domain Name System) is.

DNS is a hierarchical and distributed database that catalogs the services available in an IP network domain. It’s based on open IETF standards such as RFC 1034 and 1035.

There are a lot of DNS record types, such as addresses (record A for IPv4 addresses and AAAA for IPv6), aliases (CNAME records), and email exchange services (MX records), to name a few.

The most common DNS usage is by using static (or slowly changing) records. However, if, for instance, we have services hosted on servers with dynamic IP addresses, we must be able to update their DNS records so that their clients can easily locate them.

By default, with Windows DNS, client hosts are only allowed to update DNS records directly using a secure method. For this, Microsoft implements the RFC 3645’s GSS-TSIG protocol, which basically relies on Kerberos 5 authentication.

3. Registering if the Linux Server Is an Active Directory Member

When we use the Samba client, we can use it to join the domain. First, let’s install the required package:

$ sudo apt install samba-client

To join a domain, the hostname must have the Windows Domain Name as its suffix:

$ sudo hostnamectl hostname host.mydomain.com

Now, we can join the domain, providing a user in Active Directory with permission to do so, like a domain administrator account or a DNS administrator account. It’s done using the net command:

$ sudo net ads -U administrator

The above command registers the server IP address with the Active Directory DNS servers. We can also force an update:

$ sudo net ads register -P

Furthermore, using a privileged account, we may add other hosts DNS registries:

$ sudo net ads register -U administrator host2.mydomain.com <ip address>

This technique has some drawbacks:

  • It requires an account with the privilege to add hosts to the domain
  • Only updates a single DNS Address record at a time
  • Doesn’t allow registering other DNS record types

On the other hand, once the host has joined the Windows Domain, we can even configure the Linux to authenticate users against the domain.

4. Registering if Linux Isn’t an Active Directory Member

For simple scenarios, the above solution might work. But, if we need to add multiple records or mess with different DNS register types, we can use the nsupdate command.

The nsupdate command has two Windows DNS Server operation modes:

  • non-secure, which requires disabling secure updates on the Windows DNS Server
  • secure, using the GSS-TSIG capability of newer nsupdate versions.

4.1. Non-secure DNS Updates

We’re presenting this option only as a learning step to secure DNS updates. It’s highly advisable to keep unsecured DNS updates disabled in any network. However, if we must, we should restrict the LAN segments that will have access to the primary DNS Servers, so that no host in another network shall be able to send DNS updates. To publish these records, we can set up secondary DNS servers that serve as the zone front-end.

The nsupdate expects a series of commands that define what’s to be sent to the specified DNS server.

The following command sequence deletes an existing registry. Then, it recreates the address register on the DNS server. Notably, it doesn’t need root privileges or authentication on the server:

$ nsupdate
> server
> update delete test.mydomain.com
> update add test.mydomain.com 86400 A
> send

So, to create a set of new DNS registers, we can just create a Bash script file with all the commands we want to send:

nsupdate <<EOF
update delete test.mydomain.com A
update add test.mydomain.com 86400 A
update add virtualhost1.mydomain.com 86400 A CNAME test.mydomain.com

Once executed, this batch script updates the old test.mydomain.com host address (deleting and recreating it). Then, it adds a new virtual host alias (CNAME registry).

4.2. Secure DNS Updates

As we’ve seen, we should never enable non-secure DNS updates – they’re just too dangerous and too easy to exploit. That’s why the recommended solution is to use secure DNS updates.

To do that, we must first install the Kerberos client and configure it with the appropriate credentials. So, let’s start by installing the required packages:

$ sudo apt install krb5-user

Now, we must configure it to authenticate against our Active Directory Kerberos realm, so we’ll edit the file /etc/krb5.conf to look like the following example (we should replace with the actual domain and domain controllers hostnames):

  kdc = ms-dc-01.mydomain.com:88
  kdc = ms-dc-02.mydomain.com:88
  admin_server = ms-dc-01.mydomain.com
  default_domain = mydomain.com

To test, we can issue the kinit command:

$ kinit <user> && klist

That asks for the user password, and then displays the Kerberos authentication token metadata. Provided the user has privileges to update DNS (a member of the DnsAdmins group, for instance), the cached token allows nsupdate to run with the GSS-TSIG option. Here’s our Bash script now:

nsupdate <<EOF 
realm mydomain.com
update delete test.mydomain.com A
update add test.mydomain.com 86400 A
update add virtualhost1.mydomain.com 86400 A CNAME test.mydomain.com

If we need a non-interactive way, we can create a keytab file that holds the user’s credentials.

But we must be aware that this file access should be very well protected, as it may give privileged access to our Active Directory. So, we must always give the least privileges to the user that updates the DNS records and secure any keytab file.

Anyway, to create a keytab file, we use the ktutil command. It opens a prompt:

$ ktutil
ktutil: addent -password -p [email protected] -k 0 -f
ktutil: wkt mydnsadminuser.keytab
ktutil: quit

To create a cached authentication ticket, kinit must use our keytab file:

$ kinit -kt mydnsadminuser.keytab [email protected]

So, let’s see the full Bash script, including the required authentication:

kinit -kt mydnsadminuser.keytab [email protected]
nsupdate <<EOF 
realm mydomain.com
update delete test.mydomain.com A
update add test.mydomain.com 86400 A
update add virtualhost1.mydomain.com 86400 A CNAME test.mydomain.com

The kdestroy command at the end of the script destroys the authentication ticket after the DNS update.

5. Caveats

As we discussed, DNS updates are a very useful tool, especially when we’re dealing with a dynamic environment. However, this kind of flexibility isn’t devoid of risks.

Should an attacker obtain access to change our DNS (directly or by using DNS updates), they can create fake servers to deceive our users.

With that in mind, we should minimize the hosts and users that can deal with DNS registers. Notably, a single server, comfortably sitting in a secure DMZ, can provide DNS automation for the entire network, for instance.

6. Conclusion

In this article, we’ve seen some of the alternatives to do Windows DNS Server updates from Linux Servers. This can be quite useful as we can add, update, or delete DNS entries on the fly, programmatically even.

In modern daily IT operations, we must be always looking for ways of automating service deployment. This means that our processes will be less prone to errors and should operate on higher scales with better efficiency.