LibBeat en PHP – Creando nuestro «log-shipper».

En mi último proyecto me he visto en la necesidad de enviar datos desde una apliación PHP contra un elasticsearch que tenía montado. Los requisitos del proyecto eran:

  • Insertar trazas operacionales en ElasticSearch
  • Usar el protocolo Beats en un puerto específico
  • Hacerlo en PHP

Qué es ElasticSearch ?

ElasticSearch es un motor de búsqueda basado en Lucene, provee capacidad de búsqueda de texto avanzada, distribuida, y multi tenant. Proporciona fiabilidad, escalabilidad y proporciona múltiples formas de acceso a sus datos. Lucene es una base de datos no relacional (NoSql) de alto rendimineto hecha en Java y orientada a documentos, almacena los documentos en forma de JSON. Habitualmente, cuando se hace referencia a ElasticSearch se habla del stack de elasticsearch (ELK/BELK):

Sigue leyendo

Security Headers en WordPress

Esta breve entrada tratará de enseñar como se debe configurar de manera segura una instalación de wordpress. El requisito para que esto funcione debe ser tener wordpress con un certificado seguro (SSL/TLS) configurado.

¿Qué son los security headers o encabezados/cabeceras de seguridad?

Son extensiones que proporciona el consorcio de W3C para proteger al usuario contra ataques malintencionados al navegador de un cliente. Este tipo de cabeceras son eficaces para bloqeuar recursos de terceros que no se cargan debidamente, o de dominios no confiables. Otras impiden que la web se cargue como un iframe o incrustada dentro de algún dipo de contenedor para evitar clickjacking (robo de clicks).

Una vez sabemos para que son las security headers, deberemos editar el archivo .htaccess de nuestro wordpress:

Y añadir el siguiente bloque.

Options +FollowSymLinks -Indexes 
php_flag display_errors Off
php_flag session.cookie_httponly on
php_flag session.cookie_secure on

RewriteCond %{REQUEST_METHOD} ^(TRACE|DELETE|TRACK) [NC]
RewriteRule ^(.*)$ - [F,L]

SetEnvIf Host ^www.bitsdelocos.es$ is_main_domain
	Header set X-Content-Type-Options nosniff env=is_main_domain
	Header set X-XSS-Protection "1; mode=block" env=is_main_domain
	Header unset X-Powered-By env=is_main_domain
	Header unset X-Pingback env=is_main_domain
	Header unset SERVER env=is_main_domain
	Header set Content-Security-Policy "default-src 'self' https: data: wss: 'unsafe-inline' 'unsafe-eval';" env=is_main_domain
	Header set strict-transport-security "max-age=300; preload" env=is_main_domain

	

Las 4 primeras líneas impiden que se listen archivos en las carpetas que no poseen ningun index.php que cargue por defecto, se muestren errores que pueden exponer información sensible del servidor al haber un error o que se obtenga información de debug con los métodos trace y track del servidor apache.

La línea de SetEnvIf es útil si tenemos subdominios sin SSL y no queremos que esta configuración se herede en ellos, en caso de que todo esté securizado se puede eliminar y quitar «env=is_main_domain» de las demás.

Con estas modificaciones se consigue añadir los headers necesarios para poder tener un wordpress seguro en la capa de «navegador», y ocultar información sensible del servidor web que pudiera dar pistas a un atacante de nuestra infraestructura.


Automatizando ACLs en SQUID

Buenas noches en esta entrada os traigo una forma muy sencilla de automatizar el uso de SQUID como proxy de nagevación temporal.

¿Qué es un proxy de navegación?I

Un proxy, o servidor proxy, en una red informática, es un servidor —programa o dispositivo—, que hace de intermediario en las peticiones de recursos que realiza un cliente (A) a otro servidor (C) (Wikipedia).

Proxy inverso/ Reverse Proxy
Arquitectura de un proxy inverso
Sigue leyendo

Creando un túnel DNS para navegar saltándose un Firewall.

Buenas tardes,

