<?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>Nat on inetshell</title><link>https://inet.sh/es/tags/nat/</link><description>Recent content in Nat on inetshell</description><generator>Hugo</generator><language>es</language><lastBuildDate>Mon, 05 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://inet.sh/es/tags/nat/index.xml" rel="self" type="application/rss+xml"/><item><title>OPNsense: port-forward inalcanzable desde la misma subred WAN (reply-to)</title><link>https://inet.sh/es/posts/opnsense/reply-to-misma-subred-wan/</link><pubDate>Mon, 05 Oct 2026 00:00:00 +0000</pubDate><guid>https://inet.sh/es/posts/opnsense/reply-to-misma-subred-wan/</guid><description>Por qué un port-forward de OPNsense funciona desde internet pero da timeout desde una IP de la misma /24 que la WAN, y cómo lo arregla «Disable reply-to on WAN rules».</description><content:encoded><![CDATA[<h2 id="en-corto">En corto</h2>
<p><strong>Firewall → Settings → Advanced → Disable reply-to on WAN rules</strong> → marcar → <strong>Save</strong> → <strong>Apply</strong>.</p>
<p>Síntoma: un port-forward o una regla WAN responde desde cualquier IP de internet, pero desde un equipo que vive en <strong>la misma subred que la WAN del firewall</strong> todo da timeout (SSH, HTTPS, incluso <code>ping</code>), aunque la regla diga <code>from any</code>.</p>
<p>Con una sola WAN es seguro: el firewall deja de forzar el regreso por el gateway y vuelve a usar su tabla de rutas.</p>
<h2 id="el-escenario">El escenario</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></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">                203.0.113.0/24  (mismo segmento L2)
</span></span><span class="line"><span class="cl">   ┌────────────────────┬────────────────────┬────────────────────┐
</span></span><span class="line"><span class="cl">   │                    │                    │                    │
</span></span><span class="line"><span class="cl"> gateway             fw01 (OPNsense)      vecino               internet
</span></span><span class="line"><span class="cl"> 203.0.113.1         WAN 203.0.113.40     203.0.113.50         (vía gateway)
</span></span><span class="line"><span class="cl">                        │ rdr :22 → 192.168.1.10
</span></span><span class="line"><span class="cl">                        ▼
</span></span><span class="line"><span class="cl">                     servidor LAN
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>Desde internet: <code>ssh -p 22 203.0.113.40</code> entra al servidor de la LAN. Bien.</li>
<li>Desde <code>vecino</code> (203.0.113.50): timeout en todos los puertos.</li>
</ul>
<h2 id="qué-hace-reply-to">Qué hace <code>reply-to</code></h2>
<p>OPNsense genera las reglas de las interfaces tipo WAN (las que tienen gateway) con <code>reply-to</code> apuntando a ese gateway:</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">pfctl -sr <span class="p">|</span> grep reply-to
</span></span></code></pre></td></tr></table>
</div>
</div><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">pass in quick on vtnet0 reply-to (vtnet0 203.0.113.1) inet proto tcp from any to 192.168.1.10 port = ssh flags S/SA keep state
</span></span></code></pre></td></tr></table>
</div>
</div><p><code>reply-to</code> es una opción de <strong>pf</strong>. Cuando un paquete entra y crea un estado, pf guarda en ese estado que <strong>todas las respuestas</strong> salgan por <code>vtnet0</code> hacia <code>203.0.113.1</code>. Esas respuestas no pasan por la tabla de rutas: pf decide el siguiente salto por su cuenta.</p>
<p>Existe por <strong>multi-WAN</strong>. Si tienes dos proveedores y un cliente entra por la WAN2, la respuesta tiene que salir por la WAN2. Si sale por la ruta por defecto (WAN1), lleva una IP de origen que el proveedor 1 no reconoce y se pierde. <code>reply-to</code> garantiza el regreso simétrico sin tener que pensar en rutas.</p>
<h2 id="por-qué-rompe-a-los-vecinos">Por qué rompe a los vecinos</h2>
<p>Para un cliente en internet, «responder al gateway» es justo lo que haría la tabla de rutas, así que no se nota nada.</p>
<p>Para el vecino es distinto. Su IP (203.0.113.50) está en una <strong>red conectada</strong> del firewall. Sin <code>reply-to</code>, el firewall resolvería su MAC por ARP y le respondería directo. Con <code>reply-to</code>, el SYN-ACK sale con la <strong>MAC del gateway</strong> como destino:</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"><span class="c1"># en el OPNsense (shell csh: envuelve en sh -c)</span>
</span></span><span class="line"><span class="cl">sh -c <span class="s2">&#34;tcpdump -lnei vtnet0 host 203.0.113.50 and tcp port 22&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><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">&lt;mac-vecino&gt; &gt; &lt;mac-fw01&gt;          203.0.113.50.49612 &gt; 203.0.113.40.22: Flags [S]    ← llega directo
</span></span><span class="line"><span class="cl">&lt;mac-fw01&gt;   &gt; 00:00:5e:00:01:&lt;vrid&gt; 203.0.113.40.22 &gt; 203.0.113.50.49612: Flags [S.]   ← sale al gateway
</span></span></code></pre></td></tr></table>
</div>
</div><p>(<code>00:00:5e:00:01:xx</code> es la MAC virtual de VRRP: el gateway era un par redundante.)</p>
<p>A partir de ahí depende del gateway. Para él, el paquete entra por la misma interfaz por la que tendría que salir, y si tiene un filtro con estado ve un SYN-ACK de una conexión cuyo SYN nunca vio. En el lab, el gateway simplemente no lo devolvía al segmento. En el vecino sólo se ven SYN reintentándose y ningún <code>[S.]</code>.</p>
<p>La huella en el firewall es un estado a medias:</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">pfctl -ss <span class="p">|</span> grep 203.0.113.50
</span></span></code></pre></td></tr></table>
</div>
</div><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">all tcp 192.168.1.10:22 (203.0.113.40:22) &lt;- 203.0.113.50:57792   SYN_SENT:ESTABLISHED
</span></span></code></pre></td></tr></table>
</div>
</div><p>El servidor ya respondió (<code>ESTABLISHED</code>) y el cliente sigue esperando (<code>SYN_SENT</code>): <strong>la respuesta se pierde de regreso</strong>, no a la ida. El filtro no está bloqueando nada.</p>
<h2 id="qué-cambia-el-fix">Qué cambia el fix</h2>
<p>Con <strong>Disable reply-to on WAN rules</strong> activado, OPNsense regenera las reglas sin <code>reply-to</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></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">pass in quick on vtnet0 inet proto tcp from any to 192.168.1.10 port = ssh flags S/SA keep state
</span></span></code></pre></td></tr></table>
</div>
</div><p>El estado ya no fija el siguiente salto, así que las respuestas pasan por la tabla de rutas normal:</p>
<table>
  <thead>
      <tr>
          <th>Destino de la respuesta</th>
          <th>Con <code>reply-to</code></th>
          <th>Sin <code>reply-to</code></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Cliente en internet</td>
          <td>gateway</td>
          <td>gateway (ruta por defecto)</td>
      </tr>
      <tr>
          <td>Vecino en 203.0.113.0/24</td>
          <td>gateway ✗</td>
          <td>directo por ARP ✓</td>
      </tr>
      <tr>
          <td>Cliente que entró por otra WAN (multi-WAN)</td>
          <td>su gateway ✓</td>
          <td>ruta por defecto ✗</td>
      </tr>
  </tbody>
