Implantación de un cortafuegos perimetral con nftables

Índice

En este post se recoge un ejemplo práctico de la implantación de un sistema de cortafuegos perimetral usando la herramienta nftables para filtrar el tráfico que circula por la red.

Implementación de un cortafuegos perimetral con nftables

Para implementar un cortafuegos perimetral en una red con nftables, en primer lugar, se instala el paquete necesario para utilizar esta herramienta.

sudo apt install nftables

A diferencia de iptables, nftables no cuenta con tablas predefinidas. Por tanto, para poder usar esta herramienta como cortafuegos perimetral que filtre el tráfico que circula entre la red privada e Internet hay que crear la tabla filter.

nft add table inet filter

A continuación, hay que crear también las cadenas en esta tabla. Aunque estas cadenas van a tener política por defecto drop, en un primer momento, se crean con política por defecto accept para no perder la conexión por SSH a la máquina.

nft add chain inet filter input { type filter hook input priority 0 \; counter \; policy accept \; }
nft add chain inet filter output { type filter hook output priority 0 \; counter \; policy accept \; }
nft add chain inet filter forward { type filter hook forward priority 0 \; counter \; policy accept \; }

Como la máquina cortafuegos también actúa como router, necesitará una tabla nat.

nft add table ip nat

Esta tabla usa las cadenas prerouting y postrouting.

nft add chain ip nat prerouting { type nat hook prerouting priority 100 \; }
nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }

Para que la máquina del cortafuegos actúe también como router debe tener activado el bit de forwarding. Por tanto, en el fichero de configuración /etc/sysctl.conf se descomenta la siguiente línea:

# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1

Y se aplican los cambios.

debian@router-fw:~$ sudo sysctl -p
net.ipv4.ip_forward = 1

Además, para que desde la máquina de la red privada se pueda acceder a Internet, hay que añadir la regla SNAT correspondiente.

nft add rule ip nat postrouting oifname "ens3" ip saddr 192.168.100.0/24 counter masquerade

Antes de cambiar la política por defecto de las cadenas de filtrado a drop hay que garantizar el acceso a la máquina por SSH con las siguientes reglas:

nft add rule inet filter input ip saddr 172.22.0.0/16 tcp dport 22 ct state new,established counter accept
nft add rule inet filter output ip daddr 172.22.0.0/16 tcp sport 22 ct state established counter accept

Para poder acceder por SSH a la máquina, además, desde la VPN que permite el acceso remoto a la red de OpenStack ha sido necesario añadir una nueva regla de cortafuegos más laxa.

nft add rule inet filter input tcp dport 22 ct state new,established counter accept
nft add rule inet filter output tcp sport 22 ct state established counter accept

Ahora que la conexión por SSH a la máquina ya se permite, se puede cambiar a drop la política por defecto de las tres cadenas de la tabla filter.

nft chain inet filter input { policy drop \; }
nft chain inet filter output { policy drop \; }
nft chain inet filter forward { policy drop \; }

Para comprobar que la política por defecto está funcionando se puede hacer, desde el cortafuegos, un ping a la máquina de la red privada.

debian@router-fw:~# ping -c1 -w4 192.168.100.10
PING 192.168.100.10 (192.168.100.10) 56(84) bytes of data.

--- 192.168.100.10 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3055ms

Para que las reglas configuradas en el cortafuegos sean persistentes a los reinicios se vuelcan al fichero /etc/nftables.conf

nft list ruleset > /etc/nftables.conf

Tras aplicar estas primeras reglas, contiene la siguiente información:

