Feature #1685
closedWindows DNS: Secure connection using GSS-TSIG
Description
Hi,
we are using foreman in our heterogenous windows / linux environment. Our Master DNS servers are running on Windows / Active Directory. It is a big security issue to leave the dynamic updates on "Nonsecure and secure". I know that foreman is using nsupdate to update dns records. This supports GSS-TSIG to securely communicate with Windows DNS servers. I have tested this on a Ubuntu 12.04 machine and I can manipulate Windows DNS servers using nsupdate with GSS-TSIG just fine.
The following blog post put me in the right direction: http://blog.michael.kuron-germany.de/2011/02/isc-dhcpd-dynamic-dns-updates-against-secure-microsoft-dns/
Basically all that is needed is a keytab file, so a valid username and password that can connect to AD:
keytab can be generated using
$ ktutil
ktutil: addent -password -p dnsadmin@EXAMPLE.COM -k 1 -e aes256-cts-hmac-sha1-96
Password for dnsuser@EXAMPLE.COM:
ktutil: wkt dnsuser.keytab
ktutil: quit
With the keytab created, nsupdate can be run with the "-g" switch to enable secure GSS-TSIG communication.
My ruby skills are absolutely zero and I only have a stable foreman environment setup here at work. I'm happy to setup a new foreman dev environment and to test. :)
Regards,
Oliver
Updated by Ohad Levy over 12 years ago
Thanks Oliver!
this is surely a big step in the right direction, and I assume should not be more then a bit of documentation and a configuration value.
thanks for your help.
if you are interested to solve it your self, you can simply try to add it to this line https://github.com/theforeman/smart-proxy/blob/develop/lib/proxy/dns/bind.rb#L67
Updated by Oliver Weinmann over 12 years ago
I also think this shouldn't be too hard to accomplish even with almost no ruby skills. I will start setting up a new foreman dev environment with a Windows 2003 and 2008 Server at home and try to change the code so it uses the -g switch. The creation of the keytab file will be manually on the cmdline for now. Maybe someone can include this in the GUI Settings later on.
Thanks for the link, that points me in the right direction.
Oliver
Updated by Ohad Levy over 12 years ago
I would extracting the parameter handling into a seperate method, e.g. something like that
change the relevant line to
@om = IO.popen("#{@nsupdate} #{nsupdate_args}", "r+")
and add a new method
private
def nsupdate_args
args = ""
if SETTINGS.dns_key
args += "-k #{SETTINGS.dns_key} "
args += "-g " if SETTINGS.dns_tsig # need to add that setting
end
args
end
Updated by Oliver Weinmann over 12 years ago
Hi Ohad,
I tried to setup a fresh ubuntu 12.04 box with latest foreman dev installed, but unfortunately the company I work for, has blocked git (in and outgoing) and I'm not able to download the latest foreman dev using the bundler script. This also means that I'm not able to push any changes via git to the repo. :(
To test this at home I have to setup a win2k8 r2 server and a ubuntu box. This will take some time... I don't think I have this fixed for the 1.0 release.
Regards,
Oliver
Updated by Ohad Levy over 12 years ago
git can work over https, just change all of the git:// to https://
Updated by Oliver Weinmann over 12 years ago
Thanks. I was now able to pull the dev version, but:
You can run Foreman with the command "RAILS_ENV=production rails s"
this just creates files below my /usr/share/foreman folder but no webrick is started?
How do I start the webrick server?
Updated by Oliver Weinmann over 12 years ago
Ok,
Took a long long time but... I got it working. :)
I will clean up the code a little bit and then push it.
Regards,
Oliver
Updated by Ohad Levy over 12 years ago
Oliver Weinmann wrote:
Submitted a patch. :)
where is it ? :)
Updated by Oliver Weinmann over 12 years ago
I have no github account so I used the old way:
root@ubuntu120464:/usr/share/smart-proxy# rake mail_patches WARNING: 'require 'rake/rdoctask'' is deprecated. Please use 'require 'rdoc/task' (in RDoc 2.4.2+)' instead.
at /usr/lib/ruby/vendor_ruby/rake/rdoctask.rb
rake/gempackagetask is deprecated. Use rubygems/package_task instead
git format-patch -C -M -s -n --subject-prefix='PATCH/smart-proxy' origin/develop
0001-Windows-DNS-Secure-connection-using-GSS-TSIG-1685.patch
git send-email --no-signed-off-by-cc --suppress-from --to foreman-dev@googlegroups.com 00*.patch
0001-Windows-DNS-Secure-connection-using-GSS-TSIG-1685.patch
Who should the emails appear to be from? [theforemanuser123 <oliver_weinmann@gmx.de>]
Emails will be sent from: theforemanuser123 <oliver_weinmann@gmx.de>
Message-ID to be used as In-Reply-To for the first email?
OK. Log says:
Sendmail: /usr/sbin/sendmail -i foreman-dev@googlegroups.com
From: theforemanuser123 <oliver_weinmann@gmx.de>
To: foreman-dev@googlegroups.com
Subject: [PATCH/smart-proxy 1/1] Windows DNS: Secure connection using GSS-TSIG #1685
Date: Thu, 9 Aug 2012 15:50:25 +0200
Message-Id: <1344520225-32513-1-git-send-email-oliver_weinmann@gmx.de>
X-Mailer: git-send-email 1.7.9.5
Result: OK
In git 1.7.0, the default has changed to --no-chain-reply-to
Set sendemail.chainreplyto configuration variable to true if
you want to keep --chain-reply-to as your default.
rm 00*.patch
Does this look good?
Updated by Florent Delvaille almost 12 years ago
Hep,
I implemented the thing but even if foreman-proxy logs says the entries are created, they are not created in the MS DNS Server.
Here is a pastie of all interesting things: http://pastie.org/6073962
Regards;
Updated by Oliver Weinmann almost 12 years ago
Hi,
what foreman version are you using?
Can you please try to manaully create a dns record using the nsupdate command.
e.g.
nsupdate -g
server yourdnsserver
realm yourkrb5realm
update add testhost123.your.domain 3600 A 192.168.100.1
send
UPDATE
I really want to see this feature included in Foreman 1.1 but no one really wants to test it. :)
Updated by Florent Delvaille almost 12 years ago
Hep,
I am using Foreman 1.1RC5
Here is the result of our tests:
/etc/krb5.conf
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log
[libdefaults]
default_realm = ONPRVP.FGOV.BE
dns_lookup_realm = true
dns_lookup_kdc = true
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
[realms]
ONPRVP.FGOV.BE = {
default_domain = onprvp.fgov.be
}
[domain_realm]
.onprvp.fgov.be = ONPRVP.FGOV.BE
root@lpr-mgmt01 foreman-proxy]# ktutil
ktutil: addent -password -p SRV_FOREMAN@ONPRVP.FGOV.BE -k 1 -e aes256-cts-hmac-sha1-96
Password for SRV_FOREMAN@ONPRVP.FGOV.BE:
ktutil: wkt dns.keytab
ktutil: quit
[root@lpr-mgmt01 foreman-proxy]# kinit -F -k -t /usr/share/foreman-proxy/dns.keytab SRV_FOREMAN@ONPRVP.FGOV.BE
[root@lpr-mgmt01 foreman-proxy]# klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: SRV_FOREMAN@ONPRVP.FGOV.BE
Valid starting Expires Service principal
02/06/13 15:43:21 02/07/13 01:43:21 krbtgt/ONPRVP.FGOV.BE@ONPRVP.FGOV.BE
renew until 02/13/13 15:43:21
[root@lpr-mgmt01 foreman-proxy]# nsupdate -g
server spr-cen01.onprvp.fgov.be
realm ONPRVP.FGOV.BE
update add ldv-demo01.onprvp.fgov.be 3600 A 192.168.151.191
send
Result:
devaf@PC-20100257LINUX:~$ nslookup ldv-demo01
Server: 192.168.147.31
Address: 192.168.147.31#53
Name: ldv-demo01.onprvp.fgov.be
Address: 192.168.151.191
In foreman when creating the host: Error400 BAD REQUEST
Here is the logs of foreman-proxy with strange error:
D, [2013-02-06T15:49:35.483188 #15542] DEBUG -- : omshell: executed - set name = "ldv-demo01.onprvp.fgov.be"
D, [2013-02-06T15:49:35.483771 #15542] DEBUG -- : true
D, [2013-02-06T15:49:35.483853 #15542] DEBUG -- : omshell: executed - set ip-address = 192.168.151.191
D, [2013-02-06T15:49:35.483907 #15542] DEBUG -- : true
D, [2013-02-06T15:49:35.483983 #15542] DEBUG -- : omshell: executed - set hardware-address = 00:50:56:af:70:0a
D, [2013-02-06T15:49:35.484100 #15542] DEBUG -- : true
D, [2013-02-06T15:49:35.484203 #15542] DEBUG -- : omshell: executed - set hardware-type = 1
D, [2013-02-06T15:49:35.484259 #15542] DEBUG -- : true
D, [2013-02-06T15:49:35.484382 #15542] DEBUG -- : omshell: executed - set statements = "filename = \"pxelinux.0\"; next-server = c0:a8:97:6f; option host-name = \"ldv-demo01.onprvp.fgov.be\";"
D, [2013-02-06T15:49:35.484462 #15542] DEBUG -- : true
D, [2013-02-06T15:49:35.484537 #15542] DEBUG -- : omshell: executed - create
D, [2013-02-06T15:49:35.484592 #15542] DEBUG -- : true
I, [2013-02-06T15:49:35.489947 #15542] INFO -- : Added DHCP reservation for ldv-demo01.onprvp.fgov.be (192.168.151.191 / 00:50:56:af:70:0a)
E, [2013-02-06T15:49:35.675832 #15542] ERROR -- : invalid date
D, [2013-02-06T15:49:35.675933 #15542] DEBUG -- : /usr/lib/ruby/1.8/date.rb:1576:in `new_by_frags'
/usr/lib/ruby/1.8/date.rb:1601:in `strptime'
/usr/share/foreman-proxy/bin/../lib/proxy/dns/bind.rb:102:in `find_krb5tgt'
/usr/share/foreman-proxy/bin/../lib/proxy/dns/bind.rb:134:in `nsupdate'
/usr/share/foreman-proxy/bin/../lib/proxy/dns/bind.rb:20:in `create'
/usr/share/foreman-proxy/bin/../lib/dns_api.rb:14:in `POST /dns/'
/usr/lib/ruby/gems/1.8/gems/sinatra-1.1.0/lib/sinatra/base.rb:1032:in `call'
/usr/lib/ruby/gems/1.8/gems/sinatra-1.1.0/lib/sinatra/base.rb:1032:in `compile!'
/usr/lib/ruby/gems/1.8/gems/sinatra-1.1.0/lib/sinatra/base.rb:620:in `instance_eval'
/usr/lib/ruby/gems/1.8/gems/sinatra-1.1.0/lib/sinatra/base.rb:620:in `route_eval'
/usr/lib/ruby/gems/1.8/gems/sinatra-1.1.0/lib/sinatra/base.rb:604:in `route!'
/usr/lib/ruby/gems/1.8/gems/sinatra-1.1.0/lib/sinatra/base.rb:656:in `process_route'
/usr/lib/ruby/gems/1.8/gems/sinatra-1.1.0/lib/sinatra/base.rb:653:in `catch'
/usr/lib/ruby/gems/1.8/gems/sinatra-1.1.0/lib/sinatra/base.rb:653:in `process_route'
/usr/lib/ruby/gems/1.8/gems/sinatra-1.1.0/lib/sinatra/base.rb:603:in `route!'
/usr/lib/ruby/gems/1.8/gems/sinatra-1.1.0/lib/sinatra/base.rb:602:in `each'
/usr/lib/ruby/gems/1.8/gems/sinatra-1.1.0/lib/sinatra/base.rb:602:in `route!'
/usr/lib/ruby/gems/1.8/gems/sinatra-1.1.0/lib/sinatra/base.rb:741:in `dispatch!'
/usr/lib/ruby/gems/1.8/gems/sinatra-1.1.0/lib/sinatra/base.rb:530:in `call!'
/usr/lib/ruby/gems/1.8/gems/sinatra-1.1.0/lib/sinatra/base.rb:706:in `instance_eval'
/usr/lib/ruby/gems/1.8/gems/sinatra-1.1.0/lib/sinatra/base.rb:706:in `invoke'
/usr/lib/ruby/gems/1.8/gems/sinatra-1.1.0/lib/sinatra/base.rb:706:in `catch'
/usr/lib/ruby/gems/1.8/gems/sinatra-1.1.0/lib/sinatra/base.rb:706:in `invoke'
/usr/lib/ruby/gems/1.8/gems/sinatra-1.1.0/lib/sinatra/base.rb:530:in `call!'
/usr/lib/ruby/gems/1.8/gems/sinatra-1.1.0/lib/sinatra/base.rb:516:in `call'
/usr/lib/ruby/gems/1.8/gems/rack-1.2.5/lib/rack/methodoverride.rb:24:in `call'
/usr/lib/ruby/gems/1.8/gems/rack-1.2.5/lib/rack/showexceptions.rb:24:in `call'
/usr/lib/ruby/gems/1.8/gems/rack-1.2.5/lib/rack/commonlogger.rb:18:in `call'
/usr/lib/ruby/gems/1.8/gems/sinatra-1.1.0/lib/sinatra/base.rb:1142:in `call'
/usr/lib/ruby/gems/1.8/gems/sinatra-1.1.0/lib/sinatra/base.rb:1168:in `synchronize'
/usr/lib/ruby/gems/1.8/gems/sinatra-1.1.0/lib/sinatra/base.rb:1142:in `call'
/usr/lib/ruby/gems/1.8/gems/rack-1.2.5/lib/rack/content_length.rb:13:in `call'
/usr/lib/ruby/gems/1.8/gems/rack-1.2.5/lib/rack/handler/webrick.rb:52:in `service'
/usr/lib/ruby/1.8/webrick/httpserver.rb:104:in `service'
/usr/lib/ruby/1.8/webrick/httpserver.rb:65:in `run'
/usr/lib/ruby/1.8/webrick/server.rb:173:in `start_thread'
/usr/lib/ruby/1.8/webrick/server.rb:162:in `start'
/usr/lib/ruby/1.8/webrick/server.rb:162:in `start_thread'
/usr/lib/ruby/1.8/webrick/server.rb:95:in `start'
/usr/lib/ruby/1.8/webrick/server.rb:92:in `each'
/usr/lib/ruby/1.8/webrick/server.rb:92:in `start'
/usr/lib/ruby/1.8/webrick/server.rb:23:in `start'
/usr/lib/ruby/1.8/webrick/server.rb:82:in `start'
/usr/lib/ruby/gems/1.8/gems/rack-1.2.5/lib/rack/handler/webrick.rb:13:in `run'
/usr/share/foreman-proxy/bin/../lib/sinatra-patch.rb:42:in `run!'
/usr/share/foreman-proxy/bin/smart-proxy:44
Updated by Oliver Weinmann almost 12 years ago
I think the problem is that I've written this patch for a much older foreman release and it was working fine. When I upgraded to Foreman 1.0 I saw the same error message:
E, [2013-02-06T15:49:35.675832 #15542] ERROR -- : invalid date
I think this is related to a ruby update that has broken a few lines of code that I was using to determine if the kerberos ticket was still valid.
I'm not a ruby code expert and It was really hard for me to even write these few lines of code. Do you have any experience in ruby coding??
Updated by Florent Delvaille almost 12 years ago
Unfortunately not at all.
But since it was working for you and then suddenly it does not anymore in 1.0 ... and since we have the same error ... I assume the problem is somewhere else.
Hope to get somebody to help us with this, coz it is almost OK :-)
Updated by Oliver Weinmann almost 12 years ago
If I find some time today I might setup a fresh 1.0 install and try this patch myself. I have asked many many times in the irc channel for help with this, but unfortunately no one seems to have some spare time to test and fix it. I was asked to clean up the code by the foreman maintainers, but unfortunately my coding skills are nearly zero.
Updated by Florent Delvaille almost 12 years ago
Please have a look at https://github.com/theforeman/smart-proxy/pull/29/files
Then it will work :)
Updated by Oliver Weinmann almost 12 years ago
What do you mean? Does the code that I (r0k5t4r) have reworked work for you?
Updated by Florent Delvaille almost 12 years ago
Yes, the one with the third parameter.
It worked perfectly …
Updated by Oliver Weinmann almost 12 years ago
Hi,
glad to hear that my code actually works. I guess all that is left to do is to clean it up and include it in the next stable release 1.1.
I will try to get a hold of one of the maintainers if they can clean up the code and include it.
Thanks a lot for testing. Would you also be happy to test the final code?
Cheers,
Oli
Updated by Florent Delvaille almost 12 years ago
I think there is still a problem.
We had the thing working perfectly yesterday … today was FAIL …
Apparently every day the kerberos ticket must be recreated. I am not a ruby expert but apparently your code takes care of this …
But we are almost sure that the dns.keytab must also be regenerated every day … does this make sense to you ?
By deleting only the ticket, foreman wasnt able to create the dns record. After deletion/recreation of the dns.keytab it works.
Thx for any feedback.
About final code, yeah we will test it :)
Updated by Oliver Weinmann almost 12 years ago
As far as I can remember the dns.keytab doesn't have to be renewed every day.
It was working all the time without renewing the keytab.
I need to get my testsystem up and running to check what is going on.
Regards,
Oliver
Updated by Florent Delvaille almost 12 years ago
I did a new test this morning, and not working anymore.
The proxy logs say:
W, [2013-02-09T10:47:52.017939 #16239] WARN -- : Kerberos ticket still valid. Not aquiring new ticket.
D, [2013-02-09T10:47:52.018063 #16239] DEBUG -- : DNS TSIG authentication enabled.
D, [2013-02-09T10:47:52.024508 #16239] DEBUG -- : nsupdate: executed - update add ldv-demo04.onprvp.fgov.be. 86400 A 192.168.151.190
W, [2013-02-09T10:47:52.233962 #16239] WARN -- : Kerberos ticket still valid. Not aquiring new ticket.
D, [2013-02-09T10:47:52.234070 #16239] DEBUG -- : DNS TSIG authentication enabled.
D, [2013-02-09T10:47:52.237497 #16239] DEBUG -- : nsupdate: executed - update add 190.151.168.192.in-addr.arpa. 86400 IN PTR ldv-demo04.onprvp.fgov.be
But nothing in the DNS server.
I deleted the file /tmp/krb5cc_438 (only krb file in /tmp), deleted and recreated the host, and now it works.
W, [2013-02-09T10:53:12.709908 #16239] WARN -- : unable to find kerberos ticket. Trying to aquire a valid TGT...
D, [2013-02-09T10:53:12.710107 #16239] DEBUG -- : kinit F -k -t /usr/share/foreman-proxy/dns.keytab SRV_FOREMAN@ONPRVP.FGOV.BE. : DNS TSIG authentication enabled.
D, [2013-02-09T10:53:12.785197 #16239] DEBUG -
D, [2013-02-09T10:53:12.792365 #16239] DEBUG -- : nsupdate: executed - update add ldv-demo04.onprvp.fgov.be. 86400 A 192.168.151.190
W, [2013-02-09T10:53:13.013859 #16239] WARN -- : Kerberos ticket still valid. Not aquiring new ticket.
D, [2013-02-09T10:53:13.013954 #16239] DEBUG -- : DNS TSIG authentication enabled.
D, [2013-02-09T10:53:13.016803 #16239] DEBUG -- : nsupdate: executed - update add 190.151.168.192.in-addr.arpa. 86400 IN PTR ldv-demo04.onprvp.fgov.be
Here is the content of krb ticket before deletion:
root@lpr-mgmt01 ~]# klist /tmp/krb5cc_438
Ticket cache: FILE:/tmp/krb5cc_438
Default principal: SRV_FOREMAN@ONPRVP.FGOV.BE
Valid starting Expires Service principal
02/08/13 13:12:45 02/08/13 23:12:45 krbtgt/ONPRVP.FGOV.BE@ONPRVP.FGOV.BE
renew until 02/09/13 13:12:45
02/08/13 13:12:45 02/08/13 23:12:45 DNS/spr-cen01.onprvp.fgov.be@ONPRVP.FGOV.BE
renew until 02/09/13 13:12:45
I am surprised to see 2 entries … but well anyway …
Your patch do the following:
klist | grep #{SETTINGS.dns_tsig_realm} | grep '/' | awk -F ' ' '{print $3,$4}'
In our case, dns_tsig_realm = ONPRVP.FGOV.BE,
so …
[root@lpr-mgmt01 tmp]# klist /tmp/krb5cc_438 | grep ONPRVP.FGOV.BE | grep '/' | awk -F ' ' '{print $3,$4}'
02/08/13 23:12:45
02/08/13 23:12:45
I did the test not working this morning, so 02/09/13 … so the ticket is not valid anymore but if you check the first proxy log above, it says still valid.
So I think there is something wrong in the patch, related to the expiration of a ticket AND the recreation of an expired ticket.
I hope my debugging helped you enough.
Regards;
Updated by Florent Delvaille almost 12 years ago
The patch contains:
@format = "%d/%m/%y %H:%M"
@krbexp = `klist | grep #{SETTINGS.dns_tsig_realm} | grep '/' | awk -F ' ' '{print $3,$4}'`
The result of the klist command is:
02/08/13 23:12:45
02/08/13 23:12:45
So for me there is a problem in the @format, it should be:
@format = "%m/%d/%y %H:%M:%S"
No ?
I did the change above, and created a new vm.
I will retry tomorrow, I suspect it will work :)
Thx for any feedback
Updated by Florent Delvaille almost 12 years ago
So ...
Ticket created yesterday, expiration today 9AM.
I creaTed a new vm today at 11AM.
Proxy logs says that kinit is executed, so it creates a new ticket.
Dns record created successfully.
So please just change the @format and it will works.
Updated by Oliver Weinmann almost 12 years ago
Hi,
thanks for the fix. You are right the format is wrong.
root@gedappl01:~# klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: tuser@TEST.LOCAL
Valid starting Expires Service principal
02/07/13 11:59:02 02/07/13 18:39:02 krbtgt/TEST.LOCAL@TEST.LOCAL
I will submit a patch.
Cheers,
Oliver
Updated by Oliver Weinmann almost 12 years ago
Hi,
patch submitted. I will setup a test env clean up the code a bit and check if it is working.
Regards,
Oliver
Updated by Oliver Weinmann over 11 years ago
Hi,
can someone have a look at the submitted code and clean it up if required. This patch is really helpful for everyone that wants to use secure DNS management between Proxy and Windows DNS Server. Leaving Windows DNS set to unsecure is not a good idea as anyone on your network can delete or modify DNS records without authentication.
Please help, I'm willing to test any changes.
Regards,
Oliver
Updated by Dominic Cleal over 11 years ago
- Status changed from New to Assigned
- Assignee set to Dominic Cleal
I'm planning to look at the GSS-TSIG support soon as it's required for FreeIPA too, which is on my TODO list. If it is, then I'll take ownership of this - if you're happy to test it still works under Windows, Oliver!
Updated by Oliver Weinmann over 11 years ago
Hi Dominic,
thanks a lot. I would really appreciate to see this feature in Foreman 1.2. I have also added it on the deepdive list.
Regards,
Oliver
Updated by Dominic Cleal over 11 years ago
- Status changed from Assigned to Ready For Testing
Updated by Dominic Cleal over 11 years ago
- Status changed from Ready For Testing to Closed
- % Done changed from 0 to 100
Applied in changeset commit:"7e72434b829ccc47ef3704c72722277aa547609a".
Updated by Dominic Cleal over 10 years ago
- Has duplicate Feature #61: Add Microsoft DNS Support added