H3R3T1C Blog Writing about the C/C++ programming, about Security, about Linux, about everythings. https://lfdominguez.github.io// Tue, 20 Oct 2020 06:20:25 +0000 Tue, 20 Oct 2020 06:20:25 +0000 Jekyll v3.9.0 Disminuyendo tamaño de HDD virtual de un LXC en Proxmox <h2 id="introducción">Introducción</h2> <p>Proxmox es la plataforma de virtualización (basada en Debian) que utilizo (hasta dentro de poco, pues me mudo a Docker Swarm ;)). En un momento determinado tuve la necesidad de mover uno de los HDD virtuales de uno de mis contenedores LXC para otro espacio de almacenamiento más reducido. El HDD virtual estaba definido con un tamaño mayor al que a donde se migraría dicho HDD. Al revisar internamente el espacio ocupado de dicho HDD, era mucho menor al definido, por lo que la solución sería disminuir el HDD virtual para que pudiera ser migrado.</p> <h2 id="reducción-del-hdd">Reducción del HDD</h2> <p>Importante aclarar que los pasos siguientes son para cuando el formato del sistema de ficheros es ext2, ext3 o ext4.</p> <p>Al utilizar la propia herramienta de Proxmox para ello, en la documentación define que se utiliza solamente para el aumento del tamaño, por lo que la solución fue utilizar los comandos base para dicha tarea:</p> <ol> <li>Apagamos el contenedor que queremos migrar.</li> <li>Accedemos por la terminal al nodo Proxmox donde se encuentra el contenedor. <ul> <li>Obtenemos el HDD que queremos disminuir con: <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span><span class="nb">df</span> <span class="nt">-h</span> </code></pre></div> </div> </li> </ul> </li> <li>Comprobamos el HDD virtual para verificar que no contenga errores: <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp"> e2fsck -fy &lt;HDD-VIRTUAL&gt;</span><span class="w"> </span></code></pre></div> </div> </li> <li>Reducimos el sistema de ficheros en sí: <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp"> resize2fs &lt;HDD-VIRTUAL&gt;</span><span class="w"> </span>&lt;Tamaño final - 1&gt;&lt;Unidad&gt; </code></pre></div> </div> <p>Explicando un poco, cuando se reduce (o amplía) un sistema de ficheros, en realidad son varios los pasos a realizar. Primero se debe reducir el sistema de ficheros, para que la información que se encuentra esparcida por el HDD se quede en los ámbitos del nuevo espacio definido para que luego cuando se disminuya el espacio de la partición, no exista pérdida de datos. En cuanto a la expresión <code class="language-plaintext highlighter-rouge">&lt;Tamaño final - 1&gt;</code> es debido a que como se utilizan programas distintos para el cambio de tamaño del sistema de ficheros y la partición, éstos pueden tener distintas definiciones internas de la unidad de medida y por tanto se deja un espacio de seguridad. En cuanto a la expresión <code class="language-plaintext highlighter-rouge">&lt;Unidad&gt;</code> se refiere a la unidad de medida del nuevo espacio:</p> <ul> <li><code class="language-plaintext highlighter-rouge">M</code> Megabyte</li> <li><code class="language-plaintext highlighter-rouge">G</code> Gigabyte</li> <li><code class="language-plaintext highlighter-rouge">T</code> Terabyte</li> <li>etc.</li> </ul> </li> <li>Reducimos la partición LVM: <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">lvreduce -L &lt;Tamaño final&gt;</span>&lt;Unidad&gt; &lt;HDD-VIRTUAL&gt; </code></pre></div> </div> </li> <li>Ahora aumentamos el sistema de archivos automáticamente hasta el tamaño final de la partición. <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">resize2fs &lt;HDD-VIRTUAL&gt;</span><span class="w"> </span></code></pre></div> </div> </li> <li>Cambiamos manualmente la definición de la máquina virtual para que refleje el nuevo tamaño del HDD virtual <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">nano /etc/pve/lxc/&lt;id&gt;</span>.conf </code></pre></div> </div> <p>Una línea que contiene</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rootfs: &lt;id del hdd&gt;,size=&lt;tamaño&gt; </code></pre></div> </div> <p>En tamaño ponemos la misma definición que establecimos anteriormente en el comando <code class="language-plaintext highlighter-rouge">lvreduce</code>.</p> </li> </ol> Sat, 26 Jan 2019 00:00:00 +0000 https://lfdominguez.github.io//2019/01/26/disminuyendo_tamano_lvm_lxc_proxmox.html https://lfdominguez.github.io//2019/01/26/disminuyendo_tamano_lvm_lxc_proxmox.html proxmox lxc lvm Monitorizando las máquinas virtuales de proxmox con Prometheus <h2 id="introducción">Introducción</h2> <p>Muchos contamos con una infraestructura soportada sobre la plataforma de Proxmox y una de las necesidades que debemos tener es medir, métricamente, los diferentes aspectos de cada una de sus máquinas virtuales, ya sea LXC o KVM.</p> <p>Algunos enfoques definen que se debe tener un programa colector en cada máquina virtual, pero el enfoque que traigo actualmente es el de usar un colector por nodo físico que hace uso del API de Proxmox para pedir las métricas de los nodos virtuales. En el caso de que sea un clúster, solo se necesita en un nodo, puesto que el API de Proxmox te da la información de todos los miembros del clúster.</p> <h3 id="instalando-el-exporter">Instalando el <em>exporter</em></h3> <p>Podemos encontrar el exporter en</p> Sun, 20 Jan 2019 00:00:00 +0000 https://lfdominguez.github.io//2019/01/20/proxmox_and_prometheus.html https://lfdominguez.github.io//2019/01/20/proxmox_and_prometheus.html métricas monitoreo linux servidores docker grafana node-exporter Servidor de métricas Prometheus y aplicación práctica con Node-Exporter y Grafana <h2 id="introducción">Introducción</h2> <p>Prometheus es un sistema de monitoreo que a diferencia de sus homólogos utiliza un enfoque diferente, en lugar de que los servicios que lo soporten o los programas que obtienen las métricas se las envíen a Prometheus, éste es quien se conecta a ellos cada cierto tiempo y recopila toda la información. Las ventajas y desventajas de esta manera de trabajar pueden profundizarla más en <a href="https://prometheus.io/docs/introduction/faq/#why-do-you-pull-rather-than-push">el sitio oficial</a> o en <a href="https://prometheus.io/blog/2016/07/23/pull-does-not-scale-or-does-it/">su blog</a>. Está programado en Go, por lo que su instalación es sumamente sencilla y no tiene dependencia alguna, es un simple ejecutable.</p> <p>Vamos a ver un ejemplo de aplicación con Node-Exporter y Grafana para levantar una mínima infraestructura de monitoreo en nuestra red.</p> <h2 id="instalación-genérica">Instalación genérica</h2> <p>Como comentaba anteriormente, debido a su lenguaje de programación, es simplemente ir a la página de <a href="https://github.com/prometheus/prometheus/releases/latest">GitHub</a> y descargar la versión estable para el sistema operativo que querramos (incluido windows ;) ). Una vez descomprimido, es simplemente ejecutarlo como un programa más, queda fuera del ámbito del manual la creación de un servicio que lo use.</p> <p>Alguno de sus argumentos básicos son:</p> <ul> <li><code class="language-plaintext highlighter-rouge">--config.file</code> Ubicación del fichero de configuración en <code class="language-plaintext highlighter-rouge">YML</code>. Por defecto es <code class="language-plaintext highlighter-rouge">/etc/prometheus/prometheus.yml</code>.</li> <li><code class="language-plaintext highlighter-rouge">--web.listen-address</code> Dirección por donde escuchará la UI, el API y la telemetría. Por defecto es <code class="language-plaintext highlighter-rouge">0.0.0.0:9090</code>.</li> <li><code class="language-plaintext highlighter-rouge">--storage.tsdb.retention</code> Tiempo de retención de los datos de las métricas (Prometheus no está pensado para guardar un histórico largo de datos, para ello hay soluciones que se integran a Prometheus). Por defecto es <code class="language-plaintext highlighter-rouge">15d</code>.</li> <li><code class="language-plaintext highlighter-rouge">--log.level</code> Nivel de bitácora. Por defecto es <code class="language-plaintext highlighter-rouge">info</code>.</li> </ul> <h2 id="instalando-en-debian">Instalando en Debian</h2> <p>En el repositorio de Debian se encuentran los paquetes referentes a Prometheus. En mi caso uso siempre en mis servidores la versión estable de éste (que en el momento de escribir es <em>stretch</em>). La versión que se encuentra en los repositorios estables es la 1.x, pero Prometheus ha cambiado su modelo de almacenamiento completamente en la versión 2.x, por lo que haría incompatible los 2 modelos. En este caso tendremos que utilizar el repositorio <em>back-ports</em> de Debian, que no es más que ciertos programas que han sido portados para la versión estable de Debian.</p> <ol> <li>Primero configuramos el repositorio para agregar al <code class="language-plaintext highlighter-rouge">sources.list</code> la nueva fuente:</li> </ol> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp"> $</span><span class="w"> </span><span class="nb">echo</span> <span class="s2">"deb http://ftp.debian.org/debian stable-backports main"</span> <span class="o">&gt;&gt;</span> /etc/apt/sources.list </code></pre></div></div> <ol> <li>Luego actualizamos los índices</li> </ol> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp"> $</span><span class="w"> </span>apt update </code></pre></div></div> <ol> <li>Y ahora instalamos Prometheus, indicando que queremos la de <em>back-ports</em></li> </ol> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp"> $</span><span class="w"> </span>apt <span class="nb">install </span>prometheus/stable-backports <span class="go"> ó </span><span class="gp"> $</span><span class="w"> </span>apt <span class="nt">-t</span> stable-backports <span class="nb">install </span>prometheus </code></pre></div></div> <h2 id="ejecutando-desde-docker">Ejecutando desde Docker</h2> <p>Como siempre ejecutarlo desde Docker es más fácil, la imagen oficial de Prometheus la podemos encontrar tanto en <a href="https://quay.io/repository/prometheus/prometheus">Quay.io</a> como en <a href="https://hub.docker.com/r/prom/prometheus/">Docker Hub</a>:</p> <h3 id="quayio">Quay.io</h3> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>docker run <span class="nt">--name</span> prometheus <span class="nt">-d</span> <span class="nt">-p</span> 9090:9090 quay.io/prometheus/prometheus </code></pre></div></div> <h3 id="docker-hub">Docker Hub</h3> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>docker run <span class="nt">--name</span> prometheus <span class="nt">-d</span> <span class="nt">-p</span> 9090:9090 prom/prometheus </code></pre></div></div> <h3 id="opciones">Opciones</h3> <ul> <li><code class="language-plaintext highlighter-rouge">--name</code> Le asignamos el nombre <code class="language-plaintext highlighter-rouge">prometheus</code> a esa instancia, de manera que es más fácil encontrarla, por ejemplo, con un <code class="language-plaintext highlighter-rouge">docker ps</code></li> <li><code class="language-plaintext highlighter-rouge">-d</code> Le decimos a Docker que lo inicie en modo <em>demonio</em>, de esta manera se devuelve el control a la terminal y la instancia se queda ejecutándose en el fondo.</li> <li><code class="language-plaintext highlighter-rouge">-p</code> Definimos que exporte el puerto <code class="language-plaintext highlighter-rouge">9090</code> de la instancia, hacia el <code class="language-plaintext highlighter-rouge">9090</code> de nuestra PC (o servidor) en <a href="http://localhost:9090">http://localhost:9090</a>.</li> </ul> <h2 id="verificando-instalación">Verificando instalación</h2> <p>Ahora podremos acceder por HTTP hacia el servidor Prometheus usando un navegador. En esa interfaz podremos hacer consultas para probar las gráficas y los datos, así como ver el estado de los servicios a los cuales Prometheus se conecta para obtener la información de las métricas.</p> <h3 id="página-de-consultas">Página de consultas</h3> <p><img src="https://lfdominguez.github.io/images/posts/prometheus/web_graph.webp" alt="Escenario" /></p> <h3 id="página-de-chequeo-de-los-clientes">Página de chequeo de los clientes</h3> <p><img src="https://lfdominguez.github.io/images/posts/prometheus/web_target_status.webp" alt="Escenario" /></p> <h2 id="breves-sobre-la-configuración">Breves sobre la Configuración</h2> <p>El fichero de configuración de Prometheus por lo general se encuentra en <code class="language-plaintext highlighter-rouge">/etc/prometheus/prometheus.yml</code> y se explica por sí solo. Algunas precisiones:</p> <ul> <li><code class="language-plaintext highlighter-rouge">scrape_interval</code> Es el intervalo en que consulta cada servicio para obtener las métricas.</li> <li><code class="language-plaintext highlighter-rouge">evaluation_interval</code> Es el intervalo en que evalúa las reglas de alerta (no tratadas en el presente post).</li> <li><code class="language-plaintext highlighter-rouge">scrape_configs</code> Es donde va la configuración de los servicios a consultar:</li> </ul> <p>Partiendo un ejemplo simple, funcional y que se explica por si solo, es simplemente ubicarlo dentro de <code class="language-plaintext highlighter-rouge">scrape_configs</code>:</p> <div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="pi">-</span> <span class="na">job_name</span><span class="pi">:</span> <span class="s1">'</span><span class="s">squid'</span> <span class="na">static_configs</span><span class="pi">:</span> <span class="pi">-</span> <span class="na">targets</span><span class="pi">:</span> <span class="pi">-</span> <span class="s">192.168.0.128:9399</span> <span class="na">metrics_path</span><span class="pi">:</span> <span class="s">/metrics</span> </code></pre></div></div> <h2 id="promql">PromQL</h2> <p>Para terminar hablo sobre <em>PromQL</em> que es el lenguaje de consultas a Prometheus. Permite seleccionar y realizar operaciones sobre las series de tiempo. Puedes conocer más sobre el lenguaje en su <a href="https://prometheus.io/docs/prometheus/latest/querying/basics/">sitio oficial</a>. Solo mostraré algunos ejemplos rápidos (tomados de su <a href="https://prometheus.io/docs/prometheus/latest/querying/examples/">sitio oficial</a>):</p> <h3 id="operaciones-simples">Operaciones simples</h3> <ul> <li>Retornar todas las series de tiempo de la métrica <code class="language-plaintext highlighter-rouge">http_requests_total</code>:</li> </ul> <pre><code class="language-promql"> http_requests_total </code></pre> <ul> <li>Retornar todas las series de tiempo de la métrica <code class="language-plaintext highlighter-rouge">http_requests_total</code>, pero especificando algunas etiquetas:</li> </ul> <pre><code class="language-promql"> http_requests_total{job="apiserver", handler="/api/comments"} </code></pre> <ul> <li>De la anterior, retornar solamente un rango de tiempo (en este caso 5 min):</li> </ul> <pre><code class="language-promql"> http_requests_total{job="apiserver", handler="/api/comments"}[5m] </code></pre> <ul> <li>La búsqueda en las etiquetas se puede hacer por expresiones regulares, como subcadenas a buscar, por ejemplo, para sacar todos los datos referentes a la métrica donde el <code class="language-plaintext highlighter-rouge">job</code> termine en <code class="language-plaintext highlighter-rouge">server</code>:</li> </ul> <pre><code class="language-promql"> http_requests_total{job=~".*server"} </code></pre> <p>Todas las expresiones regulares en Prometheus utilizan la sintaxis <a href="https://github.com/google/re2/wiki/Syntax">R2</a>.</p> <p>Por ejemplo para excluir utilizando las etiquetas, seleccionando todo menos los que tengas <code class="language-plaintext highlighter-rouge">status</code> diferente a <code class="language-plaintext highlighter-rouge">4xx</code>:</p> <pre><code class="language-promql"> http_requests_total{status!~"4.."} </code></pre> <h3 id="usando-funciones-y-operadores">Usando funciones y operadores</h3> <ul> <li>Retornar el ritmo(<em>rate</em>) de la métrica <code class="language-plaintext highlighter-rouge">http_requests_total</code> durante 5 min:</li> </ul> <pre><code class="language-promql"> rate(http_requests_total[5m]) </code></pre> <p>Ahora, suponiendo que tenemos una etiqueta que define el <code class="language-plaintext highlighter-rouge">job</code> podemos sumar todos los <em>rate</em> y agruparlos por el <code class="language-plaintext highlighter-rouge">job</code>:</p> <pre><code class="language-promql"> sum(rate(http_requests_total[5m])) by (job) </code></pre> <ul> <li>Si tenemos métricas que tienen la misma definición de etiquetas podremos realizar cálculos matemáticos con ellas, por ejemplo, para calcular la memoria sin usar en MBytes por una instancia de un nodo ficticio que tendría las métricas <code class="language-plaintext highlighter-rouge">instance_memory_limit_bytes</code> y <code class="language-plaintext highlighter-rouge">instance_memory_usage_bytes</code>:</li> </ul> <pre><code class="language-promql"> (instance_memory_limit_bytes - instance_memory_usage_bytes) / 1024 / 1024 </code></pre> <ul> <li>Lo mismo que lo anterior pero ahora sumado por aplicación y proceso:</li> </ul> <pre><code class="language-promql"> sum( instance_memory_limit_bytes - instance_memory_usage_bytes ) by (app, proc) / 1024 / 1024 </code></pre> <h2 id="node-exporter">Node-Exporter</h2> <p>Es un <em>exporter</em> de Prometheus (así son llamados los programas encargados de obtener las métricas y brindarlas en un formato que Prometheus pueda obtener, algunos programas ya la traen incluidas, en otros casos se debe usar uno externo). Con Node-Exporter, Prometheus puede consumir, entre muchas otras, las siguientes métricas:</p> <ul> <li><code class="language-plaintext highlighter-rouge">arp</code> Expone las estadísticas ARP de <code class="language-plaintext highlighter-rouge">/proc/net/arp</code>.</li> <li><code class="language-plaintext highlighter-rouge">cpu</code></li> <li><code class="language-plaintext highlighter-rouge">diskstats</code> Expone las métricas de I/O de los discos.</li> <li><code class="language-plaintext highlighter-rouge">entropy</code> Expone la entropía disponible (muy importante para la criptografía).</li> <li><code class="language-plaintext highlighter-rouge">filesystem</code> Expone las estadísticas de los sistemas de ficheros, como el espacio en disco usado, etc.</li> <li><code class="language-plaintext highlighter-rouge">hwmon</code> Expone los sensores de hardware de <code class="language-plaintext highlighter-rouge">/sys/class/hwmon/</code></li> <li><code class="language-plaintext highlighter-rouge">loadavg</code> Expone el promedio de carga del nodo.</li> <li><code class="language-plaintext highlighter-rouge">meminfo</code> Expone las estadísticas de la RAM.</li> <li><code class="language-plaintext highlighter-rouge">netclass</code> Expone la información de las interfaces de red de <code class="language-plaintext highlighter-rouge">/sys/class/net/</code></li> <li><code class="language-plaintext highlighter-rouge">netdev</code> Más estadísticas de red, como los <em>bytes</em> transferidos, etc.</li> <li>Entre muchas otras …</li> </ul> <h3 id="instalación-genérica-1">Instalación genérica</h3> <p>Podemos seguir el mismo procedimiento de Prometheus, pero buscando la versión estable <a href="https://github.com/prometheus/node_exporter/releases/latest">aquí</a>.</p> <h3 id="instalación-en-debian">Instalación en Debian</h3> <p>Debian en su repositorio cuenta con el Node-Exporter, el paquete se llama <code class="language-plaintext highlighter-rouge">prometheus-node-exporter</code>, por lo que con <code class="language-plaintext highlighter-rouge">apt</code>:</p> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>apt <span class="nb">install </span>prometheus-node-exporter </code></pre></div></div> <p>En caso de que se quiera usar en la versión estable de Debian, hay que activar el repositorio de <em>backports</em> como mismo se realizó en la instalación de Prometheus.</p> <h3 id="ejecutando-desde-docker-1">Ejecutando desde Docker</h3> <p>Podemos usar la imagen de Quay.io:</p> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="go">docker run -d \ --net="host" \ --pid="host" \ -v "/:/host:ro,rslave" \ quay.io/prometheus/node-exporter \ --path.rootfs /host </span></code></pre></div></div> <p>Lo más relevante es que del host se expone la raíz, para que Node-Exporter pueda obtener las métricas y usa la propia interfaz de red del nodo, para evitar medir solo la interfaz virtual.</p> <p>Para más información ir a <a href="https://github.com/prometheus/node_exporter">su sitio</a></p> <h3 id="configurando-prometheus">Configurando Prometheus</h3> <p>Node-Exporter por defecto usa el puerto <code class="language-plaintext highlighter-rouge">9100</code> y <code class="language-plaintext highlighter-rouge">/metrics</code> para exportar las métricas, por lo que vamos a la configuración de prometheus <code class="language-plaintext highlighter-rouge">/etc/prometheus/prometheus.yml</code> y agregamos el (o los) nodo(s) que exponen sus métricas por debajo de <code class="language-plaintext highlighter-rouge">scrape_configs</code>:</p> <div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="pi">-</span> <span class="na">job_name</span><span class="pi">:</span> <span class="s1">'</span><span class="s">node_exporter'</span> <span class="na">static_configs</span><span class="pi">:</span> <span class="pi">-</span> <span class="na">targets</span><span class="pi">:</span> <span class="pi">-</span> <span class="s">ip_node_1:9100</span> <span class="pi">-</span> <span class="s">ip_node_2:9100</span> <span class="pi">-</span> <span class="s">ip_node_3:9100</span> <span class="pi">-</span> <span class="s">ip_node_4:9100</span> <span class="na">metrics_path</span><span class="pi">:</span> <span class="s">/metrics</span> </code></pre></div></div> <p>En mi caso lo tengo instalado en cada servidor Proxmox.</p> <h2 id="grafana">Grafana</h2> <p>Ahora toca visualizar todo. Uso Grafana por sus potencialidades y se ha convertido en la plataforma de visualización de facto en mi entorno, <a href="https://raw.githubusercontent.com/rfrail3/grafana-dashboards/master/prometheus/node-exporter-full.json">acá</a> les dejo un <em>dashboard</em> específico para Node-Exporter, con una foto para que vean como queda:</p> <p><img src="https://lfdominguez.github.io/images/posts/prometheus/grafana_1.webp" alt="Grafana" /></p> <p><img src="https://lfdominguez.github.io/images/posts/prometheus/grafana_2.webp" alt="Grafana" /></p> <p><img src="https://lfdominguez.github.io/images/posts/prometheus/grafana_3.webp" alt="Grafana" /></p> Sat, 19 Jan 2019 00:00:00 +0000 https://lfdominguez.github.io//2019/01/19/prometheus.html https://lfdominguez.github.io//2019/01/19/prometheus.html métricas monitoreo linux servidores docker grafana node-exporter Montando_infraestructura_swarm_rancheros <hr /> <p>layout: post title: Montando una infraestuctura Docker Swarm por PXE tags: [docker, swarm, cluster, rancheros, pxe] summary: Explico como monté mi infraestructura con Swarm y arranuqe por PXE. —1</p> Wed, 15 Aug 2018 00:00:00 +0000 https://lfdominguez.github.io//2018/08/15/montando_infraestructura_swarm_rancheros.html https://lfdominguez.github.io//2018/08/15/montando_infraestructura_swarm_rancheros.html Montando devdocs.io en nuestra red (Docker incluido) <h2 id="introducción">Introducción</h2> <p>Cuando vamos a programar un script o algo más grande, necesitamos documentarnos acerca de las bondades que nos ofrece el lenguaje que escogimos para dicha tarea, <a href="https://devdocs.io">devdocs.io</a> es un sitio que reune mucha documentación sobre disímiles tecnologías, agrupadas a veces por versiones. Es una muy buena recopilación, que permite incluso descargarla offline para el almacenamiento del navegador, para que, una vez estemos offline poder consultarla.</p> <p>Lo bueno de este proyecto es que es libre, es decir, que podemos encontrar su código fuente en <a href="https://github.com/freeCodeCamp/devdocs">GitHub</a>. De eso se trataremos, de cómo instalar en nuestra red local este servicio, incluyendo al final como hacerlo si prefieres Docker.</p> <h2 id="instalando-en-debian">Instalando en Debian</h2> <p>Una vez bajado el proyecto</p> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">#</span><span class="w"> </span>apt <span class="nb">install </span>git <span class="gp">#</span><span class="w"> </span>git clone https://github.com/freeCodeCamp/devdocs.git <span class="gp">#</span><span class="w"> </span><span class="nb">cd </span>devdocs </code></pre></div></div> <p>Lo primero que debemos hacer es instalar <code class="language-plaintext highlighter-rouge">ruby</code> y <code class="language-plaintext highlighter-rouge">bundle</code> para gestionar las dependencias del proyecto:</p> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">#</span><span class="w"> </span>apt <span class="nb">install </span>ruby bundle </code></pre></div></div> <p>Ahora procedemos a instalar algunos paquetes adicionales, para que cuando usemos <code class="language-plaintext highlighter-rouge">bundle</code>, que compile nativamente algunas dependencias, no de errores.</p> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">#</span><span class="w"> </span>apt <span class="nb">install </span>build-essential ruby-dev zlib1g-dev nodejs ruby-thor </code></pre></div></div> <p>Ahora obtenemos todas las dependencias necesarias para que funcione el proyecto</p> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">#</span><span class="w"> </span>bundle <span class="nb">install</span> </code></pre></div></div> <p>Ya tenemos la base del proyecto, pero no tenemos ninguna documentación descargada, para eso usaremos <code class="language-plaintext highlighter-rouge">thor</code></p> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">#</span><span class="w"> </span>thor docs:download <span class="nt">--all</span> </code></pre></div></div> <p>Ya el proyecto está listo para ser ejecutado y empezar a brindar el servicio, el comando para arrancar el servidor es</p> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">#</span><span class="w"> </span>rackup <span class="nt">-o</span> 0.0.0.0 <span class="nt">-p</span> 80 <span class="nt">-D</span> </code></pre></div></div> <p>donde <code class="language-plaintext highlighter-rouge">-o</code> indica por que IP escuchará el servidor, definiendo el puerto con <code class="language-plaintext highlighter-rouge">-p</code>. El <code class="language-plaintext highlighter-rouge">-D</code> indica que se ejecute como un demonio.</p> <p>Como generalmente pondermos esto en un servidor aparte (preferiblemente un contenedor), pudieramos modificar directamente <code class="language-plaintext highlighter-rouge">/etc/rc.local</code> para que ejecutara el comando, ejemplo de este fichero sería</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span> <span class="nb">cd</span> /opt/devdocs rackup <span class="nt">-o</span> 0.0.0.0 <span class="nt">-p</span> 80 <span class="nt">-D</span> <span class="nb">cd</span> - <span class="nb">exit </span>0 </code></pre></div></div> <p>Con esto cada vez que se ejecute nuestro servidor, tendremos el servicio de <code class="language-plaintext highlighter-rouge">devdocs.io</code> corriendo.</p> <h2 id="instalando-con-docker">Instalando con Docker</h2> <p>Si eres como yo, que ahora todo lo quiero dockerizar, puesto que he visto muchas ventajas en una infraestructura de contenedores con Docker, devdocs te brinda su Dockerfile para que lo construyas, los pasos son meramente sencillos</p> <p>Instalamos Docker, en los repos de Debian y Ubuntu viene el paquete, en caso de que no uses ninguno de estos, remitete a su documentación para la instalación.</p> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">#</span><span class="w"> </span>apt <span class="nb">install </span>docker.io </code></pre></div></div> <p>Teniendo Docker instalado, procedemos a descargar devdocs de su repositorio y construirlo</p> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">#</span><span class="w"> </span>apt <span class="nb">install </span>git <span class="gp">#</span><span class="w"> </span>git clone https://github.com/freeCodeCamp/devdocs.git <span class="gp">#</span><span class="w"> </span><span class="nb">cd </span>devdocs <span class="go"> </span><span class="gp">#</span><span class="w"> </span>docker build <span class="nt">-t</span> thibaut/devdocs <span class="nb">.</span> </code></pre></div></div> <p>Esperamos que se construya la imágen, de alguna manera hace todo lo que hicimos en el apartado anterior, pero automatizado. Una vez que se haya construido la imagen, solo tenemos que ejecutarlo</p> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">#</span><span class="w"> </span>docker run <span class="nt">--name</span> devdocs <span class="nt">--restart</span> always <span class="nt">-d</span> <span class="nt">-p</span> 9292:9292 thibaut/devdocs </code></pre></div></div> <p>Explicando un poco, sería que corriera un contenedor nombrado con <code class="language-plaintext highlighter-rouge">--name</code>, que se iniciara automáticamente (por <code class="language-plaintext highlighter-rouge">--restart always</code>), que corra como un demonio (<code class="language-plaintext highlighter-rouge">-d</code>) y que el puerto con que se publicará será el 9292 (por la primera parte del par <code class="language-plaintext highlighter-rouge">9292:9292</code>, la segunda parte es del servicio interno).</p> Wed, 15 Aug 2018 00:00:00 +0000 https://lfdominguez.github.io//2018/08/15/montando_devdocs.io_en_nuestra_red.html https://lfdominguez.github.io//2018/08/15/montando_devdocs.io_en_nuestra_red.html docker desarrollo documentación WireGuard, un ejemplo práctico <h2 id="introducción">Introducción</h2> <p>En un <a href="https://lfdominguez.github.io/2018/04/21/wireguard_server.html">artículo anterior</a> comentaba sobre las bondades de WireGuard, así como su instalación y configuración básica. Algunos pudieran ver ese artículo y preguntarse sobre cómo usarlo realmente, no solo basta con saber el cómo, también necesitamos ver el dónde.</p> <p>En este caso explicaré un ejemplo práctico para implementar WireGuard en su red. A grandes rasgos utilizaríamos a WireGuard para proteger todas las comunicaciones entre los clientes (usuarios de la red) y los servidores; además de una instancia adicional de WireGuard que le permitirá al encargado de Seguridad Informática acceder a los sistemas de monitoreo por el mismo canal de los usuarios normales, sin comprometer la seguridad de dichos servicios. Quedaría algo así:</p> <p><img src="https://lfdominguez.github.io/images/posts/wireguard_server/example.png" alt="Escenario" /></p> <p>Como podemos apreciar en la imagen anterior, tendríamos un firewall entre los usuarios de la red y los servidores. Dicho firewall brindaría los servicios de WireGuard a los usuarios, los cuales están conectados por el canal físico hacia éste. Al WireGuard crear interfaces virtuales TUN, el firewall solo permitiría la comunicación hacia los servicios a través de estas interfaces virtuales nuevas (las creadas por WireGuard), denegando toda comunicación restante. De esta manera todo dispositivo que no se encuentre como cliente del WireGuard no podrá consumir de los servicios, ni podrá ver la comunicación, debido a la encriptación brindada por WireGuard.</p> <p>Si se fijan, se evidencia el ejemplo de la utilización de otro canal de WireGuard específico para los especialistas de Seguridad Informática.</p> <h2 id="manos-a-la-obra">Manos a la obra</h2> <p>Primero debemos en nuestro firewall levantar los dos servidores de WireGuard (asumo que hayan leído el <a href="https://lfdominguez.github.io/2018/04/21/wireguard_server.html">artículo anterior</a>), uno para los usuarios normales y otro para el encargado de la Seguridad Informática.</p> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">#</span><span class="w"> </span>Generando las llaves privadas de los servidores <span class="go"> </span><span class="gp">$</span><span class="w"> </span>wg genkey <span class="go">YMbajbQrpvYHgFaMgUSYuwMBa9wnLa4JKG+lWMwrmGY= </span><span class="gp">$</span><span class="w"> </span>wg genkey <span class="go">kHv5yTgIvGzrbwf/VydqDHvEH4//88D/TDF/8i8gxF4= </span></code></pre></div></div> <p>Luego crearíamos con algun editor de texto los ficheros <code class="language-plaintext highlighter-rouge">/etc/wireguard/empresa.conf</code> y <code class="language-plaintext highlighter-rouge">/etc/wireguard/si.conf</code> y copiaremos la siguiente configuración:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># empresa.conf # Definición de la Interfaz [Interface] # Establecer el IP de la interfaz con la máscara de red Address = 172.16.0.1/24 # Puerto UDP de escucha del servidor ListenPort = 51820 # Llave privada generada anteriormente PrivateKey = YMbajbQrpvYHgFaMgUSYuwMBa9wnLa4JKG+lWMwrmGY= # Indica que cada configuración establecida a través de la interfaz de # WireGuard sea salvada en el fichero una vez detenido el servidor SaveConfig = false </code></pre></div></div> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># si.conf # Definición de la Interfaz [Interface] # Establecer el IP de la interfaz con la máscara de red Address = 172.16.1.1/24 # Puerto UDP de escucha del servidor ListenPort = 51821 # Llave privada generada anteriormente PrivateKey = kHv5yTgIvGzrbwf/VydqDHvEH4//88D/TDF/8i8gxF4= # Indica que cada configuración establecida a través de la interfaz de # WireGuard sea salvada en el fichero una vez detenido el servidor SaveConfig = false </code></pre></div></div> <p>Ahora que tenemos las configuraciones solo falta habilitar y arrancar los servidores de WireGuard (para eso utilizaremos la ayuda de <code class="language-plaintext highlighter-rouge">systemd</code> y <code class="language-plaintext highlighter-rouge">wg-quick</code>):</p> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">#</span><span class="w"> </span>empresa.conf <span class="gp">$</span><span class="w"> </span>systemctl <span class="nb">enable </span>wg-quick@empresa <span class="gp">$</span><span class="w"> </span>systemctl start wg-quick@empresa <span class="go"> </span><span class="gp">#</span><span class="w"> </span>si.conf <span class="gp">$</span><span class="w"> </span>systemctl <span class="nb">enable </span>wg-quick@si <span class="gp">$</span><span class="w"> </span>systemctl start wg-quick@si </code></pre></div></div> <p>Podemos asegurarnos de que todo está correcto verificando que se hayan creado 2 interfaces nuevas con el nombre del fichero de configuración, ejemplo:</p> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>ip a <span class="c">... </span><span class="gp">5: empresa: &lt;POINTOPOINT,NOARP,UP,LOWER_UP&gt;</span><span class="w"> </span>mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000 <span class="go"> link/none inet 172.16.0.1/24 scope global empresa valid_lft forever preferred_lft forever </span><span class="gp">6: si: &lt;POINTOPOINT,NOARP,UP,LOWER_UP&gt;</span><span class="w"> </span>mtu 1340 qdisc noqueue state UNKNOWN group default qlen 1000 <span class="go"> link/none inet 172.16.1.1/24 scope global si valid_lft forever preferred_lft forever </span><span class="c">... </span></code></pre></div></div> <p>Ya con esto tenemos los servidores de WireGuard listos, solo falta agregar los clientes.</p> <h2 id="agregando-clientes">Agregando clientes</h2> <p>Cada cliente que se requiera conectar al servidor tiene que tener su entrada correspondiente en el fichero de configuración de dicho servidor WireGuard; para ello se necesita un par de llaves pública y privada, donde la privada la tiene el cliente y el servidor solo necesita definir la pública dentro de su configuración. En este caso existen 2 variantes:</p> <ul> <li>Generar el par de llaves en cada cliente y copiar la pública en el servidor.</li> <li>Generar el par de llaves de cada cliente en el propio servidor.</li> </ul> <p>La diferencia entre ellas es el nivel de seguridad (y paranoia) que queremos, puesto que lo más seguro es generarlo en cada cliente por separado para aumentar el principio de incertidumbre en la generación de comportamientos aleatorios de la generación de las llaves. Pero es mucho más cómodo realizarlo en el propio servidor, por lo que es a gusto del lector como lo desea hacer.</p> <blockquote> <h3 id="en-debian">En Debian</h3> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">#</span><span class="w"> </span>Se genera la privada <span class="gp">$</span><span class="w"> </span>wg genkey <span class="go">YKB7m15Art0Y9jcAYr/9DX6mr6cr28uUzABI7Q1TwH0= </span><span class="gp">#</span><span class="w"> </span>Se genera la pública a partir de la privada <span class="gp">$</span><span class="w"> </span><span class="nb">echo</span> <span class="nt">-n</span> <span class="s2">"YKB7m15Art0Y9jcAYr/9DX6mr6cr28uUzABI7Q1TwH0="</span> | wg pubkey </code></pre></div> </div> </blockquote> <blockquote> <h3 id="en-windows">En Windows</h3> <p>Utilizando el cliente TunSafe</p> <p><img src="https://lfdominguez.github.io//images/posts/wireguard_server/tunsafe_options_button_select.png" alt="Opciones" /></p> <p><img src="https://lfdominguez.github.io//images/posts/wireguard_server/tunsafe_option_generate_key_pair_select.png" alt="Menú de Opciones" /></p> <p><img src="https://lfdominguez.github.io//images/posts/wireguard_server/tunsafe_option_generate_key_pair.png" alt="Generación de llaves" /></p> </blockquote> <p>Una vez que se tenga el par de llaves, se toma la pública y agregamos el siguiente fragmento a la configuración correspondiente, por ejemplo en <code class="language-plaintext highlighter-rouge">/etc/wireguard/empresa.conf</code>:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># empresa.conf # Por cada cliente se establece una sección como esta [Peer] # Llave pública del cliente PublicKey = JP55vfgoBIRbXuasBD0Gn5L6mb8KsVwdZiOfdi/cfCs= # IPs (con máscara) que puede tener el cliente que se conecte con esta llave, # pudiera usarse por ejemplo para un cliente que se conecte por 2 VPN AllowedIPs = 172.16.0.2/32 </code></pre></div></div> <p>Una vez agregados los clientes, procedemos y reiniciamos el servidor correspondiente:</p> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>systemctl restart wg-quick@empresa <span class="go"> </span></code></pre></div></div> <blockquote> <p>WireGuard soporta la configuración directa en cuanto está levantado el servidor, incluso agregar nuevos clientes y que se escriba en el fichero de configuración una vez terminado el proceso, éste método no lo explico por ser un poco más complicado; además en mi opinión le veo un defecto y es que si tenemos un reinicio inesperado, toda la configuración “en caliente” que hayamos hecho se habrá perdido.</p> </blockquote> <h2 id="configurando-los-clientes">Configurando los clientes</h2> <h3 id="debian">Debian</h3> <p>Para configurar el cliente en Debian el procedimiento es parecido al servidor (explicado igualmente en el artículo anterior sobre WireGuard), solo basta con agregar un fichero de configuración en <code class="language-plaintext highlighter-rouge">/etc/wireguard/empresa.conf</code> con el siguiente contenido:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Definición de la Interfaz [Interface] # IP del cliente que tiene que coincidir con el permitido en el servidor # para este cliente Address = 172.16.0.2/32 # Llave privada generada PrivateKey = YKB7m15Art0Y9jcAYr/9DX6mr6cr28uUzABI7Q1TwH0= # Si queremos establecer un DNS DNS = 172.16.0.1 # Definición del servidor al cual conectarse [Peer] # Se define la llave pública de dicho servidor PublicKey = YMbajbQrpvYHgFaMgUSYuwMBa9wnLa4JKG+lWMwrmGY= # En este apartado se define los IPs que enrutarán por esta interfaz, # como se puede ver en este caso son todas, es decir, sería la puerta # de enlace por defecto, todas las conecciones externas se enrutan hacia # el servidor de WireGuard AllowedIPs = 0.0.0.0/0 # Dirección del servidor de WireGuard Endpoint = 10.0.0.1:51820 # Esto define un intervalo en segundos que WireGuard envía un paquete # nulo para "mantener viva" la conección. Esto es útil en casos de NAT # para que el firewall mantenga el mismo IP asociado a la conección. # Comento por defecto debido a que en nuestro caso no es NAT # PersistentKeepalive = 25 </code></pre></div></div> <p>Arrancamos el cliente de la misma manera que el servidor:</p> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>systemctl <span class="nb">enable </span>wg-quick@empresa <span class="gp">$</span><span class="w"> </span>systemctl start wg-quick@empresa </code></pre></div></div> <h3 id="windows">Windows</h3> <p>En este caso utilizaremos el cliente <a href="https://tunsafe.com/download">TurnSafe</a></p> <p><img src="https://lfdominguez.github.io//images/posts/wireguard_server/tunsafe_edit_config_button_select.png" alt="Opción de configurar" /></p> <p>Se abre el editor por defecto para configurar el cliente (o servidor) de WireGuard</p> <p><img src="https://lfdominguez.github.io//images/posts/wireguard_server/tunsafe_notepad_config_edit.png" alt="Editor de la configuración" /></p> <p>Como pueden observar la configuración es idéntica a la de Debian.</p> <p>Solo queda por último las reglas de firewall para el correcto enrutado de los paquetes que vienen solo por las interfaces virtuales, pero este proceso queda fuera del ejemplo debido a la gran variedad de vías por la cual hacerlo.</p> Thu, 24 May 2018 00:00:00 +0000 https://lfdominguez.github.io//2018/05/24/wireguard_ejemplo_practico.html https://lfdominguez.github.io//2018/05/24/wireguard_ejemplo_practico.html vpn wireguard linux seguridad Usando el cliente de OpenVPN a través de un proxy <blockquote> <p><strong>Disclaimer</strong>: Solo para uso educacional, no me hago responsable por el uso que se le de al presente manual.</p> </blockquote> <h2 id="introducción">Introducción</h2> <p>En esta ocasión no explicaré como se instala, configura y despliega un servidor de OpenVPN, pues eso es para otro post, o de alguien más. En este caso mostraré como usar el cliente de OpenVPN cuando nos encontramos detrás de un proxy (la mayoría de los sysadmin que conozco).</p> <p>A veces como sysadmin nos encontramos con la necesidad de acceder a un servicio, por ejemplo el de actualizar las llaves públicas de nuestro sistema con GPG, que necesita hacer uso de algunos puertos bloqueados por nuestro proxy (varios en muchos casos) padre; o que tengamos que clonar un repositorio GIT con el último parche de algun servicio crítico de nuestra red (y los desarrolladores solo lo brinden por protocolo GIT, no HTTP o HTTPs). Son muchos los casos en que por la propia seguridad y actualización de sistemas debemos acceder por puertos diferentes al 80 o 443 y aquí es donde nos enfrentamos a los proxy padre muy restrictivos.</p> <p>Me centraré en el cliente para Debian, pues es la distribución de Linux que utilizo; pero para los demás sistemas operativos es análogo, pues el fichero de configuración es común.</p> <h2 id="diferencia-entre-proxy-http-y-socks">Diferencia entre proxy HTTP y SOCKS</h2> <p>Seguro han visto esta diferenciación en alguna que otra configuración de los programas a la hora de definir el proxy, pues estos 2 tipos de proxy son muy diferentes:</p> <h3 id="proxy-http">Proxy HTTP</h3> <p>Este tipo como su nombre lo indica, es pensado para la navegación web, pues en realidad lo que se hace es enviar la solicitud de la página a navegar (o acceder) al servidor proxy y éste es quien realiza la petición, cacheando o no la respuesta, para luego retornarla al cliente.</p> <h3 id="proxy-socks">Proxy SOCKS</h3> <p>Este tipo de proxy es más directo, en el sentido que, como su nombre lo indica, conecta directamente el cliente con el servidor, sirviendo simplemente de pasarela, es ampliamente utilizado para simular una conección directa. Por ejemplo, la aplicación <code class="language-plaintext highlighter-rouge">TOR</code> es un proxy SOCKS.</p> <p>Este es de los proxy que menos se instalan en la infraestructura, puesto que el otro tipo (HTTP) es más enfocado a la navegación.</p> <h3 id="caso-https">Caso HTTPS</h3> <p>En el caso del protocolo HTTPS (generalmente puerto TCP 443), un proxy SOCKS no tiene problemas, puesto que comunica directamente los dos nodos (como se definía anteriormente); pero un proxy HTTP, al hacer de puente, no pudiera en teoría funcionar, puesto que tendría que recibir las peticiones para poder resolverlas, caso en que el HTTPS por ser un protocolo cifrado entre el servidor remoto y el cliente no lo permitiría sin un ataque de MITM.</p> <p>Para este caso los proxy HTTP (y los navegadores o programas clientes) utilizan un método llamado <strong>CONNECT</strong> que no es más que pedirle una comunicación directa (tipo SOCKS) entre los 2 nodos. Una vez establecida la comunicación, es un enlace directo entre el cliente y el servidor, por lo que todo lo que se transmite entre los extremos es cifrado y ajeno al proxy.</p> <h2 id="manos-a-la-obra">Manos a la obra</h2> <p>Para que OpenVPN se pueda comunicar a través de un proxy HTTP, éste debe permitir el método <strong>CONNECT</strong>, por lo que debemos tener un servidor remoto que esté escuchando por un puerto por el cuál el proxy permita la comunicación directa (como el TCP 443).</p> <p>Hay muchos sitios en Internet que muestran listas de servidores de OpenVPN libres, como</p> <ul> <li><a href="https://www.bestvpnserver.com/list-of-top-free-openvpn-servers/">Lista 1</a></li> <li><a href="http://www.vpngate.net/en/">Lista 2</a></li> </ul> <p>solo bastaría descargar su fichero de configuración y debajo de <code class="language-plaintext highlighter-rouge">remote vpn_hostname 443 tcp</code> adicionarle:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http-proxy 1.2.3.4 8080 http-proxy-retry </code></pre></div></div> <p>en caso de necesidad de autenticación:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http-proxy 1.2.3.4 8080 auto &lt;http-proxy-user-pass&gt; username password &lt;/http-proxy-user-pass&gt; http-proxy-retry </code></pre></div></div> <p>De esta manera solo quedaría ejecutar nuestro cliente OpenVPN con la configuración</p> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>openvpn config.ovpn </code></pre></div></div> Wed, 25 Apr 2018 00:00:00 +0000 https://lfdominguez.github.io//2018/04/25/cliente_openvpn_proxy.html https://lfdominguez.github.io//2018/04/25/cliente_openvpn_proxy.html vpn openvpn linux seguridad proxy Asegurando nuestras comunicaciones con WireGuard <h2 id="introducción">Introducción</h2> <p>En muchos casos como SysAdmins debemos o queremos mantener comunicación con algún servidor desde un punto donde el canal de comunicación puede ser revisado (con sniffers) por otras personas o sistemas. Algunos ejemplos serían:</p> <ul> <li>Administrar nuestros servidores desde Internet.</li> <li>Darle acceso a usuarios a servicios sobre un canal inseguro.</li> <li>Brindar seguridad ante sniffer en un canal independientemente de la seguridad de los servicios que brinde.</li> <li>Queremos darle acceso a algún servicio de monitoreo al encargado de Seguridad que se encuentra fuera de la red de administración.</li> <li>Entre otros…</li> </ul> <p>Una de las soluciones que se presenta para este tipo de problema son las VPN (Virtual Private Network), que permiten crear una red dentro de otra y generalmente cifrada, por lo que los datos que se transmiten se ocultan a los ojos de los interesados, no importa que sean a servicios no seguros, pues se comunican a través del túnel creado por este servicio.</p> <p>En la actualidad hay 2 herramientas que son ampliamente para este menester:</p> <ul> <li>IPSec</li> <li>OpenVPN</li> </ul> <p>Ambos son muy buenos en esa tarea y gozan de un gran soporte por todos los equipamientos de red (IPSec más al ser el estándar de facto en muchos routers, como los de CISCO o HUAWEI). El problema a veces con éstos es que su instalación, configuración y puesta en marcha puede resultar un poco tediosa.</p> <p>Hoy vengo con una propuesta que está ganando mucho terreno a pesar de ser un producto en desarrollo, pero que muchos le han puesto el ojo, es <a href="https://www.wireguard.com">WireGuard</a> y supone una ventaja con respecto a los anteriores por:</p> <ul> <li>Extremadamente fácil en su instalación y despliegue, ellos indican que <em>“(…) aims to be easy to configure and deploy as SSH (…)”</em>.</li> <li>Usan criptografía <em>state-of-the-art</em> que no es más que la utilización de los algoritmos más modernos de éstos menesteres.</li> <li>Al igual que IPSec es compilado como módulo del kernel a través de DKMS. Lo que logra un rendimiento mucho mayor que OpenVPN (pues este es <em>user-space</em>).</li> <li>Usa los algoritmos de cifrado <em>Noise Protocol Framework, Curve25519, ChaCha20, Poly1305, BLAKE2, SipHash24, HKDF</em>.</li> <li>Se ha implementado teniendo en cuenta menor cantidad de código, lo que permite una mejor auditoría de código y una menor área de ataque. Está pensado para que una persona pueda auditar todo el código sin complicaciones.</li> <li>Entre otras ….</li> </ul> <p>WireGuard por ahora no soporta la asignación dinámica de IP, por lo que cada cliente que tengamos se le debe establecer el ip en su configuración. Además que WireGuard no permite la comunicación de un cliente que no tenga el IP especificado en su fichero de configuración.</p> <p>Algunas gráficas sobre el rendimiento de WireGuard con respecto a IPSec y OpenVPN pueden verse en <a href="https://www.wireguard.com/performance/">Performance of WireGuard</a></p> <h2 id="instalación">Instalación</h2> <p>Me voy a centrar en la instalación sobre Debian, pues es lo que uso en mis servidores gg. Debido a que WireGuard es un proyecto en desarrollo, encontrarás los paquetes de su instalación en el repositorio de <em>sid</em> que es el repositorio “intestable”:</p> <ul> <li><a href="https://packages.debian.org/sid/wireguard-dkms">wireguard-dkms</a></li> <li><a href="https://packages.debian.org/sid/wireguard-tools">wireguard-tools</a></li> </ul> <p>Luego de haber bajado los paquetes <em>.deb</em> solo debemos instalarlos, además de los <em>headers</em> del kernel para la compilación de los módulos del kernel, por ej:</p> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">#</span><span class="w"> </span>apt <span class="nb">install </span>dkms <span class="gp">#</span><span class="w"> </span>dpkg <span class="nt">-i</span> wireguard-dkms.deb wireguard-tools.deb </code></pre></div></div> <p>Luego de haberse instalado, el módulo se compila y se integra al kernel actual. Ahora sólo basta configurarlo e iniciar el servidor.</p> <h2 id="configuración-y-despliegue">Configuración y despliegue</h2> <p>Hay 2 vías por donde configurar WireGuard, una manual y otra a través de ficheros de configuración que utilizaría la utilidad <code class="language-plaintext highlighter-rouge">wg-quick</code> para levantarla. La última es la que utilizaré en este manual por ser la más rápida y cómoda.</p> <p>Lo primero que debemos hacer es generar una llave privada del servidor</p> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">#</span><span class="w"> </span>wg genkey <span class="go">iBAnhqypjo6detnodQiHUEL/Wzg/OO5e4IXef6TOnGw= </span></code></pre></div></div> <p>Esa sería la llave privada del servidor, una duda que me surgió en su momento fue acerca del por qué una llave privada tan pequeña con respecto a las que utilizaba en OpenVPN y en las investigaciones y correos de la lista, esto es debido a que los algoritmos de cifrado que utilizan que es ECC (Elliptic Curve Cryptography) utilizan menos bits para llegar a la misma complejidad criptográfica que RSA a un nivel superior de bits. Una tabla descriptiva sería:</p> <p><img src="/images/posts/wireguard_server/key-size-comparison.jpg" alt="ECC comparación con RSA" /></p> <p>En WireGuard no se define el tamaño de la llave, puesto que WireGuard define ese tamaño para evitar una mala configuración por parte del usuario. WireGuard se asegura que el tamaño de la llave sea lo suficientemente segura para evitar un ataque en intento de descifrar la llave privada desde la pública.</p> <p>Los ficheros de configuración residen en <code class="language-plaintext highlighter-rouge">/etc/wireguard/</code> por lo que crearemos nuestro fichero de configuración con el nombre de la interfaz virtual que queremos que tenga, en nuestro ejemplo será <code class="language-plaintext highlighter-rouge">empresa.conf</code></p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Definición de la Interfaz [Interface] # Establecer el IP de la interfaz con la máscara de red Address = 172.16.0.1/24 # Puerto UDP de escucha del servidor ListenPort = 51820 # Llave privada generada anteriormente PrivateKey = iBAnhqypjo6detnodQiHUEL/Wzg/OO5e4IXef6TOnGw= # Indica que cada configuración establecida a través de la interfaz de # WireGuard sea salvada en el fichero una vez detenido el servidor SaveConfig = false # Por cada cliente se establece una sección como esta [Peer] # Llave pública del cliente PublicKey = R2G89C5dpuEOrU9IEzVuuoP3liQzsdnsUyY+cQ+IZQQ= # IPs (con máscara) que puede tener el cliente que se conecte con esta llave, # pudiera usarse por ejemplo para un cliente que se conecte por 2 VPN AllowedIPs = 172.16.0.2/32 </code></pre></div></div> <p>Ahora apoyándonos en <code class="language-plaintext highlighter-rouge">systemd</code> y <code class="language-plaintext highlighter-rouge">wg-quick</code> podemos habilitar el servidor e iniciarlo:</p> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">#</span><span class="w"> </span>systemctl <span class="nb">enable </span>wg-quick@empresa <span class="gp">#</span><span class="w"> </span>systemctl start wg-quick@empresa </code></pre></div></div> <p>Podemos ver que se ha creado la interfaz con:</p> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">#</span><span class="w"> </span>ip a <span class="c">... </span><span class="gp">12: empresa: &lt;POINTOPOINT,NOARP,UP,LOWER_UP&gt;</span><span class="w"> </span>mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000 <span class="go"> link/none inet 10.11.2.1/24 scope global empresa valid_lft forever preferred_lft forever </span><span class="c">... </span></code></pre></div></div> <p>O mejor aun para ver todas las interfaces de WireGuard con sus clientes:</p> <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">#</span><span class="w"> </span>wg <span class="go">interface: empresa public key: teRk63YIGMHoaDCxS6xxwRd91oek2e378a+X6zunTy8= private key: (hidden) listening port: 51820 peer: R2G89C5dpuEOrU9IEzVuuoP3liQzsdnsUyY+cQ+IZQQ= allowed ips: 172.16.0.2/32 </span></code></pre></div></div> <p>Ahora vamos a configurar a un cliente. Importante decir que WireGuard por ahora no tiene soporte en algo que no sea Linux (la implementación oficial) o <a href="https://tunsafe.com/download">Windows</a> (por un port en user-space). Esto es debido a que para otras plataformas habría que implementar el driver en el <em>kernel-space</em> por el rendimiento superior, <a href="https://www.wireguard.com/xplatform/">ver más</a>.</p> <p>Para configurar un cliente en Debian, instalamos los mismos paquetes y creamos un fichero de configuración en el mismo lugar:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Definición de la Interfaz [Interface] # IP de cliente que tiene que coincidir con el permitido en el servidor Address = 172.16.0.2/32 # Llave privada generada al igual que la del servidor con 'wg genkey' PrivateKey = 2EHAW9zRKq8OH9Nq7ljF+QiIXPF3WlIs4mF6PFj6In4= # Si queremos establecer un DNS DNS = 172.16.0.1 # Definición del servidor al cual conectarse [Peer] # Se define la llave pública de dicho servidor PublicKey = teRk63YIGMHoaDCxS6xxwRd91oek2e378a+X6zunTy8= # En este apartado se define los IPs que enrutarán por esta interfaz, # como se puede ver en este caso son todas, es decir, sería la puerta # de enlace por defecto AllowedIPs = 0.0.0.0/0 # Dirección del servidor de WireGuard Endpoint = 10.0.0.1:51820 # Esto define un intervalo en segundos que WireGuard envía un paquete # nulo para "mantener viva" la conección. Esto es útil en casos de NAT # para que el firewall mantenga el mismo IP asociado a la conección. PersistentKeepalive = 25 </code></pre></div></div> <p>y el procedimiento es el mismo que para el servidor. Ya con esto tenemos un buen servidor de VPN, como pueden observar, el procedimiento es extremadamente sencillo comparado con las otras 2 propuestas.</p> Sat, 21 Apr 2018 00:00:00 +0000 https://lfdominguez.github.io//2018/04/21/wireguard_server.html https://lfdominguez.github.io//2018/04/21/wireguard_server.html vpn wireguard linux seguridad IP & ARP spoofing <blockquote> <p><strong>Disclaimer</strong>: This is for educational use only.</p> </blockquote> <h2 id="introduction">Introduction</h2> <p>In the post <em><a href="https://lfdominguez.github.io//2015/04/20/arp_spoofing.html">ARP Spofing</a></em> i was spoke about the ARP spoofing and how use it to get the network packages sended to another PC. In this post now, i will speak about the same thing, but with the IP, in others words, how to change the source IP of a package.</p> <h2 id="ip-spoofing">IP Spoofing</h2> <p>Into the IP layer of network, as is explained into this image</p> <p><img src="https://lfdominguez.github.io//images/posts/ip_and_arp_spoofing/ip_layer.gif" alt="IP package description" /></p> <p>Here, will can see the <code class="language-plaintext highlighter-rouge">Source Address</code> field, so when a network packet (by default ;)) leave our computer, the operating system set the ip address of the output interface into that field, that is because the remote computer need response to us.</p> <p>So, for example, we use <strong>cntlm</strong> proxy program with the gateway option filter by IP, the configuration</p> <figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1 2 3 4 5 </pre></td><td class="code"><pre><span class="s">Gateway yes</span> <span class="s">Allow 127.0.0.1</span> <span class="s">Allow 192.168.12.3</span> <span class="s">Deny 0/0</span> </pre></td></tr></tbody></table></code></pre></figure> <p>In this example, there are 2 ips allowed to enter <code class="language-plaintext highlighter-rouge">127.0.0.1</code> for local purpose and <code class="language-plaintext highlighter-rouge">192.168.12.3</code>, for example for our cellphone or another PC. Now, the atacker PC has the IP <code class="language-plaintext highlighter-rouge">192.168.12.4</code> and sniffing the network (in another post i will take about this 8)) detect what IP has access to that proxy. Our pc (has <strong>cntlm</strong>) use the IP <code class="language-plaintext highlighter-rouge">192.168.12.1</code>.</p> <p>Now, an atacker can do this with <strong>iptables</strong> that is the standard firewall of linux and can manipulate the network packets:</p> <figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1 </pre></td><td class="code"><pre>iptables <span class="nt">-t</span> nat <span class="nt">-A</span> POSTROUTING <span class="nt">-p</span> tcp <span class="nt">--destination-port</span> 3128 <span class="nt">-d</span> 192.168.12.1 <span class="nt">-j</span> SNAT <span class="nt">--to-source</span> 192.168.12.3 </pre></td></tr></tbody></table></code></pre></figure> <p>Explaining:</p> <ul> <li><code class="language-plaintext highlighter-rouge">-t nat</code> Use the table nat of iptables, this is the table of routing.</li> <li><code class="language-plaintext highlighter-rouge">-A POSTROUTING</code> Apply this rule to that packets that’s are already routed.</li> <li><code class="language-plaintext highlighter-rouge">-p tcp</code> Use TCP protocol.</li> <li><code class="language-plaintext highlighter-rouge">--destination-port 3128</code> The port of the proxy.</li> <li><code class="language-plaintext highlighter-rouge">-d 192.168.12.1</code> Apply this rule to the packets that’s go to that ip <code class="language-plaintext highlighter-rouge">192.168.12.1</code>, if not, all the packets that will exit from our pc will change the source IP.</li> <li><code class="language-plaintext highlighter-rouge">-j SNAT</code> This is the acction to apply, in this case, change the source of the packet.</li> <li><code class="language-plaintext highlighter-rouge">--to-source 192.168.12.3</code> No comments :).</li> </ul> <p>Ok, with this line all the packets change their source IP, but… when the remote PC respond to that request, the packet is send to that spoofed IP <code class="language-plaintext highlighter-rouge">192.168.12.3</code>, so how catch the packet? Here is when is needed read the post <em><a href="https://lfdominguez.github.io//2015/04/20/arp_spoofing.html">ARP Spofing</a></em> to known how <em>tell</em> to the PC objetive <code class="language-plaintext highlighter-rouge">192.168.12.1</code> that send the packets to <code class="language-plaintext highlighter-rouge">192.168.12.3</code> to our PC, in a short example (<strong>arpspoof</strong> we can found into the distribution repository, i use Debian -<em>testing</em>-):</p> <figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1 </pre></td><td class="code"><pre>arpspoof <span class="nt">-i</span> eth0 <span class="nt">-t</span> 192.168.12.1 192.168.12.3 </pre></td></tr></tbody></table></code></pre></figure> <p>Explaining:</p> <ul> <li><code class="language-plaintext highlighter-rouge">-i eth0</code> This is the network interface (can be wlan0, mon0, eth1, etc).</li> <li><code class="language-plaintext highlighter-rouge">-t 192.168.12.1</code> This is the tarjet machine, the PC that will be apply the arp spoofing.</li> <li><code class="language-plaintext highlighter-rouge">192.168.12.13</code> This is the address that will be spoofed.</li> </ul> <p>Well and that’s all, with this all the communication is around the attacker PC and the attacked PC, even when the real IP <code class="language-plaintext highlighter-rouge">192.168.12.3</code> exists or not.</p> Sun, 15 Nov 2015 00:00:00 +0000 https://lfdominguez.github.io//2015/11/15/ip_and_arp_spoofing.html https://lfdominguez.github.io//2015/11/15/ip_and_arp_spoofing.html ip arp spoofing network security ARP Spoofing <h2 id="introducción">Introducción</h2> <p>Hoy en día el uso de las tecnología ha tenido un auge importantísimo en el día a día nuestro, automatizándonos y por ende facilitándonos la mayoría de las recurrentes tareas que realizamos. En nuestro país cada vez más se ve inundada por nuevos elementos, ya sean de software como de hardware y vamos sin querer haciendo a un lado un aspecto muy importante dentro de ellos… la seguridad. Hoy la mayoría de nosotros subvaloramos la seguridad que determinado dispositivo debe tener, por lo que no nos preocupamos mucho de esto y por tanto dejamos siempre todas las configuraciones por defecto de como viene, ejemplo? instalamos un servidor de base de datos y no cambiamos la contraseña maestra, instalamos un <em>router</em> inalámbrico en la casa y no lo configuramos con una contraseña ni con filtro para permitir que solo el dueño sea el que lo administre, entre otros elementos.</p> <p>En este blog comentaré acerca de todo tipo de elementos de la tecnología, en este caso comentaré acerca de algunos elementos de seguridad, principalmente hablaré acerca de una técnica utilizada para <em>“mirar”</em> (analizar en buenos términos) toda la información que circula entre dos dispositivos. Aclaro que lo que aquí expreso, aunque nunca diré explícitamente como se realizan estos ataques, es solo para que las personas tengan el conocimiento de cómo funciona y por ende como protegerse de estas técnicas, no me responsabilizo de la falta de seguridad de sistemas donde estos ataques puedan ser cometidos por los conocimientos aquí adquiridos.</p> <h2 id="arp-spoof">ARP Spoof</h2> <p>Nombrando el ataque que hoy comentaré, se trata del <em>“ARP Spoof”</em> o envenenamiento por ARP, existen disímiles técnicas de “envenenamiento”, como DHCP, ICMP, DNS, etc. Primeramente decir que ARP (Protocolo de resolución de nombres o <em>Address Resolution Protocol</em>) es un protocolo encargado de buscar en la red la correspondencia de una dirección de hadware (las famosas MAC) con respecto a su dirección IP. Para un ejemplo más práctico hagamos un “ping” a un ip cualquiera, en este ejemplo al 192.168.0.15:</p> <figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1 </pre></td><td class="code"><pre>ping 192.168.0.15 </pre></td></tr></tbody></table></code></pre></figure> <p>que es lo que sucede a manera de resumen y teniendo en cuenta el ARP (evitando muchos elementos que trabajan en su conjunto). Los sistemas operativos que conozco (Microsoft(R) Windows(TM), Apple(R) MacOS(R) o GNU/Linux) cuentan, para un óptimo trabajo con los paquetes ARP, con una tabla interna que relaciona los IP con las MAC, de esta manera no tienen que buscar una MAC si ya las tienen. Bien, volviendo al comando “ping”, el paquete de ICMP (el paquete que se envía realmente con el “ping”) no se direcciona por el IP, sino por la MAC de destino, y como se conoce esa MAC? aquí es donde entra el ARP, si el SO (Sistema Operativo) no contiene esa relación dentro de su “tabla arp” (la cual se puede ver con “arp -a”) entonces envía al broadcast (toda la red) un paquete ARP especial que contiene el IP que requiere, cuando ese paquete llega a la PC directamente o través de varios routers, este responde con su dirección de MAC con un paquete de respuesta de ARP. Cuando éste último arriba a la PC entonces el SO ubica una nueva entrada en la tabla arp y comienza a comunicarse directamente con esa MAC. No es solamente el comando “ping” el que realiza esta tarea, sino todos los programas que requieran del protocolo IP para su comunicación, de hecho la mayoría de ellos. Bien una vez que la PC tiene la MAC correspondiente a una PC remota, cada vez que se requiera comunicar con ella, no realiza todo el proceso de pedido de MAC a través de su IP, sino que consulta en su tabla arp y se comunica directamente; claro, cada cierto tiempo se vuelve a pedir la MAC, para casos de cambios de IP, etc. Ahora, hablando más concretamente del ataque de “ARP Spoof”, supongamos que tenemos el siguiente escenario:</p> <p><img src="https://lfdominguez.github.io//images/posts/arp_spoofing/escenario.png" alt="Escenario" /></p> <p>Una PC que se conecta a un servidor utilizando para utilizar un servicio determinado, dígase XMPP (Jabber, chat), HTTP, IMAP (Correo), POP3 (Correo), etc. Además existe una persona (Atacante), la cual, en este caso se encuentra en la misma red que usted y quiere espiar dicha conexión entre el servidor y el cliente. Aquí también hay que dar un ligero detalle acerca del dispositivo que contiene todas las conexiones, ya sea un “Switch” o un HUB, la principal diferencia entre estos es que el “Switch” es orientado a conexiones directas, es decir lo que envíe una PC hacia otra, solo se transmite por los puertos requeridos para dicha conexión, mientras que el HUB lo replica todo; existen muchas diferencias adicionales, pero no es objetivo de este post. Para nuestro caso, estamos en una red interna administrada por un “switch”, por lo que los paquetes entre el cliente y el servidor no llegan a nuestra PC. Adentrándonos en el ataque como tal, consiste en que el atacante envía un paquete de respuesta ARP hacia ambas direcciones, dígase el cliente y el servidor, informando acerca de una nueva dirección MAC para un IP determinado (en caso del cliente, informando que el IP del servidor tiene otra MAC y para el caso del servidor que el IP del cliente se encuentra en otra MAC), dicha MAC nueva corresponde a la dirección física del atacante, estos paquetes se mantienen emitiendo desde la PC del atacante por intervalos de tiempos cortos, para de una manera forzar al SO de que cambie su tabla arp. Habiendo logrado esto, el escenario se transformaría de la siguiente forma:</p> <p><img src="/images/posts/arp_spoofing/escenario_arp.png" alt="Escenario ARP" /></p> <p>En este caso quedaría que a manera de ver del cliente se está comunicando correctamente con el IP del servidor, igualmente para el servidor con el IP del cliente, pero a nivel de paquetes, toda la comunicación se realiza a través del equipo del atacante. Esto puede volcarse en disímiles sub-ataques, díganse denegación de servicio (DoS), extración de usuarios y contraseñas, suplantación de sitios Web, etc. Mostraré a través de capturas de pantalla lo que sucede en el ataque, un ejemplo antes de aplicar el ataque y luego de realizarlo, en este caso el cliente es una PC Virtual y el servidor es la puerta de enlace, el atacante, yo.</p> <p><img src="https://lfdominguez.github.io//images/posts/arp_spoofing/antes_ataque.png" alt="Antes del ataque" /></p> <p>Aquí se evidencia viendo la tabla arp en el cliente cual es la dirección de .254, la puerta de enlace en este caso, el ip del atacante es el .168 el cual tiene un mac determinado. A la hora de realizar el ataque quedaría:</p> <p><img src="https://lfdominguez.github.io//images/posts/arp_spoofing/despues_ataque.png" alt="Despues del ataque" /></p> <p>Ahora podemos observar como en la tabla de arp la mac de la puerta de enlace (.254) es igual a la del atacante (.168).</p> <p>Ahora bien, ya se entiende como funciona dicho ataque, como protegernos es lo importante. Bien, la manera más eficaz de determinar cuando nos encontramos ante un ataque de este tipo es verificar nuestra tabla arp utilizando los comandos definidos por el SO:</p> <figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1 </pre></td><td class="code"><pre>arp <span class="nt">-a</span> </pre></td></tr></tbody></table></code></pre></figure> <p>de esta manera revisaremos de forma manual en cuanto a que todas las MAC de las PCs deben ser diferentes, prestando principal atención cuando nos encontramos en redes que cuentan con puertas de enlace a que su MAC se encuentre “clonada” por otra PC. Existen herramientas para automatizar dichos procesos, como lo son los Firewalls, además de otros especializados en este campo, como “arpwatch”, “arpalert”, etc.</p> <p>De manera general las maneras de defendernos serían:</p> <ol> <li>Establecer de una manera determinada por el SO o por el dispositivo hardware las tablas ARP de manera manual y eliminar la posibilidad de que se actualicen automáticamente, así se evitan los paquetes autogenerados por el atacante para confundir las tablas ARP. La desventaja de este método es que para redes medianamente grandes es una ardua tarea, pues se tendría que configurar todos los puntos de red para cada actualización de IP nueva, o la inclusión de nuevos dispositivos.</li> <li>En cuanto a GNU/Linux se puede utilizar una opción del kernel que impide que sean aceptadas los pedidos de ARP “gratuitos”, es decir que lleguen respuestas de paquetes ARP si haberlo solicitado. Importante aclarar que esta opción por defecto viene activada, pero para comprobación de los lectores pueden verlo con el comando en la consola:</li> </ol> <figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1 </pre></td><td class="code"><pre><span class="nb">cat</span> /proc/sys/net/ipv4/conf/all/arp_accept </pre></td></tr></tbody></table></code></pre></figure> <p>En caso de que el resultado no sea “0” es un riesgo de seguridad y deberían establecerlo a “0”, de esta manera y desde una terminal con acceso de administración “root”:</p> <figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1 </pre></td><td class="code"><pre><span class="nb">echo</span> <span class="s2">"0"</span> <span class="o">&gt;</span> /proc/sys/net/ipv4/conf/all/arp_accept </pre></td></tr></tbody></table></code></pre></figure> <p>En Microsoft(R) Windows(TM) esto lo logramos con el propio firewall que trae por defecto. Muy importante aclarar que esto evita solamente aquellos paquetes respuesta de ARP que no hayan sido solicitados, pero si el atacante a la hora de analizar un pedido que se haya realizado y responde a dicho pedido, no se bloqueará, pues se tomará como una respuesta esperada.</p> <h2 id="ver">Ver:</h2> <ul> <li><a href="http://www.ecured.cu/index.php/Arp">Ecured</a></li> <li><a href="http://www.arppoisoning.com/best-practices-for-defending-against-arp-poisoning-2/">ARP-Poisoning</a></li> <li><a href="https://www.raymond.cc/blog/protect-your-computer-against-arp-poison-attack-netcut/">Raymond</a></li> </ul> Mon, 20 Apr 2015 00:00:00 +0000 https://lfdominguez.github.io//2015/04/20/arp_spoofing.html https://lfdominguez.github.io//2015/04/20/arp_spoofing.html arp network spoofing