|
|
5aab14 |
# CentOS DNS authoritative and resolvers setup
|
|
|
5aab14 |
|
|
|
5aab14 |
## Public DNS setup
|
|
|
5aab14 |
|
|
|
5aab14 |
### Bind authoritative servers
|
|
|
5aab14 |
|
|
|
e5d196 |
We use [Bind](https://www.isc.org/bind/) as main DNS authoritative solution.
|
|
|
e5d196 |
For the `public` zones, we simply use the traditional primary/secondary setup, where primary zone is updated and then secondary servers are notified and so issue a IXFR/AXFR transfer to get latest zone content (and have same SOA)
|
|
|
e5d196 |
|
|
|
e5d196 |
The way we configure DNS zones is easy :
|
|
|
e5d196 |
|
|
|
e5d196 |
* update static zone (if needed, see below) in the `filestore/bind` directory , managed as a git repository, based on the environment)
|
|
|
e5d196 |
* play the [bind](https://github.com/centos/ansible-role-bind) ansible role either on trigger or just wait for automatic role to be applied (see the Ansible section for the setup)
|
|
|
e5d196 |
|
|
|
e5d196 |
We have also some delegated zones that are either still served by bind, or PowerDNS (see below)
|
|
|
e5d196 |
|
|
|
5aab14 |
#### Static zones
|
|
|
5aab14 |
|
|
|
e5d196 |
As described above, to add/delete/modify a DNS record in the static zone, one has just to :
|
|
|
e5d196 |
|
|
|
e5d196 |
* update SOA in `zone` file
|
|
|
e5d196 |
* update/add/delete record
|
|
|
e5d196 |
* commit/push to git (in the `filestore` git repository, depending on the inventory)
|
|
|
e5d196 |
* trigger ansible
|
|
|
e5d196 |
|
|
|
e5d196 |
List of zones served through static files (public zones):
|
|
|
e5d196 |
|
|
|
e5d196 |
* centos.org
|
|
|
e5d196 |
* ocp.centos.org
|
|
|
e5d196 |
* ocp.ci.centos.org
|
|
|
e5d196 |
* ocp.stg.ci.centos.org
|
|
|
e5d196 |
* centosproject.org
|
|
|
e5d196 |
|
|
|
e5d196 |
##### Specific records
|
|
|
e5d196 |
|
|
|
e5d196 |
`CAA` records: used to publicly announce which valid CA can sign our certificates for our zones :
|
|
|
e5d196 |
|
|
|
e5d196 |
```bash
|
|
|
e5d196 |
dig @ns1.centos.org -t CAA centos.org +short
|
|
|
e5d196 |
0 issue "amazon.com"
|
|
|
e5d196 |
0 issuewild "letsencrypt.org"
|
|
|
e5d196 |
0 issue "letsencrypt.org"
|
|
|
e5d196 |
0 issuewild "digicert.com"
|
|
|
e5d196 |
0 issue "digicert.com"
|
|
|
e5d196 |
|
|
|
e5d196 |
```
|
|
|
e5d196 |
|
|
|
e5d196 |
`TXT / SPF` records: used for [Sender Policy Framework](https://en.wikipedia.org/wiki/Sender_Policy_Framework) and restrict from which IP block/host one can send mail originating from @centos.org domain
|
|
|
e5d196 |
|
|
|
e5d196 |
`TXT` for kerberos : we have a pointer to announce that one can use FEDORAPROJECT for kerberos ticket
|
|
|
e5d196 |
|
|
|
e5d196 |
```
|
|
|
e5d196 |
dig @ns1.centos.org -t TXT _kerberos.centos.org +short
|
|
|
e5d196 |
"FEDORAPROJECT.ORG"
|
|
|
e5d196 |
```
|
|
|
e5d196 |
|
|
|
e5d196 |
`CNAME` : simple aliases for other A/AAAA records
|
|
|
e5d196 |
|
|
|
e5d196 |
`CNAME` for TLS/ACME dns challenge : we use some `static` CNAME pointing to equivalent record in `dynamic` zone (see below)
|
|
|
e5d196 |
|
|
|
e5d196 |
`NS` records : for the zones that we delegate to other authoritative servers, like for example (but not limited to) `mirror.centos.org` , served by PowerDNS/GeoIP (see also below)
|
|
|
e5d196 |
|
|
|
5aab14 |
#### Dynamic zones
|
|
|
5aab14 |
|
|
|
e5d196 |
We also have a specific `acme.centos.org` zone, that is only use for one specific purpose : creating on the fly TXT records that will be used by LetsEncrypt/ACME for DNS challenge.
|
|
|
e5d196 |
For this we use [acme.sh](https://github.com/Neilpang/acme.sh) tool that will do that automatically for us : it will use nsupdate with specific allowed key to create dynamically the needed record that ACME server will verify to validate and then sign the CSR.
|
|
|
e5d196 |
|
|
|
e5d196 |
See [TLS section](/tls/#how-to-obtain-new-cert-dns-challenge-is-the-preferred-way) on how to use it.
|
|
|
e5d196 |
|
|
|
e5d196 |
Some pointers:
|
|
|
e5d196 |
|
|
|
e5d196 |
* [https://github.com/acmesh-official/acme.sh/wiki/dnsapi#7-use-nsupdate-to-automatically-issue-cert](https://github.com/acmesh-official/acme.sh/wiki/dnsapi#7-use-nsupdate-to-automatically-issue-cert)
|
|
|
e5d196 |
* [https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode](https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode)
|
|
|
e5d196 |
|
|
|
e5d196 |
|
|
|
5aab14 |
### PowerDNS servers (GeoIP)
|
|
|
5aab14 |
|
|
|
e5d196 |
For some specific records, like `mirror.centos.org`, or `vault.centos.org` (and others) , we wanted to use something else than simple Round-Robin logic into Bind zone file.
|
|
|
e5d196 |
The idea was to optimize where to redirect based on GeoIP/country information, and so use nearest server for that role.
|
|
|
e5d196 |
|
|
|
e5d196 |
[PowerDNS](https://www.powerdns.com) is a really good authoritative solution that also permits you to inject your own [Pipe backend](https://doc.powerdns.com/md/authoritative/backend-pipe/) , meaning that we were able to have our own logic based on our requirements.
|
|
|
e5d196 |
|
|
|
e5d196 |
See our [pdns-custom-geoip-backend](https://github.com/CentOS/pdns-custom-geoip-backend) git repository that contains the simple code used for that and corresponding [pdns-pipe](https://github.com/CentOS/ansible-role-pdns-pipe) ansible role used to automatically deploy it.
|
|
|
e5d196 |
|
|
|
e5d196 |
Workflow for the `dynamic` backend :
|
|
|
e5d196 |
|
|
|
e5d196 |
* we have a central `nodes.db` sqlite3 DB that is where we use a specific schema to enter fqdn, ipv4/ipv6 address[es], region, continent, country, and if node is active or not (see `/var/lib/centos-infra/nodes.db`)
|
|
|
e5d196 |
* if we have to add/modify/remove a node we just do it in that sqlite DB
|
|
|
e5d196 |
* we then regenerate a .json file parsing DB and sorting in correct format that can be consummed by powerdns pipe backend (call the `/var/lib/centos-infra/gen_backend` script), that will also encrypt .json with gpg
|
|
|
e5d196 |
* delegated powerdns nodes will detect changes, decrypt files, and reload it in memory automatically
|
|
|
e5d196 |
|
|
|
e5d196 |
Worth knowing that for existing setup, and when we want to put a machine out of the pool, or add it back, we have a simple ansible adhoc-task (using prompt vars) that can be used for this : `adhoc-node-pdns-modify.yml` :
|
|
|
e5d196 |
|
|
|
e5d196 |
```
|
|
|
e5d196 |
ansible-playbook-prod playbooks/adhoc-node-pdns-modify.yml
|
|
|
e5d196 |
Host to modify in PowerDNS ? => : centosq7.centos.org
|
|
|
e5d196 |
Action (enable|disable) ? => : enable
|
|
|
e5d196 |
|
|
|
e5d196 |
PLAY [centosq7.centos.org] ********************************************************************************************
|
|
|
e5d196 |
|
|
|
e5d196 |
TASK [Enable/Disable msync node in PowerDNS geoip backend] ************************************************************
|
|
|
e5d196 |
Friday 25 June 2021 14:46:44 +0200 (0:00:07.333) 0:00:07.333 ***********
|
|
|
e5d196 |
changed: [centosq7.centos.org]
|
|
|
e5d196 |
|
|
|
e5d196 |
PLAY RECAP ************************************************************************************************************
|
|
|
e5d196 |
centosq7.centos.org : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
|
|
|
e5d196 |
|
|
|
e5d196 |
Friday 25 June 2021 14:46:51 +0200 (0:00:06.806) 0:00:14.140 ***********
|
|
|
e5d196 |
===============================================================================
|
|
|
e5d196 |
Enable/Disable msync node in PowerDNS geoip backend ------------------------------------------------------------ 6.81s
|
|
|
e5d196 |
Playbook run took 0 days, 0 hours, 0 minutes, 14 seconds
|
|
|
e5d196 |
|
|
|
e5d196 |
```
|
|
|
e5d196 |
|
|
|
e5d196 |
|
|
|
5aab14 |
## Internal DNS setup
|
|
|
5aab14 |
|
|
|
5aab14 |
### Bind authoritative and resolvers
|
|
|
5aab14 |
|
|
|
e5d196 |
For DCs that we control (Red Hat ones) and for which we have internal zone/subnet and so different set of `internal` IPs, we also use Bind, but with other features added in our Ansible role, like allow recursion (specific ACL to let internal subnet uses bind both as authoritative *and* resolver)
|
|
|
e5d196 |
|
|
|
e5d196 |
The procedure to update a zone is identical to the one described for public zone, but surely coming from a different ansible inventory and so different `filestore` git repo (tied to that inventory/env)
|
|
|
e5d196 |
|
|
|
e5d196 |
Worth knowing that we (ab)use some specific feature like Response Policy Zones [RPZ](https://www.isc.org/rpz/) : that permits us to , while still internally, answers automatically and redirect known `external` records (like mirrorlist.centos.org) to an internal IP and so not query the `public` authoritative servers.
|
|
|
e5d196 |
|
|
|
e5d196 |
All that is supported by our [bind](https://github.com/centos/ansible-role-bind) Ansible role, so consider reading defaults/main.yml to see how that works, or have access in ansible inventory/filestore for real examples.
|
|
|
e5d196 |
|
|
|
e5d196 |
|
|
|
5aab14 |
### Unbound resolvers
|
|
|
e5d196 |
|
|
|
e5d196 |
In some specific subnets/environments we also use [Unbound](https://www.nlnetlabs.nl/projects/unbound/about/) which is a also a really lightweight/fast resolver, that supports plenty of features.
|
|
|
e5d196 |
|
|
|
e5d196 |
While not technically called RPZ, Unbound let you define some records, and forward other queries to other resolvers (forwarders).
|
|
|
e5d196 |
|
|
|
e5d196 |
Our [unbound](https://github.com/CentOS/ansible-role-unbound) ansible role supports such features, like :
|
|
|
e5d196 |
|
|
|
e5d196 |
* control ACL (for recursion)
|
|
|
e5d196 |
* override some specific records through ansible list
|
|
|
e5d196 |
* also parse *automatically* an ansible group itself to generate dynamically a kind of internal zone.
|
|
|
e5d196 |
|
|
|
e5d196 |
That last feature is the one we use (through `unbound_local_groups`) for the `internal` rdu2.centos.org zone, as when we'll add a new machine, and ip defined for the host/VM, unbound will automatically add it into computed file used by unbound.
|
|
|
e5d196 |
|
|
|
e5d196 |
|
|
|
e5d196 |
|