root@router-fw:/home/debian# cat /etc/nftables.conf 
table inet filter {
	chain input {
		type filter hook input priority filter; policy drop;
		counter packets 3563 bytes 285912
		ip saddr 172.22.0.0/16 tcp dport 22 ct state established,new counter packets 387 bytes 26896 accept
	}

	chain output {
		type filter hook output priority filter; policy drop;
		counter packets 2944 bytes 288232
		ip daddr 172.22.0.0/16 tcp sport 22 ct state established counter packets 257 bytes 25248 accept
	}

	chain forward {
		type filter hook forward priority filter; policy drop;
		counter packets 11644 bytes 37493425
	}
}
table ip nat {
	chain prerouting {
		type nat hook prerouting priority 100; policy accept;
	}

	chain postrouting {
		type nat hook postrouting priority srcnat; policy accept;
		oifname "ens3" ip saddr 192.168.100.0/24 counter packets 21 bytes 1480 masquerade
	}
}

A continuación, hay que permitir también el tráfico para la interfaz loopback.

nft add rule inet filter input iifname "lo" counter accept
nft add rule inet filter output oifname "lo" counter accept

Como siguiente paso, se permite al router hacer ping a Internet.

nft add rule inet filter output oifname "ens3" icmp type echo-request counter accept
nft add rule inet filter input iifname "ens3" icmp type echo-reply counter accept

Y también a la LAN.

nft add rule inet filter output oifname "ens4" icmp type echo-request counter accept
nft add rule inet filter input iifname "ens4" icmp type echo-reply counter accept

Así, desde el router se puede hacer ping tanto al exterior como a la máquina de la red privada.

root@router-fw:/home/debian# ping -c1 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=104 time=17.4 ms

--- 8.8.8.8 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 17.447/17.447/17.447/0.000 ms
root@router-fw:/home/debian# ping -c1 192.168.100.10
PING 192.168.100.10 (192.168.100.10) 56(84) bytes of data.
64 bytes from 192.168.100.10: icmp_seq=1 ttl=64 time=2.08 ms

--- 192.168.100.10 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 2.078/2.078/2.078/0.000 ms

Para permitir que la máquina de la red LAN pueda hacer ping al exterior también hay que indicar las reglas necesarias en la cadena forward de la tabla filter.

nft add rule inet filter forward iifname "ens4" oifname "ens3" ip saddr 192.168.100.0/24 icmp type echo-request counter accept
nft add rule inet filter forward iifname "ens3" oifname "ens4" ip daddr 192.168.100.0/24 icmp type echo-reply counter accept
debian@lan:~$ ping -c1 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=103 time=18.2 ms

--- 8.8.8.8 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 18.206/18.206/18.206/0.000 ms

Para poder resolver nombres de Internet, el equipo de la LAN tiene que poder acceder al servidor DNS que tenga configurado. Para ello, la tabla filter del cortafuegos necesita incluir las reglas en la cadena forward que permitan el tráfico del puerto 53.

nft add rule inet filter forward iifname "ens4" oifname "ens3" ip saddr 192.168.100.0/24 udp dport 53 ct state new,established counter accept
nft add rule inet filter forward iifname "ens3" oifname "ens4" ip daddr 192.168.100.0/24 udp sport 53 ct state established counter accept
debian@lan:~$ ping -c1 www.google.com
PING www.google.com (142.250.185.4) 56(84) bytes of data.
64 bytes from mad41s11-in-f4.1e100.net (142.250.185.4): icmp_seq=1 ttl=104 time=27.8 ms

--- www.google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 27.831/27.831/27.831/0.000 ms

Para que el equipo de LAN pueda navegar por Internet usando los protocolos HTTP y HTTPS se debe permitir también el tráfico por los puertos de estos servicios.