Hace ya algún tiempo publiqué una entrada haciendo referencia a túneling mediante SSH (https://www.bitsdelocos.es/2015/08/tunnel-ssh-con-raspbian-y-bitvisessh/). En esta entrada, versará sobre túneling sobre DNS (Domain Name Server). El concepto es el mismo: sobre un flujo de peticiones DNS insertar consultas forjadas de un modo conveniente parainyectar información de otro protocolo sobre DNS y así saltarse las protección de un firewall. La definición de un túnel en informática es:

Se conoce como túnel o tunneling a la técnica que consiste en encapsular un protocolo de red sobre otro (protocolo de red encapsulador) creando un túnel de información dentro de una red de computadoras.

Para poder llevar a cabo este escenario, necesitaremos:

  • Servidor: VPS o un equipo linux con una IP de internet estática.
  • Cliente: Sistema operativo linux o una máquina virtual con linux en su defecto.
  • Tener control sobre un dominio y sus entradas de DNS.
  • Tener chrome con la extensión SwitchyOmega.

La idea principal se basa en crear un subdominio al que se le harán las peticiones de DNS y un NS (Name Server o Servidor de nombres) al que enviar las peticiones malformadas. Necesitaremos añadir la siguiente configuración en nuestro DNS público:

  • tunel.bitsdelocos.es (NS apuntando a ns.bitsdelocos.es)
  • ns.bitsdelocos.es (A apuntando a la IP del VPS)

De este modo se conseguirá que todas las peticiones DNS del tipo xxxx.tunel.bitsdelocos.es se envíen a ns.bitsdelocos.es. Lo siguiente que necesitamos es montar un servidor de nombres que haga la función de resolver de paquetes generados maliciosamente que le lleguen. En este caso usaremos iodine (https://github.com/yarrick/iodine) . He usado debian 9 base como servidor de DNS. Para hacer el build de iodine necesitaremos ejecutar como super usuario:

apt-get install gcc make autoconf libz-dev git
git clone https://github.com/yarrick/iodine.git
cd iodine
make && make install

Si todo ha ido bien iodine estará instalado en nuestro sistema:

root@Debi:~# iodine -v
iodine IP over DNS tunneling client
Git version: 27e5d6f

Para hacer funcionar este servidor de DNS bastará con ejecutar:

iodined -c -P <PASSWORD> -n <IP ESTATICA> 172.16.0.1 tunel.bitsdelocos.es -F /var/run/iodine.pid

En el caso de que estemos usando la red local 172.16.0.0/24 podremos cambiar este rango por uno que no estemos usando.

Para comprobar que todo salió bien, se puede ejecutar el comando ip addr show para ver si se asignó una ip a la interfaz virtual dnsX:

root@Debi:~# ip addr show dev dns0
11: dns0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1130 qdisc pfifo_fast state UNKNOWN group default qlen 500
    link/none 
    inet 172.16.0.1/27 scope global dns0
       valid_lft forever preferred_lft forever

En nuestro PC debemos ejecutar el cliente que nos levantará el túnel contra el NS ns.bitsdelocos.es haciendo uso de resoluciones DNS al subdominio tunel.bitsdelocos.es. Para ello lanzaremos iodine en el cliente del siguiente modo:

iodine  -P <PASSWORD> <IP DNS FORWARDER> tunel.bitsdelocos.es -F /var/run/iodine.pid

Donde es la ip del forwarder que use la red a la que estamos conectados o bien un servidor externo como el NS de google (8.8.8.8). Si no ha habido errores se podrá levantar un proxy SOCKS5 con el comando SSH:

ssh -fN -D *:8080 root@172.16.0.1

La IP 172.168.0.1 es la ip que se le habrá asignado a la interfaz dnsX en el servidor.

Para comprobar que todo ha ido bien se debe instalar el plugin switchy omega en el navegador chrome y configurarlo:

La IP que aparece en la captura es la ip de la máquina virtual donde se está ejecutando el cliente de iodine.

Para comprobar si ha ido bien la configruación del proxy, debemos abrir una web y con F12 inspeccionar la ip remota de la página abierta, si corresponde con la ip de nuestro proxy significa que habrá funcionado.

Se ha configurado Switchy omega con Chrome.

Otro modo de comprobar si funciona es usando CURL en un terminal linux

[root@localhost ~]# curl --socks5-hostname  127.0.0.1:8080 www.bitsdelocos.es -v
* About to connect() to proxy 127.0.0.1 port 8080 (#0)
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: www.bitsdelocos.es
> Accept: */*
> 
< HTTP/1.1 302 Found
< Server: openresty
< Date: Sun, 21 Oct 2018 15:52:40 GMT
< Content-Type: text/html; charset=iso-8859-1
< Content-Length: 211
< Connection: keep-alive
< Location: https://www.bitsdelocos.es/

Este método de túneling es mucho menos efectivo que el túnneling por ssh ya que el overhead introducido es mucho mayor.

Shaping con nginx: Limitando CPS (II)

Hace unos días, se me planteó el problema de limitar las CPS (conexiones por segundo a un servicio de APIs externo), por lo que mi primera idea fue limitarlo en el proxy de salida de los servidores (SQUID). Pero eso implicaba cambiar y tunear las IPtables de una forma poco dinámica ya que si el proveedor está en una CDN habría que montar un proceso de actualización de reglas,.. o bien limitarlo para todas las salidas externas del proxy con lo que no resultaba ser una buena opción así que seguí buscando,… en este caso encontré nginx como proxy inverso con el módulo limit_req_zone que permite hacer rate limiting de peticiones.

Siguiendo el esquema de la entrada anterior (Shaping con Iptables: Limitando CPS):

Y la misma arquitectura de pruebas:

Nombre del Servidor IP Descripción
shaper01 10.112.112.101 Nginx Reverse Proxy
webserver01 10.112.112.102 Servidor web con nginx
server01 10.112.112.106 Envío de tráfico

Para simplificar configuraciones, y la lectura de los scripts se han hecho 2 suposiciones.

  1. Tenemos acceso privilegiado a la máquina (sudo -i) o similar.
  2. En el archivo de hosts (/etc/hosts) de cada máquina se ha añadido lo siguiente:
    10.112.112.101 shaper01
    10.112.112.102 webserver01
    10.112.112.106 server01
    

Para las pruebas se ha habilitado la siguiente zona en nuestro nginx (/etc/nginx/conf.d/rate-limit.conf):

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
server {
    listen       80;
    server_name  shaper01;
    location / {
       limit_req zone=mylimit;
       proxy_set_header Host "webserver01";
       proxy_pass http://webserver01;

    }
}

En esta zona se indica que todas las peticiones con el server_name «shaper01», en la ruta / e hijas se aplicará un rate-limiting de 10r/s, y tras aplicar esta limitación serán reenviadas las peticiones contra el servidor webserver01.

El único cambio que hay que hacer en el programa cliente es la url dónde apuntarán sus peticiones, en este caso, se deberán abrir contra el servidor shaper01 en lugar del endpoint de la API.

Las pruebas se han lanzado con curl igual que en la entrada anterior:

while [ 1 ]; do curl shaper01 -s > /dev/null; done

Tras analizar los resultados del nginx del server web, podemos afirmar que está funcionando el rate-limiting.

Conexiones Por segundo usando nginx

Shaping con Iptables: Limitando CPS

Buenas noches, después de mucho tiempo sin pasarme por aquí, esta noche os traigo una pequeña entrada para ver como se puede configurar un rate limiting (shaping) en función de las conexiones por segundo en lugar del por ancho de banda (bandwidth).

Durante el transcurso de esta semana, me han consultado si se podría limitar el consumo de una API REST de un proveedor externo a priori no debería ser mucho problema, cuando te piden esto lo primero que piensas es en limitar el ancho de banda consumido en un packetshaper/firewall aplicando políticas de QoS. Pero esta vez, se solicitó que se limitara por transacciones por segundo permitidas. Tras revisarlo con los compañeros nunca habíamos montado nada así por lo que me he dispuesto a investigar un poco más y he llegado la solución que os contaré en este post.

En la siguiente imagen se describe la arquitectura inicial, en el recuadro rojo se muestra que existen N instancias de una aplicación que competirán por 10 conexiones por segundo contra la API externa (verde).


Sigue leyendo