</table>
<p>La última fila es el costo. Con multi-WAN no lo desactives global. En vez de eso, quita el <code>reply-to</code> sólo en la regla del port-forward afectado: en la regla, <strong>Advanced → reply-to</strong>. Revisa las opciones que ofrece tu versión.</p>
<h2 id="verificar">Verificar</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></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"># en el OPNsense</span>
</span></span><span class="line"><span class="cl">sh -c <span class="s2">&#34;pfctl -sr | grep -c reply-to; grep -n disablereplyto /conf/config.xml&#34;</span>
</span></span><span class="line"><span class="cl"><span class="c1"># esperado: 0  y  &lt;disablereplyto&gt;yes&lt;/disablereplyto&gt;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><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"><span class="c1"># desde el vecino</span>
</span></span><span class="line"><span class="cl">nc -z -w5 203.0.113.40 <span class="m">22</span> <span class="o">&amp;&amp;</span> <span class="nb">echo</span> abierto
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="trampas">Trampas</h2>
<ul>
<li><strong>«Disable force gateway» no es esto.</strong> Está en la misma pantalla y tiene un nombre parecido, pero sólo afecta el tráfico que <strong>origina el propio firewall</strong> (DNS, NTP, actualizaciones). No toca las respuestas a tráfico entrante.</li>
<li><strong>Una ruta estática en el gateway no ayuda.</strong> El gateway ya tiene la subred como conectada; el problema es que no regresa el paquete al mismo segmento, no que no sepa llegar.</li>
<li><strong>Shell csh.</strong> Por SSH, OPNsense entra a <code>csh</code> y cosas como <code>2&gt;/dev/null</code> fallan con <code>Ambiguous output redirect</code>. Usa <code>sh -c &quot;...&quot;</code> o <code>ssh root@fw01 sh &lt;&lt;'EOF'</code>.</li>
<li><strong>Revisa todos los puertos, no uno.</strong> Si falla sólo un puerto es otro problema (regla, NAT, servicio). Si fallan todos, incluido <code>ping</code>, y sólo desde la misma subred, sospecha de <code>reply-to</code>.</li>
</ul>
<h2 id="ver-también">Ver también</h2>
<ul>
<li>Documentación de OPNsense, configuración del firewall: <a href="https://docs.opnsense.org/manual/firewall_settings.html">https://docs.opnsense.org/manual/firewall_settings.html</a></li>
<li><code>pf.conf(5)</code>, opciones <code>route-to</code> / <code>reply-to</code>: <a href="https://man.freebsd.org/cgi/man.cgi?query=pf.conf">https://man.freebsd.org/cgi/man.cgi?query=pf.conf</a></li>
</ul>
]]></content:encoded></item><item><title>pfSense y OPNsense: el port forward no funciona desde la propia LAN (NAT reflection y split DNS)</title><link>https://inet.sh/es/posts/pfsense/nat-reflection-port-forward-desde-lan/</link><pubDate>Fri, 25 Sep 2026 00:00:00 +0000</pubDate><guid>https://inet.sh/es/posts/pfsense/nat-reflection-port-forward-desde-lan/</guid><description>Desde fuera el port forward funciona, pero desde la LAN la IP pública o el dominio te llevan a la GUI del firewall o a un error de certificado. Dos arreglos: split DNS con host overrides en el DNS Resolver (el recomendado) o NAT reflection en modo Pure NAT con outbound NAT automático. Incluye el equivalente en OPNsense y la trampa del DNS rebinding.</description><content:encoded><![CDATA[<h2 id="en-corto">En corto</h2>
<p><strong>Opción limpia (split DNS):</strong> Services → DNS Resolver → <em>Host Overrides</em> → <code>app.example.com</code> → IP interna del servidor (<code>192.168.1.50</code>). Los clientes de la LAN tienen que usar el firewall como DNS.</p>
<p><strong>Opción NAT reflection:</strong> System → Advanced → <em>Firewall &amp; NAT</em>:</p>
<ul>
<li><em>NAT Reflection mode for port forwards</em>: <strong>Pure NAT</strong></li>
<li><em>Enable NAT Reflection for 1:1 NAT</em>: ✔</li>
<li><em>Enable automatic outbound NAT for Reflection</em>: ✔</li>
</ul>
<p>Save y prueba desde un cliente de la LAN contra la IP pública.</p>
<h2 id="el-problema">El problema</h2>
<p>El port forward <code>WAN:443 → 192.168.1.50:443</code> funciona desde Internet. Desde un equipo de la misma LAN, <code>https://app.example.com</code> (que resuelve a la IP pública) responde con la GUI de pfSense, un error de certificado, o <code>Potential DNS Rebind attack detected</code>.</p>
<p>El paquete sale del cliente hacia la IP pública, llega al firewall por la interfaz LAN y ahí se queda: la regla de port forward escucha en la WAN, no en la LAN, y la IP de destino es una dirección del propio firewall. Nunca &ldquo;sale y vuelve a entrar&rdquo;.</p>
<h2 id="opción-1-split-dns">Opción 1: split DNS</h2>
<p>Es la que recomienda Netgate: el nombre resuelve a la IP interna dentro y a la pública fuera. El tráfico va directo, el servidor ve la IP real del cliente y el firewall no toca nada.</p>
<ol>
<li>Services → DNS Resolver → <em>Host Overrides</em> → <strong>Add</strong>: host <code>app</code>, dominio <code>example.com</code>, IP <code>192.168.1.50</code>. Si el servicio tiene varios nombres, añade <em>Additional Names</em>.</li>
<li>Los clientes deben usar el firewall como DNS (lo normal si el DHCP lo entrega). Un cliente con <code>8.8.8.8</code> fijo seguirá yendo a la IP pública.</li>
<li><code>nslookup app.example.com</code> desde la LAN → <code>192.168.1.50</code>.</li>
</ol>
<p>Requisitos: el puerto interno y el externo tienen que ser el mismo (si fuera reenvías <code>8443 → 443</code>, el cliente interno tendrá que usar <code>443</code> directamente).</p>
<p>Si usas DNS Forwarder (dnsmasq) en vez del Resolver, el ajuste equivalente está en Services → DNS Forwarder → <em>Host Overrides</em>.</p>
<h2 id="opción-2-nat-reflection">Opción 2: NAT reflection</h2>
<p>Cuando no controlas el DNS de los clientes, o hay un montón de puertos, el firewall puede &ldquo;reflejar&rdquo; la conexión: reescribe el destino a la IP interna y, con el outbound NAT automático, también el origen, para que la respuesta vuelva por el firewall.</p>
<p>System → Advanced → <em>Firewall &amp; NAT</em>, sección <em>Network Address Translation</em>:</p>
<table>
  <thead>
      <tr>
          <th>Ajuste</th>
          <th>Valor</th>
          <th>Por qué</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>NAT Reflection mode for port forwards</td>
          <td><strong>Pure NAT</strong></td>
          <td>Solo reglas de PF: todos los protocolos, sin límite de puertos. <em>NAT + Proxy</em> usa un daemon, solo TCP y máximo 500 puertos por regla</td>
      </tr>
      <tr>
          <td>Enable NAT Reflection for 1:1 NAT</td>
          <td>✔</td>
          <td>Si tienes 1:1 NAT además de port forwards</td>
      </tr>
      <tr>
          <td>Enable automatic outbound NAT for Reflection</td>
          <td>✔</td>
          <td>Sin esto, si cliente y servidor están en la misma subred el servidor responde directo al cliente, que no reconoce la conexión y la corta</td>
      </tr>
      <tr>
          <td>Reflection Timeout</td>
          <td>(solo NAT + Proxy)</td>
          <td>Ignóralo en Pure NAT</td>
      </tr>
  </tbody>