nft add rule inet filter forward iifname "ens4" oifname "ens3" ip protocol tcp ip saddr 192.168.100.0/24 tcp dport { 80,443} ct state new,established counter accept
nft add rule inet filter forward iifname "ens3" oifname "ens4" ip protocol tcp ip daddr 192.168.100.0/24 tcp sport { 80,443} ct state established counter accept
debian@lan:~$ curl www.example.org
<!doctype html>
<html>
<head>
    <title>Example Domain</title>

    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style type="text/css">
    body {
        background-color: #f0f0f2;
        margin: 0;
        padding: 0;
        font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI",
		 "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
        
    }
    div {
        width: 600px;
        margin: 5em auto;
        padding: 2em;
        background-color: #fdfdff;
        border-radius: 0.5em;
        box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
    }
    a:link, a:visited {
        color: #38488f;
        text-decoration: none;
    }
    @media (max-width: 700px) {
        div {
            margin: 0 auto;
            width: auto;
        }
    }
    </style>    
</head>

<body>
<div>
    <h1>Example Domain</h1>
    <p>This domain is for use in illustrative examples in documents. You may u
	se this
    domain in literature without prior coordination or asking for permission.
	</p>
    <p><a href="https://www.iana.org/domains/example">More information...</a>
	</p>
</div>
</body>
</html>

Además, en el equipo de la LAN hay un servidor web. Para acceder a él hay que permitir el acceso a través del cortafuegos. Como mejora a esta regla, se limita el número de conexiones del servidor web a 15.

nft add rule inet filter forward iifname "ens3" oifname "ens4" ip daddr 192.168.100.0/24 tcp dport 80 ct state new,established ct count 15 counter accept
nft add rule inet filter forward iifname "ens4" oifname "ens3" ip saddr 192.168.100.0/24 tcp sport 80 ct state established counter accept

Además, hay que configurar la regla de DNAT para el acceso a este servidor.

nft add rule ip nat prerouting iifname "ens3" tcp dport 80 counter dnat to 192.168.100.10

Con estas reglas de filtrado y de DNAT se puede acceder al servidor web desde el exterior a través del cortafuegos.

❯ curl 172.22.201.30
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

En este punto, el listado de reglas configuradas en el cortafuegos es el siguiente:

root@router-fw:~# nft list ruleset
table inet filter {
	chain input {
		type filter hook input priority filter; policy drop;
		counter packets 6628 bytes 555598
		ip saddr 172.22.0.0/16 tcp dport 22 ct state established,new counter packets 1924 bytes 27628 accept
		ip saddr 192.168.100.0/24 tcp sport 22 ct state established counter packets 588 bytes 97152 accept
		ip saddr 192.168.100.0/24 tcp sport 22 ct state established counter packets 0 bytes 0 accept
		iifname "lo" counter packets 0 bytes 0 accept
		iifname "ens4" icmp type echo-reply counter packets 1 bytes 84 accept
		iifname "ens3" icmp type echo-reply counter packets 6 bytes 504 accept 
        tcp dport 22 ct state established,new counter packets 885 bytes 68334 accept
	}

	chain output {
		type filter hook output priority filter; policy drop;
		counter packets 5661 bytes 618708
		ip daddr 172.22.0.0/16 tcp sport 22 ct state established counter packets 1393 bytes 152276 accept
		ip daddr 192.168.100.0/24 tcp dport 22 ct state established,new counter packets 677 bytes 61220 accept
		oifname "lo" counter packets 0 bytes 0 accept
		oifname "ens4" icmp type echo-request counter packets 1 bytes 84 accept
		oifname "ens3" icmp type echo-request counter packets 6 bytes 504 accept
		tcp sport 22 ct state established counter packets 553 bytes 95508 accept
	}

	chain forward {
		type filter hook forward priority filter; policy drop;
		counter packets 12383 bytes 38207937
		iifname "ens4" oifname "ens3" ip saddr 192.168.100.0/24 icmp type echo-request counter packets 3 bytes 252 accept
		iifname "ens3" oifname "ens4" ip daddr 192.168.100.0/24 icmp type echo-reply counter packets 3 bytes 252 accept
		iifname "ens4" oifname "ens3" ip saddr 192.168.100.0/24 udp dport 53 ct state established,new counter packets 10 bytes 638 accept
		iifname "ens3" oifname "ens4" ip daddr 192.168.100.0/24 udp sport 53 ct state established counter packets 10 bytes 1099 accept
		iifname "ens4" oifname "ens3" ip protocol tcp ip saddr 192.168.100.0/24 tcp dport { 80, 443 } ct state established,new counter packets 178 bytes 10181 accept
		iifname "ens3" oifname "ens4" ip protocol tcp ip daddr 192.168.100.0/24 tcp sport { 80, 443 } ct state established counter packets 232 bytes 680949 accept
		iifname "ens3" oifname "ens4" ip daddr 192.168.100.0/24 tcp dport 80 ct state established,new ct count 15 counter packets 6 bytes 396 accept
		iifname "ens4" oifname "ens3" ip saddr 192.168.100.0/24 tcp sport 80 ct state established counter packets 4 bytes 1069 accept
	}
}
table ip nat {
	chain prerouting {
		type nat hook prerouting priority 100; policy accept;
		iifname "ens3" tcp dport 80 counter packets 1 bytes 60 dnat to 192.168.100.10
	}

	chain postrouting {
		type nat hook postrouting priority srcnat; policy accept;
		oifname "ens3" ip saddr 192.168.100.0/24 counter packets 37 bytes 2550 masquerade
	}
}

