Guía paso a paso para endurecer un servidor Linux, cubriendo seguridad SSH, cortafuegos, detección de intrusiones, auditoría y configuración del sistema para reducir la superficie de ataque y mejorar la defensa.
Una guía en evolución para asegurar un servidor Linux que, con suerte, también te enseña un poco sobre seguridad y por qué es importante.
(TOC hecho con nGitHubTOC)
El propósito de esta guía es enseñarte cómo asegurar un servidor Linux.
Hay muchas cosas que puedes hacer para asegurar un servidor Linux y esta guía intentará cubrir tantas como sea posible. Se añadirán más temas/material a medida que aprenda, o que la gente contribuya.
Los playbooks de Ansible de esta guía están disponibles en How To Secure A Linux Server With Ansible por moltenbit.
Asumo que estás usando esta guía porque, con suerte, ya entiendes por qué una buena seguridad es importante. Eso es un tema pesado en sí mismo y desglosarlo está fuera del alcance de esta guía. Si no sabes la respuesta a esa pregunta, te aconsejo investigarlo primero.
A alto nivel, en el momento en que un dispositivo, como un servidor, está en el dominio público — es decir, visible al mundo exterior — se convierte en un objetivo para actores maliciosos. Un dispositivo no asegurado es un patio de juegos para actores maliciosos que quieren acceso a tus datos, o usar tu servidor como otro nodo para sus ataques DDOS a gran escala.
Lo que es peor es que, sin buena seguridad, quizás nunca sepas si tu servidor ha sido comprometido. Un actor malicioso podría haber obtenido acceso no autorizado a tu servidor y copiado tus datos sin cambiar nada, por lo que nunca lo sabrías. O tu servidor podría haber sido parte de un ataque DDOS, y no lo sabrías. Mira muchas de las filtraciones de datos a gran escala en las noticias: las empresas a menudo no descubrieron la fuga de datos o la intrusión hasta mucho después de que los actores maliciosos se hubieran ido.
Contrario a la creencia popular, los actores maliciosos no siempre quieren cambiar algo o bloquearte el acceso a tus datos por dinero. A veces solo quieren los datos de tu servidor para sus almacenes de datos (hay mucho dinero en big data) o para usar tu servidor de forma encubierta para sus propósitos nefastos.
Esta guía puede parecer redundante/innecesaria porque hay innumerables artículos en línea que te dicen cómo asegurar Linux, pero la información está dispersa en diferentes artículos, que cubren diferentes cosas y de diferentes maneras. ¿Quién tiene tiempo para revisar cientos de artículos?
Mientras investigaba para mi instalación de Debian, tomaba notas. Al final me di cuenta de que, junto con lo que ya sabía y lo que estaba aprendiendo, tenía los ingredientes de una guía práctica. Pensé en ponerla en línea para ayudar a otros a aprender y ahorrar tiempo.
Nunca he encontrado una guía que lo cubra todo — esta guía es mi intento.
Muchas de las cosas cubiertas en esta guía pueden ser bastante básicas/triviales, pero la mayoría de nosotros no instalamos Linux todos los días, y es fácil olvidar esas cosas básicas.
Hay muchas guías proporcionadas por expertos, líderes de la industria y las propias distribuciones. No es práctico, y a veces va contra los derechos de autor, incluir todo de esas guías. Te recomiendo que las consultes antes de empezar con esta guía.
Esta guía...
Hay muchos tipos de servidores y diferentes casos de uso. Aunque quiero que esta guía sea lo más genérica posible, habrá algunas cosas que pueden no aplicar a todos/otros casos de uso. Usa tu mejor criterio al seguir esta guía.
Para ayudar a poner contexto a muchos de los temas cubiertos en esta guía, mi caso de uso/configuración es:
Soy muy perezoso y no me gusta editar archivos a mano si no es necesario. También asumo que todos los demás son como yo. :)
Por lo tanto, cuando y donde sea posible, he proporcionado fragmentos de código para hacer rápidamente lo que se necesita, como agregar o cambiar una línea en un archivo de configuración.
Los fragmentos de código usan comandos básicos como echo, cat, sed, awk y grep. Cómo funcionan los fragmentos de código, como qué hace cada comando/parte, está fuera del alcance de esta guía — las páginas man son tus amigas.
Nota: Los fragmentos de código no validan/verifican que el cambio se haya realizado — es decir, que la línea se haya agregado o cambiado realmente. Dejaré la parte de verificación en tus capaces manos. Los pasos en esta guía incluyen realizar copias de seguridad de todos los archivos que se modificarán.
No todos los cambios se pueden automatizar con fragmentos de código. Esos cambios necesitan una buena y anticuada edición manual. Por ejemplo, no puedes simplemente añadir una línea a un archivo de tipo INI. Usa tu editor de texto Linux favorito.
Quería poner esta guía en GitHub para facilitar la colaboración. Cuanta más gente contribuya, mejor y más completa se volverá esta guía.
Para contribuir puedes hacer un fork y enviar un pull request o enviar un nuevo issue.
Antes de empezar, querrás identificar cuáles son tus Principios. ¿Cuál es tu modelo de amenazas? Algunas cosas en las que pensar:
Estas son solo algunas cosas en las que pensar. Antes de empezar a asegurar tu servidor, querrás entender contra qué estás tratando de protegerte y por qué, para saber qué necesitas hacer.
Esta guía está pensada para ser agnóstica respecto a la distribución, para que los usuarios puedan usar cualquier distribución que quieran. Dicho esto, hay algunas cosas a tener en cuenta:
Quieres una distribución que...
Instalar Linux está fuera del alcance de esta guía porque cada distribución lo hace de manera diferente y las instrucciones de instalación suelen estar bien documentadas. Si necesitas ayuda, comienza con la documentación de tu distribución. Independientemente de la distribución, el proceso general suele ser así:
Cuando sea aplicable, usa la opción de instalación experta para tener un control más estricto sobre lo que se ejecuta en tu servidor. Instala solo lo que necesites absolutamente. Personalmente, no instalo nada más que SSH. Además, marca la opción de cifrado de disco.
sudo apt update && sudo apt upgrade en sistemas basados en Debian)./etc/fstabmanapt adecuados que deberían funcionar en todas las distribuciones basadas en Debian. Si alguien está dispuesto a proporcionar los comandos respectivos para otras distribuciones, los añadiré.Los playbooks de Ansible de esta guía están disponibles en How To Secure A Linux Server With Ansible.Asegúrate de editar las variables según tus necesidades y leer todas las tareas de antemano para confirmar que no rompa tu sistema. Después de ejecutar los playbooks, ¡asegúrate de que todas las configuraciones estén ajustadas a tus necesidades!
5. Cambia todas las variables en *group_vars/variables.yml* según tus necesidades.
6. Habilita el acceso root por SSH antes de ejecutar los playbooks: ```
nano /etc/ssh/sshd_config
[...]
PermitRootLogin yes
[...]
Ejecute el playbook de requisitos usando la contraseña de root que especificó mientras instalaba el servidor:
ansible-playbook --inventory hosts.yml --ask-pass requirements-playbook.yml
Ejecute el playbook principal con la contraseña del nuevo usuario que especificó en el archivo variables.yml:
ansible-playbook --inventory hosts.yml --ask-pass main-playbook.yml
Si necesita ejecutar los playbooks varias veces, recuerde usar la clave SSH y el nuevo puerto SSH:
ansible-playbook --inventory hosts.yml -e ansible_ssh_port=SSH_PORT --key-file /PATH/TO/SSH/KEY main-playbook.yml
Es muy recomendable mantener una segunda terminal abierta a su servidor antes de hacer y aplicar cambios en la configuración SSH. De esta manera, si se bloquea en su primera sesión de terminal, aún tendrá una sesión conectada para poder solucionarlo.
Gracias a Sonnenbrand por esta idea.
Usar claves públicas/privadas SSH es más seguro que usar una contraseña. También facilita y hace más rápido conectarse a nuestro servidor porque no tiene que ingresar una contraseña.
Consulte las referencias a continuación para más detalles, pero, a alto nivel, las claves públicas/privadas funcionan usando un par de claves para verificar la identidad.
Para SSH, se crea una clave pública y privada en el cliente. Debe mantener ambas claves seguras, especialmente la clave privada. Aunque la clave pública está destinada a ser pública, es prudente asegurarse de que ninguna de las claves caiga en manos equivocadas.
Cuando se conecta a un servidor SSH, SSH buscará una clave pública que coincida con el cliente desde el que se conecta en el archivo ~/.ssh/authorized_keys en el servidor al que se conecta. Observe que el archivo está en la carpeta de inicio de la identificación a la que intenta conectarse. Entonces, después de crear la clave pública, debe agregarla a ~/.ssh/authorized_keys. Un enfoque es copiarla a una memoria USB y transferirla físicamente al servidor. Otro enfoque es usar ssh-copy-id para transferir y agregar la clave pública.
Después de que se hayan creado las claves y la clave pública se haya agregado a ~/.ssh/authorized_keys en el host, SSH usa las claves pública y privada para verificar la identidad y luego establecer una conexión segura. Cómo se verifica la identidad es un proceso complicado, pero Digital Ocean tiene una muy buena descripción de cómo funciona. A alto nivel, la identidad se verifica mediante el servidor cifrando un mensaje de desafío con la clave pública, luego enviándolo al cliente. Si el cliente no puede descifrar el mensaje de desafío con la clave privada, la identidad no se puede verificar y no se establecerá una conexión.
Se consideran más seguros porque necesita la clave privada para establecer una conexión SSH. Si establece PasswordAuthentication no en /etc/ssh/sshd_config, entonces SSH no le permitirá conectarse sin la clave privada.
También puede establecer una frase de contraseña para las claves, lo que requeriría que ingrese la frase de contraseña al conectarse usando claves públicas/privadas. Tenga en cuenta que hacer esto significa que no puede usar la clave para automatización porque no tendrá forma de enviar la frase de contraseña en sus scripts. ssh-agent es un programa que se incluye en muchas distribuciones de Linux (y generalmente ya se está ejecutando) que le permite mantener su clave privada sin cifrar en memoria durante una duración configurable. Simplemente ejecute ssh-add y le solicitará su frase de contraseña. No se le solicitará su frase de contraseña nuevamente hasta que haya pasado la duración configurable.
Usaremos claves Ed25519 que, según https://linux-audit.com/:
Utiliza un esquema de firma de curva elíptica, que ofrece mejor seguridad que ECDSA y DSA. Al mismo tiempo, también tiene un buen rendimiento.
man ssh-keygenman ssh-copy-idman ssh-addDesde la computadora que va a usar para conectarse a su servidor, el cliente, no el servidor mismo, cree una clave Ed25519 con ssh-keygen:
ssh-keygen -t ed25519
Generating public/private ed25519 key pair. Enter file in which to save the key (/home/user/.ssh/id_ed25519): Created directory '/home/user/.ssh'. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/user/.ssh/id_ed25519. Your public key has been saved in /home/user/.ssh/id_ed25519.pub. The key fingerprint is: SHA256:F44D4dr2zoHqgj0i2iVIHQ32uk/Lx4P+raayEAQjlcs user@client The key's randomart image is: +--[ED25519 256]--+ |xxxx x | |o.o +. . | | o o oo . | |. E oo . o . | | o o. o S o | |... .. o o | |.+....+ o | |+.=++o.B.. | |+..=**=o=. | +----[SHA256]-----+
Nota: Si establece una frase de contraseña, deberá ingresarla cada vez que se conecte a su servidor usando esta clave, a menos que esté usando ssh-agent.
Ahora necesita agregar la clave pública ~/.ssh/id_ed25519.pub de su cliente al archivo ~/.ssh/authorized_keys en su servidor. Dado que presumiblemente todavía estamos en casa en la LAN, probablemente estemos a salvo de ataques MIM, así que usaremos ssh-copy-id para transferir y agregar la clave pública:
ssh-copy-id user@server
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/user/.ssh/id_ed25519.pub" The authenticity of host 'host (192.168.1.96)' can't be established. ECDSA key fingerprint is SHA256:QaDQb/X0XyVlogh87sDXE7MR8YIK7ko4wS5hXjRySJE. Are you sure you want to continue connecting (yes/no)? yes /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys user@host's password: Number of key(s) added: 1 Now try logging into the machine, with: "ssh 'user@host'" and check to make sure that only the key(s) you wanted were added.
Ahora sería un buen momento para realizar cualquier tarea específica de su configuración.
Para facilitar el control de quién puede conectarse por SSH al servidor. Al usar un grupo, podemos agregar/eliminar rápidamente cuentas al grupo para permitir o no permitir rápidamente el acceso SSH al servidor.
Usaremos la opción AllowGroups en el archivo de configuración de SSH /etc/ssh/sshd_config para indicar al servidor SSH que solo permita que los usuarios inicien sesión por SSH si son miembros de un determinado grupo UNIX. Cualquier persona que no esté en el grupo no podrá conectarse por SSH.
/etc/ssh/sshd_config para limitar quién puede conectarse por SSH al servidorAllowGroup establecida en Secure /etc/ssh/sshd_config.man groupaddman usermodCree un grupo:
sudo groupadd sshusers
Agregue cuenta(s) al grupo:
sudo usermod -a -G sshusers user1
sudo usermod -a -G sshusers user2
sudo usermod -a -G sshusers ...
Deberá hacer esto para cada cuenta en su servidor que necesite acceso SSH.
/etc/ssh/sshd_configSSH es una puerta a su servidor. Esto es especialmente cierto si está abriendo puertos en su enrutador para poder conectarse por SSH a su servidor desde fuera de su red doméstica. Si no está asegurado adecuadamente, un actor malintencionado podría usarlo para obtener acceso no autorizado a su sistema.
/etc/ssh/sshd_config es el archivo de configuración predeterminado que utiliza el servidor SSH. Usaremos este archivo para indicar qué opciones debe usar el servidor SSH.
man sshd_configHaga una copia de seguridad del archivo de configuración del servidor OpenSSH /etc/ssh/sshd_config y elimine los comentarios para que sea más fácil de leer:
sudo cp --archive /etc/ssh/sshd_config /etc/ssh/sshd_config-COPY-$(date +"%Y%m%d%H%M%S")
sudo sed -i -r -e '/^#|^$/ d' /etc/ssh/sshd_config
Edite /etc/ssh/sshd_config luego busque y edite o agregue estas configuraciones que deberían aplicarse independientemente de su configuración/configuración:
Nota: SSH no tolera configuraciones duplicadas contradictorias. Por ejemplo, si tiene ChallengeResponseAuthentication no y luego ChallengeResponseAuthentication yes, SSH respetará la primera e ignorará la segunda. Su archivo /etc/ssh/sshd_config puede que ya tenga algunas de las configuraciones/líneas a continuación. Para evitar problemas, deberá revisar manualmente su archivo /etc/ssh/sshd_config y abordar cualquier configuración duplicada contradictoria.
Nota: Si está ejecutando OpenSSH 9.1 o posterior, descomente la línea RequiredRSASize 3072 en la configuración a continuación. Esto impone un tamaño mínimo de clave RSA de 3072 bits y rechazará claves RSA más pequeñas durante la autenticación. Esto solo afecta a las claves RSA. Si usa claves ED25519 o ECDSA, no se verá afectado. Puede verificar el tipo y tamaño de su clave con ssh-keygen -l -f ~/.ssh/id_rsa. En versiones anteriores de OpenSSH, deje la línea comentada ya que evitará que sshd se inicie.
########################################################################################################
# inicio configuraciones de https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67 a partir de 2019-01-01
########################################################################################################
# Algoritmos HostKey compatibles por orden de preferencia.
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
KexAlgorithms [email protected],ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
Ciphers [email protected],[email protected],[email protected],aes256-ctr,aes192-ctr,aes128-ctr
MACs [email protected],[email protected],hmac-sha2-512,hmac-sha2-256,[email protected]
# LogLevel VERBOSE registra la huella digital de la clave del usuario al iniciar sesión. Necesario para tener un rastro de auditoría claro de qué clave se usó para iniciar sesión.
LogLevel VERBOSE
# Usar mecanismos de sandbox del kernel cuando sea posible en procesos no privilegiados
# Systrace en OpenBSD, Seccomp en Linux, seatbelt en MacOSX/Darwin, rlimit en otros.
# Nota: Esta configuración está obsoleta en OpenSSH 7.5 (https://www.openssh.com/txt/release-7.5)
# UsePrivilegeSeparation sandbox
########################################################################################################
# fin configuraciones de https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67 a partir de 2019-01-01
########################################################################################################
# no permitir que los usuarios establezcan variables de entorno
PermitUserEnvironment no
# Registrar el acceso a nivel de archivo de sftp (lectura/escritura/etc.) que de otro modo no se registraría fácilmente.
Subsystem sftp internal-sftp -f AUTHPRIV -l INFO
# deshabilitar el reenvío X11 ya que X11 es muy inseguro
# realmente no deberías estar ejecutando X en un servidor de todos modos
X11Forwarding no
# deshabilitar el reenvío de puertos
AllowTcpForwarding no
AllowStreamLocalForwarding no
GatewayPorts no
PermitTunnel no
# no permitir inicio de sesión si la cuenta tiene una contraseña vacía
PermitEmptyPasswords no
# ignorar .rhosts y .shosts
IgnoreRhosts yes
# verificar que el nombre de host coincida con la IP
UseDNS yes
Compression no
# TCP keepalive se puede falsificar (se ejecuta fuera del canal cifrado)
# Use ClientAlive en su lugar (se ejecuta dentro del canal cifrado)
TCPKeepAlive no
AllowAgentForwarding no
PermitRootLogin no
# no permitir .rhosts o /etc/hosts.equiv
HostbasedAuthentication no
# OpenSSH 9.1 y posteriores
# Imponer un tamaño mínimo de clave RSA de 3072 bits
# https://www.keylength.com/en/compare/
# RequiredRSASize 3072
# https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/115
HashKnownHosts yes
Luego busque y edite o agregue estas configuraciones, y establezca los valores según sus requisitos:
Asegúrese de que no haya configuraciones duplicadas que se contradigan entre sí. El siguiente comando no debería mostrar ninguna salida.
awk 'NF && $1!~/^(#|HostKey)/{print $1}' /etc/ssh/sshd_config | sort | uniq -c | grep -v ' 1 '
Reinicie ssh:
sudo service sshd restart
Puede verificar que las configuraciones hayan funcionado con sshd -T y verificar la salida:
sudo sshd -T
port 22 addressfamily any listenaddress [::]:22 listenaddress 0.0.0.0:22 usepam yes logingracetime 30 x11displayoffset 10 maxauthtries 2 maxsessions 2 clientaliveinterval 15 clientalivecountmax 3 streamlocalbindmask 0177 permitrootlogin no ignorerhosts yes ignoreuserknownhosts no hostbasedauthentication no ... subsystem sftp internal-sftp -f AUTHPRIV -l INFO maxstartups 2:30:2 permittunnel no ipqos lowdelay throughput rekeylimit 0 0 permitopen any
Según las directrices de OpenSSH de Mozilla para OpenSSH 6.7+, "todos los módulos Diffie-Hellman en uso deben tener al menos 3072 bits de longitud".
El algoritmo Diffie-Hellman es utilizado por SSH para establecer una conexión segura. Cuanto más grande sea el módulo (tamaño de clave), más fuerte será el cifrado.
man moduliHaga una copia de seguridad del archivo de módulos de SSH /etc/ssh/moduli:
sudo cp --archive /etc/ssh/moduli /etc/ssh/moduli-COPY-$(date +"%Y%m%d%H%M%S")
Elimine los módulos cortos:
sudo awk '$5 >= 3071' /etc/ssh/moduli | sudo tee /etc/ssh/moduli.tmp
sudo mv /etc/ssh/moduli.tmp /etc/ssh/moduli
Aunque SSH es un guardia de seguridad bastante bueno para sus puertas y ventanas, sigue siendo una puerta visible que los actores malintencionados pueden ver e intentar atacar con fuerza bruta. Fail2ban monitoreará estos intentos de fuerza bruta, pero no existe tal cosa como ser demasiado seguro. Requerir dos factores agrega una capa adicional de seguridad.
El uso de autenticación de dos factores (2FA) / autenticación multifactor (MFA) requiere que cualquier persona que ingrese tenga dos llaves para entrar, lo que dificulta que los actores malintencionados. Las dos llaves son:
Sin ambas llaves, no podrán entrar.
Muchas personas pueden encontrar la experiencia engorrosa o molesta. Además, el acceso a su sistema depende de la aplicación autenticadora complementaria que genera el código.
En Linux, PAM es responsable de la autenticación. Hay cuatro tareas de PAM sobre las que puede leer en https://en.wikipedia.org/wiki/Linux_PAM. Esta sección trata sobre la tarea de autenticación.
Cuando inicia sesión en un servidor, ya sea directamente desde la consola o a través de SSH, la puerta por la que ingresó enviará la solicitud a la tarea de autenticación de PAM y PAM solicitará y verificará su contraseña. Puede personalizar las reglas que utiliza cada puerta. Por ejemplo, podría tener un conjunto de reglas al iniciar sesión directamente desde la consola y otro conjunto de reglas para cuando inicia sesión a través de SSH.
Esta sección modificará las reglas de autenticación para cuando se inicia sesión a través de SSH para requerir tanto una contraseña como un código de 6 dígitos.Usaremos el módulo PAM libpam-google-authenticator de Google para crear y verificar una clave TOTP. https://fastmail.blog/2016/07/22/how-totp-authenticator-apps-work/ y https://jemurai.com/2018/10/11/how-it-works-totp-based-mfa/ tienen muy buenas explicaciones de cómo funciona TOTP.
Lo que haremos es indicarle a la configuración PAM de SSH del servidor que le pida al usuario su contraseña y luego su token numérico. PAM verificará la contraseña del usuario y, si es correcta, enrutará la solicitud de autenticación a libpam-google-authenticator, que pedirá y verificará tu token de 6 dígitos. Si, y solo si, todo está bien, la autenticación tendrá éxito y se permitirá al usuario iniciar sesión.
Instala libpam-google-authenticator.
En sistemas basados en Debian:
sudo apt install libpam-google-authenticator
Asegúrate de haber iniciado sesión con el ID para el que deseas habilitar 2FA/MFA y ejecuta google-authenticator para crear los datos del token necesarios:
google-authenticator
Do you want authentication tokens to be time-based (y/n) y https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/user@host%3Fsecret%3DR4ZWX34FQKZROVX7AGLJ64684Y%26issuer%3Dhost ... Your new secret key is: R3NVX3FFQKZROVX7AGLJUGGESY Your verification code is 751419 Your emergency scratch codes are: 12345678 90123456 78901234 56789012 34567890 Do you want me to update your "/home/user/.google_authenticator" file (y/n) y Do you want to disallow multiple uses of the same authentication token? This restricts you to one login about every 30s, but it increases your chances to notice or even prevent man-in-the-middle attacks (y/n) Do you want to disallow multiple uses of the same authentication token? This restricts you to one login about every 30s, but it increases your chances to notice or even prevent man-in-the-middle attacks (y/n) y By default, tokens are good for 30 seconds. In order to compensate for possible time-skew between the client and the server, we allow an extra token before and after the current time. If you experience problems with poor time synchronization, you can increase the window from its default size of +-1min (window size of 3) to about +-4min (window size of 17 acceptable tokens). Do you want to do so? (y/n) y If the computer that you are logging into isn't hardened against brute-force login attempts, you can enable rate-limiting for the authentication module. By default, this limits attackers to no more than 3 login attempts every 30s. Do you want to enable rate-limiting (y/n) y
Observa que esto no se ejecuta como root.
Selecciona la opción predeterminada (y en la mayoría de los casos) para todas las preguntas que hace y recuerda guardar los códigos de emergencia de un solo uso.
Haz una copia de seguridad del archivo de configuración PAM de SSH /etc/pam.d/sshd:
sudo cp --archive /etc/pam.d/sshd /etc/pam.d/sshd-COPY-$(date +"%Y%m%d%H%M%S")
Ahora debemos habilitarlo como método de autenticación para SSH agregando esta línea a /etc/pam.d/sshd:
auth required pam_google_authenticator.so nullok
Nota: Consulta aquí qué significa nullok.
echo -e "\nauth required pam_google_authenticator.so nullok # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | sudo tee -a /etc/pam.d/sshd
Indícale a SSH que lo use agregando o editando esta línea en /etc/ssh/sshd_config:
ChallengeResponseAuthentication yes
sudo sed -i -r -e "s/^(challengeresponseauthentication .*)$/# \1 # commented by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")/I" /etc/ssh/sshd_config
echo -e "\nChallengeResponseAuthentication yes # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | sudo tee -a /etc/ssh/sshd_config
Reinicia ssh:
sudo service sshd restart
sudo permite que las cuentas ejecuten comandos como otras cuentas, incluido root. Queremos asegurarnos de que solo las cuentas que deseamos puedan usar sudo.
Debian crea el grupo sudo. Para ver los usuarios que son parte de este grupo (y por lo tanto tienen privilegios de sudo):
cat /etc/group | grep "sudo"
RedHat crea el grupo wheel
sudo no requiera contraseña. Gracias a sbrl por compartir.Crea un grupo:
sudo groupadd sudousers
Agrega cuenta(s) al grupo:
sudo usermod -a -G sudousers user1
sudo usermod -a -G sudousers user2
sudo usermod -a -G sudousers ...
Deberás hacer esto para cada cuenta en tu servidor que necesite privilegios de sudo.
Haz una copia de seguridad del archivo de configuración de sudo /etc/sudoers:
sudo cp --archive /etc/sudoers /etc/sudoers-COPY-$(date +"%Y%m%d%H%M%S")
Edita el archivo de configuración de sudo /etc/sudoers:
sudo visudo
Indícale a sudo que solo permita a los usuarios del grupo sudousers usar sudo agregando esta línea si aún no está:
%sudousers ALL=(ALL:ALL) ALL
su también permite que las cuentas ejecuten comandos como otras cuentas, incluido root. Queremos asegurarnos de que solo las cuentas que deseamos puedan usar su.
Crea un grupo:
sudo groupadd suusers
Agrega cuenta(s) al grupo:
sudo usermod -a -G suusers user1
sudo usermod -a -G suusers user2
sudo usermod -a -G suusers ...
Deberás hacer esto para cada cuenta en tu servidor que necesite privilegios de sudo.
Haz que solo los usuarios de este grupo puedan ejecutar /bin/su:
sudo dpkg-statoverride --update --add root suusers 4750 /bin/su
Es absolutamente mejor, para muchas aplicaciones, ejecutarlas en un entorno aislado.
Los navegadores (aún más los de código cerrado) y los clientes de correo electrónico son muy recomendados.
Instala el software:
sudo apt install firejail firejail-profiles
Nota: para Debian 10 Stable, se sugiere el Backport oficial:
sudo apt install -t buster-backports firejail firejail-profiles
Permite que una aplicación (instalada en /usr/bin o /bin) se ejecute solo en un entorno aislado (ver algunos ejemplos a continuación):
sudo ln -s /usr/bin/firejail /usr/local/bin/google-chrome-stable
sudo ln -s /usr/bin/firejail /usr/local/bin/firefox
sudo ln -s /usr/bin/firejail /usr/local/bin/chromium
sudo ln -s /usr/bin/firejail /usr/local/bin/evolution
sudo ln -s /usr/bin/firejail /usr/local/bin/thunderbird
Ejecuta la aplicación como de costumbre (a través de terminal o lanzador) y verifica si se está ejecutando en una jaula:
firejail --list
Permite que una aplicación enjaulada vuelva a ejecutarse como antes (ejemplo: firefox)
sudo rm /usr/local/bin/firefox
Muchos protocolos de seguridad aprovechan la hora. Si la hora de tu sistema es incorrecta, podría tener impactos negativos en tu servidor. Un cliente NTP puede resolver ese problema manteniendo la hora de tu sistema sincronizada con los servidores NTP globales.
NTP significa Protocolo de Tiempo en Red. En el contexto de esta guía, un cliente NTP en el servidor se utiliza para actualizar la hora del servidor con la hora oficial obtenida de servidores oficiales. Consulta https://www.pool.ntp.org/en/ para todos los servidores NTP públicos.
Nota: A partir de Debian 13 (Trixie), el paquete clásico
ntpha sido eliminado. Ejecutarsudo apt install ntpfallará con "Package ntp has no installation candidate". Dado que esta guía solo usa NTP como cliente (para sincronizar el reloj del servidor), el enfoque recomendado en Debian 13+ es usarsystemd-timesyncd, que ya está preinstalado y no requiere paquetes adicionales. Consulta los pasos para Debian 13+ a continuación.
systemd-timesyncd es un cliente SNTP liviano que ya está incluido en Debian. A diferencia del demonio completo ntpd, no escucha en ningún puerto, lo que lo convierte en una superficie de ataque más pequeña. Para los propósitos de esta guía (mantener el reloj de tu servidor sincronizado), es todo lo que necesitas.
Habilita la sincronización NTP:
sudo timedatectl set-ntp true
Verifica que funcione:
timedatectl status
Deberías ver NTP service: active y System clock synchronized: yes en la salida.
Configura servidores NTP de confianza. Haz una copia de seguridad del archivo de configuración y luego edítalo:
sudo cp --archive /etc/systemd/timesyncd.conf /etc/systemd/timesyncd.conf-COPY-$(date +"%Y%m%d%H%M%S")
Edita /etc/systemd/timesyncd.conf y descomenta/configura la sección [Time]:
[Time]
NTP=pool.ntp.org
FallbackNTP=0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org
sudo sed -i -r -e "s/^#?NTP=.*$/NTP=pool.ntp.org # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")/" /etc/systemd/timesyncd.conf
sudo sed -i -r -e "s/^#?FallbackNTP=.*$/FallbackNTP=0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")/" /etc/systemd/timesyncd.conf
Reinicia el servicio para aplicar los cambios:
sudo systemctl restart systemd-timesyncd
Verifica el estado de la sincronización:
timedatectl timesync-status
Server: 108.61.56.35 (pool.ntp.org) Poll interval: 32s (min: 32s; max: 34min 8s) Leap: normal Version: 4 Stratum: 2 Reference: C342F10A Precision: 1us (2^0) Root distance: 24.054ms (max: 5s) Offset: +2.156ms Delay: 48.567ms Jitter: 1.452ms Packet count: 3
Nota: Estos pasos aplican solo para Debian 12 y anteriores. En Debian 13+, el paquete
ntpya no está disponible: usa los pasos de systemd-timesyncd anteriores.
Instala ntp.
En sistemas basados en Debian:
sudo apt install ntp
Haz una copia de seguridad del archivo de configuración del cliente NTP /etc/ntp.conf:
sudo cp --archive /etc/ntp.conf /etc/ntp.conf-COPY-$(date +"%Y%m%d%H%M%S")
La configuración predeterminada, al menos en Debian, ya es bastante segura. Lo único que debemos asegurarnos es que usemos la directiva pool y no ninguna directiva server. La directiva pool permite que el cliente NTP deje de usar un servidor si no responde o sirve tiempo incorrecto. Haz esto comentando todas las directivas server y agregando lo siguiente a /etc/ntp.conf.
pool pool.ntp.org iburst
sudo sed -i -r -e "s/^((server|pool).*)/# \1 # commented by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")/" /etc/ntp.conf
echo -e "\npool pool.ntp.org iburst # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | sudo tee -a /etc/ntp.conf
Ejemplo /etc/ntp.conf:
driftfile /var/lib/ntp/ntp.drift statistics loopstats peerstats clockstats filegen loopstats file loopstats type day enable filegen peerstats file peerstats type day enable filegen clockstats file clockstats type day enable restrict -4 default kod notrap nomodify nopeer noquery limited restrict -6 default kod notrap nomodify nopeer noquery limited restrict 127.0.0.1 restrict ::1 restrict source notrap nomodify noquery pool pool.ntp.org iburst # added by user on 2019-03-09 @ 10:23:35
Reinicia ntp:
sudo service ntp restart
Verifica el estado del servicio ntp:
sudo systemctl status ntp
● ntp.service - LSB: Start NTP daemon Loaded: loaded (/etc/init.d/ntp; generated; vendor preset: enabled) Active: active (running) since Sat 2019-03-09 15:19:46 EST; 4s ago Docs: man:systemd-sysv-generator(8) Process: 1016 ExecStop=/etc/init.d/ntp stop (code=exited, status=0/SUCCESS) Process: 1028 ExecStart=/etc/init.d/ntp start (code=exited, status=0/SUCCESS) Tasks: 2 (limit: 4915) CGroup: /system.slice/ntp.service └─1038 /usr/sbin/ntpd -p /var/run/ntpd.pid -g -u 108:113 Mar 09 15:19:46 host ntpd[1038]: Listen and drop on 0 v6wildcard [::]:123 Mar 09 15:19:46 host ntpd[1038]: Listen and drop on 1 v4wildcard 0.0.0.0:123 Mar 09 15:19:46 host ntpd[1038]: Listen normally on 2 lo 127.0.0.1:123 Mar 09 15:19:46 host ntpd[1038]: Listen normally on 3 enp0s3 10.10.20.96:123 Mar 09 15:19:46 host ntpd[1038]: Listen normally on 4 lo [::1]:123 Mar 09 15:19:46 host ntpd[1038]: Listen normally on 5 enp0s3 [fe80::a00:27ff:feb6:ed8e%2]:123 Mar 09 15:19:46 host ntpd[1038]: Listening on routing socket on fd #22 for interface updates Mar 09 15:19:47 host ntpd[1038]: Soliciting pool server 108.61.56.35 Mar 09 15:19:48 host ntpd[1038]: Soliciting pool server 69.89.207.199 Mar 09 15:19:49 host ntpd[1038]: Soliciting pool server 45.79.111.114
Verifica el estado de ntp:
sudo ntpq -p
remote refid st t when poll reach delay offset jitter ============================================================================== pool.ntp.org .POOL. 16 p - 64 0 0.000 0.000 0.000 *lithium.constan 198.30.92.2 2 u - 64 1 19.900 4.894 3.951 ntp2.wiktel.com 212.215.1.157 2 u 2 64 1 48.061 -0.431 0.104
Al mirar en
/procdescubrirás muchos archivos y directorios. Muchos de ellos son solo números, que representan la información sobre un ID de proceso (PID) en particular. Por defecto, los sistemas Linux se implementan para permitir que todos los usuarios locales vean toda esta información. Esto incluye información de proceso de otros usuarios. Esto podría incluir detalles sensibles que quizás no quieras compartir con otros usuarios. Al aplicar algunos ajustes de configuración del sistema de archivos, podemos cambiar este comportamiento y mejorar la seguridad del sistema.
Nota: Esto puede romperse en algunos sistemas systemd. Consulta https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/37 para más información. Gracias a nlgranger por compartir.
/proc montado con hidepid=2 para que los usuarios solo puedan ver información sobre sus procesosHaz una copia de seguridad de /etc/fstab:
sudo cp --archive /etc/fstab /etc/fstab-COPY-$(date +"%Y%m%d%H%M%S")
Agrega esta línea a /etc/fstab para que /proc se monte con hidepid=2:
proc /proc proc defaults,hidepid=2 0 0
echo -e "\nproc /proc proc defaults,hidepid=2 0 0 # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | sudo tee -a /etc/fstab
Reinicia el sistema:
sudo reboot now
Nota: Alternativamente, puedes remontar /proc sin reiniciar con sudo mount -o remount,hidepid=2 /proc
Por defecto, las cuentas pueden usar cualquier contraseña que deseen, incluidas las malas. pwquality/pam_pwquality aborda esta brecha de seguridad proporcionando "una forma de configurar los requisitos de calidad de contraseña predeterminados para las contraseñas del sistema" y verificando "su fortaleza contra un diccionario del sistema y un conjunto de reglas para identificar malas elecciones".
En Linux, PAM es responsable de la autenticación. Hay cuatro tareas de PAM que puedes leer en https://en.wikipedia.org/wiki/Linux_PAM. Esta sección habla sobre la tarea de contraseña.Cuando es necesario establecer o cambiar la contraseña de una cuenta, la tarea de contraseña de PAM se encarga de la solicitud. En esta sección le indicaremos a la tarea de contraseña de PAM que pase la nueva contraseña solicitada a libpam-pwquality para asegurarse de que cumpla con nuestros requisitos. Si se cumplen los requisitos, se usa/establece; si no los cumple, genera un error y se lo notifica al usuario.
Instalar libpam-pwquality.
En sistemas basados en Debian:
sudo apt install libpam-pwquality
Haga una copia de seguridad del archivo de configuración de contraseña de PAM /etc/pam.d/common-password:
sudo cp --archive /etc/pam.d/common-password /etc/pam.d/common-password-COPY-$(date +"%Y%m%d%H%M%S")
Indique a PAM que use libpam-pwquality para imponer contraseñas seguras editando el archivo /etc/pam.d/common-password y cambie la línea que comienza así:
password requisite pam_pwquality.so
a esto:
password requisite pam_pwquality.so retry=3 minlen=10 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1 maxrepeat=3 gecoschec
Las opciones anteriores son:
retry=3 = solicitar al usuario 3 veces antes de devolver un error.minlen=10 = la longitud mínima de la contraseña, teniendo en cuenta cualquier crédito (o débito) de estos:
dcredit=-1 = debe tener al menos un dígitoucredit=-1 = debe tener al menos una letra mayúsculalcredit=-1 = debe tener al menos una letra minúsculaocredit=-1 = debe tener al menos un carácter no alfanuméricodifok=3 = al menos 3 caracteres de la nueva contraseña no pueden haber estado en la contraseña anteriormaxrepeat=3 = permitir un máximo de 3 caracteres repetidosgecoschec = no permitir contraseñas con el nombre de la cuentasudo sed -i -r -e "s/^(password\s+requisite\s+pam_pwquality.so)(.*)$/# \1\2 # commented by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")\n\1 retry=3 minlen=10 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1 maxrepeat=3 gecoschec # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")/" /etc/pam.d/common-password
Es importante mantener un servidor actualizado con los últimos parches y actualizaciones de seguridad críticos. De lo contrario, corre el riesgo de sufrir vulnerabilidades de seguridad conocidas que los actores maliciosos podrían usar para obtener acceso no autorizado a su servidor.
A menos que planee revisar su servidor todos los días, querrá una forma de actualizar automáticamente el sistema y/o recibir correos electrónicos sobre las actualizaciones disponibles.
No quiere hacer todas las actualizaciones porque con cada actualización hay un riesgo de que algo se rompa. Es importante realizar las actualizaciones críticas, pero todo lo demás puede esperar hasta que tenga tiempo de hacerlo manualmente.
Las actualizaciones automáticas y desatendidas pueden romper su sistema y es posible que no esté cerca de su servidor para repararlo. Esto sería especialmente problemático si rompiera su acceso SSH.
En sistemas basados en Debian puede usar:
Usaremos unattended-upgrades para aplicar parches de seguridad críticos. También podemos aplicar actualizaciones estables ya que han sido probadas a fondo por la comunidad Debian.
/etc/apt/apt.conf.d/50unattended-upgradesInstalar unattended-upgrades, apt-listchanges y apticron:
sudo apt install unattended-upgrades apt-listchanges apticron
Ahora necesitamos configurar unattended-upgrades para que aplique las actualizaciones automáticamente. Esto se hace típicamente editando los archivos /etc/apt/apt.conf.d/20auto-upgrades y /etc/apt/apt.conf.d/50unattended-upgrades que fueron creados por los paquetes. Sin embargo, como estos archivos pueden sobrescribirse con una actualización futura, crearemos un archivo nuevo en su lugar. Cree el archivo /etc/apt/apt.conf.d/51myunattended-upgrades y agregue esto:
// Enable the update/upgrade script (0=disable)
APT::Periodic::Enable "1";
// Do "apt-get update" automatically every n-days (0=disable)
APT::Periodic::Update-Package-Lists "1";
// Do "apt-get upgrade --download-only" every n-days (0=disable)
APT::Periodic::Download-Upgradeable-Packages "1";
// Do "apt-get autoclean" every n-days (0=disable)
APT::Periodic::AutocleanInterval "7";
// Send report mail to root
// 0: no report (or null string)
// 1: progress report (actually any string)
// 2: + command outputs (remove -qq, remove 2>/dev/null, add -d)
// 3: + trace on APT::Periodic::Verbose "2";
APT::Periodic::Unattended-Upgrade "1";
// Automatically upgrade packages from these
Unattended-Upgrade::Origins-Pattern {
"o=Debian,a=stable";
"o=Debian,a=stable-updates";
"origin=Debian,codename=${distro_codename},label=Debian-Security";
};
// You can specify your own packages to NOT automatically upgrade here
Unattended-Upgrade::Package-Blacklist {
};
// Run dpkg --force-confold --configure -a if a unclean dpkg state is detected to true to ensure that updates get installed even when the system got interrupted during a previous run
Unattended-Upgrade::AutoFixInterruptedDpkg "true";
//Perform the upgrade when the machine is running because we wont be shutting our server down often
Unattended-Upgrade::InstallOnShutdown "false";
// Send an email to this address with information about the packages upgraded.
Unattended-Upgrade::Mail "root";
// Always send an e-mail
Unattended-Upgrade::MailOnlyOnError "false";
// Remove all unused dependencies after the upgrade has finished
Unattended-Upgrade::Remove-Unused-Dependencies "true";
// Remove any new unused dependencies after the upgrade has finished
Unattended-Upgrade::Remove-New-Unused-Dependencies "true";
// Automatically reboot WITHOUT CONFIRMATION if the file /var/run/reboot-required is found after the upgrade.
Unattended-Upgrade::Automatic-Reboot "true";
// Automatically reboot even if users are logged in.
Unattended-Upgrade::Automatic-Reboot-WithUsers "true";
Notas:
/usr/lib/apt/apt.systemd.daily para obtener detalles sobre las opciones APT::PeriodicUnattended-UpgradeEjecute una prueba en seco de unattended-upgrades para asegurarse de que su archivo de configuración está bien:
sudo unattended-upgrade -d --dry-run
Si todo está bien, puede dejarlo ejecutar cuando esté programado o forzar una ejecución con unattended-upgrade -d.
Configure apt-listchanges a su gusto:
sudo dpkg-reconfigure apt-listchanges
Para apticron, la configuración predeterminada es suficiente, pero puede verificarla en /etc/apticron/apticron.conf si desea cambiarla. Por ejemplo, mi configuración se ve así:
EMAIL="root" NOTIFY_NO_UPDATES="1"
WIP
WIP
WIP
Instalar rng-tools.
En sistemas basados en Debian:
sudo apt-get install rng-tools
Ahora necesitamos establecer el dispositivo de hardware utilizado para generar números aleatorios agregando esto a /etc/default/rng-tools:
HRNGDEVICE=/dev/urandom
echo "HRNGDEVICE=/dev/urandom" | sudo tee -a /etc/default/rng-tools
Reinicie el servicio:
sudo systemctl stop rng-tools.service
sudo systemctl start rng-tools.service
Probar aleatoriedad:
Una buena herramienta para agregar seguridad adicional a la contraseña, contra ataques físicos (en persona) métodos de rescate/robo/asalto.
pamduress agregará al usuario X una contraseña secundaria (contraseña de pánico). Cuando esta contraseña coincida, iniciará la ejecución de un script (este script hace lo que usted quiera que haga el usuario cuando inicie sesión con ESTA contraseña de pánico).
Ejemplo práctico y real: "Un ladrón invade una casa y roba el servidor (que contiene copias de seguridad importantes del negocio, recuerdos de la vida y bla bla bla). No existe ningún cifrado de disco/arranque. El ladrón enciende el servidor en su 'zona segura' e inicia un ataque de fuerza bruta. Descifró la contraseña local por SSH con el usuario sudoer 'admin' con éxito, sí, una contraseña tonta, no la fuerte/principal. Inicia sesión SSH/física con esa contraseña tonta/de pánico con 'admin' sudoer. Empieza a notar que el servidor parece demasiado ocupado en menos de 2 minutos hasta que se congela... '¿qué demonios? reiniciemos y continuemos robando información...' lo siento amigo. todos los datos y el sistema fueron destruidos.". Conclusión, el ladrón descifró la contraseña falsa/de pánico/secundaria, y con esta contraseña, su script asociado eliminará todos los archivos, configuración, sistema, arranque y luego comenzará a cargar la RAM y la CPU para forzar al ladrón a reiniciar el sistema.
Evitar que una persona maliciosa acceda a la información del servidor cuando obtiene una contraseña por la fuerza (asalto, arma, rescate, ...). Por supuesto, esto es útil en otras situaciones.
cat > "$ScriptFile" <<-EOF #!/bin/bash sudo rm -rf /home
EOF ####################################################### } echo "Lets Config a PANIC PASSWORD ;)" && sleep 1 read -r -p "Want you REALLY configure A PANIC PASSWORD?? Write [ OK ] : " PAMDUR if [[ "$PAMDUR" = "OK" ]]; then echo "Lets Config a PANIC USER, PASSWORD and SCRIPT ;)" && sleep 1 while [ -z "$PANICUSR" ] do read -r -p "WRITE a Panic User to your pam-duress user [ root ]: " PANICUSR PANICUSR=${PANICUSR:=root} done if [ -z "$ScriptLoc" ]; then read -r -p "SET Script Directory with FULL PATH [ /root/.duress ]: " ScriptLoc ScriptLoc=${ScriptLoc:=/root/.duress} ScriptFile="$ScriptLoc/PanicScript.sh" fi else echo "NOT Use PAM DURESS aKa Panic Password!!! Bye" exit 1 fi
sudo apt install -y git build-essential libpam0g-dev libssl-dev
cd "$HOME" || exit 1 git clone https://github.com/nuvious/pam-duress.git cd pam-duress || exit 1 make sudo make install make clean #make uninstall
mkdir -p $ScriptLoc sudo mkdir -p /etc/duress.d myownscript duress_sign $ScriptFile chmod -R 500 $ScriptLoc chmod 400 $ScriptLoc/*.sha256 chown -R $PANICUSR $ScriptLoc
sudo cp --preserve /etc/pam.d/common-auth /etc/pam.d/common-auth.bck
echo " auth [success=2 default=ignore] pam_unix.so nullok_secure auth [success=1 default=ignore] pam_duress.so auth requisite pam_deny.so auth required pam_permit.so " | sudo tee /etc/pam.d/common-auth
read -r -p "Press Key to Finish PAM DURESS Script!" exit 0
([Tabla de contenido](#table-of-contents))
## La Red
### Firewall Con UFW (Uncomplicated Firewall)
#### Por Qué
Llámame paranoico, y no tienes por qué estar de acuerdo, pero quiero denegar todo el tráfico hacia y desde mi servidor excepto lo que permito explícitamente. ¿Por qué mi servidor estaría enviando tráfico que no conozco? ¿Y por qué el tráfico externo intentaría acceder a mi servidor si no sé quién o qué es? En cuanto a una buena seguridad, mi opinión es rechazar/denegar por defecto y permitir por excepción.
Por supuesto, si no estás de acuerdo, está totalmente bien y puedes configurar UFW según tus necesidades.
De cualquier manera, asegurar que solo el tráfico que permitimos explícitamente pase es el trabajo de un cortafuegos.
#### Cómo Funciona
El kernel de Linux proporciona capacidades para monitorear y controlar el tráfico de red. Estas capacidades se exponen al usuario final a través de utilidades de cortafuegos. En Linux, el cortafuegos más común es [iptables](https://en.wikipedia.org/wiki/Iptables). Sin embargo, iptables es bastante complicado y confuso (en mi humilde opinión). Aquí es donde entra UFW. Piensa en UFW como un front-end para iptables. Simplifica el proceso de administrar las reglas de iptables que le indican al kernel de Linux qué hacer con el tráfico de red.
**UFW** funciona permitiéndote configurar reglas que:
- **permiten** o **deniegan**
- tráfico de **entrada** o **salida**
- **hacia** o **desde** puertos
Puedes crear reglas especificando explícitamente los puertos o con configuraciones de aplicaciones que especifiquen los puertos.
#### Objetivos
- todo el tráfico de red, entrada y salida, bloqueado excepto aquellos que permitamos explícitamente
#### Notas
- A medida que instales otros programas, necesitarás habilitar los puertos/aplicaciones necesarios.
#### Referencias
- https://launchpad.net/ufw
#### Pasos
1. Instalar ufw.
En sistemas basados en Debian:
``` bash
sudo apt install ufw
```
1. Denegar todo el tráfico saliente:
``` bash
sudo ufw default deny outgoing comment 'deny all outgoing traffic'
```
> ```
> Default outgoing policy changed to 'deny'
> (be sure to update your rules accordingly)
> ```
Si no eres tan paranoico como yo, y no quieres denegar todo el tráfico saliente, puedes permitirlo en su lugar:
``` bash
sudo ufw default allow outgoing comment 'allow all outgoing traffic'
```
1. Denegar todo el tráfico entrante:
``` bash
sudo ufw default deny incoming comment 'deny all incoming traffic'
```
1. Obviamente queremos conexiones SSH entrantes. Usar limit en lugar de allow denegará automáticamente las conexiones desde una dirección IP si intenta iniciar 6 o más conexiones en un intervalo de 30 segundos:
``` bash
sudo ufw limit in ssh comment 'allow SSH connections in'
```
> ```
> Rules updated
> Rules updated (v6)
> ```
1. Permite tráfico adicional según tus necesidades. Algunos casos de uso comunes:
``` bash
# allow traffic out to port 53 -- DNS
sudo ufw allow out 53 comment 'allow DNS calls out'
# allow traffic out to port 123 -- NTP
sudo ufw allow out 123 comment 'allow NTP out'
# allow traffic out for HTTP, HTTPS, or FTP
# apt might needs these depending on which sources you're using
sudo ufw allow out http comment 'allow HTTP traffic out'
sudo ufw allow out https comment 'allow HTTPS traffic out'
sudo ufw allow out ftp comment 'allow FTP traffic out'
# allow whois
sudo ufw allow out whois comment 'allow whois'
# allow mails for status notifications -- choose port according to your provider
sudo ufw allow out 25 comment 'allow SMTP out'
sudo ufw allow out 587 comment 'allow SMTP out'
# allow traffic out to port 68 -- the DHCP client
# you only need this if you're using DHCP
sudo ufw allow out 67 comment 'allow the DHCP client to update'
sudo ufw allow out 68 comment 'allow the DHCP client to update'
```
**Nota**: Necesitarás permitir HTTP/HTTPS para instalar paquetes y muchas otras cosas.
1. Iniciar ufw:
``` bash
sudo ufw enable
```
> ```
> Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
> Firewall is active and enabled on system startup
> ```
1. Si deseas ver el estado:
``` bash
sudo ufw status
```
> ```
> Status: active
>
> To Action From
> -- ------ ----
> 22/tcp LIMIT Anywhere # allow SSH connections in
> 22/tcp (v6) LIMIT Anywhere (v6) # allow SSH connections in
>
> 53 ALLOW OUT Anywhere # allow DNS calls out
> 123 ALLOW OUT Anywhere # allow NTP out
> 80/tcp ALLOW OUT Anywhere # allow HTTP traffic out
> 443/tcp ALLOW OUT Anywhere # allow HTTPS traffic out
> 21/tcp ALLOW OUT Anywhere # allow FTP traffic out
> Mail submission ALLOW OUT Anywhere # allow mail out
> 43/tcp ALLOW OUT Anywhere # allow whois
> 53 (v6) ALLOW OUT Anywhere (v6) # allow DNS calls out
> 123 (v6) ALLOW OUT Anywhere (v6) # allow NTP out
> 80/tcp (v6) ALLOW OUT Anywhere (v6) # allow HTTP traffic out
> 443/tcp (v6) ALLOW OUT Anywhere (v6) # allow HTTPS traffic out
> 21/tcp (v6) ALLOW OUT Anywhere (v6) # allow FTP traffic out
> Mail submission (v6) ALLOW OUT Anywhere (v6) # allow mail out
> 43/tcp (v6) ALLOW OUT Anywhere (v6) # allow whois
> ```
o
``` bash
sudo ufw status verbose
```
> ```
> Status: active
> Logging: on (low)
> Default: deny (incoming), deny (outgoing), disabled (routed)
> New profiles: skip
>
> To Action From
> -- ------ ----
> 22/tcp LIMIT IN Anywhere # allow SSH connections in
> 22/tcp (v6) LIMIT IN Anywhere (v6) # allow SSH connections in
>
> 53 ALLOW OUT Anywhere # allow DNS calls out
> 123 ALLOW OUT Anywhere # allow NTP out
> 80/tcp ALLOW OUT Anywhere # allow HTTP traffic out
> 443/tcp ALLOW OUT Anywhere # allow HTTPS traffic out
> 21/tcp ALLOW OUT Anywhere # allow FTP traffic out
> 587/tcp (Mail submission) ALLOW OUT Anywhere # allow mail out
> 43/tcp ALLOW OUT Anywhere # allow whois
> 53 (v6) ALLOW OUT Anywhere (v6) # allow DNS calls out
> 123 (v6) ALLOW OUT Anywhere (v6) # allow NTP out
> 80/tcp (v6) ALLOW OUT Anywhere (v6) # allow HTTP traffic out
> 443/tcp (v6) ALLOW OUT Anywhere (v6) # allow HTTPS traffic out
> 21/tcp (v6) ALLOW OUT Anywhere (v6) # allow FTP traffic out
> 587/tcp (Mail submission (v6)) ALLOW OUT Anywhere (v6) # allow mail out
> 43/tcp (v6) ALLOW OUT Anywhere (v6) # allow whois
> ```
7. Si necesitas eliminar una regla
``` bash
sudo ufw status numbered
[...]
sudo ufw delete 3 #line number of the rule you want to delete
```
#### Aplicaciones Predeterminadas
ufw incluye algunas aplicaciones predeterminadas. Puedes verlas con:``` bash
sudo ufw app list
```
> ```
> Available applications:
> AIM
> Bonjour
> CIFS
> DNS
> Deluge
> IMAP
> IMAPS
> IPP
> KTorrent
> Kerberos Admin
> Kerberos Full
> Kerberos KDC
> Kerberos Password
> LDAP
> LDAPS
> LPD
> MSN
> MSN SSL
> Mail submission
> NFS
> OpenSSH
> POP3
> POP3S
> PeopleNearby
> SMTP
> SSH
> Socks
> Telnet
> Transmission
> Transparent Proxy
> VNC
> WWW
> WWW Cache
> WWW Full
> WWW Secure
> XMPP
> Yahoo
> qBittorrent
> svnserve
> ```
Para obtener detalles sobre la aplicación, como qué puertos incluye, escribe:``` bash
sudo ufw app info [app name]
```
> ``` bash
> sudo ufw app info DNS
> ```
>
> ```
> Profile: DNS
> Title: Internet Domain Name Server
> Description: Internet Domain Name Server
>
> Port:
> 53
> ```
#### Aplicación personalizada
Si no deseas crear reglas proporcionando explícitamente el(los) número(s) de puerto, puedes crear tus propias configuraciones de aplicación. Para ello, crea un archivo en `/etc/ufw/applications.d`.
Por ejemplo, aquí está lo que usarías para [Plex](https://support.plex.tv/articles/201543147-what-network-ports-do-i-need-to-allow-through-my-firewall/):``` bash
cat /etc/ufw/applications.d/plexmediaserver
```
> ```
[PlexMediaServer]
title=Plex Media Server
description=This opens up PlexMediaServer for http (32400), upnp, and autodiscovery.
ports=32469/tcp|32413/udp|1900/udp|32400/tcp|32412/udp|32410/udp|32414/udp|32400/udp
```
Luego puedes habilitarlo como cualquier otra aplicación:```bash
sudo ufw allow plexmediaserver
```
([Table of Contents](#table-of-contents))
### Detección y Prevención de Intrusiones con iptables mediante PSAD
#### Por qué
Incluso si tienes un cortafuegos que protege tus puertas, es posible que alguien intente entrar por la fuerza en cualquiera de las puertas protegidas. Queremos monitorizar toda la actividad de red para detectar posibles intentos de intrusión, como intentos repetidos de acceso, y bloquearlos.
#### Cómo funciona
No puedo explicarlo mejor que el usuario [FINESEC](https://serverfault.com/users/143961/finesec) de https://serverfault.com/ en: https://serverfault.com/a/447604/289829.
> Fail2BAN escanea los archivos de registro de varias aplicaciones como Apache, SSH o FTP y bloquea automáticamente las IP que muestran signos maliciosos, como intentos de inicio de sesión automatizados. PSAD, por otro lado, escanea los mensajes de registro de iptables e ip6tables (típicamente /var/log/messages) para detectar y, opcionalmente, bloquear escaneos y otros tipos de tráfico sospechoso, como intentos de DDoS o de huellas dactilares del SO. Está bien usar ambos programas al mismo tiempo porque operan en diferentes niveles.
Y, dado que ya estamos usando [UFW](#ufw-uncomplicated-firewall), seguiremos las excelentes instrucciones de [netson](https://gist.github.com/netson) en https://gist.github.com/netson/c45b2dc4e835761fbccc para hacer que PSAD funcione con UFW.
#### Referencias
- http://www.cipherdyne.org/psad/
- http://www.cipherdyne.org/psad/docs/config.html
- https://www.thefanclub.co.za/how-to/how-install-psad-intrusion-detection-ubuntu-1204-lts-server
- https://serverfault.com/a/447604/289829
- https://serverfault.com/a/770424/289829
- https://gist.github.com/netson/c45b2dc4e835761fbccc
- Gracias a [moltenbit](https://github.com/moltenbit) por detectar el problema ([#61](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/61)) con `psadwatchd`.
#### Pasos
1. Instalar psad.
En sistemas basados en Debian:
``` bash
sudo apt install psad
```
1. Hacer una copia de seguridad del archivo de configuración de psad `/etc/psad/psad.conf`:
``` bash
sudo cp --archive /etc/psad/psad.conf /etc/psad/psad.conf-COPY-$(date +"%Y%m%d%H%M%S")
```
1. Revisar y actualizar las opciones de configuración en `/etc/psad/psad.conf`. Prestar especial atención a estas:
|Configuración|Establecer a
|--|--|
|[`EMAIL_ADDRESSES`](http://www.cipherdyne.org/psad/docs/config.html#EMAIL_ADDRESSES)|tu(s) dirección(es) de correo electrónico|
|`HOSTNAME`|el nombre de host de tu servidor|
|`EXPECT_TCP_OPTIONS`|`EXPECT_TCP_OPTIONS Y;`|
|`ENABLE_PSADWATCHD`|`ENABLE_PSADWATCHD Y;`|
|[`ENABLE_AUTO_IDS`](http://www.cipherdyne.org/psad/docs/config.html#ENABLE_AUTO_IDS)|`ENABLE_AUTO_IDS Y;`|
|`ENABLE_AUTO_IDS_EMAILS`|`ENABLE_AUTO_IDS_EMAILS Y;`|
Consulta el archivo de configuración y la documentación de psad en http://www.cipherdyne.org/psad/docs/config.html para más detalles.
1. <a name="psad_step4"></a>Ahora necesitamos hacer algunos cambios en ufw para que funcione con psad, indicando a ufw que registre todo el tráfico para que psad pueda analizarlo. Para ello, edita **dos archivos** y añade estas líneas **al final, pero antes de la línea COMMIT**.
Realiza copias de seguridad:
``` bash
sudo cp --archive /etc/ufw/before.rules /etc/ufw/before.rules-COPY-$(date +"%Y%m%d%H%M%S")
sudo cp --archive /etc/ufw/before6.rules /etc/ufw/before6.rules-COPY-$(date +"%Y%m%d%H%M%S")
```
Edita los archivos:
- `/etc/ufw/before.rules`
- `/etc/ufw/before6.rules`
Y añade esto **al final pero antes de la línea COMMIT**:
```
# log all traffic so psad can analyze
-A INPUT -j LOG --log-tcp-options --log-prefix "[IPTABLES] "
-A FORWARD -j LOG --log-tcp-options --log-prefix "[IPTABLES] "
```
**Nota**: Estamos añadiendo un prefijo de registro a todos los registros de iptables. Lo necesitaremos para [separar los registros de iptables a su propio archivo](#separate-iptables-log-file).
Por ejemplo:
> ```
> ...
>
> # log all traffic so psad can analyze
> -A INPUT -j LOG --log-tcp-options --log-prefix "[IPTABLES] "
> -A FORWARD -j LOG --log-tcp-options --log-prefix "[IPTABLES] "
>
> # don't delete the 'COMMIT' line or these rules won't be processed
> COMMIT
> ```
1. Ahora necesitamos recargar/reiniciar ufw y psad para que los cambios surtan efecto:
``` bash
sudo ufw reload
sudo psad -R
sudo psad --sig-update
sudo psad -H
```
1. Analizar las reglas de iptables en busca de errores:
``` bash
sudo psad --fw-analyze
```
> ```
> [+] Parsing INPUT chain rules.
> [+] Parsing INPUT chain rules.
> [+] Firewall config looks good.
> [+] Completed check of firewall ruleset.
> [+] Results in /var/log/psad/fw_check
> [+] Exiting.
> ```
**Nota**: Si hubiera algún problema, recibirás un correo electrónico con el error.
1. Verificar el estado de psad:
``` bash
sudo psad --Status
```
> ```
> [-] psad: pid file /var/run/psad/psadwatchd.pid does not exist for psadwatchd on vm
> [+] psad_fw_read (pid: 3444) %CPU: 0.0 %MEM: 2.2
> Running since: Sat Feb 16 01:03:09 2019
>
> [+] psad (pid: 3435) %CPU: 0.2 %MEM: 2.7
> Running since: Sat Feb 16 01:03:09 2019
> Command line arguments: [none specified]
> Alert email address(es): root@localhost
>
> [+] Version: psad v2.4.3
>
> [+] Top 50 signature matches:
> [NONE]
>
> [+] Top 25 attackers:
> [NONE]
>
> [+] Top 20 scanned ports:
> [NONE]
>
> [+] iptables log prefix counters:
> [NONE]
>
> Total protocol packet counters:
>
> [+] IP Status Detail:
> [NONE]
>
> Total scan sources: 0
> Total scan destinations: 0
>
> [+] These results are available in: /var/log/psad/status.out
> ```
([Table of Contents](#table-of-contents))
### Detección y Prevención de Intrusiones en Aplicaciones con Fail2Ban
#### Por qué
UFW le dice a tu servidor qué puertas tapiar para que nadie pueda verlas, y qué puertas permitir que usuarios autorizados utilicen. PSAD monitoriza la actividad de red para detectar y prevenir posibles intrusiones: intentos repetidos de entrar.
Pero, ¿qué pasa con las aplicaciones/servicios que se ejecutan en tu servidor, como SSH y Apache, donde tu cortafuegos está configurado para permitir el acceso? Aunque el acceso esté permitido, eso no significa que todos los intentos de acceso sean válidos e inofensivos. ¿Qué pasa si alguien intenta forzar la entrada a una aplicación web que se ejecuta en tu servidor? Aquí es donde entra Fail2ban.
#### Cómo funciona
Fail2ban monitoriza los registros de tus aplicaciones (como SSH y Apache) para detectar y prevenir posibles intrusiones. Monitorizará el tráfico/registros de red y evitará intrusiones bloqueando actividades sospechosas (por ejemplo, múltiples intentos de conexión fallidos consecutivos en un corto período de tiempo).
#### Objetivos
- monitorización de red para actividad sospechosa con bloqueo automático de IP infractoras
#### Notas
- Hasta ahora, lo único que se ejecuta en este servidor es SSH, así que queremos que Fail2ban monitorice SSH y bloquee según sea necesario.
- A medida que instales otros programas, tendrás que crear/configurar las cárceles (jails) apropiadas y habilitarlas.
#### Referencias
- https://www.fail2ban.org/
- https://blog.vigilcode.com/2011/05/ufw-with-fail2ban-quick-secure-setup-part-ii/
- https://dodwell.us/security/ufw-fail2ban-portscan.html
- https://www.howtoforge.com/community/threads/fail2ban-and-ufw-on-debian.77261/
#### Pasos
1. Instalar fail2ban.
En sistemas basados en Debian:
``` bash
sudo apt install fail2ban
```
1. No queremos editar `/etc/fail2ban/fail2ban.conf` ni `/etc/fail2ban/jail.conf` porque una futura actualización podría sobrescribirlos, así que crearemos una copia local en su lugar. Crea el archivo `/etc/fail2ban/jail.local` y añade lo siguiente, reemplazando `[LAN SEGMENT]` y `[your email]` con los valores apropiados:
```
[DEFAULT]
# the IP address range we want to ignore
ignoreip = 127.0.0.1/8 [LAN SEGMENT]
# who to send e-mail to
destemail = [your e-mail]
# who is the email from
sender = [your e-mail]
# since we're using exim4 to send emails
mta = mail
# get email alerts
action = %(action_mwl)s
```
**Nota**: Tu servidor necesitará poder enviar correos electrónicos para que Fail2ban pueda informarte sobre actividad sospechosa y cuándo ha bloqueado una IP.
1. Necesitamos crear una cárcel para SSH que le indique a fail2ban que revise los registros de SSH y use ufw para bloquear/desbloquear IP según sea necesario. Crea una cárcel para SSH creando el archivo `/etc/fail2ban/jail.d/ssh.local` y añadiendo lo siguiente:
```
[sshd]
enabled = true
banaction = ufw
port = ssh
filter = sshd
logpath = %(sshd_log)s
maxretry = 5
```
[Para los perezosos](#editing-configuration-files---for-the-lazy):
``` bash
cat << EOF | sudo tee /etc/fail2ban/jail.d/ssh.local
[sshd]
enabled = true
banaction = ufw
port = ssh
filter = sshd
logpath = %(sshd_log)s
maxretry = 5
EOF
```
1. En lo anterior, le decimos a fail2ban que use ufw como `banaction`. Fail2ban incluye un archivo de configuración de acción para ufw. Puedes verlo en `/etc/fail2ban/action.d/ufw.conf`
1. Habilitar fail2ban:
``` bash
sudo fail2ban-client start
sudo fail2ban-client reload
sudo fail2ban-client add sshd # Esto puede fallar en algunos sistemas si la cárcel sshd se añadió por defecto
```
1. Para verificar el estado:
``` bash
sudo fail2ban-client status
```
> ```
> Status
> |- Number of jail: 1
> `- Jail list: sshd
> ```
``` bash
sudo fail2ban-client status sshd
```
> ```
> Status for the jail: sshd
> |- Filter
> | |- Currently failed: 0
> | |- Total failed: 0
> | `- File list: /var/log/auth.log
> `- Actions
> |- Currently banned: 0
> |- Total banned: 0
> `- Banned IP list:
> ```
#### Cárceles personalizadas
Todavía no he necesitado crear una cárcel personalizada. Cuando lo haga y descubra cómo, actualizaré esta guía. O, si sabes cómo, por favor ayuda a [contribuir](#contributing).
#### Desbloquear una IP
Para desbloquear una IP, usa este comando:``` bash
fail2ban-client set [jail] unbanip [IP]
```
`[jail]` es el nombre de la cárcel que tiene la IP baneada y `[IP]` es la dirección IP que deseas desbanear. Por ejemplo, para desbanear `192.168.1.100` de SSH harías:``` bash
fail2ban-client set sshd unbanip 192.168.1.100
```
([Tabla de Contenidos](#tabla-de-contenidos))
### Detección y Prevención de Intrusiones en Aplicaciones con CrowdSec
#### Por qué
UFW le dice a tu servidor qué puertas cerrar para que nadie pueda verlas, y qué puertas permitir a los usuarios autorizados. PSAD monitorea la actividad de la red para detectar y prevenir posibles intrusiones: intentos repetidos de entrada.
CrowdSec es similar a Fail2Ban en el sentido de que monitorea los registros de tus aplicaciones (como SSH y Apache) para detectar y prevenir posibles intrusiones. Sin embargo, CrowdSec está vinculado a una comunidad que comparte inteligencia de amenazas de vuelta a CrowdSec para luego distribuir una Lista de Bloqueo Comunitaria a todos los usuarios.
#### Cómo funciona
CrowdSec monitorea los registros de tus aplicaciones (como SSH y Apache) para detectar y prevenir posibles intrusiones. Monitoreará el tráfico/registros de red y evitará intrusiones bloqueando actividad sospechosa (por ejemplo, múltiples conexiones fallidas sucesivas en un corto período de tiempo). Una vez que se detecta una IP maliciosa, se agregará a tu lista de decisiones local y la información de amenazas se comparte con CrowdSec para actualizar la Lista de Bloqueo Comunitaria sobre direcciones IP maliciosas. Una vez que una dirección IP alcanza un cierto umbral de actividad maliciosa, se propagará automáticamente a todos los demás usuarios de CrowdSec para bloquearla de forma proactiva.
#### Objetivos
- Monitoreo de red para actividad sospechosa con baneo automático de las IP infractoras.
#### Notas
- Hasta ahora, lo único que se ejecuta en este servidor es SSH, por lo que queremos que CrowdSec monitoree SSH y banee según sea necesario.
- A medida que instales otros programas, necesitarás instalar colecciones adicionales y configurar las adquisiciones correspondientes.
#### Referencias
- https://www.crowdsec.net/
- [Lee cómo CrowdSec selecciona la Lista de Bloqueo Comunitaria](https://www.crowdsec.net/our-data)
- [Lee qué inteligencia de amenazas se comparte con CrowdSec](https://docs.crowdsec.net/docs/next/central_api/intro#signal-meta-data)
- https://docs.crowdsec.net/
#### Pasos
1. Instalar el Motor de Seguridad CrowdSec. (IDS)
En cualquier distribución de Linux (incluyendo sistemas basados en Debian)
Instala el repositorio de CrowdSec:
``` bash
curl -s https://install.crowdsec.net | sudo sh
```
Instala el Motor de Seguridad CrowdSec:
``` bash
sudo apt install crowdsec
```
> [!TIP]
> si `curl | sh` no es lo tuyo, puedes encontrar métodos de instalación adicionales [aquí](https://docs.crowdsec.net/u/getting_started/installation/linux).
Por defecto, mientras CrowdSec instala el Motor de Seguridad, detectará automáticamente tus aplicaciones instaladas e instalará los analizadores y escenarios correspondientes. Como sabemos que la mayoría de los servidores Linux ejecutan SSH de serie, CrowdSec lo configurará automáticamente.
2. Instalar un Componente de Corrección. (IPS)
CrowdSec por sí mismo es un motor de detección; dado que en la mayoría de las infraestructuras modernas puedes tener un cortafuegos o WAF ascendente, CrowdSec no bloqueará las direcciones IP por sí solo. Puedes instalar un Componente de Corrección para bloquear las direcciones IP detectadas por CrowdSec.
```bash
sudo apt install crowdsec-firewall-bouncer-iptables
```
> [!TIP]
> Si tu instalación de UFW no usa `iptables` como backend, puedes instalar alternativamente `crowdsec-firewall-bouncer-nftables`. No hay diferencia en los binarios instalados, solo el archivo de configuración es diferente.
Por defecto, mientras se instala el Componente de Corrección, configurará automáticamente los ajustes necesarios para funcionar con el Motor de Seguridad si se despliega en el mismo host (y si el motor de seguridad no está en un entorno de contenedor).
3. Verificar que la detección y corrección funcionan según lo previsto:
El paquete CrowdSec incluye una herramienta CLI para comprobar el estado del Motor de Seguridad y del Componente de Corrección.
```bash
sudo cscli metrics
```
```bash
Acquisition Metrics:
╭────────────────────────┬────────────┬──────────────┬────────────────┬────────────────────────┬───────────────────╮
│ Source │ Lines read │ Lines parsed │ Lines unparsed │ Lines poured to bucket │ Lines whitelisted │
├────────────────────────┼────────────┼──────────────┼────────────────┼────────────────────────┼───────────────────┤
│ file:/var/log/auth.log │ 5 │ 4 │ 1 │ 10 │ - │
│ file:/var/log/syslog │ 30 │ - │ 30 │ - │ - │
╰────────────────────────┴────────────┴──────────────┴────────────────┴────────────────────────┴───────────────────╯
Local API Decisions:
╭────────────────────────────────────────────┬────────┬────────┬───────╮
│ Reason │ Origin │ Action │ Count │
├────────────────────────────────────────────┼────────┼────────┼───────┤
│ crowdsecurity/http-backdoors-attempts │ CAPI │ ban │ 73 │
│ crowdsecurity/http-bad-user-agent │ CAPI │ ban │ 4836 │
│ crowdsecurity/http-path-traversal-probing │ CAPI │ ban │ 87 │
│ crowdsecurity/http-probing │ CAPI │ ban │ 2010 │
│ crowdsecurity/thinkphp-cve-2018-20062 │ CAPI │ ban │ 88 │
│ crowdsecurity/CVE-2019-18935 │ CAPI │ ban │ 7 │
│ crowdsecurity/CVE-2023-49103 │ CAPI │ ban │ 5 │
│ crowdsecurity/http-admin-interface-probing │ CAPI │ ban │ 91 │
│ ltsich/http-w00tw00t │ CAPI │ ban │ 3 │
│ crowdsecurity/apache_log4j2_cve-2021-44228 │ CAPI │ ban │ 18 │
│ crowdsecurity/nginx-req-limit-exceeded │ CAPI │ ban │ 280 │
│ crowdsecurity/ssh-slow-bf │ CAPI │ ban │ 3412 │
│ crowdsecurity/spring4shell_cve-2022-22965 │ CAPI │ ban │ 1 │
│ crowdsecurity/ssh-cve-2024-6387 │ CAPI │ ban │ 24 │
│ crowdsecurity/CVE-2023-22515 │ CAPI │ ban │ 2 │
│ crowdsecurity/http-cve-2021-41773 │ CAPI │ ban │ 172 │
│ crowdsecurity/netgear_rce │ CAPI │ ban │ 14 │
│ crowdsecurity/ssh-bf │ CAPI │ ban │ 2000 │
│ crowdsecurity/CVE-2022-35914 │ CAPI │ ban │ 1 │
│ crowdsecurity/http-cve-2021-42013 │ CAPI │ ban │ 2 │
│ crowdsecurity/jira_cve-2021-26086 │ CAPI │ ban │ 9 │
│ crowdsecurity/http-sensitive-files │ CAPI │ ban │ 166 │
│ crowdsecurity/http-wordpress-scan │ CAPI │ ban │ 272 │
│ crowdsecurity/CVE-2022-26134 │ CAPI │ ban │ 5 │
│ crowdsecurity/http-generic-bf │ CAPI │ ban │ 7 │
│ crowdsecurity/http-open-proxy │ CAPI │ ban │ 948 │
│ crowdsecurity/http-crawl-non_statics │ CAPI │ ban │ 339 │
│ crowdsecurity/http-cve-probing │ CAPI │ ban │ 5 │
│ crowdsecurity/CVE-2017-9841 │ CAPI │ ban │ 117 │
│ crowdsecurity/CVE-2022-37042 │ CAPI │ ban │ 1 │
│ crowdsecurity/fortinet-cve-2018-13379 │ CAPI │ ban │ 5 │
╰────────────────────────────────────────────┴────────┴────────┴───────╯
Local API Metrics:
╭──────────────────────┬────────┬──────╮
│ Route │ Method │ Hits │
├──────────────────────┼────────┼──────┤
│ /v1/alerts │ GET │ 2 │
│ /v1/decisions/stream │ GET │ 5 │
│ /v1/usage-metrics │ POST │ 2 │
│ /v1/watchers/login │ POST │ 4 │
╰──────────────────────┴────────┴──────╯
Local API Bouncers Metrics:
╭────────────────────────────────┬──────────────────────┬────────┬──────╮
│ Bouncer │ Route │ Method │ Hits │
├────────────────────────────────┼──────────────────────┼────────┼──────┤
│ cs-firewall-bouncer-1729025592 │ /v1/decisions/stream │ GET │ 5 │
╰────────────────────────────────┴──────────────────────┴────────┴──────╯
Local API Machines Metrics:
╭──────────────────────────────────────────────────┬────────────┬────────┬──────╮
│ Machine │ Route │ Method │ Hits │
├──────────────────────────────────────────────────┼────────────┼────────┼──────┤
│ <your_machine_id_will_be_here> │ /v1/alerts │ GET │ 2 │
╰──────────────────────────────────────────────────┴────────────┴────────┴──────╯
Parser Metrics:
╭─────────────────────────────────┬──────┬────────┬──────────╮
│ Parsers │ Hits │ Parsed │ Unparsed │
├─────────────────────────────────┼──────┼────────┼──────────┤
│ child-crowdsecurity/sshd-logs │ 41 │ 4 │ 37 │
│ child-crowdsecurity/syslog-logs │ 35 │ 35 │ - │
│ crowdsecurity/dateparse-enrich │ 4 │ 4 │ - │
│ crowdsecurity/sshd-logs │ 5 │ 4 │ 1 │
│ crowdsecurity/syslog-logs │ 35 │ 35 │ - │
╰─────────────────────────────────┴──────┴────────┴──────────╯
Scenario Metrics:
╭─────────────────────────────────────┬───────────────┬───────────┬──────────────┬────────┬─────────╮
│ Scenario │ Current Count │ Overflows │ Instantiated │ Poured │ Expired │
├─────────────────────────────────────┼───────────────┼───────────┼──────────────┼────────┼─────────┤
│ crowdsecurity/ssh-bf │ 1 │ - │ 1 │ 4 │ - │
│ crowdsecurity/ssh-bf_user-enum │ 1 │ - │ 1 │ 1 │ - │
│ crowdsecurity/ssh-slow-bf │ 1 │ - │ 1 │ 4 │ - │
│ crowdsecurity/ssh-slow-bf_user-enum │ 1 │ - │ 1 │ 1 │ - │
╰─────────────────────────────────────┴───────────────┴───────────┴──────────────┴────────┴─────────╯
```
La salida anterior puede ser abrumadora, pero es una buena manera de comprobar que el Motor de Seguridad está leyendo registros y el Componente de Corrección está bloqueando direcciones IP. A continuación, un desglose rápido de cada sección:
- **Acquisition Metrics**: Esta sección muestra los registros que el Motor de Seguridad está leyendo y analizando. Si ves registros en la columna `Lines unparsed`, significa que el Motor de Seguridad no puede analizar los registros. Esto podría deberse a una mala configuración o a que los registros no están en el formato esperado.
- **Local API Decisions**: Esta sección muestra las decisiones que el Motor de Seguridad tiene en la base de datos. Si ves registros en la columna `Count`, significa que el Motor de Seguridad ha detectado actividad maliciosa y ha bloqueado la dirección IP.
- Origen: De dónde proviene la decisión. En este caso, de la API Central (CAPI).
- **Local API Metrics**: Esta sección muestra el número de aciertos en la API Local. Esta es la API que el Motor de Seguridad utiliza para comunicarse con el Componente de Corrección.
- **Local API Bouncers Metrics**: Esta sección muestra el número de aciertos en la API Local por parte del Componente de Corrección.
- **Local API Machines Metrics**: Esta sección muestra el número de aciertos en la API Local por parte del Motor de Seguridad (si ejecutas varios Motores de Seguridad en una configuración centralizada, puedes ver múltiples ID aquí).
- **Parser Metrics**: Esta sección muestra los analizadores que está utilizando el Motor de Seguridad. Si ves registros en la columna `Unparsed`, significa que el Motor de Seguridad no puede analizar los registros. Esto podría deberse a una mala configuración o a que los registros no están en el formato esperado.
- **Scenario Metrics**: Esta sección muestra los escenarios que está utilizando el Motor de Seguridad. Si ves registros en la columna `Current Count`, significa que el Motor de Seguridad ha detectado actividad maliciosa y está rastreando la dirección IP.
#### Desbanear una IP
Para desbanear una IP usa este comando:``` bash
cscli decisions delete --ip [IP]
```
`[IP]` es la dirección IP que deseas desbloquear. Por ejemplo, para desbloquear `192.168.1.100` de SSH harías:``` bash
cscli decisions delete --ip 192.168.1.100
```
## La Auditoría
### Monitoreo de Integridad de Archivos/Carpetas con AIDE (WIP)
#### Por qué
WIP
#### Cómo funciona
WIP
#### Objetivos
WIP
#### Referencias
- https://aide.github.io/
- https://www.hiroom2.com/2017/06/09/debian-8-file-integrity-check-with-aide/
- https://blog.rapid7.com/2017/06/30/how-to-install-and-configure-aide-on-ubuntu-linux/
- https://www.stephenrlang.com/2016/03/using-aide-for-file-integrity-monitoring-fim-on-ubuntu/
- https://www.howtoforge.com/how-to-configure-the-aide-advanced-intrusion-detection-environment-file-integrity-scanner-for-your-website
- https://www.tecmint.com/check-integrity-of-file-and-directory-using-aide-in-linux/
- https://www.cyberciti.biz/faq/debian-ubuntu-linux-software-integrity-checking-with-aide/
- https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/83
#### Pasos
1. Instalar AIDE.
En sistemas basados en Debian:
``` bash
sudo apt install aide aide-common
```
1. Hacer una copia de seguridad del archivo de configuración predeterminada de AIDE:
``` bash
sudo cp -p /etc/default/aide /etc/default/aide-COPY-$(date +"%Y%m%d%H%M%S")
```
1. Revisar `/etc/default/aide` y establecer las configuraciones predeterminadas de AIDE según tus requisitos. Si deseas que AIDE se ejecute a diario y te envíe un correo electrónico, asegúrate de configurar `CRON_DAILY_RUN` en `yes`.
1. Hacer una copia de seguridad de los archivos de configuración de AIDE:
``` bash
sudo cp -pr /etc/aide /etc/aide-COPY-$(date +"%Y%m%d%H%M%S")
```
1. En sistemas basados en Debian:
- Los archivos de configuración de AIDE están en `/etc/aide/aide.conf.d/`.
- Deberías revisar la documentación de AIDE y los archivos de configuración para establecerlos según tus requisitos.
- Si deseas nuevas configuraciones, por ejemplo para monitorear una nueva carpeta, deberías agregarlas a `/etc/aide/aide.conf` o `/etc/aide/aide.conf.d/`.
- Realiza una copia de seguridad de los archivos de configuración originales: `sudo cp -pr /etc/aide /etc/aide-COPY-$(date +"%Y%m%d%H%M%S")`.
1. Crear una nueva base de datos e instalarla.
En sistemas basados en Debian:
``` bash
sudo aideinit
```
> ```
> Running aide --init...
> Start timestamp: 2019-04-01 21:23:37 -0400 (AIDE 0.16)
> AIDE initialized database at /var/lib/aide/aide.db.new
> Verbose level: 6
>
> Number of entries: 25973
>
> ---------------------------------------------------
> The attributes of the (uncompressed) database(s):
> ---------------------------------------------------
>
> /var/lib/aide/aide.db.new
> RMD160 : moyQ1YskQQbidX+Lusv3g2wf1gQ=
> TIGER : 7WoOgCrXzSpDrlO6I3PyXPj1gRiaMSeo
> SHA256 : gVx8Fp7r3800WF2aeXl+/KHCzfGsNi7O
> g16VTPpIfYQ=
> SHA512 : GYfa0DJwWgMLl4Goo5VFVOhu4BphXCo3
> rZnk49PYztwu50XjaAvsVuTjJY5uIYrG
> tV+jt3ELvwFzGefq4ZBNMg==
> CRC32 : /cusZw==
> HAVAL : E/i5ceF3YTjwenBfyxHEsy9Kzu35VTf7
> CPGQSW4tl14=
> GOST : n5Ityzxey9/1jIs7LMc08SULF1sLBFUc
> aMv7Oby604A=
>
>
> End timestamp: 2019-04-01 21:24:45 -0400 (run time: 1m 8s)
> ```
1. Probar que todo funciona sin cambios.
En sistemas basados en Debian:
``` bash
sudo aide.wrapper --check
```
> ```
> Start timestamp: 2019-04-01 21:24:45 -0400 (AIDE 0.16)
> AIDE found NO differences between database and filesystem. Looks okay!!
> Verbose level: 6
>
> Number of entries: 25973
>
> ---------------------------------------------------
> The attributes of the (uncompressed) database(s):
> ---------------------------------------------------
>
> /var/lib/aide/aide.db
> RMD160 : moyQ1YskQQbidX+Lusv3g2wf1gQ=
> TIGER : 7WoOgCrXzSpDrlO6I3PyXPj1gRiaMSeo
> SHA256 : gVx8Fp7r3800WF2aeXl+/KHCzfGsNi7O
> g16VTPpIfYQ=
> SHA512 : GYfa0DJwWgMLl4Goo5VFVOhu4BphXCo3
> rZnk49PYztwu50XjaAvsVuTjJY5uIYrG
> tV+jt3ELvwFzGefq4ZBNMg==
> CRC32 : /cusZw==
> HAVAL : E/i5ceF3YTjwenBfyxHEsy9Kzu35VTf7
> CPGQSW4tl14=
> GOST : n5Ityzxey9/1jIs7LMc08SULF1sLBFUc
> aMv7Oby604A=
>
>
> End timestamp: 2019-04-01 21:26:03 -0400 (run time: 1m 18s)
> ```
1. Probar que todo funciona después de hacer algunos cambios.
En sistemas basados en Debian:
``` bash
sudo touch /etc/test.sh
sudo touch /root/test.sh
sudo aide.wrapper --check
sudo rm /etc/test.sh
sudo rm /root/test.sh
sudo aideinit -y -f
```
> ```
> Start timestamp: 2019-04-01 21:37:37 -0400 (AIDE 0.16)
> AIDE found differences between database and filesystem!!
> Verbose level: 6
>
> Summary:
> Total number of entries: 25972
> Added entries: 2
> Removed entries: 0
> Changed entries: 1
>
> ---------------------------------------------------
> Added entries:
> ---------------------------------------------------
>
> f++++++++++++++++: /etc/test.sh
> f++++++++++++++++: /root/test.sh
>
> ---------------------------------------------------
> Changed entries:
> ---------------------------------------------------
>
> d =.... mc.. .. .: /root
>
> ---------------------------------------------------
> Detailed information about changes:
> ---------------------------------------------------
>
> Directory: /root
> Mtime : 2019-04-01 21:35:07 -0400 | 2019-04-01 21:37:36 -0400
> Ctime : 2019-04-01 21:35:07 -0400 | 2019-04-01 21:37:36 -0400
>
>
> ---------------------------------------------------
> The attributes of the (uncompressed) database(s):
> ---------------------------------------------------
>
> /var/lib/aide/aide.db
> RMD160 : qF9WmKaf2PptjKnhcr9z4ueCPTY=
> TIGER : zMo7MvvYJcq1hzvTQLPMW7ALeFiyEqv+
> SHA256 : LSLLVjjV6r8vlSxlbAbbEsPcQUB48SgP
> pdVqEn6ZNbQ=
> SHA512 : Qc4U7+ZAWCcitapGhJ1IrXCLGCf1IKZl
> 02KYL1gaZ0Fm4dc7xLqjiquWDMSEbwzW
> oz49NCquqGz5jpMIUy7UxA==
> CRC32 : z8ChEA==
> HAVAL : YapzS+/cdDwLj3kHJEq8fufLp3DPKZDg
> U12KCSkrO7Y=
> GOST : 74sLV4HkTig+GJhokvxZQm7CJD/NR0mG
> 6jV7zdt5AXQ=
>
>
> End timestamp: 2019-04-01 21:38:50 -0400 (run time: 1m 13s)
> ```
1. Eso es todo. Si configuras `CRON_DAILY_RUN` en `yes` en `/etc/default/aide`, entonces cron ejecutará `/etc/cron.daily/aide` todos los días y te enviará la salida por correo electrónico.
#### Actualizando la Base de Datos
Cada vez que realices cambios en archivos/carpetas que AIDE monitorea, deberás actualizar la base de datos para capturar esos cambios. Para hacerlo en sistemas basados en Debian:``` bash
sudo aideinit -y -f
```
([Table of Contents](#table-of-contents))
### Escaneo Antivirus con ClamAV (WIP)
#### Por qué
WIP
#### Cómo funciona
- ClamAV es un escáner de virus
- ClamAV-Freshclam es un servicio que mantiene actualizadas las definiciones de virus
- ClamAV-Daemon mantiene el proceso `clamd` en ejecución para acelerar el escaneo
#### Objetivos
WIP
#### Notas
- Estas instrucciones **no** le indican cómo habilitar el servicio del daemon de ClamAV para asegurarse de que `clamd` esté ejecutándose todo el tiempo. `clamd` es solo si está ejecutando un servidor de correo y no proporciona monitoreo en tiempo real de archivos. En su lugar, querrá escanear archivos manualmente o en un horario programado.
#### Referencias
- https://www.clamav.net/documents/installation-on-debian-and-ubuntu-linux-distributions
- https://wiki.debian.org/ClamAV
- https://www.osradar.com/install-clamav-debian-9-ubuntu-18/
- https://www.lisenet.com/2014/automate-clamav-to-perform-daily-system-scan-and-send-email-notifications-on-linux/
- https://www.howtoforge.com/tutorial/configure-clamav-to-scan-and-notify-virus-and-malware/
- https://serverfault.com/questions/741299/is-there-a-way-to-keep-clamav-updated-on-debian-8
- https://askubuntu.com/questions/250290/how-do-i-scan-for-viruses-with-clamav
- https://ngothang.com/how-to-install-clamav-and-configure-daily-scanning-on-centos/
#### Pasos
1. Instalar ClamAV.
En sistemas basados en Debian:
``` bash
sudo apt install clamav clamav-freshclam clamav-daemon
```
1. Haga una copia de seguridad del archivo de configuración de `clamav-freshclam` `/etc/clamav/freshclam.conf`:
``` bash
sudo cp --archive /etc/clamav/freshclam.conf /etc/clamav/freshclam.conf-COPY-$(date +"%Y%m%d%H%M%S")
```
1. Los ajustes predeterminados de `clamav-freshclam` probablemente sean suficientes, pero si desea cambiarlos, puede editar el archivo `/etc/clamav/freshclam.conf` o usar `dpkg-reconfigure`:
``` bash
sudo dpkg-reconfigure clamav-freshclam
```
**Nota**: La configuración predeterminada actualizará las definiciones 24 veces al día. Para cambiar el intervalo, revise la configuración `Checks` en `/etc/clamav/freshclam.conf` o use `dpkg-reconfigure`.
1. Iniciar el servicio `clamav-freshclam`:
``` bash
sudo service clamav-freshclam start
```
1. Puede asegurarse de que `clamav-freshclam` se esté ejecutando:
``` bash
sudo service clamav-freshclam status
```
> ```
> ● clamav-freshclam.service - ClamAV virus database updater
> Loaded: loaded (/lib/systemd/system/clamav-freshclam.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2019-03-16 22:57:07 EDT; 2min 13s ago
> Docs: man:freshclam(1)
> man:freshclam.conf(5)
> https://www.clamav.net/documents
> Main PID: 1288 (freshclam)
> CGroup: /system.slice/clamav-freshclam.service
> └─1288 /usr/bin/freshclam -d --foreground=true
>
> Mar 16 22:57:08 host freshclam[1288]: Sat Mar 16 22:57:08 2019 -> ^Local version: 0.100.2 Recommended version: 0.101.1
> Mar 16 22:57:08 host freshclam[1288]: Sat Mar 16 22:57:08 2019 -> DON'T PANIC! Read https://www.clamav.net/documents/upgrading-clamav
> Mar 16 22:57:15 host freshclam[1288]: Sat Mar 16 22:57:15 2019 -> Downloading main.cvd [100%]
> Mar 16 22:57:38 host freshclam[1288]: Sat Mar 16 22:57:38 2019 -> main.cvd updated (version: 58, sigs: 4566249, f-level: 60, builder: sigmgr)
> Mar 16 22:57:40 host freshclam[1288]: Sat Mar 16 22:57:40 2019 -> Downloading daily.cvd [100%]
> Mar 16 22:58:13 host freshclam[1288]: Sat Mar 16 22:58:13 2019 -> daily.cvd updated (version: 25390, sigs: 1520006, f-level: 63, builder: raynman)
> Mar 16 22:58:14 host freshclam[1288]: Sat Mar 16 22:58:14 2019 -> Downloading bytecode.cvd [100%]
> Mar 16 22:58:16 host freshclam[1288]: Sat Mar 16 22:58:16 2019 -> bytecode.cvd updated (version: 328, sigs: 94, f-level: 63, builder: neo)
> Mar 16 22:58:24 host freshclam[1288]: Sat Mar 16 22:58:24 2019 -> Database updated (6086349 signatures) from db.local.clamav.net (IP: 104.16.219.84)
> Mar 16 22:58:24 host freshclam[1288]: Sat Mar 16 22:58:24 2019 -> ^Clamd was NOT notified: Can't connect to clamd through /var/run/clamav/clamd.ctl: No such file or directory
> ```
**Nota**: No se preocupe por esa línea `Local version`. Consulte https://serverfault.com/questions/741299/is-there-a-way-to-keep-clamav-updated-on-debian-8 para más detalles.
1. Haga una copia de seguridad del archivo de configuración de `clamav-daemon` `/etc/clamav/clamd.conf`:
``` bash
sudo cp --archive /etc/clamav/clamd.conf /etc/clamav/clamd.conf-COPY-$(date +"%Y%m%d%H%M%S")
```
1. Puede cambiar la configuración de `clamav-daemon` editando el archivo `/etc/clamav/clamd.conf` o usando `dpkg-reconfigure`:
``` bash
sudo dpkg-reconfigure clamav-daemon
```
#### Escaneo de Archivos/Carpetas
- Para escanear archivos/carpetas use el programa `clamscan`.
- `clamscan` se ejecuta como el usuario con el que se ejecuta, por lo que necesita permisos de lectura para los archivos/carpetas que está escaneando.
- Usar `clamscan` como `root` es peligroso porque si un archivo es de hecho un virus, existe el riesgo de que pueda usar los privilegios de root.
- Para escanear un archivo: `clamscan /path/to/file`.
- Para escanear un directorio: `clamscan -r /path/to/folder`.
- Puede usar el interruptor `-i` para imprimir solo los archivos infectados.
- Consulte las páginas `man` de `clamscan` para otros interruptores/opciones.
([Table of Contents](#table-of-contents))
### Detección de Rootkits con Rkhunter (WIP)
#### Por qué
WIP
#### Cómo funciona
WIP
#### Objetivos
WIP
#### Referencias
- http://rkhunter.sourceforge.net/
- https://www.cyberciti.biz/faq/howto-check-linux-rootkist-with-detectors-software/
- https://www.tecmint.com/install-rootkit-hunter-scan-for-rootkits-backdoors-in-linux/
#### Pasos
1. Instalar Rkhunter.
En sistemas basados en Debian:
``` bash
sudo apt install rkhunter
```
1. Haga una copia de seguridad del archivo de valores predeterminados de rkhunter:
| Configuración | Valores Válidos | Ejemplo | Descripción | Notas |
|---|
| AllowGroups | nombre de grupo UNIX local | AllowGroups sshusers | grupo al que se permite el acceso SSH | |
| ClientAliveCountMax | número | ClientAliveCountMax 3 | número máximo de mensajes de keepalive del cliente enviados sin respuesta | |
| ClientAliveInterval | número de segundos | ClientAliveInterval 15 | tiempo de espera en segundos antes de una solicitud de respuesta | |
| ListenAddress | lista separada por espacios de direcciones locales |
| direcciones locales en las que sshd debe escuchar | Consulte Problema #1 para detalles importantes. |
| LoginGraceTime | número de segundos | LoginGraceTime 30 | tiempo en segundos antes de que el inicio de sesión expire | |
| MaxAuthTries | número | MaxAuthTries 2 | número máximo de intentos permitidos para iniciar sesión | |
| MaxSessions | número | MaxSessions 2 | número máximo de sesiones abiertas | |
| MaxStartups | número | MaxStartups 2 | número máximo de sesiones de inicio de sesión | |
| PasswordAuthentication | yes o no | PasswordAuthentication no | si se permite el inicio de sesión con contraseña | |
| Port | cualquier número de puerto abierto/disponible | Port 22 | puerto en el que sshd debe escuchar |
Consulte man sshd_config para más detalles sobre lo que significan estas configuraciones.