En este momento estás viendo Construcción de un firewall avanzado

Construcción de un firewall avanzado

  • Última modificación de la entrada:18 de junio de 2025
  • Tiempo de lectura:13 minutos de lectura
  • Categoría de la entrada:Seguridad

Descripción general

Intentemos construir un firewall avanzado en un router Mikrotik. En este ejemplo, usaremos todas las funciones posibles para ilustrar su funcionamiento y cuándo usarlas correctamente.

La mayor parte del filtrado se realizará en el firewall RAW, un firewall normal contendrá solo un conjunto de reglas básicas para aceptar established, related , conexiones no rastreadas y también descartará todo lo que no provenga de LAN para proteger completamente el enrutador.

Listas de interfaces

Se utilizarán dos listas de interfaces, WAN y LAN, para facilitar la gestión futura. Las interfaces conectadas a internet global deben añadirse a la lista WAN; en este caso, es ether1 .

/interface list   add comment=defconf name=WAN   add comment=defconf name=LAN /interface list member   add comment=defconf interface=bridge list=LAN   add comment=defconf interface=ether1 list=WAN

Proteger el dispositivo

El objetivo principal aquí es permitir el acceso al enrutador solo desde LAN y descartar todo lo demás.

Tenga en cuenta que aquí también se acepta ICMP; se utiliza para aceptar paquetes ICMP que pasan las reglas RAW.

/ip firewall filter add action=accept chain=input comment="defconf: accept ICMP after RAW" protocol=icmp add action=accept chain=input comment="defconf: accept established,related,untracked" connection-state=established,related,untracked add action=drop chain=input comment="defconf: drop all not coming from LAN" in-interface-list=!LAN

La parte de IPv6 es un poco más complicada, además se aceptan traceroute UDP, PD de cliente DHCPv6 e IPSec (IKE, AH, ESP) según las recomendaciones de RFC.

/ipv6 firewall filter add action=accept chain=input comment="defconf: accept ICMPv6 after RAW" protocol=icmpv6 add action=accept chain=input comment="defconf: accept established,related,untracked" connection-state=established,related,untracked add action=accept chain=input comment="defconf: accept UDP traceroute" dst-port=33434-33534 protocol=udp add action=accept chain=input comment="defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=udp src-address=fe80::/10 add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 protocol=udp add action=accept chain=input comment="defconf: accept IPSec AH" protocol=ipsec-ah add action=accept chain=input comment="defconf: accept IPSec ESP" protocol=ipsec-esp add action=drop chain=input comment="defconf: drop all not coming from LAN" in-interface-list=!LAN

En ciertas configuraciones donde se utiliza la retransmisión DHCPv6, la dirección de origen de los paquetes podría no pertenecer al rango local de enlace. En ese caso, el parámetro src-address de la regla n.º 4 debe eliminarse o ajustarse para que acepte la dirección de retransmisión.

Proteger a los clientes

Antes del conjunto de reglas real, creemos un necesario address-list que contenga todas las direcciones IPv4/6 que no se pueden reenviar.

Ten en cuenta que en esta lista se ha añadido un rango de direcciones de multidifusión. Esto se debe a que, en la mayoría de los casos, no se utiliza la multidifusión. Si deseas utilizar el reenvío de multidifusión, esta entrada de la lista de direcciones debe estar deshabilitada.

/ip firewall address-list add address=0.0.0.0/8 comment="defconf: RFC6890" list=no_forward_ipv4 add address=169.254.0.0/16 comment="defconf: RFC6890" list=no_forward_ipv4 add address=224.0.0.0/4 comment="defconf: multicast" list=no_forward_ipv4 add address=255.255.255.255/32 comment="defconf: RFC6890" list=no_forward_ipv4

En el mismo caso para IPv6, si se utiliza el reenvío de multidifusión, la entrada de multidifusión debe deshabilitarse en la lista de direcciones.