Permite poder hacer conexiones ssh al exterior desde la máquina cortafuegos

Para permitir conexiones SSH al exterior desde la máquina cortafuegos:

nft add rule inet filter output oifname "ens3" tcp dport 22 ct state new,established counter accept
nft add rule inet filter input iifname "ens3" tcp sport 22 ct state established counter accept

Así, desde el cortafuegos se puede acceder por SSH a una máquina de fuera de la red.

debian@router-fw:~$ ssh javi@172.22.12.23
The authenticity of host '172.22.12.23 (172.22.12.23)' can't be established.
ED25519 key fingerprint is SHA256:i3ZgWPBlfhW42MZfkeEZO4Oa4oqgFpeJPc9RXrpTyZM.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '172.22.12.23' (ED25519) to the list of known hosts.
Linux tepig 6.1.0-31-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.128-1 (2025-02-07) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
You have new mail.
Last login: Mon Feb 24 12:59:56 2025 from 172.22.201.30
❯ hostname -f
tepig

Permite hacer consultas DNS desde la máquina cortafuegos sólo al servidor 8.8.8.8. Comprueba que no puedes hacer un dig a 1.1.1.1

Para restringir las consultas DNS desde el cortafuegos sólo al servidor 8.8.8.8:

nft add rule inet filter output oifname "ens3" ip daddr 8.8.8.8 udp dport 53 ct state new,established counter accept
nft add rule inet filter input iifname "ens3" ip saddr 8.8.8.8 udp sport 53 ct state established counter accept

Se pueden resolver direcciones al DNS 8.8.8.8:


root@router-fw:~# dig @8.8.8.8 javihuete.site.

; <<>> DiG 9.18.33-1~deb12u2-Debian <<>> @8.8.8.8 javihuete.site.
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30545
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;javihuete.site.			IN	A

;; ANSWER SECTION:
javihuete.site.		900	IN	A	216.24.57.1

;; Query time: 88 msec
;; SERVER: 8.8.8.8#53(8.8.8.8) (UDP)
;; WHEN: Fri Feb 21 18:06:02 UTC 2025
;; MSG SIZE  rcvd: 59

Pero no a 1.1.1.1:

root@router-fw:~# dig @1.1.1.1 javihuete.site.
;; communications error to 1.1.1.1#53: timed out
;; communications error to 1.1.1.1#53: timed out
;; communications error to 1.1.1.1#53: timed out

; <<>> DiG 9.18.33-1~deb12u2-Debian <<>> @1.1.1.1 javihuete.site.
; (1 server found)
;; global options: +cmd
;; no servers could be reached

Permite que la máquina cortafuegos pueda navegar por https

Para que el cortafuegos pueda navegar por HTTPS:

nft add rule inet filter output oifname "ens3" tcp dport 443 ct state new,established counter accept
nft add rule inet filter input iifname "ens3" tcp sport 443 ct state established counter accept

Desde la máquina se puede acceder a una web HTTPS:

root@router-fw:~# curl https://example.org
<!doctype html>
<html>
<head>
    <title>Example Domain</title>

    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style type="text/css">
    body {
        background-color: #f0f0f2;
        margin: 0;
        padding: 0;
        font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI",
		 "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
        
    }
    div {
        width: 600px;
        margin: 5em auto;
        padding: 2em;
        background-color: #fdfdff;
        border-radius: 0.5em;
        box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
    }
    a:link, a:visited {
        color: #38488f;
        text-decoration: none;
    }
    @media (max-width: 700px) {
        div {
            margin: 0 auto;
            width: auto;
        }
    }
    </style>    
</head>

<body>
<div>
    <h1>Example Domain</h1>
    <p>This domain is for use in illustrative examples in documents. You may 
	use this domain in literature without prior coordination or asking for 
	permission.</p>
    <p><a href="https://www.iana.org/domains/example">More information...</a>
	</p>
</div>
</body>
</html>

Pero no por HTTP:

root@router-fw:~# time curl example.org
^C

real	4m57.055s

Los equipos de la red local deben poder tener conexión al exterior

Para que los equipos de la red local puedan tener conexión al exterior haciendo ping:

nft add rule inet filter forward iifname "ens4" oifname "ens3" ip saddr 192.168.100.0/24 icmp type echo-request counter accept
nft add rule inet filter forward iifname "ens3" oifname "ens4" ip daddr 192.168.100.0/24 icmp type echo-reply counter accept
debian@lan:~$ ping -c1 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=103 time=18.2 ms

--- 8.8.8.8 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 18.206/18.206/18.206/0.000 ms

Permitimos el ssh desde el cortafuegos a la LAN

Como, por defecto, se ha bloqueado todo el tráfico, desde el router no se puede acceder por SSH a la máquina de la red privada. Para permitir este tráfico hay que añadir dos reglas similares a las que permiten acceder por SSH al router.

nft add rule inet filter output ip daddr 192.168.100.0/24 tcp dport 22 ct state new,established counter accept
nft add rule inet filter input ip saddr 192.168.100.0/24 tcp sport 22 ct stateestablished counter accept

Tras aplicar estas reglas, se puede conectar al equipo de la red local por SSH.

debian@router-fw:~$ ssh 192.168.100.10
Linux lan 6.1.0-28-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.119-1 (2024-11-22) 
x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Fri Feb 21 13:05:49 2025 from 192.168.100.2
debian@lan:~$ hostname -f
lan

Permitimos hacer ping desde la LAN a la máquina cortafuegos

Para que la máquin de la LAN haga ping al cortafuegos:

nft add rule inet filter input iifname "ens4" icmp type echo-request counter accept
nft add rule inet filter output oifname "ens4" icmp type echo-reply counter accept
debian@lan:~$ ping -c1 192.168.100.2
PING 192.168.100.2 (192.168.100.2) 56(84) bytes of data.
64 bytes from 192.168.100.2: icmp_seq=1 ttl=64 time=0.224 ms

--- 192.168.100.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.224/0.224/0.224/0.000 ms

Permite realizar conexiones ssh desde los equipos de la LAN

Para que los equipos de la LAN se puedan conectar por SSH al router:

nft add rule inet filter input iifname "ens4" tcp dport 22 ct state new,established counter accept
nft add rule inet filter output oifname "ens4" tcp sport 22 ct state established counter accept
debian@lan:~$ ssh 192.168.100.2
The authenticity of host '192.168.100.2 (192.168.100.2)' can't be established.
ED25519 key fingerprint is SHA256:PidAI9u2QLAxIyVcwJCMBDGGXcZUUDYA3F5BL5CDzuc.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.100.2' (ED25519) to the list of known hosts.
Linux router-fw 6.1.0-28-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.119-1 (2024-11-22) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Fri Feb 21 16:37:47 2025 from 172.210.0.6
debian@router-fw:~$ hostname
router-fw

Instala un servidor de correos en la máquina de la LAN. Permite el acceso desde el exterior y desde el cortafuegos al servidor de correos. Para probarlo puedes ejecutar un telnet al puerto 25 tcp

Para permitir el acceso desde el exterior al servidor de correos:

nft add rule inet filter forward iifname "ens3" oifname "ens4" ip daddr 192.168.100.0/24 tcp dport 25 ct state new,established counter accept
nft add rule inet filter forward iifname "ens4" oifname "ens3" ip saddr 192.168.100.0/24 tcp sport 25 ct state established counter accept

Además, hay que configurar la regla de DNAT para el acceso a este servidor.

nft add rule ip nat prerouting iifname "ens3" tcp dport 25 counter dnat to 192.168.100.10
❯ telnet 172.22.201.30 25
Trying 172.22.201.30...
Connected to 172.22.201.30.
Escape character is '^]'.
220 lan ESMTP Postfix (Debian/GNU)

Para permitir el acceso desde el cortafuegos al servidor de correos:

nft add rule inet filter output ip daddr 192.168.100.0/24 tcp dport 25 ct state new,established counter accept
nft add rule inet filter input ip saddr 192.168.100.0/24 tcp sport 25 ct state established counter accept
root@router-fw:~# telnet 192.168.100.10 25
Trying 192.168.100.10...
Connected to 192.168.100.10.
Escape character is '^]'.
220 lan ESMTP Postfix (Debian/GNU)

Permite hacer conexiones ssh desde exterior a la LAN

Para permitir conexiones SSH desde el exterior a la LAN:

nft add rule inet filter forward ip daddr 192.168.100.0/24 tcp dport 22 ct state new,established counter accept
nft add rule inet filter forward ip saddr 192.168.100.0/24 tcp sport 22 ct state established counter accept

Modifica la regla anterior, para que al acceder desde el exterior por ssh tengamos que conectar al puerto 2222, aunque el servidor ssh este configurado para acceder por el puerto 22

En este caso, se puede usar una regla de DNAT

nft add rule ip nat prerouting iifname "ens3" tcp dport 2222 counter dnat to 192.168.100.10:22
nft add rule ip nat postrouting oifname "ens3" tcp sport 22 counter snat to 172.22.201.30:2222

Permite hacer consultas DNS desde la LAN sólo al servidor 8.8.8.8. Comprueba que no puedes hacer un dig a 1.1.1.1

Primero hay que eliminar las reglas que permiten el tráfico DNS desde la LAN establecidas al principio del ejercicio:

nft delete rule inet filter forward handle 33
nft delete rule inet filter forward handle 34

Y para restrigir las consultas DNS sólo al servidor 8.8.8.8 desde la LAN:

nft add rule inet filter forward iifname "ens4" oifname "ens3" ip daddr 8.8.8.8 udp dport 53 ct state new,established counter accept
nft add rule inet filter forward iifname "ens3" oifname "ens4" ip saddr 8.8.8.8 udp sport 53 ct state established counter accept
debian@lan:~$ dig @8.8.8.8 javihuete.site.

; <<>> DiG 9.18.33-1~deb12u2-Debian <<>> @8.8.8.8 javihuete.site.
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6326
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;javihuete.site.			IN	A

;; ANSWER SECTION:
javihuete.site.		900	IN	A	216.24.57.1

;; Query time: 188 msec
;; SERVER: 8.8.8.8#53(8.8.8.8) (UDP)
;; WHEN: Fri Feb 21 19:30:40 UTC 2025
;; MSG SIZE  rcvd: 59

