Tutorial: Router casero con Linux

Construye tu propio router profesional con Debian, firewall, VPN y bloqueador de anuncios

1Introducción

Este tutorial te guiará paso a paso para crear tu propio router usando un MiniPC con Debian. Obtendrás un router personalizable con funciones avanzadas como firewall, VPN, bloqueador de anuncios y soporte completo para IPv4 e IPv6.

¿Por qué crear un router propio?

🚀 Mayor rendimiento

Superior a routers comerciales con hardware dedicado

🎛️ Control total

Configuración completa sobre todos los aspectos

🔧 Flexibilidad

Añade servicios y funciones según necesites

🔒 Mejor seguridad

Firewall personalizado y actualizaciones constantes

🛡️ Privacidad

Control completo sobre DNS y tráfico

💰 Coste-efectivo

Hardware económico con prestaciones superiores

2Requisitos de Hardware

Hardware mínimo recomendado:

  • CPU: Intel Celeron o superior (4 núcleos recomendado)
  • RAM: 4 GB mínimo
  • Almacenamiento: SSD de 64 GB o más
  • Interfaces de red: Mínimo 2 puertos Ethernet

Identificar interfaces de red

ip link show
Ejemplo de salida:
enp2s0 → WAN (hacia ISP)
enp3s0 → LAN (hacia red interna)

3Instalación base de Debian

  1. Descarga Debian desde debian.org
  2. Instala Debian en tu MiniPC
  3. Actualiza el sistema:
sudo apt update && sudo apt upgrade -y

Instala paquetes necesarios:

sudo apt install systemd-networkd nftables radvd wireguard-tools curl wget -y

4Configuración de interfaces de red

Habilitar systemd-networkd

sudo systemctl enable systemd-networkd sudo systemctl disable networking sudo systemctl disable dhcpcd

Configurar interfaz WAN (enp2s0)

/etc/systemd/network/05-enp2s0.network
[Match]
Name=enp2s0

[Network]
DHCP=no
DNS=8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844 1.1.1.1 1.0.0.1 2606:4700:4700::1111 2606:4700:4700::1001
IPv6PrivacyExtensions=yes
Gateway=192.168.1.1
Address=192.168.1.15/24
Cambia la IP 192.168.1.15/24 y gateway 192.168.1.1 según tu configuración de ISP.

Configurar interfaz LAN (enp3s0)

/etc/systemd/network/05-enp3s0.network
[Match]
Name=enp3s0

[Network]
DHCP=no
IPv6PrivacyExtensions=yes
Address=192.168.10.1/24

Reiniciar servicios de red

sudo systemctl restart systemd-networkd sudo systemctl start systemd-networkd

5Configurar IPv6 con radvd

Instalar radvd

sudo apt install radvd -y

Configurar radvd

/etc/radvd.conf
interface enp3s0 {
    AdvSendAdvert on;
    prefix 2a0c:5a81::/64 {
        AdvOnLink on;
        AdvPreferredLifetime 86400;
    };
    RDNSS fe80::1ac0:4dff:fe13:f3cb {
    };
};

Habilitar radvd

sudo systemctl enable radvd sudo systemctl start radvd

6Activar reenvío de paquetes

Edita /etc/sysctl.conf y añade/descomenta:

/etc/sysctl.conf
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1

Aplicar cambios:

sudo sysctl -p

7Configurar Firewall y NAT con nftables

/etc/nftables.conf
flush ruleset

define DEV_PRIVATE = enp3s0
define DEV_WORLD = enp2s0
define DEV_WG0 = wg0
define NET_PRIVATE = 192.168.10.0/24
define NET_WORLD = 192.168.1.0/24
define NET_WG0 = 10.8.0.0/24
define TORRENT_PORTS = 51415