/ipv6 firewall address-list add address=fe80::/10 comment="defconf: RFC6890 Linked-Scoped Unicast" list=no_forward_ipv6 add address=ff00::/8 comment="defconf: multicast" list=no_forward_ipv6

Forward

La cadena tendrá un poco más de reglas que la entrada:

  • Aceptar conexiones establecidas, relacionadas y no rastreadas ;
  • Conexiones establecidas y relacionadas con FastTrack (actualmente sólo IPv4);
  • Eliminar conexiones no válidas ;
  • Descartar direcciones IP de reenvío incorrectas, ya que no podemos determinar de manera confiable en las cadenas RAW qué paquetes se reenvían
  • Eliminar conexiones iniciadas desde Internet (desde el lado WAN que no está NATizado como destino);
  • Eliminar las IP de Bogon que no deben reenviarse.

Descartamos todos los paquetes IPv4 no asignados para proteger contra ataques directos a los clientes si el atacante conoce la red LAN interna. Normalmente, esta regla no sería necesaria, ya que los filtros RAW descartan dichos paquetes; sin embargo, esta regla ofrece doble seguridad en caso de que las reglas RAW se vulneren accidentalmente.

/ip firewall filter add action=accept chain=forward comment="defconf: accept all that matches IPSec policy" ipsec-policy=in,ipsec disabled=yes add action=fasttrack-connection chain=forward comment="defconf: fasttrack" connection-state=established,related add action=accept chain=forward comment="defconf: accept established,related, untracked" connection-state=established,related,untracked add action=drop chain=forward comment="defconf: drop invalid" connection-state=invalid add action=drop chain=forward comment="defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat connection-state=new in-interface-list=WAN add action=drop chain=forward src-address-list=no_forward_ipv4 comment="defconf: drop bad forward IPs" add action=drop chain=forward dst-address-list=no_forward_ipv4 comment="defconf: drop bad forward IPs"

La cadena IPv6 forward es muy similar, excepto que IPsec y HIP se aceptan según las recomendaciones de RFC y hop-limit=1 se descarta ICMPv6.

/ipv6 firewall filter add action=accept chain=forward comment="defconf: accept established,related,untracked" connection-state=established,related,untracked add action=drop chain=forward comment="defconf: drop invalid" connection-state=invalid add action=drop chain=forward src-address-list=no_forward_ipv6 comment="defconf: drop bad forward IPs" add action=drop chain=forward dst-address-list=no_forward_ipv6 comment="defconf: drop bad forward IPs" add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" hop-limit=equal:1 protocol=icmpv6 add action=accept chain=forward comment="defconf: accept ICMPv6 after RAW" protocol=icmpv6 add action=accept chain=forward comment="defconf: accept HIP" protocol=139 add action=accept chain=forward comment="defconf: accept IKE" protocol=udp dst-port=500,4500 add action=accept chain=forward comment="defconf: accept AH" protocol=ipsec-ah add action=accept chain=forward comment="defconf: accept ESP" protocol=ipsec-esp add action=accept chain=forward comment="defconf: accept all that matches IPSec policy" ipsec-policy=in,ipsec add action=drop chain=forward comment="defconf: drop everything else not coming from LAN" in-interface-list=!LAN

Observa las reglas de coincidencia de políticas IPsec. Es fundamental que el tráfico encapsulado IPsec evite la vía rápida. Por ello, a modo de ejemplo, hemos añadido una regla deshabilitada para aceptar tráfico que coincida con las políticas IPsec. Siempre que se utilicen túneles IPsec en el enrutador, esta regla debe estar habilitada. Para IPv6, es mucho más sencillo, ya que no admite la vía rápida.

Otro enfoque para resolver el problema de IPsec es agregar reglas RAW, hablaremos de este método más adelante en la sección RAW.

Red local de mascaradas

Para que los dispositivos locales detrás del router puedan acceder a internet, las redes locales deben estar enmascaradas. En la mayoría de los casos, se recomienda usar src-nat en lugar de enmascaramiento; sin embargo, en este caso, cuando la dirección WAN es dinámica, es la única opción.