debian@lan:~$ dig @1.1.1.1 javihuete.site.
;; communications error to 1.1.1.1#53: timed out
;; communications error to 1.1.1.1#53: timed out
;; communications error to 1.1.1.1#53: timed out

; <<>> DiG 9.18.33-1~deb12u2-Debian <<>> @1.1.1.1 javihuete.site.
; (1 server found)
;; global options: +cmd
;; no servers could be reached

Permite que los equipos de la LAN puedan navegar por internet, excepto a la página www.realbetisbalompie.es

Con las reglas configuradas hasta el momento se permite el tráfico web por todo Internet. Así que hay que averiguar la IP de la páquina que hay que bloquear.

debian@router-fw:~$ dig www.realbetisbalompie.es

; <<>> DiG 9.18.33-1~deb12u2-Debian <<>> www.realbetisbalompie.es
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32924
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;www.realbetisbalompie.es.	IN	A

;; ANSWER SECTION:
www.realbetisbalompie.es. 122	IN	CNAME	realbetisbalompie.es.
realbetisbalompie.es.	122	IN	A	51.255.76.196

;; Query time: 52 msec
;; SERVER: 8.8.8.8#53(8.8.8.8) (UDP)
;; WHEN: Fri Feb 21 19:33:29 UTC 2025
;; MSG SIZE  rcvd: 83

A continuación, se eliminan las reglas que permiten el tráfico web desde la LAN.

nft delete rule inet filter forward handle 36
nft delete rule inet filter forward handle 38

Después se permite el tráfico web a todo Internet excepto a la IP 51.255.76.196.

nft add rule inet filter forward iifname "ens4" oifname "ens3" ip protocol tcp ip saddr 192.168.100.0/24 ip daddr != 51.255.76.196 tcp dport { 80,443} ct state new,established counter accept
nft add rule inet filter forward iifname "ens3" oifname "ens4" ip protocol tcp ip saddr != 51.255.76.196 ip daddr 192.168.100.0/24 tcp sport { 80,443} ct state established counter accept

Así, se puede acceder a cualquier web excepto a www.realbetisbalompie.es.

debian@lan:~$ curl www.example.org
<!doctype html>
<html>
<head>
    <title>Example Domain</title>

    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style type="text/css">
    body {
        background-color: #f0f0f2;
        margin: 0;
        padding: 0;
        font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
        
    }
    div {
        width: 600px;
        margin: 5em auto;
        padding: 2em;
        background-color: #fdfdff;
        border-radius: 0.5em;
        box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
    }
    a:link, a:visited {
        color: #38488f;
        text-decoration: none;
    }
    @media (max-width: 700px) {
        div {
            margin: 0 auto;
            width: auto;
        }
    }
    </style>    
</head>

<body>
<div>
    <h1>Example Domain</h1>
    <p>This domain is for use in illustrative examples in documents. You may use this
    domain in literature without prior coordination or asking for permission.</p>
    <p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>
debian@lan:~$ time curl www.realbetisbalompie.es
curl: (28) Failed to connect to www.realbetisbalompie.es port 80 after 129394 ms: Couldn't connect to server

real	2m9.418s
user	0m0.015s
sys	0m0.030s
comments powered by Disqus

Relacionados

Funcionamiento básico de ansible

Ansible es un software que permite la configuración automatizada de equipos a través de la ejecución de reglas. En esta entrada se recogen algunos elementos fundamentales de esta herramienta.

Leer

Autentificación SSH con cifrado asimétrico usando GPG

Para que la conexión entre cliente y servidor por SSH sea más ágil y rápida, se usa un cifrado simétrico. Sin embargo, para que una conexión con cifrado simétrico sea segura es necesario que ambos interlocutores negocien una clave simétrica usando una conexión segura.

Leer

Instalación desatendida por red de Debian12

En este post se recogen varias opciones alternativas para la configuración de un servicio de instalación desatendida de Debian 12 por red.

Leer