gss-tsig-overview

The purpose of this article demonstrate how to get GSS-TSIG or secure dynamic updates working using ISC Bind DNS on a *NIX server. After several hours of trying to get this to work, perhaps this article would have been better named "GSS-TSIG on ISC Bind -- The Missing Manual".  I know in working with others, we experienced many trials and tribulations in getting it all to work.  GSS-TSIG DNS Updates or secure dynamic updates is an extension to TSIG based updates which implements secure key exchange. GSS API calls for the use of Kerberos for authentication, integrity and confidentiality by establishing a limited lifetime security context.  Once the security context is established, special TKEY resource records are used to securely exchange key material between the DNS Server and DNS Client. GSS-TSIG support has been present in the ISC Bind code since version 9.5.0, circa mid-summer of 2008. In this HOW-TO, we compiled ISC Bind 9.7.1-P2 on Fedora 13 (32-bit) and used a single Microsoft Windows 2008 Server running as an Active Directory Domain Controller for example.com.

Before we demonstrate secure dynamic updates, we must first address a "chicken-and-egg" issue.  We need our Active Directory Domain Controller up and running prior so we can configure our AD user and Kerberos Service Principal.  Prior to running dcpromo to promote our first AD Domain Controller or DC, we must have DNS up and running with dynamic DNS support.  So, It is recommended that ISC Bind is built and configured to be authoritative for the AD Domain and support dynamic DNS updates using the allow-update directive by supplying the IP address of the AD DC. 

Building ISC Bind on Fedora, CentOS, or Red Hat Linux

In this exercise, a minimal install of the Fedora 13 and/or CentOS 5.5 (32-bit) operating system was installed.  Ensure that the following RPM dependencies openssl-devel, gcc, make, perl, krb5-workstation, and krb5-devel.  This can be done using the yum pkg manager as follows:

yum install openssl-devel
yum install gcc make perl
yum install krb5-workstation krb5-devel 

You will note that we did not specify libgssapi* modules.  The reason for this is that the GSS-API code is present and embedded in the krb5-workstation and krb5-devel library and development package. In our test, we used the latest version of ISC Bind (9.7.1-P2 was the current version at the time of this article). Unpack this version of bind and build as follows:

./configure --with-openssl --with-gssapi
make && make install 

Some key assumptions:

  • Configure our DNS server, dns1.example.com to be authoritative for the zone example.com
  • Configure our DNS server, dns1.example.com to be authoritative for the reverse zone 168.192.in-addr.arpa
  • Configure the zone(s) example.com and 168.192.in-addr.arpa to be dynamically updatable via the allow-update directive using the IP address of the AD DC(s) so they can inject any/all AD-related DNS records. 

Once that is complete, our ISC Bind name server should accept insecure dynamic DNS updates from the Domain Controllers for the forward zone example.com and the reverse zone 168.192.in-addr.arpa. At this point it is time to bring up the AD Domain Controller. 

Active Directory Domain Controller Promotion

With our Unix DNS server configured to support dynamic updates, we change our focus to the configuration of the AD Domain and DC itself.  At this point, we can now run dcpromo.exe on our Windows Server 2008 to promote it to a Domain Controller or DC for example.com. Follow the wizard and at the conclusion of dcpromo.exe, make sure that all the AD related records were properly "injected" into our ISC Bind Server. Our DC will populate the BIND DNS server with the records that are contained in the %systemroot%\system32\config\netlogon.dns file. You can verify and validate that this occurred by either querying the name server for specific SRV, A, and CNAME records or by displaying the contents of the db.example.com.jnl file using the Bind-provided named-journalprint command.

Create AD user & Service Principal

Using the Microsoft Active Directory Users and Computers Microsoft Management Console or MMC, create an AD user called "dns1" in a zone such as example.com as shown in Fig. 1 - New User below.

NOTE: we chose the name "dns1" because it will represent the "instance" or hostname of the DNS server we plan to run ISC Bind on, i.e. dns1.example.com.  You should plan to add an AD User for each DNS server that will perform GSS-TSIG secure dynamic updates.

Click Next, and set & confirm a strong password.  In this example, we chose to set a one-time fixed password so that we would not have to rebuild Kerberos keytab files with the new credentials. If you permit the password to change or require it to be rotated for security reasons, you will need to update the Kerberos keytab files that get configured on the remote DNS Servers. 

When done, click next to view the final user creation screen shown in Fig. 3. Click Finish to complete the task of creating our user. 

