<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Freebsd on inetshell</title><link>https://inet.sh/es/tags/freebsd/</link><description>Recent content in Freebsd on inetshell</description><generator>Hugo</generator><language>es</language><lastBuildDate>Fri, 25 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://inet.sh/es/tags/freebsd/index.xml" rel="self" type="application/rss+xml"/><item><title>FreeBSD: reemplazar un disco del mirror ZFS de arranque (zroot) con gpart</title><link>https://inet.sh/es/posts/zfs/freebsd-reemplazar-disco-mirror-arranque/</link><pubDate>Fri, 25 Sep 2026 00:00:00 +0000</pubDate><guid>https://inet.sh/es/posts/zfs/freebsd-reemplazar-disco-mirror-arranque/</guid><description>Cambiar un disco muerto de un mirror zroot en FreeBSD 13/14: clonar la tabla de particiones con gpart backup | gpart restore, reinstalar el bootcode BIOS (pmbr + gptzfsboot) y poblar la ESP con loader.efi para UEFI (boot1.efi ya está obsoleto), zpool replace o attach con la partición correcta, swap y resilver.</description><content:encoded><![CDATA[<h2 id="en-corto">En corto</h2>
<p>Disco bueno <code>ada0</code>, disco nuevo <code>ada3</code>, el muerto era <code>ada1</code>:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">zpool status zroot                                  <span class="c1"># ada1p4 FAULTED / UNAVAIL</span>
</span></span><span class="line"><span class="cl">gpart backup ada0 <span class="p">|</span> gpart restore -F ada3           <span class="c1"># clona la tabla de particiones</span>
</span></span><span class="line"><span class="cl">gpart show ada3                                     <span class="c1"># p1 efi, p2 freebsd-boot, p3 freebsd-swap, p4 freebsd-zfs</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Bootcode BIOS: el índice es el de la partición freebsd-boot</span>
</span></span><span class="line"><span class="cl">gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i <span class="m">2</span> ada3
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># UEFI: rellena la ESP</span>
</span></span><span class="line"><span class="cl">newfs_msdos -F <span class="m">32</span> -c <span class="m">1</span> /dev/ada3p1
</span></span><span class="line"><span class="cl">mount -t msdosfs /dev/ada3p1 /mnt
</span></span><span class="line"><span class="cl">mkdir -p /mnt/EFI/BOOT /mnt/EFI/FREEBSD
</span></span><span class="line"><span class="cl">cp /boot/loader.efi /mnt/EFI/BOOT/BOOTX64.EFI
</span></span><span class="line"><span class="cl">cp /boot/loader.efi /mnt/EFI/FREEBSD/LOADER.EFI
</span></span><span class="line"><span class="cl">umount /mnt
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># El disco nuevo entra al mirror en el lugar del muerto</span>
</span></span><span class="line"><span class="cl">zpool replace zroot ada1p4 ada3p4
</span></span><span class="line"><span class="cl">zpool status zroot                                  <span class="c1"># resilver en curso</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Cuando <code>zpool status</code> diga <code>ONLINE</code> en los dos, prueba a arrancar <strong>solo</strong> con el disco nuevo.</p>
<h2 id="antes-de-empezar">Antes de empezar</h2>
<ul>
<li><strong>Identifica el disco.</strong> <code>zpool status</code> nombra el miembro muerto (<code>ada1p4</code>, o un GUID largo si ya no está). <code>camcontrol devlist</code> lista los discos con modelo y serie para saber cuál bahía tocar.</li>
<li><strong>Si el disco malo sigue conectado</strong>, sácalo del pool antes de tirar del cable: <code>zpool offline zroot ada1p4</code>.</li>
<li><strong>Layout.</strong> Una instalación por defecto de FreeBSD 13/14 con zroot crea, por disco: <code>p1</code> <code>efi</code>, <code>p2</code> <code>freebsd-boot</code>, <code>p3</code> <code>freebsd-swap</code>, <code>p4</code> <code>freebsd-zfs</code>. Instalaciones antiguas o a mano varían: mira <code>gpart show ada0</code> y ajusta los índices. El <code>-i</code> del bootcode es el de <code>freebsd-boot</code>.</li>
<li><strong>El disco nuevo tiene que ser igual o mayor.</strong> <code>gpart restore</code> copia tamaños exactos; si es mayor, el resto queda libre y lo puedes usar después.</li>
</ul>
<h2 id="por-qué-particiones-y-no-el-disco-entero">Por qué particiones y no el disco entero</h2>
<p>En un pool de arranque cada disco lleva las particiones de boot además de la de ZFS. Si haces <code>zpool replace zroot ada1p4 ada3</code> con el disco crudo, el mirror funciona pero ese disco <strong>no puede arrancar</strong>: el día que <code>ada0</code> muera, tendrás los datos y ningún cargador. Por eso el orden es: particionar igual, bootcode, y solo entonces <code>zpool replace</code> con la partición.</p>
<h2 id="paso-a-paso">Paso a paso</h2>
<p><strong>1. Clonar la tabla de particiones.</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">gpart backup ada0 <span class="p">|</span> gpart restore -F ada3
</span></span><span class="line"><span class="cl">gpart show ada3
</span></span></code></pre></td></tr></table>
</div>
</div><p><code>-F</code> destruye lo que hubiera en <code>ada3</code>. Si el pool usa etiquetas GPT (<code>gpt/zfs0</code> en <code>zpool status</code>) en vez de nombres <code>adaXpY</code>, ponle la suya al nuevo: <code>gpart modify -i 4 -l zfs1 ada3</code>, y usa <code>gpt/zfs1</code> en el <code>zpool replace</code>.</p>
<p><strong>2. Bootcode.</strong> Instala los dos: así arranca tanto si la placa está en modo BIOS/CSM como en UEFI.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># BIOS: MBR protector + gptzfsboot en la partición freebsd-boot (p2 en el layout por defecto)</span>
</span></span><span class="line"><span class="cl">gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i <span class="m">2</span> ada3
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># UEFI: la ESP (p1) es un FAT32 con loader.efi en las rutas estándar</span>
</span></span><span class="line"><span class="cl">newfs_msdos -F <span class="m">32</span> -c <span class="m">1</span> /dev/ada3p1
</span></span><span class="line"><span class="cl">mount -t msdosfs /dev/ada3p1 /mnt
</span></span><span class="line"><span class="cl">mkdir -p /mnt/EFI/BOOT /mnt/EFI/FREEBSD
</span></span><span class="line"><span class="cl">cp /boot/loader.efi /mnt/EFI/BOOT/BOOTX64.EFI
</span></span><span class="line"><span class="cl">cp /boot/loader.efi /mnt/EFI/FREEBSD/LOADER.EFI
</span></span><span class="line"><span class="cl">umount /mnt
</span></span></code></pre></td></tr></table>
</div>
</div><p>Las guías viejas dicen <code>gpart bootcode -p /boot/boot1.efifat -i 1</code>; <code>boot1.efi</code> está obsoleto en FreeBSD actual y el camino documentado en <code>loader.efi(8)</code> es copiar <code>loader.efi</code> a la ESP. Si quieres una entrada propia en el firmware: <code>efibootmgr -c -l /mnt/EFI/FREEBSD/LOADER.EFI -L FreeBSD-ada3 -a</code>.</p>
<p><strong>3. Reemplazar en el pool.</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">zpool replace zroot ada1p4 ada3p4
</span></span></code></pre></td></tr></table>
</div>
</div><p>Si el miembro muerto ya no aparece y el mirror quedó con un solo disco, en vez de <code>replace</code> se <strong>añade</strong> al superviviente: <code>zpool attach zroot ada0p4 ada3p4</code>.</p>
<p><strong>4. Resilver.</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">zpool status zroot           <span class="c1"># scan: resilver in progress ... % done</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Horas, según lo lleno que esté el pool. Opcional, para que el resilver no ceda tanto el turno a la carga normal:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">sysctl vfs.zfs.resilver_min_time_ms<span class="o">=</span><span class="m">5000</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>5. Swap.</strong> Si <code>/etc/fstab</code> tenía <code>/dev/ada1p3</code> como swap, cámbialo a <code>/dev/ada3p3</code> (o mejor, a etiquetas <code>gpt/swapN</code> que no cambien con el nombre del disco) y <code>swapon -a</code>.</p>
<p><strong>6. Comprobar el arranque.</strong> Con el resilver terminado, apaga, desconecta <code>ada0</code> (o cambia el orden de arranque) y arranca desde el nuevo. Si entra, vuelve a conectar y <code>zpool status</code> debe seguir <code>ONLINE</code> sin quejas. Una <code>zpool scrub zroot</code> de cierre no está de más.</p>
<h2 id="trampas">Trampas</h2>
<ul>
<li><strong><code>gpart restore -F</code> no pregunta.</strong> Revisa dos veces cuál es el disco nuevo; <code>camcontrol devlist</code> y <code>diskinfo -v ada3</code> (serie) antes de escribir.</li>
<li><strong>Bootcode de un solo tipo</strong> deja el disco arrancable solo en un modo de firmware. Pon los dos.</li>
<li><strong>Sector físico distinto</strong> (512 vs 4K) puede hacer que <code>zpool replace</code> se queje del <code>ashift</code>; en un mirror moderno con <code>ashift=12</code> un disco 4Kn entra sin problema, uno con <code>ashift=9</code> no.</li>
<li><strong>Disco más grande</strong>: tras el resilver, <code>gpart resize -i 4 ada3</code> y <code>zpool online -e zroot ada3p4</code>; cuando los dos discos del mirror sean grandes, el pool crece.</li>
<li><strong>Los nombres <code>adaX</code> cambian</strong> al quitar discos; las etiquetas GPT y los GUID no. Para la operación usa lo que muestre <code>zpool status</code> en ese momento.</li>
</ul>
<h2 id="ver-también">Ver también</h2>
<ul>
<li><a href="/es/posts/zfs/reemplazar-discos/">Reemplazar un disco en un pool ZFS</a> — la versión Linux/Proxmox, sin particiones de arranque.</li>
<li><a href="/es/posts/zfs/importar-pool-despues-apagado/">Importar un pool después de un apagón</a>.</li>
<li>FreeBSD: <code>man 8 loader.efi</code>, <code>man 8 gpart</code>, y el <a href="https://farrokhi.net/posts/2020/05/replacing-a-faulty-disk-in-zfs/">artículo de Babak Farrokhi</a> sobre el reemplazo en BIOS.</li>
</ul>
]]></content:encoded></item><item><title>pfctl: cheat sheet de tablas en pfSense, OPNsense y FreeBSD</title><link>https://inet.sh/es/posts/pfsense/pfctl-tablas-cheat-sheet/</link><pubDate>Fri, 25 Sep 2026 00:00:00 +0000</pubDate><guid>https://inet.sh/es/posts/pfsense/pfctl-tablas-cheat-sheet/</guid><description>Comandos pfctl -t/-T para tablas de PF: listar, ver, añadir, borrar, probar, vaciar, recargar desde archivo y expirar entradas. Con las tablas internas de pfSense (sshguard, virusprot, snort2c, bogons, aliases y pfBlockerNG) y lo que se pierde al recargar el filtro.</description><content:encoded><![CDATA[<h2 id="en-corto">En corto</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">pfctl -sT                                    <span class="c1"># tablas cargadas</span>
</span></span><span class="line"><span class="cl">pfctl -t &lt;tabla&gt; -T show                     <span class="c1"># contenido</span>
</span></span><span class="line"><span class="cl">pfctl -t &lt;tabla&gt; -T add 192.168.1.10         <span class="c1"># añadir IP o red (también 10.20.0.0/16)</span>
</span></span><span class="line"><span class="cl">pfctl -t &lt;tabla&gt; -T delete 192.168.1.10
</span></span><span class="line"><span class="cl">pfctl -t &lt;tabla&gt; -T <span class="nb">test</span> 192.168.1.10        <span class="c1"># ¿está dentro? (match / no match)</span>
</span></span><span class="line"><span class="cl">pfctl -t &lt;tabla&gt; -T flush                    <span class="c1"># vaciar la tabla</span>
</span></span><span class="line"><span class="cl">pfctl -t &lt;tabla&gt; -T replace -f /ruta/lista   <span class="c1"># reemplazar todo el contenido desde un archivo</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">pfctl -t sshguard -T flush                   <span class="c1"># pfSense: quitar el bloqueo por intentos de login fallidos</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="qué-es-una-tabla">Qué es una tabla</h2>
<p>Una <strong>tabla</strong> de PF es un conjunto de direcciones y redes al que las reglas hacen referencia como <code>&lt;nombre&gt;</code>. Se cambia en caliente, sin recargar el ruleset, y aguanta miles de entradas con búsqueda rápida; por eso PF la usa para listas de bloqueo, bogons y cualquier cosa que cambie más a menudo que las reglas.</p>
<p>En <code>pf.conf</code>:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">table &lt;blocklist&gt; persist file &#34;/etc/pf/blocklist.txt&#34;
</span></span><span class="line"><span class="cl">block in quick from &lt;blocklist&gt;
</span></span></code></pre></td></tr></table>
</div>
</div><p><code>persist</code> mantiene la tabla aunque ninguna regla la use en ese momento; <code>file</code> la carga desde un archivo (una IP o red por línea).</p>
<h2 id="comandos">Comandos</h2>
<p>Todos con la forma <code>pfctl -t &lt;tabla&gt; -T &lt;comando&gt;</code>:</p>
<table>
  <thead>
      <tr>
          <th>Comando</th>
          <th>Qué hace</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>show</code></td>
          <td>Lista las entradas. Con <code>-v</code>, contadores por entrada (paquetes/bytes in/out)</td>
      </tr>
      <tr>
          <td><code>add &lt;ip|red&gt; …</code></td>
          <td>Añade una o varias entradas</td>
      </tr>
      <tr>
          <td><code>delete &lt;ip|red&gt; …</code></td>
          <td>Quita entradas</td>
      </tr>
      <tr>
          <td><code>test &lt;ip&gt; …</code></td>
          <td>Dice si la dirección cae dentro de la tabla (sin tocarla)</td>
      </tr>
      <tr>
          <td><code>flush</code></td>
          <td>Vacía la tabla; la tabla sigue existiendo</td>
      </tr>
      <tr>
          <td><code>kill</code></td>
          <td>Borra la tabla entera (si no la usa ninguna regla)</td>
      </tr>
      <tr>
          <td><code>replace -f &lt;archivo&gt;</code></td>
          <td>Sustituye el contenido completo por el del archivo, en una sola operación</td>
      </tr>
      <tr>
          <td><code>expire &lt;segundos&gt;</code></td>
          <td>Borra las entradas cuyos contadores llevan más de N segundos sin actividad</td>
      </tr>
      <tr>
          <td><code>zero</code></td>
          <td>Pone a cero los contadores de la tabla (o de una entrada, si la indicas)</td>
      </tr>
  </tbody>
