Environment and goals
In my testing KVM lab I have a virtual network 172.16.50/24
, in this network I have got 2 Centos 7 VMs running Bind 9 and ISC DHCP servers:
- Мастер DNS :
controller.wsvirt.home (172.16.50.2)
- Slave DNS:
controller2.wsvirt.home (172.16.50.3)
All clients in the network are Linux VMs and all of the them get network configuration from the DHCP server. This server dynamically updates DNS zones.
Bind 9 is an authoritative server for wsvirt.home
zone.
In the lab environment I test a scenario which I have to implement in our business office network. In the business environment I should create an AD domain to serve Windows clients and for this purpose we have decided to utilize Samba 4 as a DC. I have built a Samba server for Centos 7 with Heimdal Kerberos support from the sources.
For the AD I allocated subnetwork 172.16.50.192/26
and assigned ad.wsvirt.home
domain.
AD DC is a Centos 7 VM running Samba 4, Bind 9 and ISC DHCP servers. Samba makes use of BIND_DLZ as a DNS backend. AD controller has addc1.ad.wsvirt.home
domain name and IP 172.16.50.193
.
All Windows AD clients get IP from the DHCP server running on the AD DC which dynamically updates Bind DLZ zones.
In the real working physical environment all client PCs from the both networks should be connected to one broadcast domain.
To satisfy the requirements I delegated authority for the forward ad.wsvirt.home
and reverse 172.16.50.192/26
DNS zones from the Bind on the controller.wsvirt.home
server to the AD controller addc1.ad.wsvirt.home
accordingly to [RFC 2317][1].
# Problem #
Everything works perfectly except one thing. When I test revers lookup for delegated reverse zone over AD DC then result looks OK, thus Windows AD client could resolve all reverse domain name in both domains. :
$ dig -x 172.16.50.193 @addc1.ad.wsvirt.home
; <<>> DiG 9.11.4-P2-RedHat-9.11.4-9.P2.el7 <<>> -x 172.16.50.193 @addc1.ad.wsvirt.home
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43507
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;193.50.16.172.in-addr.arpa. IN PTR
;; ANSWER SECTION:
193.50.16.172.in-addr.arpa. 86400 IN CNAME 193.50.16.172.ddns.
193.50.16.172.ddns. 900 IN PTR addc1.ad.wsvirt.home.
;; Query time: 7 msec
;; SERVER: 172.16.50.193#53(172.16.50.193)
;; WHEN: Mon Mar 30 21:05:12 IDT 2020
;; MSG SIZE rcvd: 121
But when I route my requests to the DNS server ```controller.wsvirt.home``` it does not resolve any reverse name from the ```ad.wsvirt.home``` domain, consequently the Linux clients could not lookup any reverse name as well:
$ dig -x 172.16.50.193 @controller.wsvirt.home
; <<>> DiG 9.11.4-P2-RedHat-9.11.4-9.P2.el7 <<>> -x 172.16.50.193 @controller.wsvirt.home
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 48825
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;193.50.16.172.in-addr.arpa. IN PTR
;; ANSWER SECTION:
193.50.16.172.in-addr.arpa. 86400 IN CNAME 193.50.16.172.ddns.
;; AUTHORITY SECTION:
. 8133 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2020033001 1800 900 604800 86400
;; Query time: 0 msec
;; SERVER: 172.16.50.2#53(172.16.50.2)
;; WHEN: Mon Mar 30 21:49:41 IDT 2020
;; MSG SIZE rcvd: 162
**I need** Linux clients from the ```wsvirt.home``` domain to be able to resolve reverse domain names in the ```ad.wsvirt.home``` domain. Is it possible at all?
# Configurations #
To be more precise I put here my configuration files for both servers
Server controller.wsvirt.home
/etc/named.conf
acl local { 172.16.50.0/24; 127.0.0.1; };
include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";
include "/etc/rndc.key";
server 172.16.50.3 {
keys { "rndc-key"; };
};
...
options {
listen-on port 53 { local; };
listen-on-v6 port 53 { ::1; };
directory "/var/named";
dump-file "/var/named/data/cache_dump.db";
statistics-file "/var/named/data/named_stats.txt";
memstatistics-file "/var/named/data/named_mem_stats.txt";
recursing-file "/var/named/data/named.recursing";
secroots-file "/var/named/data/named.secroots";
allow-query { local; };
allow-transfer { none; };
notify no;
forwarders { 8.8.8.8; 8.8.4.4; };
forward only;
recursion yes;
dnssec-enable yes;
dnssec-validation yes;
bindkeys-file "/etc/named.iscdlv.key";
managed-keys-directory "/var/named/dynamic";
pid-file "/run/named/named.pid";
session-keyfile "/run/named/session.key";
};
zone "." IN {
type hint;
file "named.ca";
};
zone "wsvirt.home" IN {
type master;
file "wsvirt.home.db";
allow-update { key "rndc-key"; };
allow-transfer { key "rndc-key"; };
notify yes;
forwarders {};
};
zone "50.16.172.in-addr.arpa" IN {
type master;
file "50.16.172.db";
allow-update { key "rndc-key"; };
allow-transfer { key "rndc-key"; };
notify yes;
};
### /var/named/50.16.172.db ### ``` $ORIGIN . $TTL 86400 ; 1 day 50.16.172.in-addr.arpa IN SOA controller.wsvirt.home. root.wsvirt.home. ( 153 ; serial 3600 ; refresh (1 hour) 1800 ; retry (30 minutes) 604800 ; expire (1 week) 86400 ; minimum (1 day) ) NS controller.wsvirt.home. NS controller2.wsvirt.home. $ORIGIN 50.16.172.in-addr.arpa. 2 PTR controller.wsvirt.home. $TTL 86400 ; 1 day 3 PTR controller2.wsvirt.home. ... ; 50.16.172.ddns. IN NS addc1.ad.wsvirt.home. $GENERATE 193-254 $ IN CNAME $.50.16.172.ddns. ```
### /etc/dhcp/dhcpd.conf ### ``` include "/etc/rndc.key";
default-lease-time 600; max-lease-time 7200; authoritative; ddns-update-style interim;
class "windows" {
match if substring (option vendor-class-identifier, 0, 8) = "MSFT 5.0";
}
subnet 172.16.50.0 netmask 255.255.255.0 { log (info, concat("Vendor Class ID (60): ", option vendor-class-identifier)); log (info, concat("DHCP Client ID (61): ", option dhcp-client-identifier)); log (info, concat("User Class ID (77): ", option user-class)); option domain-name-servers 172.16.50.2, 172.16.50.3; option ntp-servers 172.16.50.2; option routers 172.16.50.1; option broadcast-address 172.16.50.255; default-lease-time 600; max-lease-time 7200; option ip-forwarding off; ignore client-updates; option domain-name "wsvirt.home"; option domain-search "wsvirt.home"; option netbios-scope ""; option netbios-node-type 8; option netbios-name-servers 172.16.50.2; option netbios-dd-server 172.16.50.2; ddns-updates on; ddns-domainname "wsvirt.home."; ddns-rev-domainname "in-addr.arpa.";
pool {
range 172.16.50.21 172.16.50.190;
deny members of "windows";
}
zone wsvirt.home {
primary 172.16.50.2;
key "rndc-key";
}
zone 50.16.172.in-addr.arpa {
primary 172.16.50.2;
key "rndc-key";
}
}
<br />
## AD DC addc1.ad.wsvirt.home ##
### /etc/named.conf ###
options { listen-on port 53 { any; }; listen-on-v6 port 53 { ::1; }; directory "/var/named"; dump-file "/var/named/data/cache_dump.db"; statistics-file "/var/named/data/named_stats.txt"; memstatistics-file "/var/named/data/named_mem_stats.txt"; recursing-file "/var/named/data/named.recursing"; secroots-file "/var/named/data/named.secroots"; allow-query { any; }; forwarders { 172.16.50.2; 172.16.50.3; }; forward only; recursion yes; dnssec-enable no; dnssec-validation no; bindkeys-file "/etc/named.root.key"; managed-keys-directory "/var/named/dynamic"; pid-file "/run/named/named.pid"; session-keyfile "/run/named/session.key"; tkey-gssapi-keytab "/var/lib/samba/private/dns.keytab"; minimal-responses yes; };
...
zone "." IN { type hint; file "named.ca"; };
include "/etc/rndc.key"; include "/etc/named.rfc1912.zones"; include "/etc/named.root.key"; include "/var/lib/samba/bind-dns/named.conf";
<br />
### /etc/dhcp/dhcpd.conf ###
include "/etc/rndc.key";
default-lease-time 600; max-lease-time 7200; min-secs 5; authoritative; ddns-update-style none;
class "others" { match if substring (option vendor-class-identifier, 0, 8) != "MSFT 5.0"; }
subnet 172.16.50.192 netmask 255.255.255.192 { log (info, concat("Vendor Class ID (60): ", option vendor-class-identifier)); log (info, concat("DHCP Client ID (61): ", option dhcp-client-identifier)); log (info, concat("User Class ID (77): ", option user-class)); option routers 172.16.50.1; option broadcast-address 172.16.50.255; default-lease-time 600; max-lease-time 7200; option ip-forwarding off; ignore client-updates; option ntp-servers 172.16.50.193; option domain-name-servers 172.16.50.193; option domain-name "ad.wsvirt.home"; option domain-search "ad.wsvirt.home"; option netbios-name-servers 172.16.50.193; option netbios-dd-server 172.16.50.193; option netbios-scope ""; option netbios-node-type 8; ddns-rev-domainname "ddns";
pool {
range 172.16.50.210 172.16.50.254;
deny members of "others";
}
}
on commit { set noname = concat("dhcp-", binary-to-ascii(10, 8, "-", leased-address)); set ClientIP = binary-to-ascii(10, 8, ".", leased-address); set ClientDHCID = concat ( suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,1,1))),2), ":", suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,2,1))),2), ":", suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,3,1))),2), ":", suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,4,1))),2), ":", suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,5,1))),2), ":", suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,6,1))),2) ); set ClientName = pick-first-value(option host-name, config-option-host-name, client-name, noname); log(concat("Commit: IP: ", ClientIP, " DHCID: ", ClientDHCID, " Name: ", ClientName)); execute("/usr/local/sbin/dhcp-dyndns.sh", "add", ClientIP, ClientDHCID, ClientName); }
on release {
set ClientIP = binary-to-ascii(10, 8, ".", leased-address);
set ClientDHCID = concat (
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,1,1))),2), ":",
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,2,1))),2), ":",
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,3,1))),2), ":",
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,4,1))),2), ":",
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,5,1))),2), ":",
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,6,1))),2)
);
log(concat("Release: IP: ", ClientIP));
execute("/usr/local/sbin/dhcp-dyndns.sh", "delete", ClientIP, ClientDHCID);
}
on expiry {
set ClientIP = binary-to-ascii(10, 8, ".", leased-address);
log(concat("Expired: IP: ", ClientIP));
execute("/usr/local/sbin/dhcp-dyndns.sh", "delete", ClientIP, "", "0");
}
<br />
### A DLZ revers zone 50.16.172.ddns on the AD DC ###
$ samba-tool dns query localhost 50.16.172.ddns @ ALL Password for [[email protected]]: Name=, Records=2, Children=0 SOA: serial=3, refresh=900, retry=600, expire=86400, minttl=3600, ns=addc1.ad.wsvirt.home., email=hostmaster.ad.wsvirt.home. (flags=600000f0, serial=3, ttl=3600) NS: addc1.ad.wsvirt.home. (flags=600000f0, serial=1, ttl=3600) Name=193, Records=1, Children=0 PTR: addc1.ad.wsvirt.home (flags=f0, serial=3, ttl=900) Name=230, Records=1, Children=0 PTR: winxp-1.ad.wsvirt.home (flags=f0, serial=3, ttl=3600)
[1]: https://www.rfc-editor.org/rfc/rfc2317
It's normal not to get the
PTR
on the same answer, as thecontroller.wsvirt.home.
isn't an authoritative name server for both zones. Theflags: aa
states that this is an authoritative answer, but that wouldn't be true for193.50.16.172.ddns. IN PTR
. Therefore, it can't be sent on this authoritative answer.This is not really a problem, because that only causes another query for
193.50.16.172.ddns. IN PTR
, which could then be answered recursively. Clients should be aware of doing this automatically in case of aCNAME
answer.Regarding that, there's another problem, as only
addc1.ad.wsvirt.home.
has zone50.16.172.ddns.
; you would get anNXDOMAIN
answer on:The
controller.wsvirt.home.
is configured as recursive (recursion yes;
), but it's not aware that these addresses could be found onaddc1.ad.wsvirt.home.
. Therefore, it tries to resolve them as everything else: from theforwarders { 8.8.8.8; 8.8.4.4; };
... and fails.You could add the
addc1.ad.wsvirt.home.
as a forwarder for50.16.172.ddns.
on thecontroller.wsvirt.home.
:Finally, the zone for
$ORIGIN 50.16.172.in-addr.arpa.
could only delegate control for its own subdomains – not for a completely unrelated50.16.172.ddns.
.If you really still want to send the
PTR
on the same response, you need to make this domain authoritative for50.16.172.ddns.
by adding aslave
zone (instead of aforward
zone), e.g.The primary server (
addc1.ad.wsvirt.home.
) needs to be aware of this and allow zone transfers fromcontroller.wsvirt.home.
(andcontroller2.wsvirt.home
, if it should act similarly):If you are going to use MY script, please use it correctly ;-)
Run Bind9 and isc-dhcp on the DC, no where else. See here:
https://wiki.samba.org/index.php/Setting_up_a_BIND_DNS_Server
https://wiki.samba.org/index.php/Configure_DHCP_to_update_DNS_records_with_BIND9
One of your main problems is that you are trying to store the reverse zone in a 'flatfile' and bind9_dlz does not work with flatfiles.
Accordingly to the Esa Jokinen's suggestion I did the following:
On the controller.wsvirt.home in the
/etc/named.conf
I created a zone section for50.16.172.ddns
.In the zone file
/var/named/50.16.172.db
I commented out the lines delegating the50.16.172.ddns
zone:On the addc1.ad.wsvirt.home. in the
/etc/named.conf
:As a result I have an authority for the zone
50.16.172.ddns
but revers names got unresolved at all:Finally I have discovered a root of the problem. The point is that Bind 9 strips away DNSSEC signatures, when it works as a forwarder. I knew it, so in the
named.conf
at the serveraddc1.ad.wsvirt.home
I set the following options as a workaround:But I forgot to do the same at the
controller.wsvirt.home
, now I have fixed my oversight and everything works good. And obviously the zone section for the50.16.172.ddns
must be in the Bind's config file at theaddc1.ad.wsvirt.home
server: