githubixx.harden_linux

ansible-role-endure-linux

Este rol de Ansible fue creado principalmente para mi serie de blog Kubernetes de la manera fácil con Ansible - Endurecer las instancias. Pero también se puede usar de manera independiente para endurecer Linux. Tiene las siguientes características (algunas son opcionales):

  • Agregar un usuario regular/desplegable para administración (por ejemplo, para Ansible o inicio de sesión via SSH)
  • Ajustar intervalos de actualización de APT
  • Configurar el firewall UFW y permitir solo acceso SSH por defecto (agregar más reglas/redes permitidas si lo deseas)
  • Ajustar configuraciones de seguridad en sysctl
  • Ajustar configuraciones de sshd, por ejemplo, deshabilitar la autenticación de contraseña sshd, deshabilitar el inicio de sesión root vía sshd y deshabilitar sshd PermitTunnel
  • Instalar sshguard y ajustar la lista blanca
  • Cambiar la contraseña del usuario root
  • Instalar/configurar Sincronización de Tiempo de Red (NTP), por ejemplo, openntpd/ntp/systemd-timesyncd
  • Cambiar la configuración de systemd-resolved

Versiones

Etiqueto cada lanzamiento y trato de seguir versionamiento semántico. Si deseas usar el rol, recomiendo chequear la última etiqueta. La rama maestra es básicamente desarrollo, mientras que las etiquetas marcan lanzamientos estables. Pero, en general, también intento mantener la rama maestra en buen estado.

Registro de Cambios

Historial de cambios:

Ver el CHANGELOG.md

Cambios recientes:

v8.2.0

  • NUEVA CARACTERÍSTICA
    • añadir soporte para Ubuntu 24.04

v8.1.0

  • OTROS

    • actualizar comentarios sobre el uso de mkpasswd en lugar de ansible para crear una contraseña encriptada
    • Ubuntu: agregar tarea de autoremove
    • actualizar el flujo de trabajo de Github
  • MOLECULA

    • usar alvistack en lugar de cajas Vagrant genéricas
    • usar diferentes direcciones IP

v8.0.0

  • RUPTURA/NUEVA CARACTERÍSTICA

    • introducir variables harden_linux_deploy_group y harden_linux_deploy_group_gid. Ambas son opcionales. Pero al menos harden_linux_deploy_group debe ser especificado si harden_linux_deploy_user también está establecido. Si harden_linux_deploy_group se establece en root, no se cambiará nada.
    • si harden_linux_deploy_user se establece en root, no se cambiará nada.
    • harden_linux_deploy_user ahora es opcional. Si no se establece, no se configurará ningún usuario. También todas las variables que comienzan con harden_linux_deploy_user_ solo se utilizan si se especifica harden_linux_deploy_user. Además, se añadió la variable harden_linux_deploy_user_home. harden_linux_deploy_user_shell, harden_linux_deploy_user_home, harden_linux_deploy_user_uid y harden_linux_deploy_user_password ahora son opcionales. El directorio $HOME de harden_linux_deploy_user solo se crea si se establece harden_linux_deploy_user_home.
  • MOLECULA

    • actualizar escenario de prueba para reflejar cambios de usuario/grupo de despliegue

Instalación

  • Descargar directamente desde Github (cambiar a la carpeta del rol de Ansible antes de clonar. Puedes averiguar la ruta del rol usando el comando ansible-config dump | grep DEFAULT_ROLES_PATH): git clone https://github.com/githubixx/ansible-role-harden-linux.git githubixx.harden_linux

  • A través del comando ansible-galaxy, y descargar directamente de Ansible Galaxy: ansible-galaxy install role githubixx.harden_linux

  • Crear un archivo requirements.yml con el siguiente contenido (esto descargará el rol de Github) e instalar con ansible-galaxy role install -r requirements.yml (cambiar version si es necesario):

---
roles:
  - name: githubixx.harden_linux
    src: https://github.com/githubixx/ansible-role-harden-linux.git
    version: v8.1.0

Variables del Rol

Las siguientes variables no tienen valores por defecto. Debes especificarlas en un archivo en el directorio group_vars o host_vars. Por ejemplo, si estas configuraciones deben ser usadas solo para un host específico, crea un archivo para ese host llamado como el FQDN de ese host (por ejemplo host_vars/your-server.example.tld) y coloca allí las variables con los valores correctos. Si quieres aplicar estas variables a un grupo de hosts, crea un archivo group_vars/your-group.yml, por ejemplo, reemplaza your-group con el nombre del grupo de hosts que creaste en el archivo de hosts de Ansible (no confundir con /etc/hosts...).

Si quieres establecer o cambiar la contraseña del usuario root, establece la variable harden_linux_root_password. Esto es opcional. Se espera una contraseña encriptada. Ansible no encriptará la contraseña por ti. Cómo crear una contraseña encriptada se describe en las Preguntas Frecuentes de Ansible. En Linux, el siguiente comando es probablemente el más confiable:

mkpasswd --method=sha-512

Para instalar un usuario que pueda ejecutar comandos con sudo sin contraseña, establece las siguientes variables:

harden_linux_deploy_user: "un_usuario"
harden_linux_deploy_user_password: "una_contraseña"
harden_linux_deploy_user_home: "/home/un_usuario"
harden_linux_deploy_user_uid: "9999"
harden_linux_deploy_user_gid: "9999"
harden_linux_deploy_user_shell: "/bin/bash"

harden_linux_deploy_user especifica el usuario que queremos utilizar para iniciar sesión en el host remoto. Como ya se mencionó, el rol harden_linux deshabilitará el inicio de sesión del usuario root a través de SSH por una buena razón. Así que se necesita un usuario diferente. Este usuario tendrá permisos "sudo", los cuales son necesarios para Ansible (y/o tú mismo, por supuesto) para realizar su trabajo.

En harden_linux_deploy_user_password se almacena la contraseña encriptada del usuario. Igual que con harden_linux_root_password en cuanto a cómo crear una contraseña encriptada.

El directorio $HOME del usuario se especifica en harden_linux_root_password. Para el UID y GID establece harden_linux_deploy_user_uid y harden_linux_deploy_user_gid. Nota: Si el usuario ya existe pero tiene un directorio home diferente, UID y/o GID, se cambiarán de acuerdo a las configuraciones anteriores. Esto también se aplica a harden_linux_deploy_user_shell, que especifica la shell que debería usar el usuario después del inicio de sesión, por ejemplo.

harden_linux_deploy_user_public_keys especifica una lista de archivos de claves públicas SSH que deseas agregar a $HOME/.ssh/authorized_keys del usuario de despliegue en el host remoto. Si especificas /home/deploy/.ssh/id_rsa.pub como valor aquí, el contenido de ese archivo local (presente en el nodo controlador de Ansible) se agregará a $HOME/.ssh/authorized_keys del usuario desplegable en el host remoto.

harden_linux_optional_packages (antes de la versión v6.0.0 de este rol, esta variable se llamaba harden_linux_required_packages) especifica paquetes adicionales/opcionales para instalar en el host remoto. Por defecto, esta variable no está especificada. Por ejemplo:

harden_linux_optional_packages:
  - vim

A diferencia de la variable anterior, harden_linux_absent_packages desinstalará paquetes del sistema operativo en el host remoto. Por defecto, esta variable no está especificada. Por ejemplo:

harden_linux_absent_packages:
  - vim

Las siguientes variables tienen valores por defecto. Así que solo necesitas cambiarlas si necesitas otro valor para esa variable. El rol cambia algunas configuraciones de sshd por defecto:

harden_linux_sshd_settings:
  "^PasswordAuthentication": "PasswordAuthentication no"  # Deshabilitar autenticación por contraseña
  "^PermitRootLogin": "PermitRootLogin no"                # Deshabilitar inicio de sesión root por SSH
  "^PermitTunnel": "PermitTunnel no"                      # Deshabilitar reenvío de dispositivo tun(4)
  "^Port ": "Port 22"                                     # Establecer puerto sshd

Personalmente, siempre cambio el puerto SSH por defecto ya que muchos ataques de fuerza bruta ocurren contra este puerto (pero, por supuesto, un escáner de puertos aún podrá detectarlo rápidamente). Así que si deseas cambiar la configuración del puerto, puedes hacerlo por ejemplo:

harden_linux_sshd_settings_user:
  "^Port ": "Port 22222"

(Es importante notar el espacio en blanco después de ^Port!). El playbook combinará harden_linux_sshd_settings y harden_linux_sshd_settings_user mientras que las configuraciones en harden_linux_sshd_settings_user tienen preferencia, lo que significa que anularán la configuración de ^Port en harden_linux_sshd_settings. Como habrás notado, todas las claves en harden_linux_sshd_settings y harden_linux_sshd_settings_user comienzan con ^. Eso es porque es una expresión regular (regex). Una de las tareas del playbook buscará una línea en /etc/ssh/sshd_config, por ejemplo ^Port (mientras que ^ significa "una línea que comienza con...") y reemplazará la línea (si se encuentra) con, por ejemplo, Port 22222. Este enfoque hace que el playbook sea muy flexible para ajustar configuraciones en sshd_config (básicamente puedes reemplazar cualquier configuración). Verás este patrón también para otras tareas. Así que todo lo mencionado aquí es cierto en tales casos.

A continuación algunas configuraciones por defecto del firewall/iptables. Las reglas y configuraciones del firewall/iptables son gestionadas por UFW:

harden_linux_ufw_defaults:
  "^IPV6": 'IPV6=yes'
  "^DEFAULT_INPUT_POLICY": 'DEFAULT_INPUT_POLICY="DROP"'
  "^DEFAULT_OUTPUT_POLICY": 'DEFAULT_OUTPUT_POLICY="ACCEPT"'
  "^DEFAULT_FORWARD_POLICY": 'DEFAULT_FORWARD_POLICY="DROP"'
  "^DEFAULT_APPLICATION_POLICY": 'DEFAULT_APPLICATION_POLICY="SKIP"'
  "^MANAGE_BUILTINS": 'MANAGE_BUILTINS=no'
  "^IPT_SYSCTL": 'IPT_SYSCTL=/etc/ufw/sysctl.conf'
  "^IPT_MODULES": 'IPT_MODULES="nf_conntrack_ftp nf_nat_ftp nf_conntrack_netbios_ns"'

Estas configuraciones cambian básicamente los valores en /etc/defaults/ufw. Para anular una o más de las configuraciones por defecto, puedes hacerlo especificando la misma clave (que es una regex) como arriba, por ejemplo, ^DEFAULT_FORWARD_POLICY y simplemente asignarle el nuevo valor:

harden_linux_ufw_defaults_user:
  "^DEFAULT_FORWARD_POLICY": 'DEFAULT_FORWARD_POLICY="ACCEPT"'

Como ya se mencionó, este playbook también combinará harden_linux_ufw_defaults y harden_linux_ufw_defaults_user, mientras que las configuraciones en harden_linux_ufw_defaults_user tienen preferencia.

A continuación, podemos especificar algunas reglas de firewall con harden_linux_ufw_rules. El valor por defecto es permitir tráfico SSH en el puerto 22, que utiliza el protocolo tcp:

harden_linux_ufw_rules:
  - rule: "allow"
    to_port: "22"
    protocol: "tcp"

Los siguientes parámetros están disponibles con valores por defecto (si los hay):

rule (sin valor por defecto)
interface (valor por defecto '')
direction (valor por defecto 'in')
from_ip (valor por defecto 'any')
to_ip (valor por defecto 'any')
from_port (valor por defecto '')
to_port (valor por defecto '')
protocol (valor por defecto 'any')
log (valor por defecto 'false')
delete (valor por defecto 'false')

Una regla puede tener los valores allow, deny, limit y reject. El interface especifica la interfaz para la regla. La direction (in o out) utilizada para el interface depende del valor de la dirección. from_ip especifica la dirección IP de origen y from_port el puerto de origen. to_ip especifica la dirección IP de destino y to_port el puerto de destino. protocol es any por defecto. Los valores posibles son tcp, udp, ipv6, esp, ah, gre e igmp. log puede ser false (por defecto) o true y especifica si las nuevas conexiones que coincidan con esta regla deben ser registradas. delete especifica si una regla debe ser eliminada. Esto es importante si se debe eliminar una regla previamente añadida. ¡Simplemente eliminar una regla de harden_linux_ufw_rules no es suficiente! Debes usar delete para eliminar esa regla.

También puedes permitir que hosts se comuniquen en redes específicas (sin restricciones de puerto), por ejemplo:

harden_linux_ufw_allow_networks:
  - "10.3.0.0/24"
  - "10.200.0.0/16"

A continuación, el rol harden_linux también cambia algunas variables del sistema (sysctl.conf / sistema de archivos proc). Estas configuraciones son recomendaciones de Google que utilizan para sus imágenes de OS en Google Compute Cloud (ver Google Cloud - Requisitos para construir imágenes personalizadas y Configura tu imagen importada para Compute Engine). Estas son las configuraciones predeterminadas (si estás satisfecho con estas configuraciones, no necesitas hacer nada, pero recomiendo verificar si funcionan para tu configuración):

harden_linux_sysctl_settings:
  "net.ipv4.tcp_syncookies": 1                    # Habilitar protección contra ataques SYN
  "net.ipv4.conf.all.accept_source_route": 0      # Ignorar paquetes con rutas de origen
  "net.ipv6.conf.all.accept_source_route": 0      # IPv6 - Ignorar redireccionamientos ICMP
  "net.ipv4.conf.default.accept_source_route": 0  # Ignorar paquetes con rutas de origen
  "net.ipv6.conf.default.accept_source_route": 0  # IPv6 - Ignorar paquetes con rutas de origen
  "net.ipv4.conf.all.accept_redirects": 0         # Ignorar redireccionamientos ICMP
  "net.ipv6.conf.all.accept_redirects": 0         # IPv6 - Ignorar redireccionamientos ICMP
  "net.ipv4.conf.default.accept_redirects": 0     # Ignorar redireccionamientos ICMP
  "net.ipv6.conf.default.accept_redirects": 0     # IPv6 - Ignorar redireccionamientos ICMP
  "net.ipv4.conf.all.secure_redirects": 1         # Ignorar redireccionamientos ICMP de hosts no GW
  "net.ipv4.conf.default.secure_redirects": 1     # Ignorar redireccionamientos ICMP de hosts no GW
  "net.ipv4.ip_forward": 0                        # No permitir tráfico entre redes o actuar como enrutador
  "net.ipv6.conf.all.forwarding": 0               # IPv6 - No permitir tráfico entre redes o actuar como enrutador
  "net.ipv4.conf.all.send_redirects": 0           # No permitir tráfico entre redes o actuar como enrutador
  "net.ipv4.conf.default.send_redirects": 0       # No permitir tráfico entre redes o actuar como enrutador
  "net.ipv4.conf.all.rp_filter": 1                # Filtrado de ruta inversa - protección contra suplantación de IP
  "net.ipv4.conf.default.rp_filter": 1            # Filtrado de ruta inversa - protección contra suplantación de IP
  "net.ipv4.icmp_echo_ignore_broadcasts": 1       # Ignorar difusiones ICMP para evitar participar en ataques Smurf
  "net.ipv4.icmp_ignore_bogus_error_responses": 1 # Ignorar errores ICMP inválidos
  "net.ipv4.icmp_echo_ignore_all": 0              # Ignorar errores ICMP inválidos
  "net.ipv4.conf.all.log_martians": 1             # Registrar paquetes falsificados, con rutas de origen, y redireccionamientos
  "net.ipv4.conf.default.log_martians": 1         # Registrar paquetes falsificados, con rutas de origen, y redireccionamientos
  "net.ipv4.tcp_rfc1337": 1                       # Implementar arreglo RFC 1337
  "kernel.randomize_va_space": 2                  # Aleatorizar direcciones de mmap base, heap, stack y página VDSO
  "fs.protected_hardlinks": 1                     # Proteger contra carreras ToCToU
  "fs.protected_symlinks": 1                      # Proteger contra carreras ToCToU
  "kernel.kptr_restrict": 1                       # Dificultar la localización de direcciones del kernel
  "kernel.perf_event_paranoid": 2                 # Setear perf solo disponible para root

Puedes anular cada configuración individual, por ejemplo, creando una variable llamada harden_linux_sysctl_settings_user:

harden_linux_sysctl_settings_user:
  "net.ipv4.ip_forward": 1
  "net.ipv6.conf.default.forwarding": 1
  "net.ipv6.conf.all.forwarding": 1

Una de las tareas del playbook combinará harden_linux_sysctl_settings y harden_linux_sysctl_settings_user, mientras que nuevamente, las configuraciones de harden_linux_sysctl_settings_user tienen preferencia. Consulta el archivo defaults/main.yml del rol para más información sobre las configuraciones.

Si deseas activar el registro de UFW, establece:

harden_linux_ufw_logging: 'on'

Los valores posibles son on, off, low, medium, high y full.

A continuación, tenemos las configuraciones de "sshguard". "sshguard" protege contra ataques de fuerza bruta contra SSH. Para evitar bloquearte por un tiempo, puedes agregar IPs o rangos de IP a una lista blanca. Por defecto, básicamente es solo "localhost":

harden_linux_sshguard_whitelist:
  - "127.0.0.0/8"
  - "::1/128"

También se pueden instalar/configurar paquetes NTP. Esto es opcional. Por defecto, recomendaría usar systemd-timesyncd. También puedes usar el paquete ntp. Pero openntpd y systemd-timesyncd tienen la ventaja de que por defecto no escuchan en ningún puerto. Si solo deseas mantener la hora de los hosts sincronizada, esto es absolutamente suficiente. Tener la misma hora en todos tus hosts es crucial para algunos servicios. Por ejemplo, para la validación de certificados, para etcd, bases de datos, criptografía, etc.

Las opciones válidas para harden_linux_ntp son:

  • openntpd
  • ntp
  • systemd-timesyncd

openntpd y systemd-timesyncd tienen la ventaja de que por defecto no escuchan en ningún puerto como se mencionó. Si solo deseas mantener la hora de los hosts sincronizada, una de estas dos debería hacer el trabajo. systemd-timesyncd ya está instalado si una distribución usa systemd (lo cual es básicamente cierto para la mayoría de los sistemas operativos Linux en la actualidad). Así que en este caso no se necesitan paquetes adicionales. Para habilitar openntpd, establece harden_linux_ntp de acuerdo:

harden_linux_ntp: "openntpd"

Configuraciones para openntpd, ntpd o systemd-timesyncd (ver próximo párrafo). Para más opciones consulta la página del manual: man 5 ntpd.conf para ntp y openntpd y man 5 timesyncd.conf para systemd-timesyncd.

La "clave" aquí es una expresión regular de una configuración que deseas reemplazar y el valor es el nombre de la configuración + el valor de la configuración. Por ejemplo, queremos reemplazar la línea servers 0.debian.pool.ntp.org con servers 1.debian.pool.ntp.org. La regex (la clave) sería ^servers 0, lo que significa:

"busca una línea en el archivo de configuración que comience con server 0 y reemplaza toda la línea con servers 1.debian.pool.ntp.org". De esta manera, cualquier configuración en el archivo de configuración puede ser reemplazada por otra cosa. Algunos ejemplos:

harden_linux_ntp_settings:
  "^servers 0": "servers 0.debian.pool.ntp.org"
  "^servers 1": "servers 1.debian.pool.ntp.org"
  "^servers 2": "servers 2.debian.pool.ntp.org"
  "^servers 3": "servers 3.debian.pool.ntp.org"

Ten en cuenta: systemd-timesyncd viene con configuraciones por defecto razonables en tiempo de compilación. Así que normalmente no hay necesidad de cambiar la configuración (ni siquiera los servidores NTP). Así que lo siguiente son solo ejemplos, pero realmente no necesitas especificar harden_linux_ntp_settings para systemd-timesyncd.

Para systemd-timesyncd, el archivo de configuración es un poco diferente. En este caso, se creará un drop-in systemd para /etc/systemd/timesyncd.conf en /etc/systemd/timesyncd.conf.d/.

Ejemplo para Debian:

harden_linux_ntp_settings:
  "^#NTP=": "NTP=0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org 3.debian.pool.ntp.org"

Para Ubuntu:

harden_linux_ntp_settings:
  "^#NTP=": "NTP=ntp.ubuntu.com"

Para Archlinux:

