← Volver al inicio

Añadir rutas en Linux mediante script .sh

NetRoute Pro genera un script Bash simple con comandos ip route add. Se aplica con un solo comando. Hacer las rutas persistentes entre reinicios requiere un paso extra según tu distribución.

Sintaxis del comando

Sintaxis (idempotente — usa esta forma en scripts):

ip route replace <CIDR> via <GATEWAY> dev <VPN_IF>

Ejemplo:

ip route replace 1.1.1.0/24 via 10.0.0.1 dev wg0

Ejecuta como root o con sudo. NetRoute Pro las genera en un script .sh — aplícalas con bash routes.sh. replace es idempotente: crea la ruta si no existe y la actualiza si existe, así que re-ejecutar el script es seguro; add fallaría con RTNETLINK answers: File exists en duplicados (y junto a set -e abortaría el script).

Requisitos previos

Paso 1. Genera .sh en NetRoute Pro

  1. Abre el sitio web objetivo en Chrome
  2. Lanza la extensión NetRoute Pro
  3. Selecciona la plataforma Linux
  4. Introduce el gateway VPN (p.ej. 10.8.0.1)
  5. Haz clic en Analyze Website
  6. Descarga routes.sh
Consejo: activa optimización RIPE BGP en la extensión — agrupa IPs individuales en prefijos BGP reales, dando rutas estables aunque el CDN rote IPs. Importante: RIPE BGP devuelve todos los prefijos anunciados por el AS — para CDN multi-tenant (Cloudflare AS13335, AWS AS16509, DigitalOcean AS14061) son decenas de miles de IPs cubriendo sitios sin relación. Usa optimización BGP para AS single-tenant; mantén /24 CIDR para CDN compartidos.

Paso 2. Aplica el script

chmod +x routes.sh
sudo bash routes.sh

El script añade todas las rutas al kernel en una sola pasada. Las rutas son inmediatamente efectivas.

Paso 3. Haz las rutas persistentes

Las rutas añadidas con ip route add se pierden al reiniciar. Elige una opción según tu distribución:

systemd-networkd

Crea un drop-in para la interfaz VPN:

sudo mkdir -p /etc/systemd/network/10-vpn.network.d
sudo nano /etc/systemd/network/10-vpn.network.d/routes.conf

Contenido del archivo (repite el bloque [Route] por cada subred):

[Route]
Destination=104.21.32.0/24
Gateway=10.8.0.1

[Route]
Destination=172.67.0.0/16
Gateway=10.8.0.1

Aplicar:

sudo systemctl restart systemd-networkd

NetworkManager dispatcher

Crea un script dispatcher que se ejecuta cuando la interfaz VPN sube:

sudo nano /etc/NetworkManager/dispatcher.d/99-vpn-routes
sudo chmod +x /etc/NetworkManager/dispatcher.d/99-vpn-routes

Contenido:

#!/bin/bash
# $1 = nombre de interfaz, $2 = acción
if [ "$1" = "wg0" ] && [ "$2" = "up" ]; then
    ip route add 104.21.32.0/24 via 10.8.0.1
    ip route add 172.67.0.0/16 via 10.8.0.1
fi

Ajusta wg0 al nombre real de tu interfaz VPN.

servicio systemd oneshot (recomendado)

Funciona en cualquier distro con systemd (Ubuntu, Debian, Fedora, Arch, RHEL, openSUSE — prácticamente todas las distros modernas). Espera correctamente a que el túnel VPN esté arriba antes de aplicar rutas — sin race conditions ni hacks con sleep.

sudo mv routes.sh /usr/local/bin/routes.sh
sudo chmod +x /usr/local/bin/routes.sh

sudo tee /etc/systemd/system/vpn-routes.service > /dev/null <<'EOF'
[Unit]
Description=Apply VPN split-tunnel routes
After=network-online.target wg-quick@wg0.service
Wants=network-online.target
Requisite=wg-quick@wg0.service
BindsTo=wg-quick@wg0.service