/ip firewall nat add action=accept chain=srcnat comment="defconf: accept all that matches IPSec policy" ipsec-policy=out,ipsec disabled=yes add action=masquerade chain=srcnat comment="defconf: masquerade" out-interface-list=WAN

Observa la regla de coincidencia de políticas deshabilitada. Al igual que en los filtros de firewall, el tráfico IPSec debe excluirse de la NAT (excepto en escenarios específicos donde la política IPsec esté configurada para coincidir con la dirección NAT). Por lo tanto, siempre que se utilicen túneles IPsec en el enrutador, esta regla debe estar habilitada. 

Filtrado RAW

Listas de direcciones IPv4

Antes de configurar las reglas RAW, creamos algunas listas de direcciones necesarias para nuestra política de filtrado. Se utilizará el RFC 6890 como referencia.

En primer lugar,  la lista de direcciones contiene todas las direcciones IPv4 que no se pueden usar como origen/destino/reenvío, etc. (se eliminarán inmediatamente si se ve dicha dirección)

/ip firewall address-list add address=127.0.0.0/8 comment="defconf: RFC6890" list=bad_ipv4 add address=192.0.0.0/24 comment="defconf: RFC6890" list=bad_ipv4 add address=192.0.2.0/24 comment="defconf: RFC6890 documentation" list=bad_ipv4 add address=198.51.100.0/24 comment="defconf: RFC6890 documentation" list=bad_ipv4 add address=203.0.113.0/24 comment="defconf: RFC6890 documentation" list=bad_ipv4 add address=240.0.0.0/4 comment="defconf: RFC6890 reserved" list=bad_ipv4

Otra lista de direcciones contiene todas las direcciones IPv4 que no se pueden enrutar globalmente.

/ip firewall address-list add address=0.0.0.0/8 comment="defconf: RFC6890" list=not_global_ipv4 add address=10.0.0.0/8 comment="defconf: RFC6890" list=not_global_ipv4 add address=100.64.0.0/10 comment="defconf: RFC6890" list=not_global_ipv4 add address=169.254.0.0/16 comment="defconf: RFC6890" list=not_global_ipv4 add address=172.16.0.0/12 comment="defconf: RFC6890" list=not_global_ipv4 add address=192.0.0.0/29 comment="defconf: RFC6890" list=not_global_ipv4 add address=192.168.0.0/16 comment="defconf: RFC6890" list=not_global_ipv4 add address=198.18.0.0/15 comment="defconf: RFC6890 benchmark" list=not_global_ipv4 add address=255.255.255.255/32 comment="defconf: RFC6890" list=not_global_ipv4

Y las dos últimas listas de direcciones son para direcciones que no pueden usarse como dirección de destino o de origen.

/ip firewall address-list add address=224.0.0.0/4 comment="defconf: multicast" list=bad_src_ipv4 add address=255.255.255.255/32 comment="defconf: RFC6890" list=bad_src_ipv4 add address=0.0.0.0/8 comment="defconf: RFC6890" list=bad_dst_ipv4 add address=224.0.0.0/4 comment="defconf: RFC6890" list=bad_dst_ipv4

Reglas IPv4 RAW

Las reglas IPv4 sin procesar realizarán las siguientes acciones:

  • add disabled «accept» rule: se puede usar para deshabilitar rápidamente el filtrado RAW sin deshabilitar todas las reglas RAW;
  • accept el descubrimiento de DHCP: la mayoría de los paquetes DHCP no son vistos por un firewall IP, pero algunos de ellos sí, así que asegúrese de que sean aceptados;
  • drop paquetes que utilizan IPs de bogon;
  • drop desde direcciones IP SRC y DST no válidas;
  • drop direcciones IP globalmente no enrutables provenientes de la WAN;
  • drop paquetes con dirección de origen distinta a 192.168.88.0/24 (rango IP predeterminado) provenientes de LAN;
  • drop paquetes provenientes de la WAN para ser reenviados a la red 192.168.88.0/24, esto protegerá contra ataques si el atacante conoce la red interna;
  • drop ICMP, UDP y TCP defectuosos;
  • accept todo lo demás que viene de WAN y LAN;
  • drop todo lo demás para asegurarse de que cualquier interfaz recién agregada (como la conexión PPPoE al proveedor de servicios) esté protegida contra una configuración incorrecta accidental.

/ip firewall raw add action=accept chain=prerouting comment="defconf: enable for transparent firewall" disabled=yes add action=accept chain=prerouting comment="defconf: accept DHCP discover" dst-address=255.255.255.255 dst-port=67 in-interface-list=LAN protocol=udp src-address=0.0.0.0 src-port=68 add action=drop chain=prerouting comment="defconf: drop bogon IP's" src-address-list=bad_ipv4 add action=drop chain=prerouting comment="defconf: drop bogon IP's" dst-address-list=bad_ipv4 add action=drop chain=prerouting comment="defconf: drop bogon IP's" src-address-list=bad_src_ipv4 add action=drop chain=prerouting comment="defconf: drop bogon IP's" dst-address-list=bad_dst_ipv4 add action=drop chain=prerouting comment="defconf: drop non global from WAN" src-address-list=not_global_ipv4 in-interface-list=WAN add action=drop chain=prerouting comment="defconf: drop forward to local lan from WAN" in-interface-list=WAN dst-address=192.168.88.0/24 add action=drop chain=prerouting comment="defconf: drop local if not from default IP range" in-interface-list=LAN src-address=!192.168.88.0/24 add action=drop chain=prerouting comment="defconf: drop bad UDP" port=0 protocol=udp add action=jump chain=prerouting comment="defconf: jump to ICMP chain" jump-target=icmp4 protocol=icmp add action=jump chain=prerouting comment="defconf: jump to TCP chain" jump-target=bad_tcp protocol=tcp add action=accept chain=prerouting comment="defconf: accept everything else from LAN" in-interface-list=LAN add action=accept chain=prerouting comment="defconf: accept everything else from WAN" in-interface-list=WAN add action=drop chain=prerouting comment="defconf: drop the rest"

Ten en cuenta que utilizamos algunas cadenas opcionales, la primera cadena TCP para descartar paquetes TCP que se sabe que son inválidos.

/ip firewall raw add action=drop chain=bad_tcp comment="defconf: TCP flag filter" protocol=tcp tcp-flags=!fin,!syn,!rst,!ack add action=drop chain=bad_tcp comment=defconf protocol=tcp tcp-flags=fin,syn add action=drop chain=bad_tcp comment=defconf protocol=tcp tcp-flags=fin,rst add action=drop chain=bad_tcp comment=defconf protocol=tcp tcp-flags=fin,!ack add action=drop chain=bad_tcp comment=defconf protocol=tcp tcp-flags=fin,urg add action=drop chain=bad_tcp comment=defconf protocol=tcp tcp-flags=syn,rst add action=drop chain=bad_tcp comment=defconf protocol=tcp tcp-flags=rst,urg add action=drop chain=bad_tcp comment="defconf: TCP port 0 drop" port=0 protocol=tcp

Y otra cadena para ICMP . Ten en cuenta que si deseas un firewall muy estricto, puedes usar dicho filtrado ICMP , pero en la mayoría de los casos no es necesario y simplemente sobrecarga la CPU del enrutador. El límite de velocidad ICMP también suele ser innecesario, ya que el kernel de Linux ya limita los paquetes ICMP a 100 pps.

/ip firewall raw add action=accept chain=icmp4 comment="defconf: echo reply" icmp-options=0:0 limit=5,10:packet protocol=icmp add action=accept chain=icmp4 comment="defconf: net unreachable" icmp-options=3:0 protocol=icmp add action=accept chain=icmp4 comment="defconf: host unreachable" icmp-options=3:1 protocol=icmp add action=accept chain=icmp4 comment="defconf: protocol unreachable" icmp-options=3:2 protocol=icmp add action=accept chain=icmp4 comment="defconf: port unreachable" icmp-options=3:3 protocol=icmp add action=accept chain=icmp4 comment="defconf: fragmentation needed" icmp-options=3:4 protocol=icmp add action=accept chain=icmp4 comment="defconf: echo" icmp-options=8:0 limit=5,10:packet protocol=icmp add action=accept chain=icmp4 comment="defconf: time exceeded " icmp-options=11:0-255 protocol=icmp add action=drop chain=icmp4 comment="defconf: drop other icmp" protocol=icmp

Listas de direcciones IPv6

Lista de direcciones IPv6 que deben eliminarse instantáneamente

/ipv6 firewall address-list add address=::1/128 comment="defconf: RFC6890 lo" list=bad_ipv6 add address=::ffff:0:0/96 comment="defconf: RFC6890 IPv4 mapped" list=bad_ipv6 add address=2001::/23 comment="defconf: RFC6890" list=bad_ipv6 add address=2001:db8::/32 comment="defconf: RFC6890 documentation" list=bad_ipv6 add address=2001:10::/28 comment="defconf: RFC6890 orchid" list=bad_ipv6 add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6

Lista de direcciones IPv6 que no son enrutables globalmente

/ipv6 firewall address-list add address=100::/64 comment="defconf: RFC6890 Discard-only" list=not_global_ipv6 add address=2001::/32 comment="defconf: RFC6890 TEREDO" list=not_global_ipv6 add address=2001:2::/48 comment="defconf: RFC6890 Benchmark" list=not_global_ipv6 add address=fc00::/7 comment="defconf: RFC6890 Unique-Local" list=not_global_ipv6

Lista de direcciones como dirección de destino no válida

/ipv6 firewall address-list add address=::/128 comment="defconf: unspecified" list=bad_dst_ipv6

Lista de direcciones como dirección de origen no válida

/ipv6 firewall address-list add address=::/128 comment="defconf: unspecified" list=bad_src_ipv6 add address=ff00::/8 comment="defconf: multicast" list=bad_src_ipv6

Reglas RAW de IPv6

Las reglas IPv6 sin procesar realizarán las siguientes acciones:

  • add disabled accept rule: se puede usar para deshabilitar rápidamente el filtrado RAW sin deshabilitar todas las reglas RAW;
  • drop paquetes que utilizan IPs de bogon;
  • drop desde direcciones IP SRC y DST no válidas;
  • drop direcciones IP globalmente no enrutables provenientes de la WAN;
  • drop ICMP incorrecto;
  • acccept todo lo demás que viene de WAN y LAN;
  • drop todo lo demás para asegurarse de que cualquier interfaz recién agregada (como la conexión PPPoE al proveedor de servicios) esté protegida contra una configuración incorrecta accidental.

/ipv6 firewall raw add action=accept chain=prerouting comment="defconf: enable for transparent firewall" disabled=yes add action=accept chain=prerouting comment="defconf: RFC4291, section 2.7.1" src-address=::/128 dst-address=ff02:0:0:0:0:1:ff00::/104 icmp-options=135 protocol=icmpv6 add action=drop chain=prerouting comment="defconf: drop bogon IP's" src-address-list=bad_ipv6 add action=drop chain=prerouting comment="defconf: drop bogon IP's" dst-address-list=bad_ipv6 add action=drop chain=prerouting comment="defconf: drop packets with bad SRC ipv6" src-address-list=bad_src_ipv6 add action=drop chain=prerouting comment="defconf: drop packets with bad dst ipv6" dst-address-list=bad_dst_ipv6 add action=drop chain=prerouting comment="defconf: drop non global from WAN" src-address-list=not_global_ipv6 in-interface-list=WAN add action=jump chain=prerouting comment="defconf: jump to ICMPv6 chain" jump-target=icmp6 protocol=icmpv6 add action=accept chain=prerouting comment="defconf: accept local multicast scope" dst-address=ff02::/16 add action=drop chain=prerouting comment="defconf: drop other multicast destinations" dst-address=ff00::/8 add action=accept chain=prerouting comment="defconf: accept everything else from WAN" in-interface-list=WAN add action=accept chain=prerouting comment="defconf: accept everything else from LAN" in-interface-list=LAN add action=drop chain=prerouting comment="defconf: drop the rest"