Next, we must create a Kerberos Service Principal Name or SPN, that is mapped to our Active Directory User dns1. This is accomplished using the ktpass.exe utility that is installed on modern Microsoft Windows 2008 Server Installations.  If you are operating on Microsoft Windows 2003, you will need to install the Microsoft "Support Tools".  You MUST make sure to install the same release of the Support Tools as the version of Windows Server you are operating.  Run the ktpass.exe utility with the following flags and/or options:

Parameter/ValueDescription
-princ DNS/This email address is being protected from spambots. You need JavaScript enabled to view it. This represents the Kerberos Service Principal Account for the <instance> dns1.example.com in the realm EXAMPLE.COM
-mapuser This email address is being protected from spambots. You need JavaScript enabled to view it. The Kerberos SPN is mapped to this AD User Account that was created
-mapOp set Specifies how the mapping attribute is set
+DesOnly Sets the encryption type to Des only
-ptype KRB5_NT_PRINCIPAL This is the type of Kerberos Principal
-pass Pa$$w0rd The password of the AD user This email address is being protected from spambots. You need JavaScript enabled to view it. must be correctly passed as an argument.
-out dns1.keytab  This option names the output file for ktpass.exe.  The file that is outputted is a Kerberos Keytab File that can be imported or merged to an existing keytab file on the Unix Host. 
 gss-tsig1  gss-tsig2  gss-tsig3 gss-tsig4 
 Fig. 1 - New User  Fig. 2 - Password  Fig. 3 - Finish  Fig. 4 - ktpass.exe usage

The ktpass.exe command above should be executed for as many Bind DNS server instances you plan to operate.  In our testing, we generated two such SPN instances for two (2) different Linux hosts that were running ISC Bind 9.7.2-P2, dns1.example.com and dns2.example.com. Copy each keytab file to a temporary directory on the corresponding instance or Linux host, e.g. dns1.keytab should be copied to /tmp on dns1.example.com. 

Configuring The Kerberos Client on Linux

The first step is to ensure that the krb5-workstation utilities are properly installed, and that the location of the utilities are in your current PATH environment variable.  In our case, we added /usr/kerberos/bin to our default path. Set up Kerberos with a config similar to that shown below:

[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 default_realm = EXAMPLE.COM
 default_tkt_enctypes = des-cbc-md5
 default_tgs_enctypes = des-cbc-md5
 dns_lookup_realm = true
 dns_lookup_kdc = true
 ticket_lifetime = 30d
 forwardable = yes
 default_keytab_name = FILE:/etc/krb5.keytab

[realms]
 EXAMPLE.COM = {
  kdc = dc1.example.com:88
  admin_server = dc1.example.com:749
  default_domain = example.com
 }

[domain_realm]
 .example.com = EXAMPLE.COM
 example.com = EXAMPLE.COM

[appdefaults]
 pam = {
   debug = false
   ticket_lifetime = 36000
   renew_lifetime = 36000
   forwardable = true
   krb4_convert = false
 }

Run the ktutil command to read in the freshly copied keytab file, and write out the full contents to our target keytab file as follows:

[root@dns1 ~]# ktutil
ktutil:  rkt /tmp/dns1.keytab
ktutil:  list
slot KVNO Principal
---- ---- ---------------------------------------------------------------------
   1    3         DNS/This email address is being protected from spambots. You need JavaScript enabled to view it.
ktutil:  wkt /etc/krb5.keytab
ktutil:  quit
[root@dns1 ~]# 

If you are running ISC Bind as a lesser privileged user than the root user, you MUST set new ownership on the /etc/krb5.keytab file to the user that is running Bind. In our testing, we set the owner to 'named'.

Now, that our keytab file is in place, and our krb5.conf file is set up, you can initiate Kerberos authentication in obtaining Kerberos Tickets from the AD Server. This is done via the following command:

/usr/kerberos/bin/kinit -k -t /etc/krb5.keytab DNS/dns1.example.com

If there is no output and/or the return value $? is 0, then the command completed without any errors. You can now view the Kerberos tickets that have been granted by:

[root@dns1 ~]# klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: DNS/This email address is being protected from spambots. You need JavaScript enabled to view it.

Valid starting     Expires            Service principal
10/02/10 11:12:58  10/02/10 21:12:54  krbtgt/This email address is being protected from spambots. You need JavaScript enabled to view it.
    renew until 10/09/10 11:12:58


Kerberos 4 ticket cache: /tmp/tkt0
klist: You have no tickets cached

At this point, you should now have a working Kerberos Workstation or client that can authenticate and obtain Kerberos Tickets via the AD Domain Controller. If you run kdestroy, this command will remove any cached tickets from the Kerberos Client. Remove these cached tickets so that you don't have any cached tickets that will expire. Once that is done, the named process should renew tickets as needed to remain authenticated and capable of performing secure dynamic updates.

Configuring ISC Bind to Perform GSS-TSIG Secure Dynamic Updates

Previously, we had configured our DNS server to support dynamic DNS updates in the clear (insecure) by using the allow-update directive.  Now that our server has been "Kerberized", you can change the configuration of the name server to accept only secure dynamic updates by tweaking the server's global and zone configuration(s).  In the global options block of the named.conf file, you will need to add the tkey-gssapi-credential and tkey-domain directives.  The following was used for the example.com domain name server dns1.example.com:

tkey-gssapi-credential "DNS/This email address is being protected from spambots. You need JavaScript enabled to view it.";
tkey-domain "EXAMPLE.COM"; 

It was during the next part of the configuration, that we experienced difficulty in getting our configuration to work.  Since we are configuring secure dynamic updates on two zone(s), example.com, and 168.192.in-addr.arpa, we first needed to remove the allow-update { update_acl; }; because that directive is based upon IP access lists and is associated with insecure updates. The newer update-policy directive is what should be used to configure zones to support secure dynamic updates. We struggled with the documentation and exact syntax of this policy while trying to get GSS-TSIG working. The following syntax was used to get things working for our two (2) zones:

zone "example.com" { 
    type master;
    file "db.example.com";
    check-names ignore;
    allow-transfer { localhost; 192.168.0.0/16; };
    update-policy {
        grant * subdomain example.com. ANY;
    };
};

zone "168.192.in-addr.arpa" {
    type master;
    file "db.168.192.in-addr.arpa";
    check-names ignore;
    allow-transfer { localhost; 192.168.0.0/16; };
    update-policy {
        grant * subdomain 168.192.in-addr.arpa. PTR TXT;
    };
};

While the above configuration allowed our ISC Bind Server to handle GSS-TSIG secure dynamic updates, it is far less than optimal from a security perspective.  With all that said, how do we really know it's working? During testing, it's best to start named at a low debugging level so that log output shows details and evidence of the GSS-TSIG signed updates. Running ISC Bind in Debug level 6 will output logged messages as shown in gss-tsig.log. This is the first part of a two (2) article series on GSS-TSIG Updates using ISC Bind.  Part 2 - will cover some of the "gotchas", exceptions, and provide some additional recipes for a more secure update-policy usage. 

Comments   

0 #22 Nicola Canepa 2016-03-17 03:23
Hello, I'm trying to make a windows client (win2012 standalone as a server in domain) to do secure dynamic updates through the ms-self directove, but I always get "request is not signed" in the debug log, and the update fails (denied)
What am I doing wrong?

Thank you for any pointer
Quote
+1 #21 Peter K 2013-11-19 10:35
If you use Windows Server 2008 and greater (Windows Server 2012 in my case), set in GPO for domain controller: Network Security: Configure encryption types allowed for Kerberos. Make sure DES-CBC-MD5 (for your BIND9), AES and "Future" are selected.
Quote
0 #20 Peter 2013-09-10 16:01
Hello Patrick,

I ran additional test. I started new AD domain on Windows 2003 and configured account and SPN using ktpass. All good, I was able to obtain kerberos ticket.

Next, I joined 2008 AD controller to domain and tried to obtain ticket from 2008 which failed (wireshark showing error 6 KDC_ERR_C_PRINCIPAL_UNKNOWN).

In case I will still try Win 2003 - AD still answers properly to ticket request, so it looks like some bits in 2008 AD differently processing kerberos request.

Will continue my searching about it.

Peter
Quote
0 #19 Patrick Piper 2013-08-19 12:10
Quoting Peter:
I try to follow instruction on this great guideline, but I am failing on obtaining ticket on unix side.

I have SPN defined on AD side properly
C:\>setspn -L example\dns1
Registered ServicePrincipalNames for CN=dns1,CN=Users,DC=example,DC=com:
DNS/dns1.example.com

but still getting unknown user on unix side:
# kinit -k -t /etc/krb5.keytab DNS/dns1.example.com
kinit: krb5_get_init_creds: Client (DNS/) unknown


=== The krb5 config is fine, as I am able to get ticket for standard user.

I will appreciate any hint for possible mistake in my approach.


I'm wondering if it's through the use of setspn. I believe I created my user via the User UI tool, and then issue my ktpass. Could that be it? I know I've tried the setspn utility, perhaps to view my handiwork, not in creating it.
Quote
0 #18 Peter 2013-08-19 09:51
I try to follow instruction on this great guideline, but I am failing on obtaining ticket on unix side.

I have SPN defined on AD side properly
C:\>setspn -L example\dns1
Registered ServicePrincipa lNames for CN=dns1,CN=User s,DC=example,DC =com:
DNS/dns1.example.com

but still getting unknown user on unix side:
# kinit -k -t /etc/krb5.keyta b DNS/dns1.example.com
kinit: krb5_get_init_c reds: Client (DNS/) unknown


=== The krb5 config is fine, as I am able to get ticket for standard user.

I will appreciate any hint for possible mistake in my approach.
Quote
0 #17 Peter 2013-08-19 09:47
I try to follow your guideline, but I am failing to obtain kerberos ticket for SPN from Win2008.

My SPN looks properly defined on AD side:
C:\>setspn -L example\dns1
Registered ServicePrincipa lNames for CN=dns1,CN=User s,DC=example,DC =com:
DNS/dns1.example.com

but on unix side, I am getting

# kinit -k -t /etc/krb5.keyta b DNS/dns1.example.com
kinit: krb5_get_init_c reds: Client (DNS/) unknown

Wireshark reports: PDF_ERR_C_PRINC IPAL_UNKNOWN (error code 6)

As initializing kerberos ticket for standard user works fine, I am little unsure which part is not fully correct.

# kinit dns2
's Password:
# klist
Credentials cache: FILE:/tmp/krb5c c_0
Principal:

Issued Expires Principal
Aug 19 15:32:26 Aug 20 01:32:26 krbtgt/


Appreciate any hint.
Quote
0 #16 David 2012-11-30 07:54
I have been using bind 9.8.x for several months and the the issue has not come back since the upgrade.

Quoting Paul:

I'll personally try this in a couple of weeks with BIND 9.8.2rc1 and Win2003 DHCP.
Quote
0 #15 Paul 2012-11-28 08:56
Quoting Patrick H. Piper:

David, may have run into similar issues. Although I didn't try configuring Microsoft DHCP as a GSS-TSIG "client", I noticed that when the name server was left running, it would simply stop working after a period of time. It seemed to be related to a timeout issue with regard to GSS-TSIG replay cache. I have not revisited this in some time, but perhaps there is a way to tell the DNS server to re-initialize and re-negotiate it's credentials. Let me know if you come up with anything. Thanks!!

Well, it should work in BIND 9.8.0. From new features list of this version:

named now retains GSS-TSIG keys across restarts. This is for compatibility with Microsoft DHCP servers doing dynamic DNS updates for clients, which don't know to renegotiate the GSS-TSIG session key when named restarts. [RT #22639]

I'll personally try this in a couple of weeks with BIND 9.8.2rc1 and Win2003 DHCP.
Quote
0 #14 GreenOgre 2012-03-27 11:57
Patrick, thank you!
Your work and the invaluable comments are greatly appreciated.

Some hard-won "gotcha" fixes...

BIND error: "default realm from krb5.conf (EXAMPLE.COM) does not match tkey-gssapi-cre dential (DNS/)
BIND 7.2 and 7.3 require an environment variable: KEYTAB_FILE="/etc/krb5.keytab"
CentOS has a line in /etc/sysconfig/ named for it.
Stumbling upon that line was the key (no pun intended) to resolving this error.

Kerberos 1.9 required an entry in krb5.conf "allow_weak_cry pto = true" to support des-cbc-md5 encryption.

Thanks again for your work, our network can finally be free from randomly changing A records and periodic deletion of our statics.
Quote
0 #13 Patrick Piper 2011-10-20 09:54
Quoting David:
I found this and I have it working for client PC's. However, when I switch to having my Microsoft DHCP servers 2003 and 2008 do the updates on behalf of the clients, they only work until the tsig key timer expires or named restarts.
Is there a problem with having the Microsoft DHCP servers do these updates?

David,

I may have run into similar issues. Although I didn't try configuring Microsoft DHCP as a GSS-TSIG "client", I noticed that when the name server was left running, it would simply stop working after a period of time. It seemed to be related to a timeout issue with regard to GSS-TSIG replay cache. I have not revisited this in some time, but perhaps there is a way to tell the DNS server to re-initialize and re-negotiate it's credentials. Let me know if you come up with anything. Thanks!!
Quote

Add comment


Security code
Refresh