</table>
<p>Y sin <code>-t</code>:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">pfctl -sT                    <span class="c1"># nombres de todas las tablas</span>
</span></span><span class="line"><span class="cl">pfctl -vvsT                  <span class="c1"># info global por tabla: entradas, evaluaciones, referencias</span>
</span></span><span class="line"><span class="cl">pfctl -T load -f /etc/pf.conf   <span class="c1"># recarga solo las definiciones de tabla del pf.conf</span>
</span></span><span class="line"><span class="cl">pfctl -sr <span class="p">|</span> grep <span class="s1">&#39;&lt;nombre&gt;&#39;</span>  <span class="c1"># qué reglas usan una tabla</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="tablas-en-pfsense">Tablas en pfSense</h2>
<ul>
<li><strong>Los aliases son tablas.</strong> Un alias de tipo Host, Network o URL Table llamado <code>Admins</code> existe en PF como <code>&lt;Admins&gt;</code>; <code>pfctl -t Admins -T show</code> te enseña lo que resolvió pfSense, incluidos los FQDN que ya convirtió a IPs.</li>
<li><strong><code>sshguard</code></strong>: donde caen las IPs bloqueadas por intentos de login fallidos a SSH o a la webGUI. Si te bloqueaste a ti mismo, <code>pfctl -t sshguard -T flush</code> (documentado por Netgate en <a href="https://docs.netgate.com/pfsense/en/latest/troubleshooting/locked-out.html">Locked out of the WebGUI</a>).</li>
<li><strong><code>virusprot</code></strong>: hosts bloqueados por superar los límites <em>Max. src. conn. rate</em> o <em>Max. states</em> de una regla. <code>pfctl -t virusprot -T show</code> y <code>-T delete &lt;ip&gt;</code> para soltar a uno.</li>
<li><strong><code>snort2c</code></strong>: bloqueos de Snort/Suricata en modo legacy. <code>-T flush</code> para desbloquear todo.</li>
<li><strong><code>bogons</code> / <code>bogonsv6</code></strong>: las listas que se actualizan solas cuando activas <em>Block bogon networks</em> en una interfaz.</li>
<li><strong>pfBlockerNG</strong>: cada lista es un alias <code>pfB_*</code>. Para saber si una IP está bloqueada por alguna: <code>pfctl -t pfB_Top_v4 -T test 203.0.113.7</code>.</li>
</ul>
<p>En OPNsense la mecánica es la misma (<code>pfctl -sT</code> para ver los nombres); la tabla de bloqueo por login se llama <code>sshlockout</code>.</p>
<h2 id="lo-que-se-pierde-al-recargar">Lo que se pierde al recargar</h2>
<p>Cualquier <code>-T add</code>, <code>-T delete</code> o <code>-T flush</code> vive hasta la siguiente <strong>recarga del filtro</strong>: guardar casi cualquier cosa en la GUI, <code>Filter Reload</code> en Status → Filter Reload, o el cron de actualización de aliases. En ese momento pfSense regenera cada tabla desde su alias y tus cambios a mano desaparecen. Para que algo sea permanente, edita el alias; para pruebas rápidas y desbloqueos, <code>pfctl</code> es perfecto.</p>
<h2 id="más-allá-de-las-tablas">Más allá de las tablas</h2>
<p>Lo que más se usa junto a lo anterior:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">pfctl -sr                    <span class="c1"># reglas cargadas (con -vv, contadores y números de regla)</span>
</span></span><span class="line"><span class="cl">pfctl -ss                    <span class="c1"># tabla de estados</span>
</span></span><span class="line"><span class="cl">pfctl -si                    <span class="c1"># estadísticas globales</span>
</span></span><span class="line"><span class="cl">pfctl -k 192.168.1.10        <span class="c1"># matar los estados de un host</span>
</span></span><span class="line"><span class="cl">pfctl -F states              <span class="c1"># matar todos los estados (corta todas las conexiones)</span>
</span></span><span class="line"><span class="cl">pfctl -d / pfctl -e          <span class="c1"># desactivar / activar PF (sin PF no hay NAT: úsalo solo para salir de un bloqueo)</span>
</span></span><span class="line"><span class="cl">pfctl -nf /etc/pf.conf       <span class="c1"># comprobar sintaxis sin cargar</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Referencia completa: <a href="https://www.openbsdhandbook.com/pf/cheat_sheet/">pfctl cheat sheet</a> del OpenBSD Handbook y <code>man pfctl</code> en FreeBSD.</p>
]]></content:encoded></item><item><title>pfSense: ld-elf.so.1: Shared object "libssl.so.30" not found, required by "pkg"</title><link>https://inet.sh/es/posts/pfsense/libssl-so-30-not-found-pkg/</link><pubDate>Fri, 25 Sep 2026 00:00:00 +0000</pubDate><guid>https://inet.sh/es/posts/pfsense/libssl-so-30-not-found-pkg/</guid><description>pkg update y el Package Manager de pfSense mueren con &amp;#39;Shared object libssl.so.30 not found, required by pkg&amp;#39;: el binario pkg quedó enlazado contra un OpenSSL que el sistema base todavía no tiene. Recuperación con pkg-static (certctl rehash, reinstalar pkg, pfSense-repo y pfSense-upgrade) y cómo terminar la actualización bien.</description><content:encoded><![CDATA[<h2 id="en-corto">En corto</h2>
<p>Desde la consola (opción 8) o <strong>Diagnostics → Command Prompt</strong>:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">certctl rehash
</span></span><span class="line"><span class="cl">pkg-static clean -ay
</span></span><span class="line"><span class="cl">pkg-static install -fy pkg
</span></span><span class="line"><span class="cl">pkg-static install -xfy pfSense-repo pfSense-upgrade
</span></span><span class="line"><span class="cl">pkg-static update -f
</span></span><span class="line"><span class="cl">pfSense-upgrade -d -c        <span class="c1"># muestra qué versión ofrece la rama configurada</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Con <code>pkg</code> vivo otra vez, termina la actualización pendiente por <strong>System → Update</strong> (o <code>pfSense-upgrade -d</code>), no con <code>pkg upgrade</code>.</p>
<h2 id="el-error">El error</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">ld-elf.so.1: Shared object &#34;libssl.so.30&#34; not found, required by &#34;pkg&#34;
</span></span></code></pre></td></tr></table>
</div>
</div><p>Lo verás al hacer <code>pkg update</code>, al instalar un paquete, o de forma indirecta: <strong>System → Package Manager</strong> aparece vacío y <strong>System → Update</strong> no puede comprobar versiones. A veces el binario que se queja es <code>pfSense-repoc</code> en vez de <code>pkg</code>; es el mismo problema.</p>
<h2 id="por-qué-pasa">Por qué pasa</h2>
<p>pfSense es FreeBSD, y <code>pkg</code> es un binario enlazado dinámicamente contra la <code>libssl</code> del sistema. Cuando el repositorio configurado corresponde a una versión de pfSense construida sobre un FreeBSD más nuevo, sus paquetes vienen enlazados contra un OpenSSL más nuevo (<code>libssl.so.30</code> = OpenSSL 3). Si <code>pkg</code>, o <code>pfSense-repoc</code>, se actualiza desde ese repo <strong>antes</strong> que el sistema base, el binario nuevo pide una biblioteca que en tu instalación todavía no existe.</p>
<p>Cómo se llega ahí:</p>
<ul>
<li>Un <code>pkg upgrade</code> a mano desde la shell. En pfSense no se hace nunca.</li>
<li>Instalar o reinstalar un paquete después de cambiar la <strong>Branch</strong> en System → Update a una versión mayor, sin haber actualizado.</li>
<li>Una actualización interrumpida a medias (fue típico en el salto 2.7.0 → 2.7.1/2.7.2, cuando la base cambió a OpenSSL 3).</li>
<li>En pfSense Plus, volver a un boot environment anterior con el repo apuntando al nuevo (Redmine #15070).</li>
</ul>
<p>El nombre de la biblioteca cambiará con las versiones; la mecánica y el arreglo son los mismos.</p>
<h2 id="arreglo">Arreglo</h2>
<p><code>pkg-static</code> es la copia de <code>pkg</code> enlazada estáticamente: no necesita <code>libssl</code> y por eso funciona cuando <code>pkg</code> no.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># 1. Que pkg-static pueda hablar TLS con el repo (vale hasta el siguiente reinicio)</span>
</span></span><span class="line"><span class="cl">certctl rehash
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 2. Tirar la caché y reinstalar pkg y la configuración del repo</span>
</span></span><span class="line"><span class="cl">pkg-static clean -ay
</span></span><span class="line"><span class="cl">pkg-static install -fy pkg
</span></span><span class="line"><span class="cl">pkg-static install -xfy pfSense-repo pfSense-upgrade   <span class="c1"># -x: regex, así entra también pfSense-repoc</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 3. Refrescar metadatos y comprobar</span>
</span></span><span class="line"><span class="cl">pkg-static update -f
</span></span><span class="line"><span class="cl">pfSense-upgrade -d -c
</span></span></code></pre></td></tr></table>
</div>
</div><p>Si <code>pkg-static update</code> sigue fallando, <code>pkg-static -d update</code> da la traza completa (certificados, DNS, rama equivocada).</p>
<p>Antes del paso 3 revisa la <strong>Branch</strong> en System → Update: debe ser la versión a la que quieres ir, no una intermedia. Y termina el trabajo por la GUI o con <code>pfSense-upgrade -d</code>: un <code>pkg upgrade</code> suelto te deja a medio camino otra vez.</p>
<p>Si el sistema base está tan mezclado que ni así arranca, el último recurso documentado por Netgate es <code>pkg-static upgrade -f</code> (reinstala todo), y tras eso reiniciar.</p>
<h2 id="trampas">Trampas</h2>
<ul>
<li><strong><code>pkg upgrade</code> no existe en pfSense.</strong> El único camino soportado es System → Update / <code>pfSense-upgrade</code>. Toda esta situación nace de saltárselo.</li>
<li><strong>Respaldo antes</strong>: Diagnostics → Backup &amp; Restore. Con ZFS, además un boot environment (System → Boot Environments) te deja volver atrás en un reinicio.</li>
<li><strong>No copies <code>libssl.so.30</code> de otro FreeBSD.</strong> Circula como truco; deja el sistema con bibliotecas de dos versiones y rompe la siguiente actualización.</li>
<li><strong>Paquetes primero, no.</strong> Con una actualización pendiente, actualiza el sistema y luego instala paquetes, no al revés.</li>
<li>El repo y el upgrade usan HTTPS: si <code>certctl rehash</code> no basta, revisa hora del sistema y DNS del firewall.</li>
</ul>
<p>Referencia: <a href="https://docs.netgate.com/pfsense/en/latest/troubleshooting/upgrades.html">Upgrade Troubleshooting</a> en la documentación de Netgate.</p>
]]></content:encoded></item></channel></rss>