</table>
<p>También se puede activar por regla: Firewall → NAT → Port Forward → editar → <em>NAT reflection</em> → <em>Enable (Pure NAT)</em>, dejando el global en <em>Disable</em>.</p>
<p>Costes: el servidor ve como origen la IP LAN del firewall (no la del cliente), y todo ese tráfico pasa por el firewall aunque cliente y servidor estén en el mismo switch.</p>
<h2 id="opnsense">OPNsense</h2>
<p>Misma idea, otros menús:</p>
<ul>
<li>Split DNS: Services → Unbound DNS → <em>Overrides</em> → Host Overrides.</li>
<li>Reflection: Firewall → Settings → <em>Advanced</em> → <strong>Reflection for port forwards</strong>, <strong>Reflection for 1:1</strong>, <strong>Automatic outbound NAT for Reflection</strong>.</li>
</ul>
<h2 id="trampas">Trampas</h2>
<ul>
<li><strong>DNS rebinding.</strong> Si en vez de un host override apuntas el Resolver a un DNS externo que devuelve IPs privadas (un DNS interno de otra sede, un proveedor con vistas), Unbound descarta esas respuestas por protección contra rebinding. No desmarques <em>Disable DNS Rebinding Checks</em> en System → Advanced → Admin Access: añade en Services → DNS Resolver → <em>Custom options</em> <code>private-domain: &quot;example.com&quot;</code> y solo ese dominio queda exento.</li>
<li><strong>El cliente con DNS fijo</strong> se salta el split DNS. O lo obligas por DHCP, o lo capturas con una regla de NAT de puerto 53, o usas reflection.</li>
<li><strong>Pure NAT necesita saber la interfaz y el gateway</strong> en el momento de cargar reglas; con WANs dinámicas que cambian de IP, un <em>Filter Reload</em> después del cambio de IP lo arregla.</li>
<li><strong>Puertos distintos dentro y fuera</strong> solo funcionan con reflection; split DNS no traduce puertos.</li>
<li><strong>Certificados</strong>: con split DNS el navegador sigue viendo <code>app.example.com</code>, así que el certificado del servidor sirve igual. Si reflejas por IP pública, también. El error de certificado del principio era el de la GUI del firewall, no el del servidor.</li>
</ul>
<p>Referencias: <a href="https://docs.netgate.com/pfsense/en/latest/recipes/port-forwards-from-local-networks.html">Port Forwards from Local Networks</a> y <a href="https://docs.netgate.com/pfsense/en/latest/nat/reflection.html">NAT Reflection</a> en la documentación de Netgate.</p>
]]></content:encoded></item></channel></rss>