Ten en cuenta que se utilizó la cadena ICMP opcional. Si deseas un firewall muy estricto, puedes usar dicho filtrado ICMP , pero en la mayoría de los casos no es necesario y simplemente sobrecarga la CPU del enrutador. El límite de velocidad ICMP también suele ser innecesario, ya que el kernel de Linux ya limita los paquetes ICMP a 100 pps.

/ipv6 firewall raw # Be aware that different operating systems originate packets with different default TTL values add action=drop chain=icmp6 comment="defconf: rfc4890 drop ll if hop-limit!=255" dst-address=fe80::/10 hop-limit=not-equal:255 protocol=icmpv6 add action=accept chain=icmp6 comment="defconf: dst unreachable" icmp-options=1:0-255 protocol=icmpv6 add action=accept chain=icmp6 comment="defconf: packet too big" icmp-options=2:0-255 protocol=icmpv6 add action=accept chain=icmp6 comment="defconf: limit exceeded" icmp-options=3:0-1 protocol=icmpv6 add action=accept chain=icmp6 comment="defconf: bad header" icmp-options=4:0-2 protocol=icmpv6 add action=accept chain=icmp6 comment="defconf: Mobile home agent address discovery" icmp-options=144:0-255 protocol=icmpv6 add action=accept chain=icmp6 comment="defconf: Mobile home agent address discovery" icmp-options=145:0-255 protocol=icmpv6 add action=accept chain=icmp6 comment="defconf: Mobile prefix solic" icmp-options=146:0-255 protocol=icmpv6 add action=accept chain=icmp6 comment="defconf: Mobile prefix advert" icmp-options=147:0-255 protocol=icmpv6 add action=accept chain=icmp6 comment="defconf: echo request limit 5,10" icmp-options=128:0-255 limit=5,10:packet protocol=icmpv6 add action=accept chain=icmp6 comment="defconf: echo reply limit 5,10" icmp-options=129:0-255 limit=5,10:packet protocol=icmpv6 add action=accept chain=icmp6 comment="defconf: rfc4890 router solic limit 5,10 only LAN" hop-limit=equal:255 icmp-options=133:0-255 in-interface-list=LAN limit=5,10:packet protocol=icmpv6 add action=accept chain=icmp6 comment="defconf: rfc4890 router advert limit 5,10 only LAN" hop-limit=equal:255 icmp-options=134:0-255 in-interface-list=LAN limit=5,10:packet protocol=icmpv6 add action=accept chain=icmp6 comment="defconf: rfc4890 neighbor solic limit 5,10 only LAN" hop-limit=equal:255 icmp-options=135:0-255 in-interface-list=LAN limit=5,10:packet protocol=icmpv6 add action=accept chain=icmp6 comment="defconf: rfc4890 neighbor advert limit 5,10 only LAN" hop-limit=equal:255 icmp-options=136:0-255 in-interface-list=LAN limit=5,10:packet protocol=icmpv6 add action=accept chain=icmp6 comment="defconf: rfc4890 inverse ND solic limit 5,10 only LAN" hop-limit=equal:255 icmp-options=141:0-255 in-interface-list=LAN limit=5,10:packet protocol=icmpv6 add action=accept chain=icmp6 comment="defconf: rfc4890 inverse ND advert limit 5,10 only LAN" hop-limit=equal:255 icmp-options=142:0-255 in-interface-list=LAN limit=5,10:packet protocol=icmpv6 add action=drop chain=icmp6 comment="defconf: drop other icmp" protocol=icmpv6

Creado por Artūrs C., actualizado por última vez por Guntis G. el abr 26, 2024
Ayuda de Mikrotik

Ilustración propia, generada con IA