bertvv.bind

Rol de Ansible BIND

Estado de Acciones

Un rol de Ansible para configurar ISC BIND como un servidor DNS autoritario para múltiples dominios. Específicamente, las responsabilidades de este rol son:

  • instalar BIND
  • configurar el archivo de configuración principal (servidor primario/secundario/retransmisor)
  • configurar archivos de zona de búsqueda directa e inversa

Este rol admite múltiples zonas de búsqueda directa e inversa, incluyendo para IPv6. Aunque se admite habilitar la recursión (aunque se desaconseja fuertemente), considera usar otro rol si deseas configurar un servidor de nombres en caché o de retransmisión.

¡Si te gusta/uses este rol, considera darle una estrella y calificarlo en la página de Ansible Galaxy del rol! ¡Gracias!

Consulta el registro de cambios para cambios notables entre versiones.

ADVERTENCIA: Si has estado usando este rol desde antes de v5.0.0, verifica el registro de cambios para información importante sobre cambios que rompen la compatibilidad. Los playbooks antiguos fallarán si actualizas a v5.0.0.

Plataformas soportadas

Este rol se puede usar en varias plataformas, consulta meta/main.yml para una lista actualizada. Nos esforzamos por configurar pruebas automáticas para cada plataforma soportada (ver .ci.yml), pero no siempre es posible.

Algunas observaciones sobre roles soportados que no están incluidos en pruebas automáticas:

  • Arch Linux y FreeBSD deberían funcionar, pero en este momento no es posible probar el rol en estas distribuciones, ya que no hay imágenes de Docker adecuadas disponibles.
  • CentOS 6 debería funcionar, pero las pruebas de idempotencia fallan incluso si BIND se instala correctamente y las pruebas de aceptación tienen éxito.

Requisitos

Los paquetes python-netaddr (requerido para el filtro ipaddr) y dnspython deben estar instalados en el nodo de gestión.

Variables del Rol

Variable Por Defecto Comentarios (tipo)
bind_acls [] Una lista de definiciones de ACL, que son mappings con claves name: y match_list:.
bind_allow_query ['localhost'] Una lista de hosts que están permitidos para consultar este servidor DNS. Establecer en ['any'] permite a todos los hosts.
bind_allow_recursion ['any'] Similar a bind_allow_query, esta opción se aplica a las consultas recursivas.
bind_check_names [] Verifica los nombres de los hosts para cumplir con RFC 952 y RFC 1123 y toma la acción definida (por ejemplo, warn, ignore, fail).
bind_dns_keys [] Una lista de claves de enlace, que son mappings con claves name:, algorithm: y secret:.
bind_dns64 false Si es true, se habilita el soporte para DNS64.
bind_dns64_clients ['any'] Una lista de clientes a los que se aplica la función DNS64 (puede ser cualquier ACL).
bind_dnssec_enable true Si es true, DNSSEC está habilitado.
bind_dnssec_validation true Si es true, la validación de DNSSEC está habilitada.
bind_extra_include_files [] Una lista de archivos de configuración personalizados a incluir desde el archivo de configuración principal.
bind_forward_only false Si es true, BIND se configura como un servidor de nombres en caché.
bind_forwarders [] Una lista de servidores de nombres a los que se reenvían las consultas DNS.
bind_listen_ipv4 ['127.0.0.1'] Una lista de las direcciones IPv4 de las interfaces de red para escuchar. Establecer en ['any'] permite escuchar en todas las interfaces.
bind_listen_ipv4_port [53] Una lista de números de puerto para escuchar en direcciones IPv4.
bind_listen_ipv6 ['::1'] Una lista de las direcciones IPv6 de las interfaces de red para escuchar.
bind_listen_ipv6_port [53] Una lista de números de puerto para escuchar en direcciones IPv6.
bind_log data/named.run Ruta al archivo de registro.
bind_other_logs - Una lista de canales de registro para configurar, con un mapeo separado para cada zona, con los detalles pertinentes.
bind_query_log - Un mapeo con claves file: (por ejemplo, data/query.log), versions:, size:. Cuando se define, esto habilitará el registro de consultas.
bind_recursion false Determina si se deben reenviar solicitudes para las cuales el servidor DNS no es autoritativo.
bind_rrset_order random Define el orden para round robin de DNS (ya sea random o cyclic).
bind_statistics_channels false Si es true, BIND se configura con una cláusula de statistics-channels (actualmente solo admite escuchar en una sola interfaz).
bind_statistics_allow ['127.0.0.1'] Una lista de hosts que pueden acceder a las estadísticas del servidor.
bind_statistics_host 127.0.0.1 Dirección IP de la interfaz de red en la que el servicio de estadísticas debería escuchar.
bind_statistics_port 8053 Puerto de red en el que el servicio de estadísticas debería escuchar.
bind_zone_dir - Cuando se define, establece una ruta absoluta personalizada al directorio del servidor (para archivos de zona, etc.) en lugar del predeterminado.
bind_key_mapping [] Primary: Keyname - mapeo de claves TSIG a usar para un primario específico.
bind_zones n/a Una lista de mapeos con definiciones de zona.
- allow_update ['none'] Una lista de hosts que están permitidos para actualizar dinámicamente esta zona DNS.
- also_notify - Una lista de servidores que recibirán una notificación cuando se recargue el archivo de zona primaria.
- create_forward_zones - Cuando se inicializa y se establece en false, se omitirá la creación de zonas de reenvío (resultando en una zona solo inversa).
- create_reverse_zones - Cuando se inicializa y se establece en false, se omitirá la creación de zonas inversas (resultando en una zona solo de reenvío).
- delegate [] Delegación de zona.
- forwarders - Lista de reenvíos para la zona de tipo reenvío.
- hostmaster_email hostmaster La dirección de correo electrónico del administrador del sistema para la zona.
- hosts [] Definiciones de hosts.
- ipv6_networks [] Una lista de redes IPv6 que son parte del dominio, en notación CIDR (por ejemplo, 2001:db8::/48).
- mail_servers [] Una lista de mapeos (con claves name: y preference:) especificando los servidores de correo para este dominio.
- name_servers [ansible_hostname] Una lista de los servidores DNS para este dominio.
- name example.com El nombre de dominio.
- naptr [] Una lista de mapeos con claves name:, order:, pref:, flags:, service:, regex: y replacement: especificando registros NAPTR.
- networks ['10.0.2'] Una lista de las redes que son parte del dominio.
- other_name_servers [] Una lista de los servidores DNS fuera de este dominio.
- primaries - Una lista de servidores DNS primarios para esta zona.
- services [] Una lista de servicios a ser anunciados por registros SRV.
- text [] Una lista de mapeos con claves name: y text:, especificando registros TXT. text: puede ser una lista o una cadena.
- caa [] Una lista de mapeos con claves name: y text:, especificando registros CAA. text: puede ser una lista o una cadena.
- type - Tipo de zona opcional. Si no se especifica, se utilizará la autodetección. Los valores posibles incluyen primary, secondary o forward.
bind_zone_file_mode 0640 Los permisos de archivo para el archivo de configuración principal (named.conf).
bind_zone_minimum_ttl 1D Campo TTL mínimo en el registro SOA.
bind_zone_time_to_expire 1W Campo de tiempo de expiración en el registro SOA.
bind_zone_time_to_refresh 1D Campo de tiempo de actualización en el registro SOA.
bind_zone_time_to_retry 1H Campo de tiempo de reintento en el registro SOA.
bind_zone_ttl 1W Campo de Tiempo de Vida en el registro SOA.
bind_python_version - La versión de python que debería usarse para ansible. Depende de la distribución, ya sea 2 o 3. Por defecto, es la estándar del SO.

† La mejor práctica para un servidor de nombres autoritativo es dejar la recursión desactivada. Sin embargo, en algunos casos puede ser necesario tener la recursión activada.

Variables mínimas para una zona funcional

Para configurar un servidor de nombres autoritativo que esté disponible para los clientes, debes definir al menos las siguientes variables:

Variable Primario Secundario Reenvío
bind_allow_query V V V
bind_listen_ipv4 V V V
bind_zones V V V
- hosts V -- --
- name_servers V -- --
- name V V --
- networks V V V
- primaries V V --
- forwarders -- -- V

Definiciones de dominio

bind_zones:
  # Ejemplo de una zona primaria (hosts: y name_servers: están definidos)
  - name: mydomain.com         # Nombre de dominio
    create_reverse_zones: false # Omitir creación de zonas inversas
    primaries:
      - 192.0.2.1              # Servidor(es) primario(s) para esta zona
    name_servers:
      - pub01.mydomain.com.
      - pub02.mydomain.com.
    hosts:
      - name: pub01
        ip: 192.0.2.1
        ipv6: 2001:db8::1
        aliases:
          - ns1
      - name: pub02
        ip: 192.0.2.2
        ipv6: 2001:db8::2
        aliases:
          - ns2
      - name: '@'               # Permite "http://mydomain.com/"
        ip:
          - 192.0.2.3           # Múltiples direcciones IP para un solo host
          - 192.0.2.4           #   resulta en DNS round robin
        sshfp:                  # Huella digital de shell seguro
          - "3 1 1262006f9a45bb36b1aa14f45f354b694b77d7c3"
          - "3 2 e5921564252fe10d2dbafeb243733ed8b1d165b8fa6d5a0e29198e5793f0623b"
        ipv6:
          - 2001:db8::2
          - 2001:db8::3
        aliases:
          - www
      - name: priv01            # Esta IP está en otra subred y resultará en
        ip: 10.0.0.1            #   zonas inversas múltiples
      - name: mydomain.net.
        aliases:
          - name: sub01
            type: DNAME         # Ejemplo de un registro de alias DNAME
    networks:
      - '192.0.2'
      - '10'
      - '172.16'
    delegate:
      - zone: foo
        dns: 192.0.2.1
    services:
      - name: _ldap._tcp
        weight: 100
        port: 88
        target: dc001
    naptr:                      # Registro de Puntero de Autoridad de Nombre, usado para IP  
      - name: "sip"             #   telefonía
        order: 100
        pref: 10
        flags: "S"
        service: "SIP+D2T"
        regex: "!^.*$!sip:[email protected]!"
        replacement: "_sip._tcp.example.com."
  # Ejemplo mínimo de una zona secundaria
  - name: acme.com
    primaries:
      - 172.17.0.2
    networks:
      - "172.17"
  # Ejemplo mínimo de una zona de reenvío
  - name: acme.com
    forwarders:
      - 172.17.0.2
    networks:
      - "172.17"

Hosts

Los nombres de host que este servidor DNS debe resolver se pueden especificar en bind_zones.hosts como una lista de mapeos con claves name:, ip:, aliases: y sshfp:. Los alias pueden ser registros CNAME (por defecto) o DNAME.

Para permitir que se navegue a http://example.com/, establece el nombre del host de tu servidor web en '@' (debe estar entre comillas). En la sintaxis de BIND, @ indica el nombre de dominio en sí.

Si deseas especificar múltiples direcciones IP para un host, agrega entradas a bind_zones.hosts con el mismo nombre (por ejemplo, priv01 en el fragmento de código). Esto resulta en múltiples registros A/AAAA para ese host y permite DNS round robin, una técnica simple de balanceo de carga. El orden en el que se devuelven las direcciones IP se puede configurar con la variable del rol bind_rrset_order.

Redes

Como puedes ver, no todos los hosts están en la misma subred. Este rol generará zonas de búsqueda inversa adecuadas para cada subred. Todas las subredes deben especificarse en bind_zones.networks, de lo contrario, el host no recibirá un registro PTR para la búsqueda inversa.

Observa que solo se debe especificar la parte de la red aquí. Al especificar una dirección IP de clase B (por ejemplo, "172.16") en un archivo de variables, debe estar entre comillas. De lo contrario, el analizador Yaml lo interpretará como un flotante.

Basado en la idea y ejemplos detallados en https://linuxmonk.ch/wordpress/index.php/2016/managing-dns-zones-with-ansible/ para el paquete gdnsd, los archivos de zona son completamente idempotentes y, por lo tanto, solo se actualizan si cambian "contenidos reales".

Tipos de zona y autodetección de tipo de zona

El tipo de zona es un parámetro opcional que define si el tipo de zona debería ser primario, secundario o de reenvío. Cuando se omite el parámetro tipo, el tipo de zona se autodetectará en función de la intersección de direcciones IP de hosts y el registro de primarios al configurar la zona primaria o secundaria. Cuando primarios no está definido y forwarders está definido, el tipo de zona se establecerá como forward.

La funcionalidad de autodetección de zonas es especialmente útil al implementar una infraestructura DNS multi-sitio. Es conveniente tener definiciones de bind_zones "compartidas" en un solo archivo de inventario de grupo para todos los servidores DNS (por ejemplo, group_vars\dns.yml). Tal enfoque permite cambiar entre los roles de servidor primario y secundario al actualizar solo el registro de primarios y volver a ejecutar el playbook. La autodetección de tipo de zona se puede probar con el escenario de molécula "shared_inventory" ejecutando: molecule test --scenario-name shared_inventory


NOTA

  • BIND no admite la configuración multi-maestro automatizada y la lista de primarios debe tener solo una entrada.
  • Cuando se actualiza el registro de primarios para cambiar los roles de servidor primario a secundario, las zonas se eliminarán y recrearán desde la plantilla ya que aún no admitimos actualizaciones dinámicas para zonas existentes.

Los tipos de zona también se pueden definir explícitamente en el inventario por host para omitir la autodetección:

# Servidor Primario
bind_zones:
  - name: mydomain.com
    type: primary
    primaries:
      - 192.0.2.1
...
# Servidor Secundario
bind_zones:
  - name: mydomain.com
      type: secondary
      primaries:
        - 192.0.2.1
...
# Servidor de Reenvío
bind_zones:
  - name: anotherdomain.com
      type: forward
      forwarders:
        - 192.0.3.1

Delegación de Zona

Para delegar una zona a un servidor DNS, es suficiente crear un registro NS (bajo delegate) que es equivalente a:

foo IN NS 192.0.2.1

Registros de Servicio

Los registros de servicio (SRV) se pueden agregar con los servicios. Esto debería ser una lista de mapeos con las claves obligatorias name: (nombre del servicio), target: (host que proporciona el servicio), port: (puerto TCP/UDP del servicio) y las claves opcionales priority: (por defecto = 0) y weight: (por defecto = 0).

ACLs

Las ACLs se pueden definir de esta manera:

bind_acls:
  - name: acl1
    match_list:
      - 192.0.2.0/24
      - 10.0.0.0/8

Los nombres de las ACLs se agregarán a la cláusula allow-transfer en las opciones globales.

Claves de Vínculo

Las claves de vínculo se pueden definir de esta manera:

bind_dns_keys:
  - name: primary_key
    algorithm: hmac-sha256
    secret: "azertyAZERTY123456"
bind_extra_include_files:
  - "{{ bind_auth_file }}"

Consejo: El archivo adicional debe establecerse como una variable de ansible porque el archivo depende del SO.

Esto se establecerá en un archivo "{{ bind_auth_file }} (por ejemplo, /etc/bind/auth_transfer.conf para Debian) que debe agregarse a la lista de la variable bind_extra_include_files.

Uso de TSIG para autorización de transferencia de zona (XFR)

Para autorizar la transferencia de zona entre servidores primarios y secundarios en función de una clave TSIG, establece el mapeo en la variable bind_key_mapping:

bind_key_mapping:
  primary_ip: nombre_clave_TSIG

Cada primario solo puede tener una clave (por vista).

Se realizará una verificación para asegurarse de que la clave esté realmente presente en el mapeo bind_dns_keys. Esto agregará una declaración de servidor para el a en bind_auth_file en un servidor secundario que contenga la clave especificada.

Dependencias

Sin dependencias.

Ejemplos de Playbooks

Consulta los playbooks de prueba e inventario para un ejemplo detallado que muestra la mayoría de las características.

Inventario Estándar

❯ tree --dirsfirst molecule/default
molecule/default
├── group_vars
│   └── all.yml
├── host_vars
│   ├── ns1.yml    # Primario
│   ├── ns2.yml    # Secundario
│   └── ns3.yml    # Retransmisor
├── converge.yml
...

Inventario Compartido

Variables comunes entre servidores primarios y secundarios definidas en all.yml

❯ tree --dirsfirst molecule/shared_inventory
molecule/shared_inventory
├── group_vars
│   └── all.yml
├── converge.yml
...

Pruebas

Este rol se prueba utilizando Ansible Molecule. Las pruebas se lanzan automáticamente en Github Actions después de cada commit y PR.

