httpd

Sitio web estático para protocolo HTTP (HTML + CSS) que sostiene el blog de fjbalon
Log | Files | Refs

commit 6666a7b7fac3334d13dccec52dd1f3c2ffceb7ed
parent 4f37912526b02e4e0bd40b34c2d01b1e583d223c
Author: fjbalon <fbalon@templier.es>
Date:   Sun, 25 Oct 2026 02:40:18 +0200

Revisión y corrección de errores en múltiples artículos

Diffstat:
Marchlinux/index.html | 14+++++++-------
Mbateria/index.html | 10+++++-----
Mdd/index.html | 6+++---
Mdwm-howto/index.html | 8++++----
Mdwm-slock/index.html | 6+++---
Mdwm-slstatus/index.html | 4++--
Mext4-wsl2/index.html | 6+++---
Mgit-server/index.html | 12+++++++-----
Mgit-stagit/index.html | 4++--
Mhttp-darkmode/index.html | 6+++---
Mindex.html | 12++++++------
Minterpolacion-lineal/index.html | 10+++++-----
Mjdbc-sql-injection/index.html | 12++++++------
Mkernel-compression/index.html | 6+++---
Mlinus-torvalds-hijas/index.html | 46+++++++++++++++++++---------------------------
Mmachine-id/index.html | 4++--
Mmechanic-keyboard/index.html | 10+++++-----
Mpropagacion-malware-script/index.html | 4++--
Mslackware-slackbuild/index.html | 8++++----
Mslackware/index.html | 3+--
Mssh-tunneling/index.html | 8++++----
Mssh/index.html | 46+++++++++++++++++++++-------------------------
Mswap/index.html | 10+++++-----
Mtanque-gasoil/index.html | 2+-
Mtor/index.html | 6+++---
Munix-passwd/index.html | 12++++++------
Murxvtd/index.html | 4++--
Mwatchdog/index.html | 12+++++-------
Mxz-liblzma/index.html | 8++++----
29 files changed, 143 insertions(+), 156 deletions(-)

