Esta guía se compondrá de tres partes (series) sobre la correcta instalación de LAMP (Linux, Apache, MySQL, PHP). Optimizar y configuración avanzada de Apache (MPM, diferencias 2.2 y 2.4, http2, mod_security (WAF) , Apache suExec, migración a nginx. Segunda parte: Optimizar y configurar PHPFPM (módulo PHP) y opciones de seguridad en PHP y la tercera parte configuración y optimización y seguridad en MySQL (MariaDB, Percona) (MyISAM vs InnoDB, log binario, copias de seguridad mysqldump, variables key_buffer_size (MyISAM), innodb_buffer_pool_size para InnoDB etc)
Esta guía se compondrá de tres partes (series) sobre la correcta instalación de LAMP (Linux, Apache, MySQL, PHP)
- Optimizar y configuración avanzada de Apache (MPM, diferencias 2.2 y 2.4, http2, mod_security (WAF) , Apache suExec, migración a nginx
- Optimizar y configurar PHPFPM (módulo PHP) y opciones de seguridad en PHP
- Configuración y optimización y seguridad en MySQL (MariaDB, Percona) (MyISAM vs InnoDB, log binario, copias de seguridad mysqldump, variables key_buffer_size (MyISAM), etc)
Configuración Avanzada y optimización de Apache
ServerTokens ProdServerSignature OffTraceEnable Off
<Directory /var/www/html>Options –Indexes</directory>
Header always unset X-Powered-By
# ya es off por defecto#HostnameLookups Off# ok por defecto es 5# KeepAliveTimeout 5# por defecto ya es on correcto#KeepAlive On# config ok por defecto es 100MaxKeepAliveRequests 500
Habilitar HTTP2
- HTTP/2 es un protocolo binario, al contrario que HTTP 1.1 que es texto plano. La intención para HTTP 1.1 es que sea legible (por ejemplo capturando el tráfico de red) mientras que para HTTP/2 no. Más información en el FAQ oficial ¿Por qué es binario HTTP/2?
- h2 es HTTP/2 sobre TLS (negociación de protocolo a través de ALPN).
- h2c es HTTP/2 sobre TCP.
- HTTP/2 es capaz de llevar múltiples streams de datos
sobre la misma conexión TCP, evitando la clásica solicitud lenta
"head-of-line blocking" de HTTP 1.1 y evitando generar múltiples conexiones
TCP para cada solicitud/respuesta (KeepAlive parcheó el problema en
HTTP 1.1 pero no lo resolvió completamente).
Para habiltiar http2 es necesario cargar el módulo en httpd.conf
LoadModule http2_module modules/mod_http2.so
La segunda directiva que necesita añadir a la configuración de su servidor (vhost) es:
# enable HTTP/2, if available
Protocols h2 http/1.1
Esto permite h2, la variante segura, para ser el protocolo preferido de las conexiones en su servidor. Cuando quiera habilitar todas las variantes de HTTP/2, entonces simplemente configure:
Protocols h2 h2c http/1.1Recuerda que si utilizas CloudFlare no es necesario habilitar HTTP2 ya que todas las peticiones que realizar CloudFlare al servidor de origen son HTTP 1.1
Aunque http2 es "compatible" con MPM prefork pero con limitaciones severas. Se recomienda utilizar worker o event para http2
Apache MPM (Módulos de MultiProcesamiento)
Apache 2.4 tiene 3 módulos disponibles:
- 1) prefork --> Por defecto en Apache 2.2 y obligatorio para mod_php (DSO)
- 2) worker
- 3) event --> una evolución de Worker, ideal para PHP-FPM. Perfeccionada en 2.4.x
/etc/httpd/conf.modules.d/00-mpm.conf
Podemos ver que módulo mpm estamos usando:
1)No usa el mpm prefork MPM (está comentado)
#LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
Usa 3) Event
LoadModule mpm_event_module modules/mod_mpm_event.so
Trucos configuración
- Establece MinSpareThreads en un 50% de MaxRequestWorkers.
- Haz coincidir tanto MinSpareThreads como MaxSpareThreads con MaxRequestWorkers. Requisitos: asegúrate de que haya suficiente RAM en el servidor para ejecutar todos los MaxRequestWorkers a la vez.
- En los MPM basados en Worker: ServerLimit, ThreadsPerChild y MaxRequestWorkers están intrínsecamente vinculados entre sí. Es fundamental comprender el papel de cada uno y cómo el cambio de uno afecta a los demás. Las siguientes directivas gobiernan el ajuste fino de las capacidades de manejo de subprocesos de los servidores web Apache.
Comprueba desde el registro de errors servidor web, encontramos que no haya mensajes relacionados con "la configuración de MaxRequestWorkers alcanzada", por lo que parece que el problema está relacionado con nuestra configuración predeterminada de Apache
reached MaxRequestWorkers setting
1) MPM Prefork
<IfModule prefork.c>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 150
MaxConnectionsPerChild 0
</IfModule>
<IfModule mpm_prefork_module>
StartServers 4
MinSpareServers 20
MaxSpareServers 40
MaxRequestWorkers 200
MaxConnectionsPerChild 4500
</IfModule>
<IfModule prefork.c>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 150
MaxRequestsPerChild 3000
</IfModule>
<IfModule MODULE_NAME>
StartServers 4
MinSpareServers 20
MaxSpareServers 40
MaxClients 200
MaxRequestsPerChild 4000
</IfModule>
StartServers 4
MinSpareServers 3
MaxSpareServers 40
MaxRequestWorkers 200
MaxConnectionsPerChild 10000
MinSpareServer number, more processes are created at the rate of one per second on Apache 2.2 or lower. With Apache 2.4, this rate increases exponentially starting with 1 and ending with 32 children spawned per second.MaxRequestWorkers --> antes MaxClients (Apache 2.3.13 or lower), this parameter indicates the maximum amount of requests that can be served simultaneously, with any number going past the limit being queued. The size of the queue is based on the ListenBacklog directive. If MaxRequestWorkers is set too low, connections sent to the queue eventually time-out; however, if set too high, it causes the memory to start swapping. If this value is increased past 256, the ServerLimit value must also be increased
2) MPM Worker
<IfModule worker.c>
StartServers 2
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
MaxRequestWorkers 150
MaxConnectionsPerChild 0
</IfModule>
<IfModule event.c>
StartServers 2
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
# por defecto es 256 https://httpd.apache.org/
# cambiar por algo si es 150 mas grande si es > 256 ServerLimit debe aumentarse
MaxRequestWorkers 150
MaxConnectionsPerChild 0
</IfModule>
<IfModule mpm_event_module>
ServerLimit 2800
StartServers 4
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
MaxRequestWorkers 2800
MaxConnectionsPerChild 1000
</IfModule>
Herramientas benchmark y optimización Apache
Apache2Buddy
curl -sL https://raw.githubusercontent.com/richardforth/apache2buddy/master/apache2buddy.pl | perl
ApacheBench (ab)
ab -k -n 1000 -c 10 "http://elhacker.net/ddos"
modSecurity filtra ataques por XSS, SQL Injection, comportamientos anómalos en protocolos, robots, troyanos, LFI ... incorporando además reglas específicas para algunos de los gestores de contenido más populares como Joomla o Wordpress. modSecurity también funciona con nginx e IIS.
modSecurity es un firewall de aplicaciones Web embebible bajo licencia GNU que se ejecuta como módulo del servidor web Apache, provee protección contra diversos ataques hacia aplicaciones Web y permite monitorizar tráfico HTTP, así como realizar análisis en tiempo real sin necesidad de hacer cambios a la infraestructura existente.
ModSecurity cuenta con una consola de administración que permite recopilar registros de monitorización y alertas en tiempo real así como de opciones automatizadas de mantenimiento, entre otras características.
yum install mod_security mod_security_crs
- On: The rules are enforced and connections will be terminated when matching rules are found.
- Detect Only: The rules are enforced and connections will be logged when matching rules are found. Not traffic will be dropped.
- Off: Rules are not enforced.
Debug Log – /var/log/httpd/modsec_debug.log
Audit log – /var/log/httpd/modsec_audit.log
Rules – /etc/httpd/modsecurity.d/activated_rules
#SecRuleEngine DetectionOnly
SecRuleEngine On
SecAuditLog /var/log/apache2/modsec_audit.log
- Phase 1: Inspeccionar las cabeceras de la petición
- Phase 2: Inspeccionar el cuerpo de la petición
- Phase 3: Inspeccionar las cabeceras de la respuesta
- Phase 4: Inspeccionar el cuerpo de la respuesta
- Phase 5: Acción (registrar/bloquear peticiones maliciosas)
- Serial: un archivo para todos los registros. Este es el predeterminado.
- Concurrent: varios archivos de registro. Esto puede proporcionar un mejor rendimiento de escritura. Si nota que sus páginas web se ralentizan después de activar ModSecurity, puede elegir usar el tipo de registro concurrente.
sección A: cabecera del registro de auditoríasección B: cabecera de la peticiónsección C: cuerpo de la peticiónsección D: reservadosección E: cuerpo de la respuesta intermediasección F: cabecera de la respuesta finalsección G: reservadasección H: tráiler del registro de auditoríasección I: alternativa al cuerpo compacto de la solicitud, que excluye los archivossección J: información sobre los archivos cargadossección K: todas las reglas coincidentes con un evento, por orden de coincidenciasección Z: límite final
Si tiene un sitio web con mucho tráfico, el log de auditoría de ModSecurity puede volverse demasiado grande muy rápidamente, por lo que necesitamos configurar la rotación de logs para el log de auditoría de ModSecurity. Cree un fichero de configuración logrotate para ModSecurity.
sudo nano /etc/logrotate.d/modsecurity
Añada las siguientes líneas a este fichero.
/var/log/httpd/modsec_audit.log
{
rotate 10
daily
missingok
compress
delaycompress
notifempty
}
Esto rotará el archivo de registro cada día (daily), comprimiendo las versiones antiguas (compress). Los 10 archivos de registro anteriores se mantendrán (rotate 10), y no se producirá ninguna rotación si el archivo está vacío (notifempty).
SecRuleRemoveById 920350
Excluir rango de reglas:
SecRuleRemoveById "9000-9010"
Excluir reglas según tipo:
SecRuleRemoveByTag "WEB_ATTACK/XSS"
OWASP ModSecurity CRS incluye:
- AUTOMATION/MALICIOUS
- AUTOMATION/MISC
- AUTOMATION/SECURITY_SCANNER
- LEAKAGE/SOURCE_CODE_ASP_JSP
- LEAKAGE/SOURCE_CODE_CF
- LEAKAGE/SOURCE_CODE_PHP
- WEB_ATTACK/CF_INJECTION
- WEB_ATTACK/COMMAND_INJECTION
- WEB_ATTACK/FILE_INJECTION
- WEB_ATTACK/HTTP_RESPONSE_SPLITTING
- WEB_ATTACK/LDAP_INJECTION
- WEB_ATTACK/PHP_INJECTION
- WEB_ATTACK/REQUEST_SMUGGLING
- WEB_ATTACK/SESSION_FIXATION
- WEB_ATTACK/SQL_INJECTION
- WEB_ATTACK/SSI_INJECTION
- WEB_ATTACK/XSS
<LocationMatch "/wp-admin/post.php">SecRuleRemoveById 980130 941180 949110</LocationMatch>
SecRule REMOTE_ADDR "@IPMatch IP" "id:932160,ctl:ruleEngine=Off"SecRule REMOTE_ADDR "@IPMatch IP" "id:980130,ctl:ruleEngine=Off"SecRule REMOTE_ADDR "@ipMatch IP" "id:980130,phase:2,t:none,log,allow"SecRule REMOTE_ADDR "@ipMatch IP" "id:941180,phase:2,t:none,log,allow"
SecRule REMOTE_ADDR "^127\.0\.0\.1" "id:1004,phase:1,allow,ctl:ruleEngine=off"
SecRule REMOTE_ADDR "^10\.10\.10.*" "id:1005,phase:1,allow,ctl:ruleEngine=off"
<IfModule mod_security2.c>
SecRuleEngine On
SecRequestBodyAccess On
SecResponseBodyAccess On
SecResponseBodyMimeType text/plain text/html text/xml application/octet-stream
SecDataDir /tmp
</IfModule>
# mkdir /etc/httpd/crs-tecmint
# cd /etc/httpd/crs-tecmint
# wget -c https://github.com/SpiderLabs/owasp-modsecurity-crs/archive/v3.2.0.tar.gz -O master
# tar xzf master
# mv owasp-modsecurity-crs-3.2.0 owasp-modsecurity-crs
# cd owasp-modsecurity-crs/
# cp crs-setup.conf.example crs-setup.conf
<IfModule security2_module>
Include crs-tecmint/owasp-modsecurity- Include crs-tecmint/owasp-modsecurity-crs/rules/*.conf
</IfModule>
Falsos Positivos
crs-setup.conf
Ves a la sección Exclusiones de reglas específicas de la aplicación y busca las siguientes líneas.
#SecAction \
# "id:900130,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:tx.crs_exclusions_cpanel=1,\
# setvar:tx.crs_exclusions_drupal=1,\
# setvar:tx.crs_exclusions_dokuwiki=1,\
# setvar:tx.crs_exclusions_nextcloud=1,\
# setvar:tx.crs_exclusions_wordpress=1,\
# setvar:tx.crs_exclusions_xenforo=1"
Por ejemplo, si quiero activar las exclusiones de WordPress, las líneas anteriores deben cambiarse por las siguientes:
SecAction \
"id:900130,\
phase:1,\
nolog,\
pass,\
t:none,\
setvar:tx.crs_exclusions_wordpress=1"
Exclusiones para un subdominio:
SecRule REQUEST_HEADERS:Host "@streq blog.elhacker.net" "id:1000,phase:1,setvar:tx.crs_exclusions_wordpress=1"
Por ejemplo un subdominio con nextcloud:
SecRule REQUEST_HEADERS:Host "@streq nextcloud.elhacker.net" "id:1001,phase:1,setvar:tx.crs_exclusions_nextcloud=1"
modsecurity + Fail2ban
modsecurity se puede integrar fácilmente con Fail2Ban
[apache-modsecurity]
enabled = true
filter = apache-modsecurity
#logpath = /var/log/httpd/modsec_audit.log
backend = pyinotify
action = abuseipdb[abuseipdb_category="15,21"]
bantime = 1h
logencoding = UTF-8
Proxy Inverso con Apache (Reverse proxy)
- ServerName: la directiva ServerName define bajo qué nombres primarios se puede acceder a un servidor en Internet. Estos tienen que poder resolverse o bien vía DNS o por medio de los /etc/hosts. En el ejemplo se le indica al servidor Apache que tiene que hacerse cargo de todas las solicitudes en domain.tld.
- ProxyPass: la directiva ProxyPass define la dirección de destino para los reenvíos. El servidor proxy inverso reenviará todas las peticiones dirigidas a la dirección depositada bajo la etiqueta ServerName a la dirección interna consignada en el argumento de la directiva ProxyPass. En el ejemplo se trataría de la dirección IP ficticia 123.456.7.89.
- ProxyPassReverse: un proxy server no solo se ocupa de las peticiones, sino que también transmite los paquetes de respuesta del servidor backend a los clientes. Para impedir que dichas respuestas se entreguen con datos de encabezado que no sean correctos (es decir, con datos del servidor en un segundo plano), la directiva ProxyPassReverse transcribe el encabezamiento de las respuestas del servidor de tal manera que estas se adapten al servidor proxy. El servidor backend permanece anónimo.
Además, en el ejemplo aparecen dos directivas adicionales: ServerAlias y ProxyRequests. Estas no ofrecen funciones básicas para el servidor proxy y son, por lo tanto, facultativas.
- ServerAlias: la directiva ServerAlias permite, junto al nombre del servidor primario, definir un nombre alternativo para el servidor de destino.
- ProxyRequest: la directiva ProxyRequests con el argumento Off impide que se utilice el servidor Apache HTTP como proxy forward o de reenvío para evitar posibles abusos.
Apache2.4 puede funcionar como proxy inverso usando el módulo proxy
junto a otros módulos, por ejemplo:
- proxy_http: Para trabajar con el protocolo HTTP.
- proxy_ftp: Para trabajar con el protocolo FTP.
- proxy_html: Permite reescribir los enlaces HTML en el espacio de direcciones de un proxy.
- proxy_ajp: Para trabajar con el protocolo AJP para Tomcat.
ProxyPass "/" "http://192.168.0.5:8080/"
Ahora bien, la directiva ProxyPassReverse sólo modifica las cabeceras anteriormente citadas. Si en la página www.interno.com existen enlaces absolutos, éstos no son modificados.
Para que funcionen todas las rutas:
ProxyHTMLURLMap /
Para que funcionen enlaces:
ProxyHTMLEnable On
y ficheros JS y ficheros CSS:
ProxyHTMLExtended On
Vamos a explicar cómo excluir un determinado subdirectorio o ruta cuando ya hemos configurado un proxy inverso en Apache (módulo mod_proxy) que por defecto incluye esa URL. Un ejemplo para verlo más claro:
[...] ServerName foo.com [...] ProxyPass / http://localhost:4789 ProxyPassReverse / http://localhost:4789 [...]
La configuración especificada en el ejemplo anterior iría normalmente dentro de un virtualhost de Apache, ya sea en httpd.conf
o en otro fichero de configuración mediante include
. Básicamente, indica que toda petición que vaya dirigida al raíz (/) de foo.com será redirigida a http://localhost:4789
.
¿Qué sucede si quiero que esto sea así a excepción de para la URL http://foo.com/bar
? En ese caso, hay que excluir de forma explícita ese path para que no sea redirigido a través del proxy inverso del siguiente modo:
[...] ServerName foo.com [...] ProxyPass /bar/ ! ProxyPass / http://localhost:4789 ProxyPassReverse / http://localhost:4789 [...]
Al especificar la ruta seguida de !
se indica explícitamente que esa URL no será manejada por las directivas de proxy inverso.
Autenticación Digest y Basic
Para crear los usuarios
htpasswd -nB alex
Y pega el resultado en: /home/alex/htpasswd
Recuerda usar siempre https en autenticación Basic
Podemos hacer que pida contraseña o bien si es una ip de confianza no la pida:
<Location /directorio>
AuthUserFile /home/alex/htpasswd
AuthType Basic
AuthName "Directorio protegido menos para la IP x"
require valid-user
Order deny,allow
Deny from all
Allow from IP x
Allow from ns2.elhacker.net
# o password o ip correcta
Satisfy any
</Location>
O si queremos que pida contraseña ya demás la ip sea correcta cambiar el any por all en el Satisfy
Satisfy ALL
Apache suExec
Documentación Oficial
SuexecUserGroup "#1001" "#1001"
command not in docroot
[root@ns2 rpmbuild]# /usr/sbin/suexec -VEn Ubuntu y otras distribuciones existe un
-D AP_DOC_ROOT="/var/www"
-D AP_GID_MIN=1000
-D AP_HTTPD_USER="apache"
-D AP_LOG_SYSLOG
-D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
-D AP_UID_MIN=1000
-D AP_USERDIR_SUFFIX="public_html"
apache2-suexec-custom
Que permite cambiar el path (ruta) sin tener que recompilar. Pero en CentOS no es posible.
rpm -Uvh httpd-2.4.37.xxx.centos.src.rpm
/root/rpmbuild/SOURCES/httpd-2.4.37.tar.gz
cd /root/rpmbuild/httpd-2.4.37
./configure --enable-suexec --with-suexec-docroot=/hone --with-suexec-caller=apache --without-suexec-logfile --with-suexec-syslog
make -j4
/root/rpmbuild/SOURCES/httpd-2.4.37/support/suexec
cp -a /usr/sbin/suexec{,.bak}
cp /root/rpmbuild/SOURCES/httpd-2.4.37/support/suexec /usr/sbin/suexecY aplicamos permisos:
# chown root:root /usr/sbin/suexec
# chmod 4755 /usr/sbin/suexec
/root/rpmbuild/SPECS/httpd.spec
--enable-suexec --with-suexec \
--enable-suexec-capabilities \
--with-suexec-caller=%{suexec_caller} \
--with-suexec-docroot=/home \
--without-suexec-logfile \
--with-suexec-syslog \
--with-suexec-bin=%{_sbindir}/suexec \
--with-suexec-uidmin=1000 --with-suexec-gidmin=1000 \
Migrar Apache 2.2 a Apache 2.4
Allow from allahora es:Require all granted
Deny from allahora es:Require all denied
<IfModule mod_authz_core.c># Apache 2.4Require all deniedRequire ip 127.0.0.1</IfModule><IfModule !mod_authz_core.c># Apache 2.2Order deny,allowDeny from allAllow from 127.0.0.1</IfModule>
No hay comentarios:
Publicar un comentario