[Service]
Type=oneshot
ExecStart=/usr/local/bin/routes.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now vpn-routes.service

Reemplaza wg-quick@wg0.service con tu unidad VPN:

Verifica el servicio:

systemctl status vpn-routes.service
journalctl -u vpn-routes.service
¿Por qué no @reboot cron? El demonio cron normalmente arranca antes de que el túnel VPN esté arriba — ip route add se ejecuta contra una interfaz que aún no existe, falla silenciosamente, y descubres las rutas rotas sólo tras un reinicio. After= y Requisite= de systemd esperan a la unidad VPN y eliminan el race. BindsTo= también detiene las rutas cuando la VPN cae.

DNS leak — lectura obligatoria

Esta guía enruta tráfico por IP. No enruta DNS. Tu navegador sigue preguntando al resolver del sistema (normalmente el de tu ISP, vía DHCP) por example.com — sólo el tráfico IP resultante pasa por la VPN. El ISP ve qué sitios visitas aunque los datos estén cifrados.

Tres opciones, según tu modelo de amenazas:

  1. Ocultar DNS del ISP totalmente (split-DNS). En systemd-resolved, configura el DNS por enlace sólo para los dominios tunelizados:
    sudo resolvectl dns wg0 10.0.0.1
    sudo resolvectl domain wg0 ~example.com ~another-site.com
    Las consultas de example.com ahora pasan por la VPN; el resto usa el resolver por defecto. Sustituye 10.0.0.1 por el DNS interno de tu proveedor VPN.
  2. Reducir visibilidad para el ISP (DoH/DoT público). Apunta el resolver del sistema a un DNS cifrado público:
    sudo resolvectl dns wg0 1.1.1.1#cloudflare-dns.com
    sudo resolvectl dnsovertls wg0 yes
    El ISP deja de ver consultas de dominio; el resolver público sí las ve.
  3. Aceptar la fuga. Si tu objetivo es acceder a contenido, no evitar vigilancia, esto está bien — sólo se filtran los lookups, los datos siguen cifrados.

Verifica el estado actual en dnsleaktest.com o browserleaks.com/dns — el resolver mostrado debe pertenecer a tu VPN o al DoH elegido, no al ISP. Localmente, resolvectl status muestra la configuración por enlace.

Fuga por IPv6 dual-stack

Si el destino tiene un registro AAAA (la mayoría de sitios populares lo tienen — Cloudflare, Google, AWS son dual-stack), el SO prefiere IPv6 sobre IPv4 (RFC 6724). Las rutas añadidas en esta guía son sólo IPv4 — el tráfico IPv6 elude la VPN y sale por la ruta v6 por defecto del ISP. Resultado: la VPN parece activa pero no hace nada para destinos dual-stack.

Comprobación rápida:

curl -6 -s -o /dev/null -w "remote=%{remote_ip}\n" https://example.com
ip -6 route get $(dig +short AAAA example.com | head -1)

Si la traza IPv6 no pasa por tu interfaz VPN, estás eludiendo el túnel. Dos soluciones:

Fail-closed (kill switch)

Cuando el túnel VPN cae (cambio de red, problema del proveedor, sleep/wake), el kernel elimina las rutas asociadas a la interfaz muerta — y el tráfico a los CIDR antes tunelizados cae a la ruta por defecto del ISP. Resultado: fuga silenciosa sin error visible. Para forzar fail-closed (bloquear en vez de filtrar):

# nftables (Linux moderno)
sudo nft add table inet vpnkill
sudo nft add chain inet vpnkill output { type filter hook output priority 0 \; }
sudo nft add rule inet vpnkill output ip daddr 1.1.1.0/24 oif != wg0 drop
sudo nft add rule inet vpnkill output ip daddr 8.8.8.0/24 oif != wg0 drop
# Repite para cada CIDR tunelizado.

Equivalente con iptables:

sudo iptables -I OUTPUT ! -o wg0 -d 1.1.1.0/24 -j REJECT
sudo iptables -I OUTPUT ! -o wg0 -d 8.8.8.0/24 -j REJECT

Ahora el tráfico a esos prefijos por cualquier interfaz que no sea wg0 se bloquea — VPN caída = bloqueado, no filtrado. El usuario ve un error de conexión (señal clara de que la VPN no funciona) en vez de una salida silenciosa por el ISP. Este es el modo de fallo seguro.

Verificar

ip route show | grep 10.8.0.1

Debes ver todas las subredes enrutadas por tu gateway VPN. Prueba con traceroute:

traceroute example.com

Revertir

El script guarda un snapshot de la tabla de rutas en /tmp/route-table.<timestamp>.txt antes de aplicar cambios — útil para diagnosticar qué cambió. Para eliminar las rutas añadidas por NetRoute Pro, borra cada prefijo:

for cidr in 1.1.1.0/24 8.8.8.0/24 162.159.0.0/16; do
    sudo ip route del "$cidr" 2>/dev/null || true
done

O, más conservadoramente, genera una lista inversa desde tu routes.sh, sustituyendo replace (o add) por del:

awk '/ip route /{ sub(/^ip route (replace|add)/, "ip route del"); print }' routes.sh | sudo bash

Si algo salió catastróficamente mal, el snapshot en /tmp/route-table.<timestamp>.txt muestra el estado previo — puedes restaurar manualmente lo necesario.

Problemas comunes

Network is unreachable

La interfaz VPN no está activa. Comprueba con ip link show que tu interfaz VPN (p.ej. wg0, tun0) está UP. Activa la VPN antes de aplicar rutas.

Permission denied

Necesitas privilegios root. Ejecuta con sudo.

Las rutas no se aplican tras reiniciar

No configuraste persistencia. Elige una de las tres opciones del Paso 3.

Archivo de configuración de ejemplo

Plantilla lista para editar con comentarios. Reemplaza las rutas de ejemplo con la salida de NetRoute Pro para tus sitios.


#!/bin/bash
# Example Linux routing script for split tunneling.
# Generated by NetRoute Pro: https://alexander2k.github.io/netroute-site/
#
# Run as root or with sudo. Routes added here last until reboot —
# for persistence see the Linux guide (systemd-networkd / NetworkManager).
#
# Idempotent: uses `ip route replace` so re-running the script is safe.
# `add` would fail with "RTNETLINK answers: File exists" on a duplicate;
# combined with `set -e`, the first existing route would abort the script
# and skip the rest. `replace` creates if missing, updates if present.

set -euo pipefail

DEV="wg0"          # VPN interface name (wg0, tun0, ppp0, ...)
GW="10.0.0.1"      # VPN gateway IP (or use only "dev $DEV" if VPN is point-to-point)

# Snapshot current route table — useful for rollback if something breaks.
SNAPSHOT="/tmp/route-table.$(date +%s).txt"
ip route show > "$SNAPSHOT"
echo "Route table snapshot saved to $SNAPSHOT"

ip route replace 1.1.1.0/24    via "$GW" dev "$DEV"
ip route replace 8.8.8.0/24    via "$GW" dev "$DEV"
ip route replace 162.159.0.0/16 via "$GW" dev "$DEV"

# Verify with: ip route show
# Remove a single route: ip route del <CIDR>
# Full rollback (delete all routes added by this script):
#   for cidr in 1.1.1.0/24 8.8.8.0/24 162.159.0.0/16; do
#     ip route del "$cidr" 2>/dev/null || true
#   done

Consejo: ¿Necesitas un config sin estas líneas de comentarios? En las opciones de NetRoute Pro desactiva «Incluir comentarios en archivos exportados» — la extensión exportará solo los comandos de rutas. Útil para routers que no toleran comentarios.

Ver todos los ejemplos en GitHub →

Documentación oficial

¿Listo para probar?

NetRoute Pro — extensión gratuita de Chrome para generar rutas desde cualquier sitio web.

Instalar extensión