diff --git a/archlinux/index.html b/archlinux/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -14,14 +14,14 @@ </header> <p>Adentrándonos en el vasto universo de Unix y GNU/Linux, en especial en su distributismo característico; Arch Linux se presenta como una distro recomendada a usuarios avanzados y con cierto conocimiento técnico dentro del cosmos de Linux. Arch presenta un enfoque minimalista y <i>KISS</i> (<i>Keep It Simple, Stupid</i>) y, en cierto modo, <i>Do It Yourself</i>.</p> <p>Esta distribución tiene sus raíces en 2002, cuando Judd Vinet la construyó en un enfoque de entorno simple y elegante, permitiendo a sus usuarios modelar su sistema de acuerdo a sus necesidades y preferencias. Se trata además de un sistema de actualización <i>rolling release</i>, lo que aporta un mantenimiento continuo sin necesidad de reinstalaciones periódicas; característica que, unida a su gestor de paquetes <emb>pacman</emb> ofrece una experiencia de usuario ágil y, sobre todo, rápida de gestión de las últimas versiones del software.</p> -<p>Realmente, el uso de Arch es muy simple, siendo incluso más simple que distribuciones basadas en Debian (sobre todo, por su gestor de paquetes, que lo hace excesivamente sencillo de utilizar incluso para un novato). Sin embargo, si hay una barrera de entrada para comenzar a usar este sistema operativo no es otra que la instalación. La instalación del sistema no cuenta con formularios gráficos ni diálogos que guíen al usuario; sino simplemente ofrece una sesión de shell y otorga libertad total sobre ella al usuario.</p> +<p>Realmente, el uso de Arch es muy simple, siendo incluso más simple que distribuciones basadas en Debian (sobre todo, por su gestor de paquetes, que lo hace excesivamente sencillo de utilizar incluso para un novato). Sin embargo, si hay una barrera de entrada para comenzar a usar este sistema operativo no es otra que la instalación. La instalación del sistema no cuenta con formularios gráficos ni diálogos que guíen al usuario (más allá del asistente opcional <emb>archinstall</emb>, que no trataré aquí); sino simplemente ofrece una sesión de shell y otorga libertad total sobre ella al usuario.</p> <p>Es por esta razón que he compendiado los pasos que realizo personalmente a la hora de construir mi sistema de Arch.</p> <p>El inicio es sencillo, el console keymap por defecto es US (inglés americano). Para modificar el diseño, se puede agregar el nombre de layout correspondiente. Por ejemplo, para establecer una distribución de teclado en español utilizo:</p> <pre><code>loadkeys es</code></pre> <h2>Verificación de modo de arranque (boot mode)</h2> <p>En términos simples, la BIOS (Sistema Básico de Entrada/Salida) y UEFI (Interfaz de Firmware Extensible Unificada) son dos tecnologías diferentes utilizadas para iniciar un sistema operativo en una computadora.</p> <p>La BIOS, que significa Sistema Básico de Entrada/Salida, ha sido la interfaz estándar durante décadas. Se encarga de las operaciones básicas del sistema, incluido el proceso de arranque. Sin embargo, tiene limitaciones en cuanto a la capacidad de manejar discos duros grandes y sistemas operativos modernos.</p> -<p>Por otro lado, UEFI, que significa Interfaz de Firmware Extensible Unificada, es una tecnología más reciente que reemplaza gradualmente a la BIOS. UEFI proporciona una interfaz más avanzada y versátil, permitiendo un arranque más rápido y una mayor capacidad para gestionar hardware y sistemas operativos modernos. Además, UEFI supera las limitaciones de tamaño de disco asociadas con la BIOS. +<p>Por otro lado, UEFI, que significa Interfaz de Firmware Extensible Unificada, es una tecnología más reciente que reemplaza gradualmente a la BIOS. UEFI proporciona una interfaz más avanzada y versátil, permitiendo un arranque más rápido y una mayor capacidad para gestionar hardware y sistemas operativos modernos. Además, UEFI supera las limitaciones de tamaño de disco asociadas con la BIOS.</p> <p>Para verificar el modo de arranque, bastaría listar el directorio <emb>efivars</emb>:</p> <pre><code>ls /sys/firmware/efi/efivars</code></pre> <p>Si la salida muestra el contenido del directorio (stdout) sin error, entonces el sistema de inicio es UEFI. Si por el contrario ofrece error (stderr) debido a que el directorio no existe, entonces el sistema se inicia en modo BIOS (o CSM).</p> <h2>Conexión a Internet</h2> @@ -36,8 +36,8 @@ <pre><code>boot /dev/sda1 /boot 150MB *Bootable root /dev/sda2 / - home /dev/sda3 /home - -swap /dev/sda4 /swap 2GB Type: Linux Swap / Solaris</code></pre><h2>Formateo de particiones</h2> -<p>Una vez particionados los discos y sus particiones, éstas deben ser formateadas con un sistema de archivos apropiado.</p> +swap /dev/sda4 [SWAP] 2GB Type: Linux Swap / Solaris</code></pre><h2>Formateo de particiones</h2> +<p>Una vez particionados los discos y sus particiones, éstas deben ser formateadas con un sistema de archivos apropiado. En los comandos de esta guía se asume que las variables <emb>$boot</emb>, <emb>$root</emb>, <emb>$home</emb> y <emb>$swap</emb> contienen la ruta de cada partición (por ejemplo, <emb>boot=/dev/sda1</emb>) y que <emb>$hostname</emb> y <emb>$username</emb> son el nombre de equipo y de usuario elegidos.</p> <pre><code>mkfs.vfat -F32 $boot # UEFI mkfs.ext2 $boot # BIOS mkfs.ext4 $root @@ -61,12 +61,12 @@ pacstrap /mnt efibootmgr # UEFI</code></pre> <pre><code>genfstab -U -p /mnt >> /mnt/etc/fstab arch-chroot /mnt</code></pre> <p>Una vez enjaulados, podemos proceder a realizar parametrizaciones y configuraciones propias del sistema operativo en instalación, como son la zona horaria, la localización y el mapa de teclas (keymap):</p> -<pre><code>ln -s /usr/share/zoneinfo/Europe/Madrid /etc/localtime +<pre><code>ln -sf /usr/share/zoneinfo/Europe/Madrid /etc/localtime echo "LANG=es_ES.UTF-8" >> /etc/locale.conf echo "es_ES.UTF-8 UTF-8" >> /etc/locale.gen locale-gen echo "KEYMAP=es" >> /etc/vconsole.conf -hwclock -w</code></pre> +hwclock --systohc</code></pre> <p>También configuraremos el hostname e instalaremos los paquetes adicionales a través de pacman:</p> <pre><codeb>echo $hostname >> /etc/hostname pacman -Sy --noconfirm git tree openssh openvpn gnupg nmap ipcalc pulseaudio pulseaudio-alsa pavucontrol pamixer acpi acpid</codeb></pre> diff --git a/bateria/index.html b/bateria/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -83,7 +83,7 @@ POWER_SUPPLY_VOLTAGE_NOW=11759000</code></pre> <p>Siendo <emb>voltage_min_design</emb> 11400000µV, sea 11,4V. El voltaje actual según la medida en este momento es de 11,759V. La batería en este momento proporciona 1,089A de corriente:</p> <pre><code>POWER_SUPPLY_CURRENT_NOW=1089000</code></pre> <p>Como una simple estimación, con la corriente que está tomando de la batería en este momento:</p> -<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="\frac{0,675Ah}{1,089A}=0.62h=37m" display="block"> +<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="\frac{0,675Ah}{1,089A}=0,62h=37m" display="block"> <mrow> <mfrac> <mrow> @@ -109,7 +109,7 @@ POWER_SUPPLY_VOLTAGE_NOW=11759000</code></pre> </mfrac> <mo>=</mo> <mrow> - <mn>0.62</mn> + <mn>0,62</mn> <mo></mo> <mi>h</mi> </mrow> @@ -135,9 +135,9 @@ UserParameter=Status,if [ "$(cat /sys/class/power_supply/BAT0/status)" = "Chargi <img class="color-invertible" style="width: 100%;" src="resources/graph-charge.png" /> <p>Por otro lado, comprobamos la capacidad porcentual (y bruta). Esto nos muestra valores interesantes, como que la batería tarda en desgastarse prácticamente lo mismo que al rellenarse, sin embargo, al llegar al umbral de 8% de capacidad, ésta se vacía a una velocidad mucho más lenta hasta el 0%, lo que constituye un primer indicador del funcionamiento extraño de la batería:</p> <img class="color-invertible" style="width: 100%;" src="resources/graph-perc.png" /> -<p>Otro de los indicadores más extraños proviene al apagar el equipo durante unas horas. Éste al encenderse de nuevo, marca una batería que no se corresponde con el valor de apagado. En el ejemplo registrado, se observa cómo la batería se encontraba aproximadamente marcando un 10% de capacidad, pero tras 1,45h sin interacción de ningún tipo (lógicamente no estuvo conectado a la red eléctrica en este tiempo) vuelve a marcar un valor entre el 60-70% de capacidad:</p> +<p>Otro de los indicadores más extraños proviene al apagar el equipo durante unas horas. Éste al encenderse de nuevo, marca una batería que no se corresponde con el valor de apagado. En el ejemplo registrado, se observa cómo la batería se encontraba aproximadamente marcando un 10% de capacidad, pero tras 1h 45m sin interacción de ningún tipo (lógicamente no estuvo conectado a la red eléctrica en este tiempo) vuelve a marcar un valor entre el 60-70% de capacidad:</p> <img class="color-invertible" style="width: 100%;" src="resources/graph-poweroff.png" /> -<p>Como sabemos, el valor mínimo establecido por diseño que indica la batería es de 11.4V. Sin embargo y tal como se ve, sólo excede el mínimo cuando está conectado a AC:</p> +<p>Como sabemos, el valor mínimo establecido por diseño que indica la batería es de 11,4V. Sin embargo y tal como se ve, sólo excede el mínimo cuando está conectado a AC:</p> <img class="color-invertible" style="width: 100%;" src="resources/graph-voltage.png" /> <p>Por lo tanto y con toda la información recopilada, concretamente la pronunciada degradación de la batería (diferencia entre <emb>charge_full_design</emb> y <emb>charge_full</emb>) y la evidencia de que baja regularmente del voltaje mínimo establecido por diseño (<emb>voltage_min_design</emb>) sugiere que la batería probablemente esté en un estado crítico, y que podría fallar en cualquier momento.</p> </body> diff --git a/dd/index.html b/dd/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -22,9 +22,9 @@ <p>Si lo único que deseamos es clonar de un disco a otro, podemos evitar el intermediario y hacerlo directamente jugando con if y of, dados los discos <emb>/dev/sdx</emb> y <emb>/dev/sdy</emb>:</p> <pre><code>dd bs=512K if=/dev/sdx of=/dev/sdy status=progress</code></pre> <p>Quizá sea porque hay que ser extremadamente cauteloso utilizando dd, ya que es sencillo destruir datos de forma irreversible en caso de negligencia; lo que hace que muchas veces nos enfoquemos únicamente en acertar con el parámetro of (archivo de salida - output file), o quizá sea pereza mental, pero un aspecto que se pasa normalmente por alto es el relativo a los tres argumentos de tamaño de bloque: ibs (tamaño de bloque de entrada), obs (tamaño de bloque de salida) y bs (tamaño de bloque de entrada y salida, abarcándolo todo).</p> -<p>Partamos de la base de que un bloque es una unidad que mide el número de bytes que se leen, escriben o convierten a la vez. De forma general y predeterminada, dd utiliza un tamaño de bloque de 512 bytes, tanto para la entrada como para la salida. Esto quizás ha sido correcto entre 1980 y 1999, cuando la mayoría de discos tenían un tamaño de sector de 512 bytes, sin embargo en los últimos años la mayoría de los discos tienen un tamaño de sector de al menos 4096 bytes (4K). Aunque el cambio puede parecer intrascendente, puede conducir a ineficiencia e inestabilidad, más teniendo en cuenta que los discos actuales pueden tener más de 1TB de capacidad, lo que requiere un tamaño de bloque más óptimo.</p> +<p>Partamos de la base de que un bloque es una unidad que mide el número de bytes que se leen, escriben o convierten a la vez. De forma general y predeterminada, dd utiliza un tamaño de bloque de 512 bytes, tanto para la entrada como para la salida. Esto quizás ha sido correcto durante muchos años, cuando la mayoría de discos tenían un tamaño de sector de 512 bytes, sin embargo en los últimos años la mayoría de los discos tienen un tamaño de sector de al menos 4096 bytes (4K). Aunque el cambio puede parecer intrascendente, puede conducir a ineficiencia e inestabilidad, más teniendo en cuenta que los discos actuales pueden tener más de 1TB de capacidad, lo que requiere un tamaño de bloque más óptimo.</p> <p>Por convención, hoy en día se recomienda utilizar un tamaño de bloque de 64K (en ocasiones se indica como 128K), asegurándose como más óptimos. Sin embargo, al no existir contexto ni explicación, lo considero un argumento viciado y arbitrario, teniendo en cuenta que no existe un tamaño de bloque universalmente correcto: lo que es óptimo para una situación puede ser terriblemente ineficiente para otra.</p> -<p>Si tomamos como ejemplo de lectura el fichero <emb>/dev/zero</emb> y lo escribimos en un disco de 1TB SSD, producimos un rendimiento de 39,6 MB/s tomando el tamaño de bloque predeterminado de 512 bytes. Esto daría una duración de 26.479 segundos, unas 26 horas. Para el mismo caso pero en un disco de 1TB HDD, el rendimiento descendería a 10,9 MB/s, es decir, 96.200 segundos o unas 26 horas. Si tomamos el tamaño de bloque recomendado de 64K obtenemos un rendimiento de 266 MB/s (3.942s, ~1,1h) para SSD y 108 MB/s (9.709s, ~2,7h) para HDD. Si lo que buscamos es velocidad óptima, evidentemente cuanto mayor sea el tamaño de bloque, menos llevará a dd realizar la copia.</p> +<p>Si tomamos como ejemplo de lectura el fichero <emb>/dev/zero</emb> y lo escribimos en un disco de 1TB SSD, producimos un rendimiento de 39,6 MB/s tomando el tamaño de bloque predeterminado de 512 bytes. Esto daría una duración de unos 25.250 segundos, es decir, unas 7 horas. Para el mismo caso pero en un disco de 1TB HDD, el rendimiento descendería a 10,9 MB/s, es decir, 96.200 segundos o unas 26 horas. Si tomamos el tamaño de bloque recomendado de 64K obtenemos un rendimiento de 266 MB/s (3.942s, ~1,1h) para SSD y 108 MB/s (9.709s, ~2,7h) para HDD. Si lo que buscamos es velocidad óptima, evidentemente cuanto mayor sea el tamaño de bloque, menos llevará a dd realizar la copia.</p> <p>Para ilustrarnos técnicamente, dado el script:</p> <pre><code>#!/bin/bash diff --git a/dwm-howto/index.html b/dwm-howto/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -12,7 +12,7 @@ <p class="title">Configuración y uso personal de dwm</p> <p class="date">9 de octubre de 2021 • fjbalon</p> </header> -<p>En orden a construir <emb>dwm</emb> necesita los archivos de cabecera de Xlib. Edite config.mk para localizar tu configuración local (<emb>dwm</emb> es instalado en usr/local por defecto). La instalación se realiza directamente compilando el código, para ello dispone de un archivo <emb>makefile</emb>. Para limpieza de archivos compilados y temporales en directorio de trabajo, dispone de la orden <emb>clean</p>emb>.</p> +<p>En orden a construir <emb>dwm</emb> necesita los archivos de cabecera de Xlib. Edite config.mk para localizar tu configuración local (<emb>dwm</emb> es instalado en usr/local por defecto). La instalación se realiza directamente compilando el código, para ello dispone de un archivo <emb>makefile</emb>. Para limpieza de archivos compilados y temporales en directorio de trabajo, dispone de la orden <emb>clean</emb>.</p> <p><emb>dwm</emb> se configura mediante el archivo <emb>config.h</emb> y (re)compilando.</p> <p>Existen parches ya programados y publicados por la comunidad de suckless que permiten extender fácilmente el windows manager según los parámetros requeridos por el usuario. En mi caso, utilizo éstos de base:</p> <ul> @@ -20,7 +20,7 @@ <ul> <li><a href="https://dwm.suckless.org/patches/actualfullscreen">actualfullscreen</a>: Alterna la pantalla completa para una ventana, en lugar de alternar la barra de estado y el diseño monocle2.</li> <li><a href="https://dwm.suckless.org/patches/titlecolor">titlecolor</a>: Añade un nuevo esquema de color utilizado por el título de la ventana en la barra, de modo que sus colores (primer plano y fondo) se pueden cambiar de forma independiente.</li> -<li><a href="https://dwm.suckless.org/patches/noborder">noborderfloating</a>: Elimina el borde cuando sólo haya una ventana visible.</li> +<li><a href="https://dwm.suckless.org/patches/noborder">noborder</a>: Elimina el borde cuando sólo haya una ventana visible.</li> </ul> <li>Parches funcionales</li> <ul> @@ -51,7 +51,7 @@ <p>Además, alterna entre los dos layouts más actuales con <kbd>Mod4</kbd>+<kbd>Space</kbd>. Para cambiar entre los estados de mosaico y flotante en la ventana enfocada <kbd>Mod4</kbd>+<kbd>Shift</kbd>+<kbd>Space</kbd>.</p> <img style="width: 45%;" src="resources/toggle_window_floating.png"/> <h2>Administración de ventanas</h2> -<p>De forma predeterminada, hay dos formas de abrir una nueva ventana: abrir una shell (por defecto <emb>st</emb>) o ejecutar <emb>dmenu</emb>. Ambas son aplicaciones separadas que se construyeron específicamente y modularmente para trabajar con <emb>dwm</emb> (aunque pueden usarse fuera de éste sin problemas). En mi caso uso ambas, cuyas combinaciones de teclas predeterminadas para cada una son:</p> +<p>De forma predeterminada, hay dos formas de abrir una nueva ventana: abrir una shell (por defecto <emb>st</emb>) o ejecutar <emb>dmenu</emb>. Ambas son aplicaciones separadas que se construyeron específicamente y modularmente para trabajar con <emb>dwm</emb> (aunque pueden usarse fuera de éste sin problemas). En mi caso uso ambas, cuyas combinaciones de teclas (en mi configuración) son:</p> <p><kbd>Mod4</kbd>+<kbd>Return</kbd> abre específicamente <emb>st</emb>, si desea que abra otra terminal, como <emb>xterm</emb> o <emb>urxvt</emb>, deberá configurar <emb>config.h</emb>.</p> <img style="width: 45%;" src="resources/new_term.png"/> <p><kbd>Mod4</kbd>+<kbd>r</kbd> ejecuta el pequeño menú dinámico llamado dmenu en la barra superior de <emb>dwm</emb>.</p> diff --git a/dwm-slock/index.html b/dwm-slock/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -317,12 +317,12 @@ <p>De tal forma que, con la pulsación de teclas <kbd>Mod4</kbd>+<kbd>Shift</kbd>+<kbd>l</kbd> se ejecuta slock y se bloquea la pantalla.</p> <p>Cuando cierro la tapa del portátil, el equipo se suspende. Esto provoca que el equipo apague casi todos los componentes físicos, pero mantenga una leve alimentación a la memoria RAM, la cual contiene todo el contenido tal cual estaba. De tal forma, al despertar (o abrir la tapa) el equipo alimenta todos los componentes de nuevo, e inicia rápidamente, casi instantáneamente, pues la información ya estaba en RAM. Por lo que cuando voy a desplazarme, cierro y abro la tapa manteniendo la sesión íntegra.</p> <p>Sin embargo, si no he ejecutado slock antes, al abrir la sesión no estará protegida. Esto es un riesgo de seguridad, pues un tercero podría hacerse con la máquina suspendida, despertarla y tener acceso a toda la sesión sin protección de ningún tipo. Por lo tanto, es interesante añadir una ejecución de slock automática al suspender el equipo.</p> -<p>Eso sí, a menudo tengo el equipo conectado por HDMI a algún monitor o TV, siendo que me interesa cerrar la tapa directamente y mantener el equipo en funcionamiento en otro monitor, por lo que hacerlo automático al cerrar la tapa no sería útil; sino, en concreto, suspender el equipo. La forma, pues, más limpia y fiable será usar, con <emb>elogind</emb>, los hooks de <emb>system-sleep</emb>. Estos son los scripts que se ejecutan automáticamente antes y después de cualquier suspensión o hibernación, independientemente si se activa por cerrar la tapa o por cualquier otro motivo programado. <emb>elogind</emb> es un módulo de systemd que gestiona el login de usuarios, sesiones gráficas y el manejo de energía, pero separada y sin depender de todo systemd, claro (si no, no sería software nativo en Slackware 15).</p> +<p>Eso sí, a menudo tengo el equipo conectado por HDMI a algún monitor o TV, siendo que me interesa cerrar la tapa directamente y mantener el equipo en funcionamiento en otro monitor, por lo que hacerlo automático al cerrar la tapa no sería útil; sino, en concreto, suspender el equipo. La forma, pues, más limpia y fiable será usar, con <emb>elogind</emb>, los hooks de <emb>system-sleep</emb>. Estos son los scripts que se ejecutan automáticamente antes y después de cualquier suspensión o hibernación, independientemente si se activa por cerrar la tapa o por cualquier otro motivo programado. <emb>elogind</emb> es una extracción del componente systemd-logind, que gestiona el login de usuarios, sesiones gráficas y el manejo de energía, pero separada y sin depender del resto de systemd, claro (si no, no sería software nativo en Slackware 15).</p> <p>Lo que he hecho es crear un script en <emb>/lib64/elogind/system-sleep</emb> como el siguiente:</p> <pre><code>#!/bin/sh #/lib64/elogind/system-sleep/lock-slock -USER="javier" +USER="fjbalon" USERHOME="/home/$USER" DISPLAY=:0 XAUTHORITY="$USERHOME/.Xauthority" diff --git a/dwm-slstatus/index.html b/dwm-slstatus/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -22,7 +22,7 @@ static const char unknown_str[] = "n/a"; static const struct arg args[] = { { datetime, "%s", "%F %T" }, };</code></pre> -<p>La configuración por defecto de <emb>datetime</emb> la he dejado con una configuración que me gusta algo más: <emb>{ datetime, " %s", "%d/%m/%y %H:%M" },</emb>, de tal forma que la fecha mostrada es <emb>22/07/26 16:59</emb>.</p> +<p>La configuración por defecto de <emb>datetime</emb> la he dejado con una configuración que me gusta algo más: <emb>{ datetime, " %s", "%d/%m/%y %H:%M" },</emb>, de tal forma que la fecha mostrada es <emb>22/06/26 16:59</emb>.</p> <p>Lo que más nos interesa por el momento es la estructura <emb>arg</emb>, que es un array de elementos a mostrar por pantalla. En un inicio, sólo mostrará la fecha y hora. Pero hay muchas más opciones ya programadas en el código base, como <emb>battery_perc</emb>. <emb>battery_remaining</emb> y <emb>battery_state</emb>, que muestra el porcentaje de batería, el cálculo del tiempo restante y el estado de la batería (en carga, en descarga, completa...), respectivamente.</p> <p>De tal forma añado, en mi caso, el siguiente contenido para su muestra en la barra de estado:</p> <pre><code>{ battery_state, "%s", "BAT0" }, diff --git a/ext4-wsl2/index.html b/ext4-wsl2/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -13,12 +13,12 @@ <p class="date">5 de junio de 2026 • fjbalon</p> </header> <p>En un artículo algo extraño para lo que suelo escribir, enfocado en el sistema de Microsoft Windows. Tranquilícese el lector, incluso encuadrando el artículo a través del sistema operativo ajeno a las buenas costumbres, no se trata de él mismo, sino que sigue tratándose de Linux por:</p> -<p>a. los formatos de sistemas de archivos transaccionales ext2, ext3 o ext4, pertenecientes nativamente al kernel de Linux desde la introducción en 1993 de ext2, y</p> +<p>a. los formatos de sistemas de archivos ext2, ext3 o ext4, pertenecientes nativamente al kernel de Linux desde la introducción en 1993 de ext2, y</p> <p>b. WSL2 que no es siquiera una capa de compatibilidad con el kernel, como era WSL; sino que ofrece un kernel de Linux a través de virtualización, con llamadas a la API del kernel.</p> <p>Si hubiera alguna categoría para ello creo que las más adecuadas sería compatibilidad o virtualización. Ya que, por trabajo, he tenido la necesidad de montar uno de mis discos duros externos, que suelo llevar formateados con el sistema de archivos ext4, en un sistema Windows.</p> <p>Obviando la blasfemia, con un poco de humor, creo que los pasos a realizar pueden ser de interés para muchos. Ya que, no lo sabía, no existe compatibilidad nativa en Windows para montar estos sistemas de archivos. Y no basta, como en GNU/Linux, con instalar un paquete de compatibilidad para montar, por ejemplo, NTFS.</p> -<p>Entonces, ¿cómo puedo utilizar mi disco ext4 en un sistema Windows incompatible? Hay softwares de terceros que se pueden buscar e instalar, pero de primeras lo evitaría. Primero, por seguridad; ya bastante inseguro es Windows como para que le metamos más códigos cerrados y obtusos para pequeñas funcionalidades; además que crea aun más basura en un sistema tan sucio, estructural y organizativamente hablando. Por ello, he optado por utilizar WSL o Windows Subsystem Linux que, para quien no lo sepa, es una implementación de Windows relativamente reciente que permite ejecutar un entorno, más o menos virtualizado, de Linux en una máquina Windows. Como decía antes, de hecho, WSL2 ofrece directamente un núcleo de Linux optimizado por Microsoft.</p> +<p>Entonces, ¿cómo puedo utilizar mi disco ext4 en un sistema Windows incompatible? Hay softwares de terceros que se pueden buscar e instalar, pero de primeras lo evitaría. Primero, por seguridad; ya bastante inseguro es Windows como para que le metamos más códigos cerrados y obtusos para pequeñas funcionalidades; además que crea aun más basura en un sistema tan sucio, estructural y organizativamente hablando. Por ello, he optado por utilizar WSL o Windows Subsystem for Linux que, para quien no lo sepa, es una implementación de Windows relativamente reciente que permite ejecutar un entorno, más o menos virtualizado, de Linux en una máquina Windows. Como decía antes, de hecho, WSL2 ofrece directamente un núcleo de Linux optimizado por Microsoft.</p> <p>De ahí, lo primero necesario es tener actualizado WSL2 con una distribución Linux, en mi caso, Debian:</p> <pre><code>C:\>wsl --mount PATH Esta operación solo es compatible con WSL2 diff --git a/git-server/index.html b/git-server/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -13,8 +13,8 @@ <p class="date">22 de noviembre de 2020 • fjbalon</p> </header> <p>Aquí todos conocemos el software o protocolo desarrollado en inicio por Linus Torvalds: Git. Un sistema de control de versiones, que se constituye como una herramienta indispensable, a día de hoy, para cualquier programador; especialmente en el software libre. Git funciona como cliente o como servidor, y cada cliente aloja en local una copia del software que sincronizará con el servidor en función de lo que el cliente convenga. Los despliegues de Git más conocidos son Github o Gitlab, donde éstos te ofrecen una interfaz gráfica pulida y almacenamiento de servidor para todos los proyectos que se deseen incluir. Por ello, la duda razonable que debe asaltar al lector sería: ¿por qué querría crear mi propio servidor de Git?</p> -<p>Veamos, una buena razón para alojar tus propios repositorios Git es tener y mantener el control sobre tu propia infraestructura informática, tanto a nivel de sistema como a nivel de código, guardando incluso el secreto de aquellos códigos que quieras mantener sin publicar (y que de otra forma lo estarías cediendo al ordenador de otro, confiando ciegamente en que verdaderamente se encuentre oculto). Considero que los servidores de Git comúnmente utilizados como Github, Gitlab, Bitbucket… No son de fiar, en cuanto son propietarios desconocidos y sostenedores de tu código. No es secreto que estos servicios analizan el código, aplican telemetría e inteligencia sobre ellos, analizan las conexiones de sus usuarios y aplican restricciones y limitaciones. Al fin y al cabo son empresas con fines comerciales, y a menudo con fines ocultos. En el caso de Microsoft, como propietario de Github es mucho más lamentable y peligrosa la situación.</p> -<p>En cuanto a economía doméstica, estos servicios también tienen diferentes planes de precios y varias restricciones (arbitrarias en muchos casos). Sin embargo cuando usted mismo lo aloja, las restricciones son los límites de recursos del sistema y su conexión, por lo tanto, es una solución mucho más flexible, adaptada y convergente con el usuario.</p> +<p>Veamos, una buena razón para alojar tus propios repositorios Git es tener y mantener el control sobre tu propia infraestructura informática, tanto a nivel de sistema como a nivel de código, guardando incluso el secreto de aquellos códigos que quieras mantener sin publicar (y que de otra forma lo estarías cediendo al ordenador de otro, confiando ciegamente en que verdaderamente se encuentre oculto). Considero que los servidores de Git comúnmente utilizados como Github, Gitlab, Bitbucket… No son de fiar, en cuanto son propietarios desconocidos y sostenedores de tu código. Es razonable suponer que estos servicios pueden analizar el código, aplicar telemetría e inteligencia sobre ellos, analizar las conexiones de sus usuarios y aplicar restricciones y limitaciones. Al fin y al cabo son empresas con fines comerciales, y a menudo con fines ocultos. En el caso de Microsoft, como propietario de Github es mucho más lamentable y peligrosa la situación.</p> +<p>En cuanto a economía doméstica, estos servicios también tienen diferentes planes de precios y varias restricciones (arbitrarias en muchos casos). Sin embargo cuando tú mismo lo alojas, las restricciones son los límites de recursos del sistema y de tu conexión, por lo tanto, es una solución mucho más flexible, adaptada y convergente con el usuario.</p> <h2>¿Cómo creo mi propio servidor de Git?</h2> <p>Bien, entremos en el barro técnico.</p> <p>Lo primero que debemos hacer es tener Git instalado. Debido a la gran cantidad de distribuciones y formas variopintas de realizar la instalación, voy a obviarla. No es difícil instalar Git y se encuentra disponible, que yo sepa, en todos los repositorios oficiales de todas las distros.</p> @@ -27,10 +27,12 @@ mkdir .ssh && chmod 700 .ssh touch .ssh/authorized_keys chmod 600 .ssh/authorized_keys</code></pre> <p>Los repositorios pueden estar en el directorio que se quiera. En este caso, se encontrarán en el directorio git en la raíz del sistema. Para lo que tendremos que crearlo. Por cada repositorio, se crea un directorio (aconsejable es que terminen con .git). Para iniciar un repositorio como server usamos el parámetro <emb>init --bare.</emb></p> -<pre><code>mkdir /git +<pre><code>exit # volvemos a root +mkdir /git +chown git:git /git +su git cd /git mkdir code.git -chown git:git code.git cd code.git git init --bare Initialized empty Git repository in /git/code.git/</code></pre> diff --git a/git-stagit/index.html b/git-stagit/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -119,7 +119,7 @@ cp stagit/logo.png /srv/git/</code></pre> # /git/arrakis.git/hooks/post-receive echo "Ejecutando hook post-receive: desplegando a producción el static-site" -git --work-tree=/srv/http --git-dir=/tex/arrakis.git checkout -f master</code></pre> +git --work-tree=/srv/http --git-dir=/git/arrakis.git checkout -f master</code></pre> <p>Por supuesto, los permisos del directorio htmlroot deben tener los permisos para git.</p> <pre><code>drwxr-xr-x 3 git git 4096 Dec 14 15:53 http</code></pre> </body> diff --git a/http-darkmode/index.html b/http-darkmode/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -78,7 +78,7 @@ <p>En computación, para indicar con qué proporción es mezclado cada color, se asigna un valor a cada uno de estos tres colores, de forma que el valor 0 indica que no interviene en la mezcla y, a medida que el valor aumenta, se entiende que aporta intensidad a ésta. Aunque el intervalo de valores podría ser cualquiera, es frecuente que cada color primario se codifique con un byte (8 bits). Así, de manera prácticamente estándar, la intensidad de cada uno de los componentes se mide según una escala del 0 al 255.</p> -<p>De tal forma que el rojo se obtiene con (255, 0, 0), el verde con (0, 255, 0) y el azul con (0, 0, 255), obteniendo en cada caso un resultado monocromático. La ausencia de color -o negro- se obtiene cuando los tres componentes son 0: (0, 0, 0). Amarillo sería (255, 255, 0), cian (0, 255, 255) y magenta (255, 0, 255). El color blanco de forma mezclando en el nivel máximo los colores primarios, o sea, (255, 255, 255). En el caso de la presente web, contamos con un gris propio de (28, 28, 28). El lector puede usar un <a href="https://imagecolorpicker.com/es">color picker</a> para experimentar y jugar con estos colores.</p> +<p>De tal forma que el rojo se obtiene con (255, 0, 0), el verde con (0, 255, 0) y el azul con (0, 0, 255), obteniendo en cada caso un resultado monocromático. La ausencia de color -o negro- se obtiene cuando los tres componentes son 0: (0, 0, 0). Amarillo sería (255, 255, 0), cian (0, 255, 255) y magenta (255, 0, 255). El color blanco de forma mezclando en el nivel máximo los colores primarios, o sea, (255, 255, 255). En el caso de la presente web, el fondo en modo oscuro no es negro puro, sino un gris propio de (28, 28, 28). El lector puede usar un <a href="https://imagecolorpicker.com/es">color picker</a> para experimentar y jugar con estos colores.</p> <p>En términos más técnicos del tema objeto del artículo, invertir el color en RGB significa restar cada componente del color al valor máximo posible. Así:</p> @@ -185,7 +185,7 @@ </mrow> </math> -<p>La teoría de inversión de color RGB la tenemos clara. Sin embargo, no podemos indicar directamente que requerimos el valor (277, 277, 277) al fondo de una imagen para que se corresponda con éste en modo oscuro. Lo que requerimos es el valor o porcentaje de inversión necesaria para que se produzca el cálculo anterior transparentemente.</p> +<p>La teoría de inversión de color RGB la tenemos clara. Sin embargo, no podemos indicar directamente que requerimos el valor (227, 227, 227) al fondo de una imagen para que se corresponda con éste en modo oscuro. Lo que requerimos es el valor o porcentaje de inversión necesaria para que se produzca el cálculo anterior transparentemente.</p> <p>Si el caso fuera invertir de blanco (255, 255, 255) a negro (0, 0, 0) y viceversa en todas las ocasiones, es decir, si mantenemos un fondo blanco, y negro en modo oscuro. Simplemente valdría con usar la unidad <emb>filter: invert(1);</emb> o el porcentaje total <emb>filter: invert(100%);</emb>.</p> <p>Pero si requerimos de una inversión parcial, la fórmula sería:</p> diff --git a/index.html b/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -93,6 +93,11 @@ <p class="info">25 de noviembre de 2021 · fjbalon</p><p>El principio básico de un RTD es que su sensor de cable, hecho de un metal con una resistencia eléctrica conocida, cambia su valor de resistencia a medida que la temperatura sube o baja. Aunque las ...</p> </a> +<a href="./kernel-compression/" class="article"> + <p class="title">Demostración empírica de tipo de compresión usada en el kernel de Linux</p> + <p class="info">19 de noviembre de 2021 · fjbalon</p><p>Para la realización de una práctica de preparación de LPIC-1/2, debía averiguar el tipo de compresión del kernel de Linux empleado en mi sistema. En ese momento, usando la distribución archlinux...</p> +</a> + <a href="./dwm-howto/" class="article"> <p class="title">Configuración y uso personal de dwm</p> <p class="info">9 de octubre de 2021 · fjbalon</p><p>En orden a construir dwm necesita los archivos de cabecera de Xlib. Edite config.mk para localizar tu configuración local (dwm es instalado en usr/local por defecto). La instalación se realiza direc...</p> @@ -133,11 +138,6 @@ <p class="info">27 de febrero de 2020 · fjbalon</p><p>El caso que hoy me ocupa, nace de la necesidad de apagar la memoria de intercambio (o swap) en mi equipo portátil para poder gestionar varias pruebas sobre clústers de kubernetes. Algo curioso, pues...</p> </a> -<a href="./kernel-compression/" class="article"> - <p class="title">Demostración empírica de tipo de compresión usada en el kernel de Linux</p> - <p class="info">19 de noviembre de 2019 · fjbalon</p><p>Para la realización de una práctica de preparación de LPIC-1/2, debía averiguar el tipo de compresión del kernel de Linux empleado en mi sistema. En ese momento, usando la distribución archlinux...</p> -</a> - <a href="./ssh-tunneling/" class="article"> <p class="title">SSH Tunneling</p> <p class="info">28 de marzo de 2019 · fjbalon</p><p>El tunneling es un proceso por el que se utiliza el protocolo SSH para fortificar la comunicación entre otros protocolos inseguros, por ejemplo para realizar peticiones HTTP, SMTP, etc....</p> diff --git a/interpolacion-lineal/index.html b/interpolacion-lineal/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -12,7 +12,7 @@ <p class="title">Interpolación lineal simple para calcular la temperatura de termorresistencias Pt100</p> <p class="date">25 de noviembre de 2021 • fjbalon</p> </header> -<p>El principio básico de un RTD es que su sensor de cable, hecho de un metal con una resistencia eléctrica conocida, cambia su valor de resistencia a medida que la temperatura sube o baja. Aunque las termorresistencias tienen ciertas limitaciones, que incluyen una temperatura de medición máxima de alrededor de 1,100°F (600°C), en general, son la solución de medición de temperatura ideal para una multitud de procesos.</p> +<p>El principio básico de un RTD es que su sensor de cable, hecho de un metal con una resistencia eléctrica conocida, cambia su valor de resistencia a medida que la temperatura sube o baja. Aunque las termorresistencias tienen ciertas limitaciones, que incluyen una temperatura de medición máxima de alrededor de 1.100°F (600°C), en general, son la solución de medición de temperatura ideal para una multitud de procesos.</p> <p>Los cables de detección en un RTD pueden estar hechos de níquel (Ni), cobre (Cu) o tungsteno (W), pero el platino (Pt) es, con mucho, el metal más popular usado en la actualidad. Es más caro que otros materiales, pero el platino tiene varias características que lo hacen particularmente adecuado para las mediciones de temperatura, que incluyen:</p> <ul> <li>Relación temperatura-resistencia casi lineal.</li> @@ -23,9 +23,9 @@ <li>Alta resistencia a la contaminación.</li> </ul> <p>Entre los sensores RTD de platino, Pt100 y Pt1000 son los más comunes. Los sensores Pt100 tienen una resistencia nominal de 100Ω en el punto de hielo (0°C). La resistencia nominal de los sensores Pt1000 a 0°C es de 1.000Ω. La linealidad de la curva característica, el rango de temperatura de operación y el tiempo de respuesta son los mismos para ambos. El coeficiente de temperatura de resistencia es también el mismo.</p> -<p>Sin embargo, debido a la diferente resistencia nominal, las lecturas de los sensores Pt1000 son mayores en un factor de 10 en comparación con los sensores Pt100. Esta diferencia se hace evidente cuando se comparan configuraciones de 2 cables, donde se aplica el error de medición del cable. Por ejemplo, el error de medición en un Pt100 podría ser <emb>+1.0ºC</emb>, y en el mismo diseño, un Pt1000 podría ser <emb>+0.1ºC</emb>.</p> +<p>Sin embargo, debido a la diferente resistencia nominal, las lecturas de los sensores Pt1000 son mayores en un factor de 10 en comparación con los sensores Pt100. Esta diferencia se hace evidente cuando se comparan configuraciones de 2 cables, donde se aplica el error de medición del cable. Por ejemplo, el error de medición en un Pt100 podría ser <emb>+1,0ºC</emb>, y en el mismo diseño, un Pt1000 podría ser <emb>+0,1ºC</emb>.</p> <p>Tras contextualizar expongo el problema: leyendo mediante modbus los datos recibidos de un par de termorresistencias Pt100, me percaté que recibía, evidentemente, los datos raw. Pero no encontraba en documentación de los sensores ni en Internet el factor de conversión de esta unidad a grados. Mi única pista era la interfaz web del aparato, que establecía el rango de limitación como <emb>-100~100ºC</emb>.</p> -<p>Tengo entonces, por comprobación o por determinación (<emb>"By default, the High Alarm value is +32767 (0x7FFF) and the low alarm value is -32768 (0xFFFF)"</emb>) que el valor límite absoluto es <emb>32768</emb>; siendo entonces un rango de <emb>-32768~32767</emb>.</p> +<p>Tengo entonces, por comprobación o por determinación (<emb>"By default, the High Alarm value is +32767 (0x7FFF) and the low alarm value is -32768 (0x8000)"</emb>) que el valor límite absoluto es <emb>32768</emb>; siendo entonces un rango de <emb>-32768~32767</emb>.</p> <pre><code>./modpoll -r2 -1 -t3 172.16.20.13 Protocol configuration: MODBUS/TCP, FC4 @@ -48,7 +48,7 @@ Data type.............: 16-bit register, input register table [3]: 8388 </code></pre> <p>Y obteniendo los valores raw de cada sensor, necesitaría reproducir lo más fiel posible una función a la representada con estos valores. Para ello, realizaría una interpolación lineal simple, consiste en trazar una recta que pasa por dos puntos conocidos <emb>y = r(x)</emb> y calcular los valores intermedios según esta recta.</p> -<p>La ecuación de una recta conocido dos puntos <emb>(x1,y1)</emb> y <emb>(x2,y2)</emb> es:</p> +<p>La ecuación de una recta conocidos dos puntos <emb>(x1,y1)</emb> y <emb>(x2,y2)</emb> es:</p> <math xmlns="http://www.w3.org/1998/Math/MathML" alttext="\frac{(y-y_{1})}{(y_{2}-y_{1})}=\frac{(x-x_{1})}{(x_{2}-x_{1})}" display="block"> <mrow> diff --git a/jdbc-sql-injection/index.html b/jdbc-sql-injection/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -76,7 +76,7 @@ public class SQLInjection extends JFrame implements WindowListener { Class.forName("org.mariadb.jdbc.Driver"); String dbpass = ""; - Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/dbftwr", "root", dbpass); + Connection connection = DriverManager.getConnection("jdbc:mariadb://localhost/dbftwr", "root", dbpass); Statement s = connection.createStatement(); addWindowListener(this); @@ -112,7 +112,7 @@ public class SQLInjection extends JFrame implements WindowListener { <p>Los dos bloques de código que nos ocupan son los siguientes: el bloque de conexión a la base de datos y el contenido del botón de aceptar, que almacena la consulta.</p> <pre><code>Class.forName("org.mariadb.jdbc.Driver"); String dbpass = ""; -Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/dbftwr", "root", dbpass); +Connection connection = DriverManager.getConnection("jdbc:mariadb://localhost/dbftwr", "root", dbpass); Statement s = connection.createStatement(); btnAceptar.addActionListener((ActionEvent event) -> { @@ -126,14 +126,13 @@ btnAceptar.addActionListener((ActionEvent event) -> { <p>Como vemos la consulta <emb>select secreto from Usuarios where (nombre = '" + txtUsuario.getText() + "' and pass = '" + txtPass.getText() + "');</emb> es vulnerable a un SQL Injection, ya que al almacenar las variables directamente en la sentencia SQL, enviará la cadena de texto tal y como lo recoja de los campos de texto. Por lo que podemos jugar. Una consulta típica, siguiendo el ejemplo de pedro, sería:</p> <pre><codeb>select secreto from Usuarios where (nombre = ' pedro ' and pass = ' 123456 ');</codeb></pre> <p>Esta sentencia mostraría el secreto de la tabla <emb>Usuarios</emb>, donde el nombre sea <emb>pedro</emb> y su contraseña 123456. Con esto comprobamos que la contraseña corresponda al usuario. Al ser nombre igual a pedro devolverá un booleano true (verdadero); al ser la contraseña 123456 también devolverá un booleano true. <emb>True AND True = True</emb>: Sesión iniciada correctamente. Pero ¿y si insertamos código SQL, para engañar al servidor y que nos muestre el secreto de quien queramos, sin necesidad de conocer su contraseña?. Esto lo podemos hacer aprovechando esta vulnerabilidad.</p> -</body> <pre><codeb>select secreto from Usuarios where (nombre = ' pedro' or '1'='1 ' and pass = '');</codeb></pre> <p>De esta forma hemos inyectado código: asignamos el nombre, es pedro (es true). O bien (<emb>1=1</emb> -sentencia obviamente cierta, verdadera- y <emb>pass=''</emb> (cadena en blanco, obviamente falsa). <emb>True OR (True AND False) = True OR False = True</emb>. Obtenemos finalmente un booleano verdadero, sin conocer la contraseña, lo que nos devolverá el secreto de este usuario. Podemos realizar una prueba con el usuario Miguel, el cual no conocemos su contraseña.</p> <img style="width: 300px;" src="jdbc2.png" /> <p>¿Cómo podemos solucionarlo? Con el fin de evitar este tipo de ataques sobre nuestro programa deberemos utilizar el método seguro: sustituir el <emb>Statement</emb> por el <emb>PreparedStatement</emb>. Vemos el bloque de código que hemos de editar: en primer lugar comentamos nuestro <emb>Statement</emb>, ya que no le daremos uso. Lo sustituimos por el <emb>PreparedStatement</emb>, donde le indicamos directamente la sentencia SQL; sustituyendo los elementos a insertar por signos de cerrar interrogación (?) (omitir comillas). Con la orden <emb>ps(PreparedStatement).setString</emb> y el número de posición del elemento que hemos colocado en la sentencia, indicaremos el valor a dar, ya sea una variable o un <emb>getText()</emb> como en mi caso.</p> <pre><code>Class.forName("org.mariadb.jdbc.Driver"); String dbpass = ""; -Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/dbftwr", "root", dbpass); +Connection connection = DriverManager.getConnection("jdbc:mariadb://localhost/dbftwr", "root", dbpass); //Statement s = connection.createStatement(); btnAceptar.addActionListener((ActionEvent event) -> { @@ -151,7 +150,7 @@ btnAceptar.addActionListener((ActionEvent event) -> { <p>Otra alternativa, también válida, para solventar esta vulnerabilidad, es hacer una única sentencia sin posibilidad de edición. Y a su vez jugar con las respuestas. El código será similar, de forma que:</p> <pre><code>Class.forName("org.mariadb.jdbc.Driver"); String dbpass = ""; -Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/dbftwr", "root", dbpass); +Connection connection = DriverManager.getConnection("jdbc:mariadb://localhost/dbftwr", "root", dbpass); Statement s = connection.createStatement(); btnAceptar.addActionListener((ActionEvent event) -> { @@ -170,4 +169,5 @@ btnAceptar.addActionListener((ActionEvent event) -> { <p>Como podemos ver, el bloque de conexión se mantiene intacto a la primera opción. El interior del botón simplemente tendrá la sentencia <emb>select * from Usuarios</emb>. De los resultados que obtenga, mientras haya irá recorriendo de uno en uno, comprobando que el contenido del campo de texto de usuario sea el mismo que el nombre de usuario de la tabla, Y el contenido del campo de texto de la contraseña sea igual a la contraseña del usuario de la tabla. Si estas condiciones se cumplen, se mostrará el secreto, si no, mostrará un error.</p> <img style="width: 70%;" src="jdbc3.png" /> <p>De esta forma, al no modificar la sentencia directamente, sino jugar con sus resultados evitaremos esta vulnerabilidad en concreto. Así, hemos explotado y solucionado el riesgo que supone la vulnerabilidad de SQL Injection en nuestro software, evitando así posibles ataques a nuestra base de datos.</p> +</body> </html> \ No newline at end of file diff --git a/kernel-compression/index.html b/kernel-compression/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -10,14 +10,14 @@ <body> <header> <p class="title">Demostración empírica de tipo de compresión usada en el kernel de Linux</p> -<p class="date">19 de noviembre de 2019 • fjbalon</p> +<p class="date">19 de noviembre de 2021 • fjbalon</p> </header> <p>Para la realización de una práctica de preparación de LPIC-1/2, debía averiguar el tipo de compresión del kernel de Linux empleado en mi sistema. En ese momento, usando la distribución <emb>archlinux</emb>.</p> <p>Ejecutando file sobre el fichero de kernel obtengo:</p> <pre><code>$ file /boot/vmlinuz-linux /boot/vmlinuz-linux: Linux kernel x86 boot executable bzImage, version 5.14.16-arch1-1 (linux@archlinux) #1 \ SMP PREEMPT Tue, 02 Nov 2021 22:22:59 +0000, RO-rootFS, swap_dev 0X9, Normal VGA</code></pre> -<p>Y revisando la documentación teórica, observo que bzImage debería ir comprimido por <emb>gzip</emb> (<emb>z</emb>). Véase <a href="http://www.linfo.org/vmlinuz.html">vmlinuz.html</a>. De hecho, existe la idea errónea popular de que el prefijo <emb>bz</emb> significa que se utiliza la compresión <emb>bzip2</emb>, pero este no es el caso, por lo que el bz en bzImage no tiene relación con <emb>bzip2</emb>, y <emb>bzImage</emb> no tiene que ser comprimido con <emb>bzip2</emb>, como algunas veces se postula. De hecho, el modo de compresión predeterminado del kernel sigue siendo <emb>gzip</emb>, y hay pocas razones para usar bzip2 hoy en día: es más lento que <emb>LZMA</emb> y <emb>xz</emb>, pero no se comprime tan bien.</p> +<p>Y revisando la documentación teórica, observo que bzImage debería ir comprimido por <emb>gzip</emb> (<emb>z</emb>). Véase <a href="http://www.linfo.org/vmlinuz.html">vmlinuz.html</a>. De hecho, existe la idea errónea popular de que el prefijo <emb>bz</emb> significa que se utiliza la compresión <emb>bzip2</emb>, pero este no es el caso, por lo que el bz en bzImage no tiene relación con <emb>bzip2</emb>, y <emb>bzImage</emb> no tiene que ser comprimido con <emb>bzip2</emb>, como algunas veces se postula. De hecho, el modo de compresión predeterminado del kernel sigue siendo <emb>gzip</emb>, y hay pocas razones para usar bzip2 hoy en día: se descomprime más lento que <emb>LZMA</emb> y <emb>xz</emb>, y no comprime tan bien.</p> <h2>Pero, ¿cómo puedo probarlo empíricamente?</h2> <p>Para determinar de manera concluyente qué compresión se utilizó para una imagen dada del kernel, sin necesidad de ejecutarla o encontrar su configuración, podemos seguir el enfoque utilizado por el propio script <a href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/scripts/extract-vmlinux">extract-vmlinux</a> del kernel.</p> <p>Buscando primero la firma del compresor en la imagen:</p> diff --git a/linus-torvalds-hijas/index.html b/linus-torvalds-hijas/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -13,7 +13,7 @@ <p class="date">1 de marzo de 2019 • fjbalon</p> </header> <p>Me han propuesto un reto: encontrar las fechas de nacimiento de Torvalds y de sus tres hijas en las cabeceras del kernel. Es un easter egg que dejó Linus para los más curiosos. Vamos allá.</p> -<p>Encontrar las fechas es relativamente sencillo para quien sabe dónde buscar. No es mi caso, que tras una breve búsqueda en Internet identifiqué la localización de dichas fechas en la ruta /usr/include/linux/, encontrándose con la extensión .h. Es fácilmente localizable utilizando la conocida herramienta grep y buscando las cadenas de texto 'LINUX REBOOT MAGIC'.</p> +<p>Encontrar las fechas es relativamente sencillo para quien sabe dónde buscar. No es mi caso, que tras una breve búsqueda en Internet identifiqué la localización de dichas fechas en la ruta /usr/include/linux/, encontrándose con la extensión .h. Es fácilmente localizable utilizando la conocida herramienta grep y buscando las cadenas de texto 'LINUX_REBOOT_MAGIC'.</p> <pre><code># grep LINUX_REBOOT_MAGIC /usr/include/linux/*.h /usr/include/linux/reboot.h:#define LINUX_REBOOT_MAGIC1 0xfee1dead /usr/include/linux/reboot.h:#define LINUX_REBOOT_MAGIC2 672274793 @@ -33,18 +33,16 @@ Sun Jan 18 19:33:36 1987</code></pre> <p>Obtenemos las fechas: 22/04/1991, 11/09/1972, 15/09/1981 y 18/01/1987.</p> <p>¿He conseguido el reto? Nada más lejos... Al corroborar la fecha de nacimiento de Linus Torvalds hay algo que no me cuadra. Torvalds nació el 28 de diciembre de 1969. La primera fecha podría pasar; pero las 3 siguientes que correspondieran a las fechas de nacimiento de las 3 hijas me hacen pensar: ¿Torvalds tuvo su primera hija con 3 años? Algo no cuadra.</p> <p>Tras un tiempo de investigación he dado con la tecla: es necesario pasar a hexadecimal para poder leer la fecha. Siendo</p> -<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="0x672274793=2812196928/12/1969" display="block"> +<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="672274793=0x28121969→28/12/1969" display="block"> <mrow> <mrow> - <mn>0</mn> - <mo></mo> - <mi>x</mi> - <mo></mo> <mn>672274793</mn> </mrow> <mo>=</mo> <mrow> - <mn>28121969; 28</mn> + <mn>0x28121969</mn> + <mo>→</mo> + <mn>28</mn> <mo>/</mo> <mn>12</mn> <mo>/</mo> @@ -53,18 +51,16 @@ Sun Jan 18 19:33:36 1987</code></pre> </mrow> </math> <p>el nacimiento de Linus Torvalds,</p> -<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="0x85072278=51219965/12/1996" display="block"> +<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="85072278=0x05121996→5/12/1996" display="block"> <mrow> <mrow> - <mn>0</mn> - <mo></mo> - <mi>x</mi> - <mo></mo> <mn>85072278</mn> </mrow> <mo>=</mo> <mrow> - <mn>5121996; 5</mn> + <mn>0x05121996</mn> + <mo>→</mo> + <mn>5</mn> <mo>/</mo> <mn>12</mn> <mo>/</mo> @@ -73,18 +69,16 @@ Sun Jan 18 19:33:36 1987</code></pre> </mrow> </math> <p>el nacimiento de Patricia Miranda,</p> -<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="0x367369448=1604199816/04/1998" display="block"> +<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="369367448=0x16041998→16/04/1998" display="block"> <mrow> <mrow> - <mn>0</mn> - <mo></mo> - <mi>x</mi> - <mo></mo> - <mn>367369448</mn> + <mn>369367448</mn> </mrow> <mo>=</mo> <mrow> - <mn>16041998; 16</mn> + <mn>0x16041998</mn> + <mo>→</mo> + <mn>16</mn> <mo>/</mo> <mn>04</mn> <mo>/</mo> @@ -93,18 +87,16 @@ Sun Jan 18 19:33:36 1987</code></pre> </mrow> </math> <p>el nacimiento de Daniela Yolanda y</p> -<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="0x537993216=2012200020/12/2000" display="block"> +<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="537993216=0x20122000→20/12/2000" display="block"> <mrow> <mrow> - <mn>0</mn> - <mo></mo> - <mi>x</mi> - <mo></mo> <mn>537993216</mn> </mrow> <mo>=</mo> <mrow> - <mn>20122000; 20</mn> + <mn>0x20122000</mn> + <mo>→</mo> + <mn>20</mn> <mo>/</mo> <mn>12</mn> <mo>/</mo> diff --git a/machine-id/index.html b/machine-id/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -13,7 +13,7 @@ <p class="date">22 de marzo de 2021 • fjbalon</p> </header> <p>¿Qué es el <emb>machine-id</emb>? Desde las páginas de <a href="https://www.man7.org/linux/man-pages/man5/machine-id.5.html">man</a> se define como un identificador exclusivo de la máquina. «Este debe considerarse confidencial y no debe exponerse en entornos que no sean de confianza» se encuentra escrito en la documentación, lo que de primeras nos presenta algunos problemas que he desarrollado más adelante.</p> -<p>Lo primero que hay que entender es que éste se genera en el momento de la instalación del sistema operativo sobre el hardware concreto. Cuando, como administradores de sistemas nos dedicamos a clonar discos, es común que éstos mantengan el mismo identificador, generado a partir del hardware inicial del primer elemento de la clonación. Esto puede provocar conflicto a posteriori, por ejemplo, cuando generamos una interfaz de red bridge, que generará la MAC a partir del <emb>machine-id</emb>, y podría ocasionar conflicto en la red por simultaneidad.</p> +<p>Lo primero que hay que entender es que éste se genera en el momento de la instalación del sistema operativo sobre el hardware concreto. Cuando, como administradores de sistemas nos dedicamos a clonar discos, es común que éstos mantengan el mismo identificador, generado aleatoriamente durante la instalación del primer elemento de la clonación. Esto puede provocar conflicto a posteriori, por ejemplo, cuando generamos una interfaz de red bridge, que generará la MAC a partir del <emb>machine-id</emb>, y podría ocasionar conflicto en la red por simultaneidad.</p> <p>Lo segundo, quizá, es su uso. El uso que da <emb>systemd</emb> al <emb>machine-id</emb> parece ambiguo, sirviendo a:</p> <ul> <li>La creación de identificador de host DHCP (probablemente causando que varias máquinas peleen por la misma dirección IP en el servidor DHCP).</li> diff --git a/mechanic-keyboard/index.html b/mechanic-keyboard/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -16,10 +16,10 @@ <p>Uno de estos elementos es el teclado mecánico. Hace ya un tiempo compré, en <a href="https://www.littlekeyboards.com/">Little Keyboards</a>, dos PCB para hacer un teclado mecánico, ortolineal y dividido (un teclado para cada mano). Usé, de hecho, la PCB <a href="https://github.com/MakotoKurauchi/helix">Helix</a>, diseñada por Makoto Kurauchi. Estéticamente, preciosa:</p> <img src="imagen1.jpeg" /> <h2>Componentes</h2> -<p>Entonces, me hice con los componentes necesarios: PCBs, conectores TTRS Jack, cable TTRS, reset switches, diodos, Cherry MX Blue, Kailh Choc Low Profile Switches -en blanco-… Más exactamente:</p> +<p>Entonces, me hice con los componentes necesarios: PCBs, conectores TRRS Jack, cable TRRS, reset switches, diodos, Cherry MX Blue, Kailh Choc Low Profile Switches -en blanco-… Más exactamente:</p> <ul> <li>Helix Hotswap PCB (2)</li> -<li>TTRS Jack (2)</li> +<li>TRRS Jack (2)</li> <li>Reset switch (2)</li> <li>Diodo (64)</li> <li>Kailh MX Hotswap Socket (64)</li> @@ -45,7 +45,7 @@ <img style="width: 60%;" src="imagen5.jpeg" /> <p>La herramienta que yo utilicé es QMK, basado en Python, y que trae un código por defecto para la placa Helix.</p> <pre><code>python3 -m pip install --user qmk -export PATH=$PATH:/home/ssh/.local/bin +export PATH=$PATH:$HOME/.local/bin qmk setup cd qmk_firmware make helix/rev3_5rows:default:clean @@ -55,7 +55,7 @@ qmk compile -kb helix/rev3_5rows -km default</code></pre> <p>Una ventaja añadida del sea-micro es que cuenta con botón reset integrado. Esto nos permite flashear el firmware sin necesidad de puente hardware o estar soldado ya en PCB de teclado.</p> <img style="width: 60%;" src="imagen7.jpeg" /> <h2>Soldadura de diodos</h2> -<p>Necesitaremos 64 diodos, uno por cada tecla. Son un componente electrónico de dos terminales que permite la circulación de la corriente eléctrica a través de él en un solo sentido, bloqueando el paso si la corriente circula en sentido contrario, no solo sirve para la circulación de corriente eléctrica sino que este la controla y resiste.</p> +<p>Necesitaremos 64 diodos, uno por cada tecla. Son un componente electrónico de dos terminales que permite la circulación de la corriente eléctrica a través de él en un solo sentido, bloqueando el paso si la corriente circula en sentido contrario, lo que evita que, al pulsar varias teclas a la vez, se produzcan pulsaciones fantasma (<i>ghosting</i>).</p> <img style="width: 10%;" src="imagen8.png" /> <img style="width: 60%;" src="imagen9.jpeg" /> <h2>Soldadura de hotswaps</h2> diff --git a/propagacion-malware-script/index.html b/propagacion-malware-script/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -160,6 +160,6 @@ catch { <p>Una vez extraídos, ejecuta <emb>7zr.exe</emb> para extraer el <emb>7z</emb> contenido en los archivos extraídos del zip; usando además la contraseña declarada en las variables. Después invoca un ejecutable (<emb>.exe</emb>).</p> <p>Conocer el propósito del ejecutable es más difícil, habría que ejecutar técnicas de ingeniería inversa para averiguar qué hace, pero podría hacer cualquier cosa: ransomware, troyano, software espía, minero de criptomonedas... Quizá si tenga tiempo me aventiure a montar una máquina virtual aislada con Windows para ejecutarlo y ver qué hace. O analizar el exe a ver si podemos averiguar parte del código y poder deducirlo.</p> <p>Desde luego, nunca dejará de sorprenderme la capacidad y el ingenio humano para el transmitir elementos maliciosos, y como decía, lo peor es que todo este procedimiento de scripting es únicamente para descargar y ejecutar el malware. Es decir, ni siquiera hemos tocado la superficie del malware, sólo su método de infección y propagación.</p> -<p>El tweet ya ha sido eliminado, pero de su eliminación he podido ver que tenía casi 100.000 visualizaciones, es decir, 100.000 de potenciales víctimas; y sólo ha estado publicado 2 horas por una cuenta de unos 50 seguidores. Imagínense las campañas que cuenten con más recursos.</p> +<p>El tweet ya ha sido eliminado, pero de su eliminación he podido ver que tenía casi 100.000 visualizaciones, es decir, hasta 100.000 potenciales víctimas; y sólo ha estado publicado 2 horas por una cuenta de unos 50 seguidores. Imagínense las campañas que cuenten con más recursos.</p> </body> </html> \ No newline at end of file diff --git a/slackware-slackbuild/index.html b/slackware-slackbuild/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -12,8 +12,8 @@ <p class="title">Anatomía de un SlackBuild</p> <p class="date">12 de diciembre de 2025 • fjbalon</p> </header> -<p>Como usuario de Slackware, he usado alguna vez scripts de SlackBuild para crear un paquete de software que pueda ser instalado fácil y limpiamente, y eliminado más tarde si es necesario con la misma facilidad y limpieza. Lo veremos en más profundidad más adelante, pero resumidamente sabemos que un SlackBuild es un script de shell que nos permite compilar e instalar paquetes desde el código fuente, creando un paquete -generalmente <emb>txz</emb>, aunque también <emb>tgz</emb>- y se instala mediante la herramienta nativa de Slackware <emb>installpkg</emb>. Se distribuyen principalmente en el repositorio oficial de <a href="https://slackbuilds.org">slackbuilds.org</a>.</p> -<p>Al final, los SlackBuilds constituyen la forma oficial, digamos, de instalar software que no viene en los repositorios base de Slackware.</p> +<p>Como usuario de Slackware, he usado alguna vez scripts de SlackBuild para crear un paquete de software que pueda ser instalado fácil y limpiamente, y eliminado más tarde si es necesario con la misma facilidad y limpieza. Lo veremos en más profundidad más adelante, pero resumidamente sabemos que un SlackBuild es un script de shell que nos permite compilar e instalar paquetes desde el código fuente, creando un paquete -generalmente <emb>tgz</emb>, aunque también <emb>txz</emb>- y se instala mediante la herramienta nativa de Slackware <emb>installpkg</emb>. Se distribuyen principalmente en el repositorio oficial de <a href="https://slackbuilds.org">slackbuilds.org</a>.</p> +<p>Al final, los SlackBuilds constituyen la forma más extendida, digamos, de instalar software que no viene en los repositorios base de Slackware.</p> <p>Existen diferentes enfoques de un script de SlackBuild, por ejemplo <i>Alien Bob</i> tiene su muy útil <a href="https://alien.slackbook.org/AST/">creador de SlackBuilds</a> y, en términos generales, lo respetaremos. Y como ejemplo mediante el cual encarnar lo que vamos a describir, usaré el paquete <a href="https://slackbuilds.org/repository/15.0/system/ksh-openbsd/">ksh-openbsd</a>. La descarga, generalmente, viene en un paquete comprimido <emb>.tar.gz</emb>, que se destarea y descomprime con <emb>tar xzvf</emb>, siendo el contenido del directorio:</p> <pre><code>ls doinst.sh ksh-openbsd.info ksh-openbsd.SlackBuild README slack-desc</code></pre> @@ -116,7 +116,7 @@ definida.</p> echo "$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE" exit 0 fi</code></pre> -<p>Es una parte muy útil para herramientas de gestión de paquetes como <emb>sbopkg</emb> o <emb>sbotools</emb>. Si la variable <emb>PRINT_PACKAGE_NAME</emb> está definida, aunque vacía, el script imprimirá el nombre completo del paquete (<emb>ksh-openbsd-20190804-x86_64-1_SBo.tgz</emb>). Esto permite a los gestores de paquetes saber el nombre sin tener que construir todo.</p> +<p>Es una parte muy útil para herramientas de gestión de paquetes como <emb>sbopkg</emb> o <emb>sbotools</emb>. Si la variable <emb>PRINT_PACKAGE_NAME</emb> está definida y no está vacía, el script imprimirá el nombre completo del paquete (<emb>ksh-openbsd-20190804-x86_64-1_SBo.tgz</emb>). Esto permite a los gestores de paquetes saber el nombre sin tener que construir todo.</p> <p>Después definirá los entornos de trabajo en <emb>TMP</emb> (por defecto <emb>/tmp/SBo</emb>), <emb>PKG</emb> (directorio donde se va a instalar el software en la fase de compilación) y <emb>OUTPUT</emb> (dónde se almacenará el <emb>.tgz</emb> final).</p> <pre><code>if [ "${ARCH}" == "i586" ];then SLKCFLAGS='-march=i586 -mtune=i686' diff --git a/slackware/index.html b/slackware/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -33,7 +33,6 @@ <li>slackpkg es la herramienta de gestión de paquetes más parecida a APT o DNF, permitiéndote buscar, instalar, actualizar y eliminar paquetes de los repositorios oficiales de Slackware. También puede manejar actualizaciones de seguridad y parches del sistema.</li> <li>sbopkg es un gestor de paquetes para <a href="https://slackbuilds.org/">Slackbuilds.org</a>, que es un repositorio de software fuera del reducido catálogo de Slackware. Diría que es el equivalente a AUR en Archlinux. sbopkg ofrece un conjunto de herramientas de terminal y de dialog que automatizan la compilación e instalación de software. Te permite buscar, descargar, compilar e instalar paquetes slackbuilds.</li> </ol> -</p> </li> </ol> <p>Evidentemente, que a pesar de su rito iniciático, su rigidez, su tradicionalismo y su misticismo, Slackware puede ser utilizado y dominado como cualquier otra distribución de GNU/Linux, se puede instalar el mismo software y se puede conducir de la misma forma. Pero exige, exige al usuario paciencia y sacrificio.</p> diff --git a/ssh-tunneling/index.html b/ssh-tunneling/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -15,16 +15,16 @@ <p>El tunneling es un proceso por el que se utiliza el protocolo SSH para fortificar la comunicación entre otros protocolos inseguros, por ejemplo para realizar peticiones HTTP, SMTP, etc.</p> <p>Los túneles pueden ser locales o remotos. En los túneles locales, la máquina del administrador o cliente redirecciona un puerto local hacia un puerto de la máquina remota, a la que se disponga de acceso. En los túneles remotos se redirecciona un puerto remoto de la máquina remota, a la que se disponga de acceso, a un puerto de la máquina local, donde se encuentra el administrador.</p> <p>La sintaxis para la creación de un túnel local hacia el puerto remoto de la máquina remota es la siguiente:</p> -<pre><code>ssh -L [direccion de escucha:]puerto escucha:maquina remota: puerto remoto usuario@server</code></pre> +<pre><code>ssh -L [dirección de escucha:]puerto escucha:máquina remota:puerto remoto usuario@server</code></pre> <img class="color-invertible" src="resources/ssh01.png"/> <p>El escenario idóneo para la utilización de túneles SSH locales es el siguiente:</p> <ul> <li>Máquina A con conexión a Internet requiere conexión a máquina C, que se encuentra detrás de un servidor que impide el paso. En otras palabras, la máquina C no es accesible desde Internet.</li> -<li>El usuario de la máquina A dispone de cuenta en una máquina B. La máquina B es el servidor que proporciona la salida a Internet a la máquina C. La máquina A creará un túnel con la máquina B y a través del forwarding (véase sección \ref{sshforwarding} para más detalle) de la máquina B llegará a la máquina C.</li> +<li>El usuario de la máquina A dispone de cuenta en una máquina B. La máquina B es el servidor que proporciona la salida a Internet a la máquina C. La máquina A creará un túnel con la máquina B y a través del forwarding de la máquina B llegará a la máquina C.</li> <li>Lo importante es proteger la comunicación en Internet entre la máquina A y B. La comunicación entre B y C puede ir sin cifrar, ya que se encuentra en una Intranet. Aunque también puede ser altamente recomendable fortificar dicha comunicación.</li> </ul> <p>El túnel remoto, por su lado, generará un socket a la escucha en un servidor, el cual al recibir una petición reenviará el tráfico mediante SSH a la máquina local donde se encuentre el administrador. La sintaxis es:</p> -<pre><code>ssh -R puerto local:maquina remota:puerto remoto</code></pre> +<pre><code>ssh -R [dirección de escucha:]puerto remoto:máquina local:puerto local usuario@server</code></pre> <img class="color-invertible" src="resources/ssh02.png"/> <p>Un ejemplo sería querer que una máquina en Internet llegase al interior de la Intranet a través de una máquina puente de la propia red privada, manteniendo una interfaz hacia Internet. El escenario sería el siguiente:</p> <ul> diff --git a/ssh/index.html b/ssh/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -14,12 +14,12 @@ </header> <p>SSH es uno de los protocolos más interesantes de los que dispone el administrador de sistemas, permitiendo acceder a otros equipos de forma remota; pero sobre todo, de forma segura. Con SSH creamos un túnel entre cliente y servidor que simula, en la capa de aplicación, la shell o intérprete de comandos del servidor, dotando al administrador de toda funcionalidad en el equipo.</p> <p>SSH puede considerarse una evolución del protocolo Telnet, pero el primero cuenta con técnicas de criptografía para proteger los datos intercambiados entre ambos nodos que conforman la conexión SSH. SSH utiliza un intercambio de claves basado en el protocolo criptográfico de Diffie-Hellman, imprescindible en el robustecimiento de la capa de transporte.</p> -<p>SSH trabaja sobre el protocolo TCP/IP. Por ello, en primer lugar se realiza la conexión TCP, realizando el three-way handshake. Después de abrir la conexión, cliente y servidor se envían la versión disponible del protocolo. Se utilizará luego el par de claves, pública y privada, de RSA. El servidor enviará su clave pública de host al cliente, de forma que éste pueda cifrar lo que necesite enviar al servidor. El cliente comparará la clave pública de host con la que tenga almacenada en el archivo known_hosts, si lo hubiera.</p> -<p>Una vez el cliente dispone de la clave pública del host del servidor, este generará una clave de sesión aleatoria y seleccionará un algoritmo de cifrado simétrico. Con esta clave de sesión, que se generará por defecto cada 3600 segundos, se cifrará el túnel. El cliente enviará un mensaje que contiene la clave de sesión y el algoritmo de cifrado seleccionado, información que viajará cifrada mediante la clave pública de host, al servidor. En este instante, el resto de la comunicación se utilizará el algoritmo de cifrado simétrico y la clave compartida de sesión, dando velocidad a la conexión (en técnicas de clave simétrica el cifrado y descifrado se hace más rápido), pero utilizando siempre primero el protocolo de Diffie-Hellman para poder enviar de forma segura la clave compartida de sesión; y supliendo así la principal carencia en seguridad de los algoritmos de criptografía simétrica: el intercambio de claves.</p> +<p>SSH trabaja sobre el protocolo TCP/IP. Por ello, en primer lugar se realiza la conexión TCP, realizando el three-way handshake. Después de abrir la conexión, cliente y servidor se envían la versión disponible del protocolo. Se utilizará luego el par de claves, pública y privada, de host del servidor (RSA, ECDSA o Ed25519). El servidor enviará su clave pública de host al cliente, de forma que éste pueda verificar la identidad del servidor. El cliente comparará la clave pública de host con la que tenga almacenada en el archivo known_hosts, si lo hubiera.</p> +<p>Una vez el cliente dispone de la clave pública del host del servidor, ambos acuerdan un algoritmo de cifrado simétrico y, mediante el intercambio de claves de Diffie-Hellman, establecen una clave de sesión compartida sin que ésta viaje por la red; el servidor firma el intercambio con su clave privada de host para demostrar su identidad. Con esta clave de sesión, que se renegocia periódicamente (por defecto, cada hora o cada cierta cantidad de datos transferidos), se cifra el túnel. A partir de este instante, el resto de la comunicación utiliza el algoritmo de cifrado simétrico y la clave compartida de sesión, dando velocidad a la conexión (en técnicas de clave simétrica el cifrado y descifrado se hace más rápido), pero utilizando siempre primero el protocolo de Diffie-Hellman para poder establecer de forma segura la clave compartida de sesión; y supliendo así la principal carencia en seguridad de los algoritmos de criptografía simétrica: el intercambio de claves.</p> <p>Con el túnel creado, se llevará a cabo la autenticación del usuario en el servidor, pudiendo utilizar distintos métodos para llevar a cabo tal autenticación.</p> <img src="resources/ssh00.png" style="width: 70%;"/> - <h1>Autenticación mediante par de claves</h1> + <h2>Autenticación mediante par de claves</h2> <p>Una conexión común usando el protocolo SSH es de por sí segura; al menos más segura que una conexión no cifrada como telnet, pero presenta, grosso modo dos inconvenientes:</p> <ul> <li>La contraseña, aún yendo cifrada, viaja por la red siempre que nos autenticamos. Esto puede ser peligroso en el caso que haya alguien sniffeando el tráfico de nuestra red y fuese capaz de descifrar nuestra clave (mediante ataques por fuerza bruta o diccionario, utilizando alguna vulnerabilidad conocida, etc.).</li> @@ -38,7 +38,6 @@ <p>La configuración del servidor oldscizor es sencilla:</p> <pre><code># /etc/ssh/sshd_config -RSAAuthentication yes PubkeyAuthentication yes AuthorizedKeysFile %h/.ssh/authorized_keys</code></pre> <p>Véase la última línea, donde añadimos el fichero que almacenará las claves públicas de los clientes reconocidos. Si no existiera este directorio y/o fichero deberemos crearlo.</p> @@ -47,11 +46,11 @@ AuthorizedKeysFile %h/.ssh/authorized_keys</code></pre> <pre><code>$ ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/home/scizor/.ssh/id_rsa): -/home/scizor/.ssh/rsa +/home/scizor/.ssh/oldscizor Enter passphrase (empty for no passphrase): Enter same passphrase again: -Your identification has been saved in /home/scizor/.ssh/rsa -Your public key has been saved in /home/scizor/.ssh/rsa.pub +Your identification has been saved in /home/scizor/.ssh/oldscizor +Your public key has been saved in /home/scizor/.ssh/oldscizor.pub The key fingerprint is: SHA256:aVgQfYrakZnFhaw4Gcl0bHqrJj7QtR3dXm332wx9qdE scizor@client The key's randomart image is: @@ -70,16 +69,16 @@ The key's randomart image is: <pre><code>$ eval $(ssh-agent -s) Agent pid 15081 -$ ssh-add ~/.ssh/rsa -Identity added: /home/scizor/.ssh/rsa -(/home/scizor/.ssh/rsa)</code></pre> +$ ssh-add ~/.ssh/oldscizor +Identity added: /home/scizor/.ssh/oldscizor +(/home/scizor/.ssh/oldscizor)</code></pre> Otra opción es utilizar el fichero config: <pre><code># ~/.ssh/config Host oldscizor.es User scizor - IdentityFile ~/.ssh/server_key</code></pre> + IdentityFile ~/.ssh/oldscizor</code></pre> <p>La clave pública deberá ser enviada al servidor y almacenada en authorized_keys o en el fichero seleccionado.</p> <pre><code># cat ~/.ssh/authorized_keys @@ -105,8 +104,6 @@ debug1: Connecting to oldscizor.es [54.38.52.183] port 22. debug1: Connection established. debug1: identity file /home/scizor/.ssh/oldscizor type 0 debug1: identity file /home/scizor/.ssh/oldscizor-cert type -1 -debug1: identity file /home/scizor/.ssh/scizorc type 0 -debug1: identity file /home/scizor/.ssh/scizorc-cert type -1 debug1: Local version string SSH-2.0-OpenSSH_8.8 debug1: Remote protocol version 2.0, remote software version OpenSSH_7.9p1 Debian-10+deb10u2 debug1: compat_banner: match: OpenSSH_7.9p1 Debian-10+deb10u2 pat OpenSSH* compat 0x04000000 @@ -134,7 +131,6 @@ debug1: expecting SSH2_MSG_NEWKEYS debug1: SSH2_MSG_NEWKEYS received debug1: rekey in after 134217728 blocks debug1: Will attempt key: /home/scizor/.ssh/oldscizor RSA SHA256:zFOQBJRsUuKhgVyvCkKaJDcJ/Y7qWq2VEN1lRkJxL74 explicit -debug1: Will attempt key: /home/scizor/.ssh/scizorc RSA SHA256:0zdBByBWUvwkcfgcRYL68IdoNMOmJwijG2QiHsgcTaM explicit debug1: SSH2_MSG_EXT_INFO received debug1: kex_input_ext_info: server-sig-algs=&lt;ssh-ed25519,ssh-rsa,rsa-sha2-256,rsa-sha2-512,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521&gt; debug1: SSH2_MSG_SERVICE_ACCEPT received @@ -165,13 +161,13 @@ permitted by applicable law. Last login: Tue Nov 16 21:56:22 2021 from 172.16.7.12 scizor@oldscizor:~$</code></pre> <p>El cliente lee el fichero ssh_config antes de realizar la conexión al servidor oldscizor.es en su puerto por defecto 22. Tras esto, se crea la conexión TCP y, una vez se realiza el three-way handshake entre cliente y servidor, la conexión queda establecida; pero aún no existe canal cifrado.</p> -<p>El cliente verifica la existencia de posibles claves privadas y verifica si se encuentra alguna en la lista negra. Una vez realizado este proceso, verifica también la versión del protocolo. Es en este instante en el que se intercambian la clave pública host del servidor al cliente, para que éste pueda generar y cifrar la clave simétrica, la cual será la encargada de cifrar el canal.</p> +<p>El cliente verifica la existencia de posibles claves privadas y verifica si se encuentra alguna en la lista negra. Una vez realizado este proceso, verifica también la versión del protocolo. Es en este instante en el que se intercambian la clave pública host del servidor al cliente, para que éste pueda verificar la identidad del servidor y acordar la clave simétrica, la cual será la encargada de cifrar el canal.</p> <p>Una vez el cliente recibe la clave del host, la verifica en el fichero known_hosts. Si se encuentra, se verifica la identidad del servidor. Si por el contrario no se encuentra mostraría un mensaje avisando de la posible suplantación (por defecto).</p> <p>Tras aceptar el cliente al servidor, verificando la identidad de éste, se establece la conexión en un canal ya seguro. El servidor envía el banner y el cliente lo muestra por pantalla. Después, el servidor envía al cliente los métodos de autenticación para el usuario de los que se disponen y el cliente valorará su configuración previamente cargada para realizar la autenticación pertinente; que en nuestro ejercicio es una autenticación basada en claves RSA, y tras autenticarse, se envían desde el servidor las variables de entorno de la sesión y proporciona el control de la shell en remoto.</p> - <h1>Aplicaciones del protocolo SSH</h1> + <h2>Aplicaciones del protocolo SSH</h2> <p>Sobre SSH existen varias aplicaciones que sirven de arsenal bastante completo al administrador de sistemas. Enumero las que conozco:</p> -<h2>Automatización envío de claves públicas RSA</h2> +<h3>Automatización del envío de claves públicas RSA</h3> <p>La utilidad ssh-copy-id permite enviar las claves públicas directamente a tantos servidores sea necesario, automatizando y simplificando la comunicación cifrada contra múltiples equipos sin necesidad de abrir una sesión en cada uno de ellos.</p> <pre><code> .---------------------------------------. @@ -209,12 +205,12 @@ scizor@oldscizor:~$</code></pre> |----------------------------------------| | ssh-rsa AAAA... user10@host | '----------------------------------------'</code></pre> -<h2>Automatización de contraseñas con sshpass</h2> -<p>Aunque no soy amigo de utilizar la autenticación básica por contraseña en mis infraestructuras SSH, a veces es necesario autenticar de esta forma, y nunca esta utilidad que permite al usuario cierta automatización a la hora de gestionar conexiones, principalmente cuando esta administración se hace desde otros programas o scripts donde no puede haber interactividad directa. La utilidad sshpass está diseñada para ejecutar SSH utilizando el modo de autenticación de contraseña interactiva de teclado, pero de una manera no interactiva, utilizando acceso TTY directo para garantizar que la contraseña sea emitida por un usuario de teclado interactivo, engañando a SSH haciéndole creer que está obteniendo la contraseña de un usuario interactivo.</p> +<h3>Automatización de contraseñas con sshpass</h3> +<p>Aunque no soy amigo de utilizar la autenticación básica por contraseña en mis infraestructuras SSH, a veces es necesario autenticar de esta forma, y por ello no está de más conocer esta utilidad, que permite al usuario cierta automatización a la hora de gestionar conexiones, principalmente cuando esta administración se hace desde otros programas o scripts donde no puede haber interactividad directa. La utilidad sshpass está diseñada para ejecutar SSH utilizando el modo de autenticación de contraseña interactiva de teclado, pero de una manera no interactiva, utilizando acceso TTY directo para garantizar que la contraseña sea emitida por un usuario de teclado interactivo, engañando a SSH haciéndole creer que está obteniendo la contraseña de un usuario interactivo.</p> <p>Su modo de uso es tan sencillo como indicar previamente a la comunicación con el servidor SSH la clave de éste tras el comando propio de sshpass:</p> <pre><code>$ sshpass -p !4u2tryhack ssh user@host</code></pre> -<h2>SCP</h2> +<h3>SCP</h3> <p>SCP o Secure Copy es un protocolo similar funcionalmente a RCP (Remote Copy), cuyo objetivo es transferir archivos desde una máquina a otra. La diferencia entre ambos protocolos es que SCP utiliza el protocolo SSH para establecer sus comunicaciones, estableciendo un túnel cifrado por el que enviar dichos archivos.</p> <p>La ejecución de SCP es realmente sencilla, contando con la sintaxis:</p> @@ -229,14 +225,14 @@ scizor@oldscizor:~$</code></pre> <pre><code>$ scp oldscizor:/usr/archivo2 /home/scizor/archivo2</code></pre> <p>Cabe destacar que también podemos realizar copias seguras entre máquinas remotas, no necesariamente debe ser un origen o destino local:</p> <pre><code>$ scp oldscizor.es:/root/origen root@172.16.1.2:/etc/destino</code></pre> - <h2>SFTP</h2> + <h3>SFTP</h3> <p>SSH File Transfer Protocol o SFTP permite el envío de ficheros a nivel de aplicación, a través de SSH, utilizando las aplicaciones y los comandos propios del protocolo FTP. Es sabido que el protocolo FTP no es seguro per se, debido a que no cuenta con cifrado.</p> <p>La sintaxis es similar al protocolo FTP, manteniendo una vez establecida la conexión una cadena de conexión a nivel de aplicación similar a SSH.</p> <pre><code>$ sftp oldscizor.es -Connected to 10.101.5.3- +Connected to oldscizor.es. sftp></code></pre> -<h2>SSHFS</h2> +<h3>SSHFS</h3> <p>El protocolo SSH dispone de la posibilidad de gestionar el sistema de archivos de manera remota y segura utilizando SSHFS o Secure Shell File System. En el equipo local donde se realiza el montaje de SSHFS, la implementación hace uso del módulo del kernel FUSE.</p> <p>La sintaxis es sencilla. Se debe ejecutar el comando sshfs seguido de la ruta remota que se quiere montar localmente y, por último, la ruta local que se utilizará como punto de montaje.</p> @@ -250,7 +246,7 @@ drwxr-xr-x 7 git git 4096 Nov 12 10:22 dmenu.git drwxr-xr-x 7 git git 4096 Nov 15 09:32 dotfiles.git drwxr-xr-x 7 git git 4096 Nov 9 23:32 dwm.git</code></pre> <p>Una vez realizado el montaje, se puede utilizar cualquier tipo de operación como si la ruta fuera local. También podemos utilizar sobre el punto de montaje cualquier software, como un gestor de archivos gráfico para desempeñar el trabajo que sea. Todas las acciones remotas las hará de forma transparente al usuario y mediante un túnel cifrado.</p> -<h2>X11 forwarding</h2> +<h3>X11 forwarding</h3> <p>Esta opción del protocolo SSH permite al usuario conectarse a un servidor para levantar procesos que requieran de un servidor gráfico para su interacción. De tal modo que un administrador pueda, por ejemplo, ejecutar un navegador en un servidor remoto, y la presentación gráfica se realizará en la máquina local a pesar del proceso encontrarse ejecutando en la máquina remota. Evidentemente, toda comunicación cliente-servidor se realizará de manera segura mediante el protocolo SSH, por lo que los datos de presentación del proceso viajarán por la red bajo este protocolo. Para poder redirigir la salida de las ventanas de los procesos que se ejecutan, el servidor debe habilitar la directiva X11Forwarding en su fichero sshd_config.</p> <p>Si bien el <a href="../ssh-tunneling/">SSH Tunneling</a> puede considerarse una aplicación del protocolo, he decidido hacer una entrada aparte sólo para ese caso, pues es más complejo y especial.</p> diff --git a/swap/index.html b/swap/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -13,8 +13,8 @@ <p class="date">27 de febrero de 2020 • fjbalon</p> </header> <p>El caso que hoy me ocupa, nace de la necesidad de apagar la memoria de intercambio (o swap) en mi equipo portátil para poder gestionar varias pruebas sobre clústers de kubernetes. Algo curioso, pues ningún programa me había obligado nunca a apagar la swap para funcionar (ya sé que puedo configurar kubernetes para evitar esta obligación, pero no se trata de un artículo sobre cómo evadir esta opción, sino de la memoria swap en sí). A raíz de este hecho, han avivado en mi memoria las viejas discusiones sobre la necesidad, o no, de la memoria de intercambio.</p> -<p>Allá por el 2008, <a href="https://etbe.coker.com.au/2007/09/28/swap-space">Russell Coker discutía</a> sobre el uso de memoria swap que se daba en sistemas Unix, asegurando que la 'tradición' de utilizar el doble de swap que de RAM era obsoleto con las memorias de entonces (imagínese las actuales), llegando a la conclusión de que el tamaño más adecuado es el mismo que el tamaño de la memoria RAM siempre que ésta sea inferior a 1GB; la mitad del tamaño de la RAM cuando ésta tenga un tamaño de entre 2GB y 4GB; y 2GB de swap cuando el tamaño de la RAM sea mayor de 4GB. Coker además dudaría que exista ningún sistema de almacenamiento masivo que pueda manejar la carga de más de 2GB de espacio de intercambio en uso activo.</p> -<p>¿Es necesaria la swap? La pregunta nace debido a que, por otro lado, hay quien defiende que hoy en día, con módulos de memoria baratos y de tal almacenamiento (tenga en cuenta que en mi equipo portátil tengo un almacenamiento de 32GB RAM), y debido al hecho de que el propio uso de memoria de intercambio supone una caída importante de rendimiento, la swap estaría obsoleta. También influye la idea de que, debe ser preferible tener suficiente RAM para evitar que llegue a sobrecargarse nunca y a necesitar espacio adicional, quedando éste relegado para máquinas con poca RAM o equipos antiguos.</p> +<p>Allá por el 2007, <a href="https://etbe.coker.com.au/2007/09/28/swap-space">Russell Coker discutía</a> sobre el uso de memoria swap que se daba en sistemas Unix, asegurando que la 'tradición' de utilizar el doble de swap que de RAM era obsoleto con las memorias de entonces (imagínese las actuales), llegando a la conclusión de que el tamaño más adecuado es el mismo que el tamaño de la memoria RAM siempre que ésta sea inferior a 1GB; la mitad del tamaño de la RAM cuando ésta tenga un tamaño de entre 1GB y 4GB; y 2GB de swap cuando el tamaño de la RAM sea mayor de 4GB. Coker además dudaría que exista ningún sistema de almacenamiento masivo que pueda manejar la carga de más de 2GB de espacio de intercambio en uso activo.</p> +<p>¿Es necesaria la swap? La pregunta nace debido a que, por otro lado, hay quien defiende que hoy en día, con módulos de memoria baratos y de tal almacenamiento (tenga en cuenta que en mi equipo portátil tengo una memoria de 32GB RAM), y debido al hecho de que el propio uso de memoria de intercambio supone una caída importante de rendimiento, la swap estaría obsoleta. También influye la idea de que, debe ser preferible tener suficiente RAM para evitar que llegue a sobrecargarse nunca y a necesitar espacio adicional, quedando éste relegado para máquinas con poca RAM o equipos antiguos.</p> <p>Al respecto, <a href="https://web.archive.org/web/20081022092522/http://sourcefrog.net/weblog/software/linux-kernel/swap.html">Martin Pool aseveraba en 2004</a>, que cuando el sistema empieza a quedarse sin memoria, el núcleo escogerá qué páginas pasan al disco, siendo normalmente las que se usan con menor frecuencia. Si una página escogida es 'no anónima' <sup>1</sup> siempre existe un archivo que sirve de respaldo al contenido de la página, por lo que puede ser recuperada fácilmente en el caso de que volvamos a necesitarla. Pero las páginas anónimas carecen de dicho respaldo, por lo que solo pueden ser salvadas y copiadas en la swap. Sin embargo, si no tenemos suficiente memoria, el kernel no podrá escoger páginas 'no anónimas' para liberarla, obligando al sistema a ganar memoria a costa de páginas 'no anónimas', aunque éstas estén siendo utilizadas en mayor medida que las anónimas, afectando al rendimiento del sistema. «Disk is cheap, so allocate a gigabyte or two for swap».</p> <p>Evidentemente, es necesario tener en cuenta, aparte del rendimiento, la seguridad. Existen circunstancias imprevisibles que pueden suceder, como que una acción requiera mucho más espacio del esperado, que un programa se vuelva loco (algo muy común si programamos), etc.</p> <p>Por lo tanto, concluimos que la swap no está obsoleta. Pero, ¿cuánta swap debo reservar en mi sistema?. Como ya he comentado anteriormente, la memoria de Coker se ha convertido en prácticamente una regla. Para equipos con 8GB o 16GB emplear 2GB de swap es correcto, pero, ¿lo sigue siendo para equipos con 32GB, 64GB o 256GB de RAM? 2GB se antoja poco, aparentemente.</p> @@ -25,9 +25,9 @@ <pre><code><b>RAM Swap Swap+Hib</b> <b>RAM Swap Swap+Hib</b> <b>RAM Swap Swap+Hib</b> 256MB 256MB 512MB 6GB 2GB 8GB 32GB 6GB 38GB 512MB 512MB 1GB 8GB 3GB 11GB 64GB 8GB 72GB -1GB 1GB 2GB 12GB 3GB 15GB 128GB 12GB 140GB +1GB 1GB 2GB 12GB 3GB 15GB 128GB 11GB 139GB 2GB 1GB 3GB 16GB 4GB 20GB 256GB 16GB 272GB -4GB 2GB 6GB 24GB 5GB 29GB 512GB 22GB 534GB</code></pre> +4GB 2GB 6GB 24GB 5GB 29GB 512GB 23GB 535GB</code></pre> <p><sup>1</sup> Una página anónima es aquella que no corresponde con ningún archivo en disco. Eso incluye la pila, el montón o la memoria reservada dinámicamente con <emb>malloc()</emb>.</p><p><sup>2</sup> La hibernación, o suspensión en disco, consiste en apagar un ordenador conservando su estado, hecho que se logra volcando el contenido de la memoria RAM en la partición de memoria swap, que después se restaura.</p> </body> diff --git a/tanque-gasoil/index.html b/tanque-gasoil/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> diff --git a/tor/index.html b/tor/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -15,7 +15,7 @@ <p>Tor son las siglas de The Onion Routing, algo que podríamos traducir al español como enrutamiento cebolla; denominado así por su criptografía en capas, como veremos más adelante. Se trata de un proyecto de software libre creado originalmente con fines militares por parte del ejército y la inteligencia norteamericanas, con el objetivo de dar comunicaciones seguras, privadas y anónimas entre espías y agentes en campo enemigo orientado a las operaciones realizadas en territorios, principalmente soviéticos.</p> <p>Tor consiste en una gran red descentralizada compuesta por nodos repartidos por todo el mundo, a través de los cuales viajan nuestros paquetes de red dotando de anonimato, como veremos más tarde. Tras ser abandonado por el ejército fue reciclado por la Electronic Frontier Foundation y, finalmente soportado por su propia comunidad.</p> <p>El objetivo de Tor es preservar la privacidad y el anonimato (diferenciados) de los que navegan por su red, manteniendo comunicaciones seguras, asegurando la integridad de la información, pretendiendo evitar monitorización y registro de actividad, etc. Con el fin de proteger la libertad de los usuarios en Internet y evitar la censura. Actualmente es utilizado por diversos perfiles, desde disidentes políticos de países autoritarios, denunciantes, periodistas, gobiernos, hackers --tanto de sombrero blanco como de sombrero negro--, vendedores de diversa índole e, incluso narcotraficantes, delincuentes, etc. El anonimato ofrecido, como en cualquier herramienta, es un arma de doble filo.</p> -<p>Es necesario continuar esta contextualización definiendo la red profunda de la que tanto se habla -y con tan poco fundamento en muchas ocasiones-. La definición es clara y concisa: la deep web es el contenido de internet que no está indexado por los motores de búsqueda convencionales, sea por la razón que sea. Como podemos ver, no existe delincuencia ni malicia en la propia definición de esta. Un servidor privado conectado mediante Dynamic DNS que permite trabajar con direcciones IP dinámicas. de un particular o cualquier base de datos empresarial (que lógicamente no es accesible mediante indexadores) podría considerarse y, de hecho, se considera parte de la red profunda.</p> +<p>Es necesario continuar esta contextualización definiendo la red profunda de la que tanto se habla -y con tan poco fundamento en muchas ocasiones-. La definición es clara y concisa: la deep web es el contenido de internet que no está indexado por los motores de búsqueda convencionales, sea por la razón que sea. Como podemos ver, no existe delincuencia ni malicia en la propia definición de esta. Un servidor privado de un particular (por ejemplo, conectado mediante Dynamic DNS, que permite trabajar con direcciones IP dinámicas) o cualquier base de datos empresarial (que lógicamente no es accesible mediante indexadores) podría considerarse y, de hecho, se considera parte de la red profunda.</p> <p>Cuando la cultura popular se refiere a la red Tor como homóloga a la Deep Web, lo hace erróneamente. Sí es cierto que debemos admitir a la red Tor (y cualquier red semejante o parecida, como las redes i2p o freenet) como parte de la deep web. Para solucionar este conflicto de conceptos, se ideó la conocida como darknet o red oscura, haciendo referencia exclusivamente a estas redes especiales; concepto que vuelve a ser salpicado por la leyenda negra que lo absorbe -que no exime de la existencia de inmoralidad y delincuencia en ella, hay que admitir-. Por ello, en el presente documento se hablará con propiedad a la hora de mencionar la deep web y la darknet.</p> <p>A priori la técnica detrás de Tor puede parecer muy complejo, pero en lo que avanza el desarrollo de este documento podremos comprobar que su funcionamiento es sencillo; no eximiendo un grandísimo potencial de uso y, como veremos más adelante, un gran margen de mejora.</p> <p>Si nos conectamos a Internet de manera habitual, nuestra dirección IP pública y un conjunto de información más quedará expuesta, tanto para el destino de la conexión como para Man in the Middle, las propias empresas que nos proveen servicios, autoridades, gobiernos, etc. Además si la conexión no se encuentra cifrada podrá incluso filtrarse contraseñas y mensajes secretos y confidenciales. Todo lo que hacemos en Internet puede ser --y se encuentra, de hecho-- monitorizado y almacenado.</p> @@ -24,7 +24,7 @@ <img class="color-invertible" src="resources/torconn.png" /> <p>El proceso continuará hasta llegar al nodo de salida y este (Moscú) pedirá la página deseada (recordamos que este servidor verá como cliente a Moscú y no a nosotros) y realizará el mismo proceso de cifrado pero a la inversa, para devolverla al cliente de Tor. A continuación será desglosado este tema tan amplio como la criptografía, en concreto lógicamente la de la red que estamos estudiando.</p> <p>Tor es el heredero del sistema desarrollado por el Departamento de Defensa de Estados Unidos. Ahondando un poco más en el tema, podemos llamar a David M. Goldschlag, Michael Reed y Paul Syverson los padres del encaminamiento cebolla, idea algorítmica que precede y, es a su vez, núcleo del concepto y de la técnica de Tor. Éstos se basaron y aplicaron las ideas de redes de mezclado de David Chaum. El objetivo fundamental y sin añadidos de estos conceptos criptográficos no es más que permitir infraestructuras para comunicaciones privadas sobre redes públicas.</p> -<p>Tor no es la única red basada en estos conceptos criptográficos y algorítmicos, pero sí es la más conocida, la más utilizada y, en principio, la que mejor resultados otorgan a los usuarios. Además, el tratarse de una red de software libre y de código abierto ha permitido la afluencia de una gran comunidad de desarrolladores que la han hecho crecer y mejorar. Dicho esto, podemos hacer menciones honoríficas a otras redes que, como Tor, siguen esta idea: Freedom Network, Onion Routing, MixMaster, Babel, Mixminion, Zach Brown's Onion, PipeNet, IronKey, MorphMix, y Tarzan.</p> +<p>Tor no es la única red basada en estos conceptos criptográficos y algorítmicos, pero sí es la más conocida, la más utilizada y, en principio, la que mejor resultados otorgan a los usuarios. Además, el tratarse de una red de software libre y de código abierto ha permitido la afluencia de una gran comunidad de desarrolladores que la han hecho crecer y mejorar. Dicho esto, podemos hacer menciones honoríficas a otras redes que, como Tor, siguen esta idea: Freedom Network, Onion Routing, MixMaster, Babel, Mixminion, Zach Brown's Onion, PipeNet, MorphMix, y Tarzan.</p> <h2>Idea primigenia</h2> <p>La idea primigenia era utilizar criptografía de clave asimétrica tradicional. Este sistema es vulnerable a ataques basados en sniffing de tráfico. Efectivamente, supongamos que un atacante puede esnifar todos los datos que son intercambiados entre los nodos. Si finalmente el atacante consigue comprometer todos los routers (accediendo a sus claves privadas) entonces este puede descifrar todo el tráfico almacenado anteriormente. </p> <p>Para acotar este problema podríamos cambiar periódicamente las claves (pública y privada) de los routers. Para ello estableceríamos un periodo de tiempo a la finalización del cual las claves caducarían y sería necesario establecer nuevas claves. La clave pública habría que difundirla y la antigua clave privada se destruiría para que no pudiera ser obtenida nunca, asegurando así la persistencia de la seguridad del tráfico que se realizó usando la antigua clave. Sería acertado que el cambio de claves fuera frecuente ya que esto limitaría la cantidad de tiempo que tiene A para comprometer B y C, pero a la vez requeriría que los routers del sistema contactaran frecuentemente con un sistema que les actualizara las nuevas claves lo que llevaría a problemas de escalabilidad. En resumidas cuentas: viable pero poco práctico.</p> diff --git a/unix-passwd/index.html b/unix-passwd/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -15,11 +15,11 @@ <p>El contenido del fichero <emb>/etc/passwd</emb> determina el esqueleto de usuarios del sistema, constituyéndose como la primera línea de defensa del sistema contra accesos no deseados, por lo que debe mantenerse escrupulosamente y libre de errores y fallos de seguridad. En él mantenemos registrados las cuentas de usuarios, así como las claves de accesos y privilegios. Separado por :, indica respectivamente el nombre del usuario, la clave cifrada, UID, GID, nombre completo del usuario, directorio de trabajo (<emb>/home</emb>) e intérprete usado. Si el campo de contraseña, en lugar de contener la clave cifrada contiene una x indica que la clave se encuentra cifrada en el archivo <emb>/etc/shadow</emb>, dando un mayor grado de seguridad. La sintaxis de passwd es:</p> <pre><code>usuario1:FXWUuZ.vwXttg:500:501:usuario pepito:/home/usuario1:/bin/bash</code></pre> <p>Los permisos predeterminados de passwd son 644 y los propietarios son root:root, evitando modificaciones erróneas, de modo que cualquier usuario sólo pueda leer el archivo.</p> -<p>Por otro lado, el archivo <emb>/etc/shadow</emb> almacena información sensible de los usuarios; que separados por :, indica respectivamente el nombre del usuario, la clave cifrada, el lastchanged o último cambio de contraseña en días transcurridos desde el 1 de enero de 1970, el mínimo número de días entre cambios de contraseña, el máximo número de días de validez de la cuenta, los días que avisa antes de caducar la cuenta, los días desde que caduca una contraseña para deshabilitar la cuenta y la fecha de caducidad de la cuenta en días transcurridos desde el 1 de enero de 1970. Su sintaxis es:</p> +<p>Por otro lado, el archivo <emb>/etc/shadow</emb> almacena información sensible de los usuarios; que separados por :, indica respectivamente el nombre del usuario, la clave cifrada, el lastchanged o último cambio de contraseña en días transcurridos desde el 1 de enero de 1970, el mínimo número de días entre cambios de contraseña, el máximo número de días de validez de la contraseña, los días que avisa antes de caducar la cuenta, los días desde que caduca una contraseña para deshabilitar la cuenta y la fecha de caducidad de la cuenta en días transcurridos desde el 1 de enero de 1970. Su sintaxis es:</p> <pre><code>test:$1$CQoPk7Zh$370xDLmeGD9m4aF/ciIlC.:14425:0:99999:7:::</code></pre> -<p>Los permisos predeterminados de passwd son 400 y los propietarios son root:root, sólo puede leer root. La contraseña se puede cifrar utilizando diferentes métodos, que son reconocidos por el identificador presente después del primer carácter $$. A continuación puedes tener el valor del id y la técnica de cifrado correspondiente que indica:</p> -<pre><codeb>$1$: MD5: $1$5df9f63916ebf8528697b629022993e8/li> -$2a$: blowfish (pez globo): $2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy</li> +<p>Los permisos predeterminados de shadow son 400 (o 640 con propietarios root:shadow, según la distribución) y los propietarios son root:root, sólo puede leer root. La contraseña se puede cifrar utilizando diferentes métodos, que son reconocidos por el identificador presente después del primer carácter $$. A continuación puedes tener el valor del id y la técnica de cifrado correspondiente que indica:</p> +<pre><codeb>$1$: MD5: $1$CQoPk7Zh$370xDLmeGD9m4aF/ciIlC. +$2a$: blowfish (pez globo): $2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy $5$: SHA-256: $5$93fa3e4624676f2e9aa143911118b4547087e9b6e0b6076f2e1027d7a2da2b0a $6$: SHA-512: $6$6859f96680702a57a951eabe43fec49964ea51dde72df97e43a1fcf6f8b41b89a51cae8f3162c0cbb3e7fd0850577759aa653e25c4bdfd57264015fa6588360f</codeb></pre> <p>De la misma forma que se organiza y componen los ficheros anteriores sobre los usuarios, tenemos los ficheros <emb>/etc/group</emb> (similar a <emb>/etc/passwd</emb>) y <emb>/etc/gshadow</emb> (similar a <emb>/etc/shadow</emb>); ambos con la diferencia que no se centran en los usuarios, sino en los grupos, que separados por :, indica respectivamente el nombre de grupo, la clave cifrada, GID y la lista de usuarios que pertenecen al grupo separados por ,. La sintaxis es:</p> @@ -39,7 +39,7 @@ john --wordlist=diccionario.lst --rules unshadowed # Diccionario Using default input encoding: UTF-8 Loaded 4 password hashes with 4 different salts (sha512crypt, crypt(3) $6$ [SHA512 128/128 AVX 2x]) -Remaining 1 password hash +Remaining 3 password hashes Cost 1 (iteration count) is 5000 for all loaded hashes Will run 2 OpenMP threads Proceeding with single, rules:Single diff --git a/urxvtd/index.html b/urxvtd/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -91,7 +91,7 @@ URxvt.internalBorder: 20</code></pre></li> <li>Desactivada barra estética de desplazamiento y mantenemos el estilo tradicional de urxvt<pre><code>URxvt*scrollBar: false URxvt.scrollStyle: rxvt</code></pre></li> <li>Hace que urxvt inicie un shell de login, que leerá los archivos de inicialización específicos de login del shell.<pre><code>URxvt*loginShell: true</code></pre></li> - <li>Habilita el desplazamiento con Shift-PageUp/PageDown, útil cuando se usa screen o tmux.<pre><code>Urxvt*secondaryScroll: true</code></pre></li> + <li>Habilita el desplazamiento con Shift-PageUp/PageDown, útil cuando se usa screen o tmux.<pre><code>URxvt*secondaryScroll: true</code></pre></li> <li>Definida a 5000 el número de líneas que se guardan en el historial de desplazamiento.<pre><code>URxvt*saveLines: 5000</code></pre></li> <li>Establece el nombre del terminal (valor de $TERM), que es importante para la compatibilidad con aplicaciones que detectan el tipo de terminal.<pre><code>URxvt*termName: rxvt-unicode</code></pre></li> <li>Habilita extensiones Perl comunes, incluyendo la detección de URLs (<emb>matcher</emb>), manejo del portapapeles (<emb>clipboard</emb>), y la copia de selecciones al portapapeles (<emb>selection-to-clipboard</emb>).<pre><code>URxvt.perl-ext-common: default,matcher,clipboard,selection-to-clipboard</code></pre></li> diff --git a/watchdog/index.html b/watchdog/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -22,22 +22,21 @@ <li>Reinicios aleatorios impredecibles.</li> </ul> <p>Por lo que es preferible evitar el uso de servidores en vivo para probar el funcionamiento de watchdog.</p> -<ol> -<li>Watchdog module</li> +<h2>1. Watchdog module</h2> <p>La funcionalidad de watchdog sobre hardware configura un temporizador que agota el tiempo de espera después de un período predeterminado. El software de watchdog actualiza periódicamente el temporizador del hardware, y si éste deja de actualizarse luego del período establecido el temporizador realizará un restablecimiento de hardware del dispositivo. Para que un temporizador watchdog sea funcional, el fabricante de la placa base tiene que permitir esta funcionalidad en el chip.</p> <p>A menudo, la documentación del fabricante de hardware no deja claro sobre si se implementó o no esta funcionalidad. En ese caso hay que testearlo directamente.</p> <p>Además es necesario el módulo del kernel de vigilancia correcto, que será cargado en el sistema Linux. Diferentes chips utilizan diferentes módulos, por ejemplo:</p> <ul> <li>Intel utiliza <emb>iTCO_wdt</emb>.</li> <li>El hardware de HP utiliza <emb>hpwdt</emb>.</li> -<li>Los mainframes de IBM utilizan <emb>vmwatchdog</emb>.</li> +<li>Los mainframes de IBM utilizan <emb>vmwatchdog</emb>.</li></li> <li>Xen VM utiliza <emb>xen_wdt</emb>.</li> </ul> <p>Una vez corroborado la carga del módulo es posible verificar <emb>/dev/watchdog</emb> en el sistema Linux. Si el archivo está presente, significa que se cargó el controlador. El sistema escribe periódicamente a <emb>/dev/watchdog</emb> (esta acción suele llamarse coloquialmente <i>patear o alimentar al perro guardián</i> o <i>kicking or feeding the watchdog</i>). Si el sistema falla y no 'patea' o 'alimenta' al perro, el sistema se restablecerá completamente.</p> -<li>Watchdog daemon</li> +<h2>2. Watchdog daemon</h2> <p>El demonio de watchdog abre el dispositivo y proporciona la actualización necesaria para evitar que el sistema se restablezca. Éste puede comprobar el espacio de la tabla de procesos, el uso de memoria (memory usage), la accesibilidad de archivos, la carga de trabajo, desbordamientos en la tabla de archivos, ping a direcciones IP, tráfico de interfaz de red, temperatura, procesos en ejecución, etc. Como ya hemos visto, si las pruebas fallan el perro provocará el apagado.</p> <p>El demonio de watchdog debería iniciarse en el momento del arranque. Podemos verificar si está iniciado con:</p> -<pre><code>ps -af | grep watch*</code></pre> +<pre><code>ps -af | grep watchdog</code></pre> <p>Si el kernel no estuviera compilado con <emb>CONFIG_WATCHDOG_NOWAYOUT</emb> y cerramos correctamente <emb>/dev/watchdog</emb> no habrá reinicio. Podemos escribir un carácter V en <emb>/dev/watchdog</emb> y luego cerrar el archivo; lo que detendrá al perro guardián.</p> <p>Si queremos comprobar que el control de hardware está funcionando, podemos lanzar la siguiente orden con privilegios root:</p> <pre><code>cat >> /dev/watchdog</code></pre> @@ -46,6 +45,5 @@ <pre><code># cat /etc/watchdog.conf realtime = yes priority = 1</code></pre> -</ol> </body> </html> \ No newline at end of file diff --git a/xz-liblzma/index.html b/xz-liblzma/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<html> +<html lang="es"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> @@ -13,11 +13,11 @@ <p class="date">1 de abril de 2024 • fjbalon</p> </header> <p>Como bien se sabe, este no es un blog de noticias. Ni me interesan por regla común, ni mucho menos quiero ser partícipe o servidor de ellas. Este es un blog que se centra en el mundo de las ideas, de la técnica, de lo permanente, de lo relativamente inmutable. No obstante, me gustaría hacer una noble excepción, no para producir ni informar sobre la noticia, sino para analizar la portentosa técnica que encierra.</p> -<p>Y me refiero a la noticia, que habréis visto en diversos foros de GNU/Linux y feudos de noticias técnicas; y no habréis visto en ningún medio de masas, del intento de backdoor en SSH a través de la biblioteca de <emb>xz/liblzma</emb>.</p> +<p>Y me refiero a la noticia, que habréis visto en diversos foros de GNU/Linux y feudos de noticias técnicas; y poco habréis visto en los medios de masas generalistas, del intento de backdoor en SSH a través de la biblioteca de <emb>xz/liblzma</emb>.</p> <p>He considerado que la complejidad del ataque, de una precisión y técnica sobresaliente y digna de un gran intelecto, merece unas letras y un breve análisis.</p> <p>La biblioteca de <emb>lzma</emb> comprometida activaría, a través de un enlace de <emb>openssh</emb>, a <emb>sd_notify</emb> (<i>systemd notify</i>) para obtener código oculto en <emb>liblzma</emb>. Así, podría crear una puerta trasera a cualquier servidor SSH de Debian/Fedora/Ubuntu.</p> -<p>Aparentemente, ni siquiera <emb>openssh-selinux</emb> sería seguro en esas condiciones (glibc, x86-64, fuente de tarball preconfigurada de Github 5.6.0 y 5.6.1, systemd empaquetado, OpenSSH, RPM o DEB, con llamadas habilitadas a systemd a través de <emb>openssh.service</emb>). Si la fuente se creó a partir de git con autoconf/make limpio nativo, el código malicioso no se habría incluido. Los sistemas musl (Alpine, Gentoo, OpenWRT o Void) no tienen nada de qué preocuparse, simplemente porque ni siquiera pueden compilar <emb>sd_notify</emb>.</p> -<p>Una cosa muy llamativa es cómo gran parte de la comunidad cruzada contra systemd criticaba a <emb>zstd</emb>, defendiendo en contraposición al amigable <emb>xz</emb>. Sospechaban que el propio <emb>zstd</emb> (o Zstandard, que para quien no lo conozca, es un algoritmo de compresión desarrollado por Facebook para Linux), tenía el riesgo de ser un caballo de Troya para la seguridad y el cifrado, siendo que incluso <emb>zstd</emb> se construye, mayoritariamente, con la biblioteca <emb>lzma</emb> habilitada...</p> +<p>Aparentemente, ni siquiera <emb>openssh-selinux</emb> sería seguro en esas condiciones (glibc, x86-64, fuente de tarball preconfigurada de Github 5.6.0 y 5.6.1, systemd empaquetado, OpenSSH, RPM o DEB, con llamadas habilitadas a systemd a través de <emb>openssh.service</emb>). Si la fuente se creó a partir de git con autoconf/make limpio nativo, el código malicioso no se habría incluido. Los sistemas musl (Alpine, Gentoo con musl, OpenWRT o Void) no tienen nada de qué preocuparse, simplemente porque ni siquiera pueden compilar <emb>sd_notify</emb>.</p> +<p>Una cosa muy llamativa es cómo gran parte de la comunidad cruzada contra systemd criticaba a <emb>zstd</emb>, defendiendo en contraposición al amigable <emb>xz</emb>. Sospechaban que el propio <emb>zstd</emb> (o Zstandard, que para quien no lo conozca, es un algoritmo de compresión desarrollado por Facebook para Linux), tenía el riesgo de ser un caballo de Troya para la seguridad y el cifrado.</p> <p>«<i>Es sólo un algoritmo de compresión, no se puede usar para explotar la seguridad de un sistema, es imposible</i>» he llegado a leer por feudos del Internet. Pues este backdoor nos ha demostrado que es totalmente posible.</p> <p>Buena noticia, por lo tanto, para Slackware y otras distros no-systemd: hasta donde los expertos en Debian, Fedora, Arch o Ubuntu han llegado, se necesita necesariamente systemd para 'energizar' la puerta trasera, específicamente un gancho utilizado por Debian para construir <emb>openssh</emb> de cierta manera para que <emb>systemd/dbus/sd-bus/sd-notify</emb> ejecute código malicioso para obtener material de un blob de <emb>lzma</emb> para modificar los binarios en ejecución para abrir la puerta trasera. Es una genialidad, se mire por donde se mire. Y los cruzados contra systemd siguen teniendo, pues, razón.</p> <p>Este complejísimo ataque sobre librerías y códigos abiertos -apertura que permite a la comunidad, o a cualquiera que entienda, monitorizar los commits y evolución del código- ha llevado prácticamente 2 años a través de la librería <emb>xz</emb> en Github (llevado a cabo principalmente por la cuenta <i>JiaT75</i> y otras de dudosa legitimidad), para afectar como decíamos a <emb>liblzma</emb>, el vector de ataque. Tenga en cuenta el lector, que esta gran complejidad para insertar un backdoor es precisamente por la naturaleza del código abierto, en código cerrado probablemente otro gallo cantaría, incluso para la detección.</p>