##############
# IPv4 rules #
##############
table ip filter {
    chain inbound_world {
        udp dport 51821 counter accept
        udp dport $TORRENT_PORTS counter accept
        tcp dport $TORRENT_PORTS counter accept
        counter drop
    }
    
    chain inbound_private {
        icmp type echo-request limit rate 10/second counter accept
        udp dport {53, 67, 123, 20002, 5335, 5353, 42202, 51821} counter accept
        tcp dport 0-65535 counter accept
        counter drop
    }
    
    chain input {
        type filter hook input priority filter; policy drop;
        ct state {established, related} accept
        ct state invalid drop
        iifname vmap { lo : accept, $DEV_WORLD : jump inbound_world, $DEV_PRIVATE : jump inbound_private, $DEV_WG0 : jump inbound_private }
        counter drop
    }
    
    chain forward {
        type filter hook forward priority filter; policy drop;
        ct state {established, related} accept
        ct state invalid drop
        iifname $DEV_PRIVATE counter accept
        iifname { $DEV_WG0, $DEV_PRIVATE } oifname $DEV_WORLD counter accept
        counter drop
    }
    
    chain output {
        type filter hook output priority filter; policy accept;
    }
}

table ip nat {
    chain prerouting {
        type nat hook prerouting priority dstnat; policy accept;
        iifname $DEV_WORLD tcp dport $TORRENT_PORTS dnat ip to 192.168.10.33:$TORRENT_PORTS
        iifname $DEV_WORLD udp dport $TORRENT_PORTS dnat ip to 192.168.10.33:$TORRENT_PORTS
    }
    
    chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;
        iifname { $DEV_WG0, $DEV_PRIVATE } oifname $DEV_WORLD masquerade
    }
}

##############
# IPv6 rules #
##############
table ip6 filter {
    chain rfc4890 {
        ip6 nexthdr ipv6-icmp icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request, echo-reply } accept
        ip6 nexthdr ipv6-icmp icmpv6 type { nd-neighbor-solicit, nd-neighbor-advert, nd-router-advert, nd-router-solicit } ip6 hoplimit 255 accept
        return
    }
    
    chain inbound_world {
        udp dport 51821 accept
        udp dport 546 accept
        udp dport 547 accept
        udp dport $TORRENT_PORTS accept
        tcp dport $TORRENT_PORTS accept
        jump rfc4890
        drop
    }
    
    chain inbound_private {
        udp dport 0-65535 accept
        tcp dport 0-65535 accept
        jump rfc4890
        drop
    }
    
    chain input {
        type filter hook input priority filter; policy drop;
        ct state {established, related} accept
        iifname vmap { lo : accept, $DEV_WORLD : jump inbound_world, $DEV_PRIVATE : jump inbound_private, $DEV_WG0 : jump inbound_private }
        drop
    }
    
    chain forward {
        type filter hook forward priority filter; policy drop;
        ct state {established, related} accept
        iifname $DEV_PRIVATE accept
        iifname { $DEV_WG0, $DEV_PRIVATE } oifname $DEV_WORLD accept
    }
    
    chain output {
        type filter hook output priority filter; policy accept;
        jump rfc4890
    }
}

table ip6 nat {
    chain prerouting {
        type nat hook prerouting priority dstnat; policy accept;
    }
    
    chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;
        iifname { $DEV_WG0, $DEV_PRIVATE } oifname $DEV_WORLD masquerade
    }
}

Habilitar nftables

sudo systemctl enable nftables sudo systemctl start nftables

8Configurar WireGuard VPN

Generar claves

# Generar clave privada del servidor wg genkey > /etc/wireguard/server_private.key # Generar clave pública del servidor wg pubkey < /etc/wireguard/server_private.key > /etc/wireguard/server_public.key # Generar claves del cliente wg genkey > /etc/wireguard/client_private.key wg pubkey < /etc/wireguard/client_private.key > /etc/wireguard/client_public.key

Configurar servidor WireGuard

/etc/wireguard/wg0.conf
[Interface]
Address = 10.8.0.1/24
ListenPort = 51821
PrivateKey = CONTENIDO_DE_server_private.key

[Peer]
PublicKey = CONTENIDO_DE_client_public.key
AllowedIPs = 10.8.0.2/32

Habilitar WireGuard

sudo systemctl enable wg-quick@wg0 sudo systemctl start wg-quick@wg0

9Servicios adicionales

Pi-hole (Bloqueador de anuncios)

# Descargar e instalar Pi-hole curl -sSL https://install.pi-hole.net | bash
Durante la instalación:
  • Selecciona la interfaz LAN (enp3s0)
  • Configura la IP estática: 192.168.10.1
  • Elige Google DNS como upstream inicialmente

Unbound (DNS recursivo)

# Instalar Unbound sudo apt install unbound -y # Configurar Unbound como upstream para Pi-hole sudo nano /etc/unbound/unbound.conf.d/pi-hole.conf