Esta configuración de molécula:

  • Ejecutará Yamllint y Ansible Lint
  • Creará tres contenedores Docker, uno primario (ns1), uno secundario (ns2) y un retransmisor (ns3) - escenario de molécula default
  • Ejecutará una verificación de sintaxis
  • Aplicará el rol con un playbook de prueba y comprobará la idempotencia
  • Ejecutará pruebas de aceptación con el playbook de verificación
  • Creará dos contenedores Docker adicionales, uno primario (ns4) y uno secundario (ns5) y ejecutará el escenario shared_inventory

Este proceso se repite para todas las distribuciones de Linux soportadas.

Entorno de prueba local

Para ejecutar las pruebas de aceptación en este rol localmente, puedes instalar las herramientas necesarias en tu máquina, o usar esta configuración reproducible en una VM de VirtualBox (configurada con Vagrant): https://github.com/bertvv/ansible-testenv.

Pasos para instalar las herramientas manualmente:

  1. Docker debe estar instalado en tu máquina.
  2. Como recomienda Molecule, crea un entorno virtual de python.
  3. Instala las herramientas de software python3 -m pip install molecule molecule-docker docker netaddr dnspython yamllint ansible-lint.
  4. Navega a la raíz del directorio del rol y ejecuta molecule test.

Molecule elimina automáticamente los contenedores después de una prueba. Si deseas revisar los contenedores tú mismo, ejecuta molecule converge seguido de molecule login --host HOSTNAME.

Los contenedores Docker se basan en imágenes creadas por Jeff Geerling, específicamente para pruebas de Ansible (busca imágenes nombradas geerlingguy/docker-DISTRO-ansible). Puedes usar cualquiera de sus imágenes, pero solo se admiten las distribuciones mencionadas en meta/main.yml.

La configuración predeterminada iniciará tres contenedores de Centos 8 (la plataforma primaria soportada en este momento). Elige otra distribución estableciendo la variable MOLECULE_DISTRO con el comando, por ejemplo:

MOLECULE_DISTRO=debian9 molecule test

o

MOLECULE_DISTRO=debian9 molecule converge

Puedes ejecutar las pruebas de aceptación en todos los servidores con molecule verify.

Las pruebas de verificación se realizan utilizando el módulo de búsqueda "dig" consultando registros dns y validando respuestas. Esto requiere comunicación de red directa entre el nodo de controlador Ansible (tu máquina que ejecuta Ansible) y el contenedor docker objetivo.


NOTA

Las pruebas de verificación de molécula fallarán si Docker está ejecutándose en MacOS, ya que MacOS no puede acceder a la IP del contenedor directamente. Este es un problema conocido. Ver #2670.

Solución alternativa:

  1. Ejecuta el linter de molécula: molecule lint.
  2. Provisióna los contenedores: molecule converge.
  3. Conéctate al contenedor: molecule login --host ns1.
  4. Ve al directorio del rol: cd /etc/ansible/roles/bertvv.bind.
  5. Ejecuta el playbook de verificación:
ansible-playbook -c local -i "`hostname`," -i molecule/default/inventory.ini molecule/default/verify.yml
  1. Repite los pasos 2-4 para ns2 y ns3.

Licencia

BSD

Contribuidores

Este rol solo pudo ser realizado gracias a las contribuciones de muchos. Si tienes una idea para mejorarlo aún más, ¡no dudes en participar!

Los problemas, solicitudes de características, ideas, sugerencias, etc., se pueden publicar en la sección de problemas.

Las solicitudes de extracción también son muy bienvenidas. Por favor, crea una rama de tema para tus cambios propuestos. Si no lo haces, esto creará conflictos en tu fork después de la fusión. ¡No dudes en agregarte a la lista de contribuyentes a continuación en tu PR!

Mantenedores:

Contribuidores:

Acerca del proyecto

Sets up ISC BIND as an authoritative DNS server for one or more domains (primary and/or secondary).

Instalar
ansible-galaxy install bertvv.bind
Licencia
other
Descargas
406.9k
Propietario
Hi! My contribs are often related to my job (teaching Linux), but are mostly done in my free time. I can't always respond quickly to PRs and Issues. Sorry!