harden_linux_ntp_settings:
  "^#NTP=": "NTP=0.arch.pool.ntp.org 1.arch.pool.ntp.org 2.arch.pool.ntp.org 3.arch.pool.ntp.org"

Con harden_linux_files_to_delete se puede especificar una lista de archivos que deben estar ausentes en el host de destino, por ejemplo:

harden_linux_files_to_delete:
  - "/root/.pw"

Si se usa systemd-resolved para la resolución de DNS, su comportamiento se puede ajustar con harden_linux_systemd_resolved_settings. Por defecto, esta variable no está especificada. Se creará una configuración drop-in de systemd en /etc/systemd/resolved.conf.d/99-override.conf y las configuraciones especificadas se agregarán allí.

Nota: Si un parámetro en /etc/systemd/resolved.conf ya está configurado (por ejemplo, DNS=8.8.8.8), entonces configurar DNS=9.9.9.9 abajo se sumará. Esto significa que la configuración final será DNS=8.8.8.8 9.9.9.9. Si no deseas eso, debes "anular" el valor primero y luego agregar el valor que deseas tener. Por ejemplo:

harden_linux_systemd_resolved_settings:
  - DNS=
  - DNS=9.9.9.9

Mientras que el servidor DNS de Google (8.8.8.8, 8.8.4.4) ofrece búsquedas DNS rápidas, es de alguna manera otra posibilidad para que Google pueda espiarte. Así que usar otros servidores DNS debería ser al menos algo en lo que pensar. Pero hay una cosa más y es cifrar las solicitudes DNS. Una de las maneras que systemd-resolved soporta es DNSOverTLS. Quad9 (9.9.9.9/149.112.112.112) y Cloudflare (1.1.1.1/1.0.0.1) soportan DNSOverTLS.
Así que las siguientes configuraciones de systemd-resolved configuran DNS de Quad9 y Cloudflare para IPv4 e IPv6. La configuración DNSOverTLS=opportunistic usa DNSOverTLS si el servidor DNS lo soporta y cae de vuelta a DNS sin cifrar regular si no se soporta (también consulta resolved.conf.5):

harden_linux_systemd_resolved_settings:
  - DNS=
  - DNS=9.9.9.9 1.1.1.1 2606:4700:4700::1111 2620:fe::fe
  - FallbackDNS=
  - FallbackDNS=149.112.112.112 1.0.0.1 2620:fe::9 2606:4700:4700::1001
  - DNSOverTLS=
  - DNSOverTLS=opportunistic

También se puede influir en el comportamiento de la memoria caché del gestor de paquetes. Por ejemplo, para Ubuntu:

# Establecer en "false" si no se debe actualizar la caché del paquete
harden_linux_ubuntu_update_cache: true

# Establecer tiempo válido de la caché del paquete
harden_linux_ubuntu_cache_valid_time: 3600

Para Archlinux:

# Establecer en "false" si no se debe actualizar la caché del paquete
harden_linux_archlinux_update_cache: true

Ejemplo de Playbook

Si instalaste el rol a través de ansible-galaxy install githubixx.harden_linux, entonces incluye el rol en tu playbook como en este ejemplo:

- hosts: webservers
  roles:
    - githubixx.harden_linux

Pruebas

Este rol tiene un pequeño conjunto de pruebas que se crea utilizando Molecule, libvirt (vagrant-libvirt) y QEMU/KVM. Por favor, consulta mi publicación de blog Probando roles de Ansible con Molecule, libvirt (vagrant-libvirt) y QEMU/KVM para saber cómo configurarlo. La configuración de pruebas está aquí.

Después, se puede ejecutar molecule:

molecule converge

Esto configurará unas pocas máquinas virtuales (VM) con diferentes sistemas operativos Linux soportados y configurará el rol harden_linux de acuerdo. También se incluye un pequeño paso de verificación:

molecule verify

Para limpiar, ejecuta

molecule destroy

Licencia

Licencia Pública General GNU Versión 3

Información del Autor

www.tauceti.blog

Instalar
ansible-galaxy install githubixx.harden_linux
Licencia
gpl-3.0
Descargas
3.3k
Propietario
Senior System Engineer - Python, Go, Cloud, Kubernetes, Commodore, Retro, 80's ;-)