Hace ya unos años, y sin ningún software de administración tipo Puppet/Chef/Ansible, creamos un documento para que todos los técnicos pudieran decir la suya respecto a los pasos a dar tras instalar un sistema operativo Linux (CentOS en nuestro caso), con tal de no olvidarnos ninguno e ir mejorando entre todos este proceso de configuración inicial de un servidor. Eso significa que si tú, amado lector, tienes cualquier sugerencia de mejora, no dudes en dejarla en los comentarios.
Hoy en día, ese documento, muy pensado para instalaciones CentOS 6, tanto en entornos Cloud Computing como para en máquinas propias, es algo parecido a lo que listo a continuació.
NOTA: No te tomes todos los puntos al pie de la letra, seguramente querrás valorar si lo que propongo a continuación tiene sentido en tu entorno antes de aplicarlo, y seguro que más de un punto es mejorable.
1. Actualización del SO
Tras la instalación, es una buena idea forzar un update para estar a la última de los paquetes de nuestro SO.
yum update
2. Deshabilitar selinux
Selinux es una herramienta útil, pero que no compensa, y proporciona más dolores de cabeza de los que pretende solucionar. Es por eso que proveedores como RackSpace o Hetzner proveen sistemas con Selinux deshabilitado de fábrica. Si aún así quieres trabajar con Selinux, seguramente este sea el momento de configurarlo adecuadamente. En caso contrario, símplemente deshabilitalo tal y como sigue:
vi /etc/selinux/config
SELINUX=disabled
Tras deshabilitarlo, será necesario reinciar el sistema para activar los cambio. Así pues, reinicia para evitar tener problemas con los próximos pasos.
3. Usuarios de sistema
Especialmente si se trata de una máquina creada a partir de una AMI (Amazon), pero en general con cualquier instalación del SO que no sea la oficial, se deberá revisar el archivo /etc/passwd en busca de usuarios creados en la propia AMI, y:
- Cambiar el password del usuario de root
- Deshabilitar (ponerles como shell un /sbin/nologin) o eliminar los usuarios innecesarios
- Crear los usuarios (no root) que se usarán para conectar con el sistema via SSH.
- Crear el Grupo de usuarios que se usará para aceptar conexiones SSH (por ejemplo «sshusers») y añadir a él los usuarios que usaremos para conectar via SSH (se habla de ésto en profundidad en el punto 5).
Para crear el grupo, bastará con ejecutar:
groupadd sshusers
Tras ello, podremos añadir los usuarios que tendrán acceso SSH al grupo, editando el fichero de grupos:
vi /etc/group
Además, se recomienda revisar el fichero sudoers para tener una idea de los usuarios que tienen permisos para hacer sudo, y quitar del mismo a los usuarios innecesarios.
cat /etc/sudoers
Recuerda usar «visudo» si vas a editar este fichero.
4. Cambiar useradd por defecto
Otra costumbre que tenemos es cambiar el default template del comando useradd para que los usuarios que se crean sin especificar shell, por defecto no tengan acceso a ninguna shell. Así evitaremos tener, por descuido, usuarios con acceso a la shell que no deberían tenerlo. Para ello, bastará con editar el fichero «useradd» e indicar como shell «/sbin/nologin»:
vi /etc/default/useradd
SHELL=/sbin/nologin/
5. Configurar OpenSSH correctamente
Se deberá revisar el fichero de sshd para permitir únicamente los métodos de conexión seguros. En este punto hay un muchas posibilidades y seguramente ésto sea suficientemente complejo como para contar con su propio post, así que te recomendaría documentarte un poco sobre cómo configurar OpenSSH de forma segura, antes de aplicar nada.
En mi caso, en este post me centraré en:
- Asegurar que el protocolo de conexión es seguro
- No permitir acceso SSH como root
- Únicamente permitir acceso SSH a los usuarios autorizados (nunca «root»). En el ejemplo se tratará de los usuarios que pertenezcan al grupo «sshusers» que hemos creado en el punto 3.
- Controlar el número de accesos para evitar ataques
Bastará con aplicar las siguientes directivas en el fichero de configuración «/etc/ssh/sshd_config«:
Protocol 2
PermitRootLogin no
MaxAuthTries 3
PasswordAuthentication yes
MaxStartups 3
AllowGroups sshusers
Después de modificar, reiniciar el servicio sshd sin abandonar nunca el terminal actual, pues en caso de equivocarnos en algún punto, el terminal actual nos permitirá modificar la configuración de OpenSSH aun cuando hayamos cerrado el acceso por error.
/etc/init.d/sshd restart
Así pues, abriremos un nuevo terminal (repito: sin cerrar el actual) e intentaremos conectar con un usuario del grupo sshusers para comprobar que funciona. Una vez dentro, comprobaremos que también podemos cambiar a root sin mayores problemas:
su root -
Otra buena práctica, es intentar conectar por SSH directamente con root para verificar que en efecto, no podemos.
6. Configurar iptables
Tengo la sensación de que mientras escribo estas líneas, la explicación queda obsoleta, pues en las nuevas versiones basadas en RHEL7 iptables ha sido substituido por firewalld. En cualquier caso, respecto a iptables, usaremos un script cuya base servirá para únicamente aceptar las conexiones de entrada que se especifiquen de forma explícita.
Para ello, crearemos un fichero con el siguiente código (adaptado a las necesidades) para posteriormente ejecutarlo una vez, lo cual dejará iptables configurado.
cd path_to_scrips_folder
vi set_iptables.sh
#!/bin/bash
# Flush chains
iptables -F INPUT
iptables -F FORWARD
iptables -F OUTPUT
iptables -F
# Set up default policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Related and localhost
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p icmp -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
# Custom rules. Ej:
# iptables -A INPUT -p tcp --dport 80 -j ACCEPT
# iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# Save settings
service iptables save
# List rules
iptables -L -v
Una vez añadidas las reglas necesarias, deberemos asegurarnos de que iptables se ejecuta al inicio, y posteriormente dar permisos de ejecución al script para poder aplicar los cambios.
chkconfig iptables on
chmod 750 set_iptables.sh
./set_iptables.sh
7. Revisar los procesos de inicio
Se recomienda también, ver qué procesos se están ejecutando de inicio con la máquina, y deshabilitar aquellos que no interesen. Este punto está pensado para instalaciones de imágenes que no sean la Oficial de CentOS, como las AMIs de AWS o las imágenes predefinidas de RackSpace o Hetzner. En general, si no te has bajado tú la imágen de CentOS de la página oficial, es interesante revisar este punto.
Con el siguiente comando, podremos listar los procesos que pueden ejecutarse al inicio, según el runlevel.
chkconfig --list
8. Configurar la zona horaria y el servicio de NTPd
Otro punto clave es mantener la hora de todos los sistemas sincronizada y actualizada, para evitar discrepancias. Para ello, podemos valernos de ntpd, el cual si no viene instalado se puede obtener con yum (yum install ntp).
grep -v "^$" /etc/ntp.conf | grep -v "^#"
driftfile /var/lib/ntp/drift
restrict default kod nomodify notrap nopeer noquery
restrict -6 default kod nomodify notrap nopeer noquery
restrict 127.0.0.1
restrict -6 ::1
includefile /etc/ntp/crypto/pw
keys /etc/ntp/keys
server 0.es.pool.ntp.org
server 1.europe.pool.ntp.org
server 2.europe.pool.ntp.org
chkconfig ntpd on
/etc/init.d/ntpd restart
Además de ntp, me gusta asegurarme de contar con la zona horaria especificada en mis servidores. Aquí tienes la documentación oficial.
cat /etc/sysconfig/clock
ZONE="Europe/Madrid"
ln -sf /usr/share/zoneinfo/Europe/Madrid /etc/localtime
9. Revisar /etc/resolv.conf
Por lo general, cada proveedor que nos ofrezca una instalación propia de CentOS, incorporará sus propios servidores de nombres, que en la mayoría de casos serán más que suficientes para resolver las DNS. Sin embargo, será bueno revisar este fichero para asegurarnos de que efectivamente hay definidos unos servidores de nombres, y que éstos están funcionando o nos fiamos de ellos.
10. Modificar el hostname de la máquina
Revisar /etc/sysconfig/network para configurar un hostname correcto para nuestro servidor.
HOSTNAME=nombre.dominio
Hace falta reiniciar para aplicar los cambios
11. Modificar ulimit
Revisar el ulimit del servidor y aumentarlo según sea necesario. En las últimas versiones de CentOS estos parámetros vienen con valores más acordes a los tiempos actuales.
ulimit -a
La instrucción anterior nos mostrará los límites de procesos en ejecución por usuario configurados en nuestro sistema. La siguiente tabla muestra los límites y qué significan cada uno.
# - core - limits the core file size (KB)
# - data - max data size (KB)
# - fsize - maximum filesize (KB)
# - memlock - max locked-in-memory address space (KB)
# - nofile - max number of open files
# - rss - max resident set size (KB)
# - stack - max stack size (KB)
# - cpu - max CPU time (MIN)
# - nproc - max number of processes
# - as - address space limit (KB)
# - maxlogins - max number of logins for this user
# - maxsyslogins - max number of logins on the system
# - priority - the priority to run user process with
# - locks - max number of file locks the user can hold
# - sigpending - max number of pending signals
# - msgqueue - max memory used by POSIX message queues (bytes)
# - nice - max nice priority allowed to raise to values: [-20, 19]
# - rtprio - max realtime priority
# Para kernels anteriores a 2.2.5, no podemos superar los 1024. Espero que no sea tu caso :-)
Modificaremos el archivo /etc/security/limits.conf y nos aseguraremos de modificar por lo menos, los límites correspondientes a nproc y nofile.
Cuidado, podría ser que en el server existiera el fichero llamado «90-nproc.conf» con un límite que sobreescribe los ulimits del fichero limits.conf:
/etc/security/limits.d/90-nproc.conf
Tras reiniciar el sistema veremos como los límites han adquirido los nuevos valores.
12. Connection Tracking
El connection tracking es el proceso del Kernel encargado de gestionar las conexiones que afectan al servidor. Así pues, las conexiones que podemos ver con un netstat, tienen un límite. Si se trata de un servidor web que va a soportar muchas conexiones o de un postfix que va a enviar muchos mails y por tanto va a abrir muchas conexiones, sería una buena idea revisar estos parámetros. Si quieres profundizar sobre el la tabla de conntrack, ya hablamos de ella hace un tiempo aquí.
Necesitaremos:
cat /proc/meminfo
MemTotal: 49521980 kB
uname -m
x86_64
Con ésto, usaremos la siguientes fórmula:
CONNTRACK_MAX = RAMSIZE (in bytes) / 16384 / (x / 32)
Por ejemplo:
CONNTRACK_MAX = (49521980 x 1024) / 16384 / (64 / 32) = 1547561,875 => 1547561
Ahora sabremos el número máximo de conexiones que podemos gestionar, y lo modificaremos en el /etc/sysctl.conf:
# Número máximo de asignaciones (calculo prévio)
net.netfilter.nf_conntrack_max=1547561
# Timeout de 12 días en established (lo cambiamos a 12h)
net.netfilter.nf_conntrack_tcp_timeout_established=43200
# Otros parámetros que podrían ser útiles
##net.core.somaxconn=65535
##net.netfilter.nf_conntrack_tcp_timeout_time_wait=40
##net.netfilter.nf_conntrack_expect_max=4096
Tras modificar los parámetros, deberemos aplicar los cambios y verificar que en efecto se han hecho efectivos:
sysctl -p
cat /proc/sys/net/netfilter/nf_conntrack_max
Como muchas de las secciones de este post, los cambios se habrán aplicado en todas las sesiones tras el reinicio del server.
13. Mejorar el history
Puede ser muy interesante aumentar la capacidad del history del sistema, así como guardar la fecha en la que se ejecutó un determinado comando. Como «root», podremos mejorar el «history» de la máquina creando un script personalizado para el profile:
vi /etc/profile.d/custom.sh
#Custom global bash parameters
#Adding time to history and increasing it to 10000 linesexport
HISTTIMEFORMAT="%h %d %H:%M:%S "
HISTSIZE=10000
Tras el reinicio del server ya tendremos nuestro flamante «history» funcionando.
14. Mensaje de bienvenida
Otro punto interesante es el de mostrar un mensaje de bienvenida personalizado al loguearse al servidor. Es fráncamente fácil de conseguir, pues bastará con dejar el mensaje en el fichero motd:
vi /etc/motd
##################################################################################
# Welcome to my super server #
# All connections are monitored and recorded #
# Please, disconnect IMMEDIATELY if you are not an authorized user! #
##################################################################################
15. Monitorización
Añade la máquina a tu sistema de monitorización (¿Alguien dijo Nagios?). Bajo mi punto de vista es importante que este punto se incluya dentro de la configuración inicial de un server, y no como un extra, pues en caso contrario, corres el riesgo de que el día a día retrase la monitorización del sistema y después tengas que correr para que el servidor no salga a producción sin estar monitorizado.
16. Backups
Tres cuartas partes de lo mismo respecto a los backups: no dejes la configuración del sistema de backups del server para más adelante, prepáralo todo ya. Recuerda que es interesante (por no decir imprescindible) guardar los backups fuera de la máquina, junto con los ficheros de configuración del server.
Ah, y asegúrate de que funcionan.
Hay otros muchos puntos que podrían tratarse aquí, y que dependerán de los servicios que alojará nuestro servidor, como por ejemplo si queremos habilitar IPv6 y por consiguiente configurar ip6tables, o si estamos instalando un servicio MySQL quizá querramos asegurarnos de que los logs se rotan con logrotate, así como que la configuración del servidor MySQL usa un fichero ibdata para cada tabla InnoDB. Si estás con Apache, recuerda configurar el timezone en el php.ini para evitar llenar de warnings los logs.
En cualquier caso, si has llegado a leer hasta aquí, seguramente tengas algo que aportar, así que no dudes en plasmar tus opiniones en los comentarios.
Fuentes:
- https://helloit.es/2013/09/limpieza-y-rotacion-del-slow-query-logs/
- http://dev.mysql.com/doc/refman/5.5/en/log-file-maintenance.html
- http://www.mysqlperformanceblog.com/2013/08/20/why-is-the-ibdata1-file-continuously-growing-in-mysql/
- http://systemadmin.es/2011/04/fichero-ibdata1-enorme-y-el-parametro-innodb_file_per_table
Hay que recalcar, que el problema que nos causa Selinux con las aplicaciones es debido a que acceden a recursos de la forma errónea, y por ello, son bloqueados por el mismo. Esto es debido a que la mayoría de aplicaciones (webapps la mayoría), acceden a cosas que no deberían.
También apuntar que en el caso que haya un bug en la aplicación y selinux haya sido deshabilitado, puede poner en riesgo el sistema entero y no solo el usuario donde se ejecute si se llegara a explotar algún bug de escalado de privilegios local.
Reflexión para todos.