Estas aquíBlogs / blog de calel / Creando un router en Debian

Creando un router en Debian


Por calel Enviado el 01 junio 2011

Este manual fue actualizado mayo 2 2015 para funcionar en Jessie

Esta es una receta para crear un router en Debian. La idea es sustituir el típico router inalámbrico de casa con una máquina corriendo en Debian, mientras que la función del router inalámbrico cambiaría a la de Access Point/switch para manejar la red interna.

Es necesario que el servidor Debian tenga dos tarjetas de red. Vamos a llamarlas eth0 y eth1, siguiendo la denominación convencional. La interfaz eth0 se conecta a Internet mientras que eth1 se conecta al router inalámbrico (Access Point).

Antes de continuar, debemos ingresar a la interfaz de administración del router inalámbrico y anotar la sub-red que utiliza. Vamos a suponer que es 192.168.1.0/24.

La conexión a Internet es generalmente de tipo Banda Ancha, mediante un cable modem. En este caso, el cable módem se encarga de adquirir un número IP del proveedor a través de DHCP y el servidor Debian simplemente lo agarra como suyo. Edita /etc/network/interfaces y define eth0 como DHCP,

# The primary network interface
auto eth0
       iface eth0 inet dhcp

Conecta eth0 al módem con un cable de red ("twisted pair"), luego reinicia el módem y el computador Debian. Prueba conexiones Internet. El comando,

# ifconfig eth0

debería retornar los parámetros de red asignados.

Alternativa, la conexión a Internet es de tipo ADSL, en cuyo caso se requiere PPPoE. Sigue las instrucciones de la guía http://man-es.debianchile.org/adsl.html

Edita /etc/network/interfaces y define eth1 como una sub-red estática privada,

auto eth1
iface eth1 inet static
       address 192.168.0.1
       netmask 255.255.255.0
       network 192.168.0.0
       broadcast 192.168.0.255

Es muy importante que esta definición no contenga una pasarela (gateway). Es igualmente importante que esta sub-red sea diferente a la sub-red del router inalámbrico, esta siendo 192.168.0.0/24 mientras que la del router inalámbrico 192.168.1.0/24.

Levanta la interfaz eth1 con,

# ifup eth1

'ifconfig eth1' debería retornar los parámetros de red recién asignados.

Conecta eth1 al router inalámbrico con un cable de red ("twisted pair") al mismo puerto que antes estaba conectado a Internet.

Vamos a suponer que el router inalámbrico estaba configurado para adquirir valores de red WAN vía DHCP. Como ahora está conectado al servidor Debian, necesitamos reconfigurarlo en una red estática, con valores,

IP Address :         192.168.0.2
Subnet Mask :        255.255.255.0
Default Gateway :    192.168.0.1
Primary DNS Server : 192.168.0.1

La pasarela (gateway) debe ser el número IP del servidor Debian.

Si no es posible definir una red estática, debido a que el router inalámbrico no permite la opción de red más que con DHCP, es necesario instalar y configurar el servidor DHCP en el servidor Debian. Instala isc-dhcp-server,
# apt-get install isc-dhcp-server

Edita /etc/default/isc-dhcp-server y modifica la variable INTERFACES con,

INTERFACES="eth1"

Edita /etc/dhcp/dhcpd.conf. Descomenta el instructivo "authoritative",

authoritative;

y define una sub-red,

subnet 192.168.0.0 netmask 255.255.255.0 {
  range 192.168.0.2 192.168.0.2;
  option routers 192.168.0.1;
  option ip-forwarding off;
  option broadcast-address 192.168.0.255;
  option subnet-mask 255.255.255.0;
  option domain-name-servers 192.168.0.1;
  default-lease-time 86400;
  max-lease-time 86400;
}

Esta definición va a servir un solo IP; 192.168.0.2. Observa /var/log/syslog en un terminal con,

$ tail -f /var/log/syslog

luego reinicia en otro terminal el servidor DHCP,

# /etc/init.d/isc-dhcp-server restart

Observa en /var/log/syslog como el router inalámbrico automáticamente adquiere un IP,

May 30 20:27:01 debian dhcpd: DHCPDISCOVER from 00:24:b2:28:8e:f7 via eth1
May 30 20:27:01 debian dhcpd: icmp_echorequest 192.168.0.2: Operation not permitted
May 30 20:27:02 debian dhcpd: DHCPOFFER on 192.168.0.2 to 00:24:b2:28:8e:f7 via eth1
May 30 20:27:05 debian dhcpd: DHCPREQUEST for 192.168.0.2 (192.168.0.1) from 00:24:b2:28:8e:f7 via eth1
May 30 20:27:05 debian dhcpd: DHCPACK on 192.168.0.2 to 00:24:b2:28:8e:f7 via eth1

El router inalámbrico tiene dirección Internet 192.168.0.2, pasarela y servidor DNS 192.168.0.1.

Necesitamos instalar y configurar el servidor DNS. Instala bind9,

# apt-get install bind9

Edita el archivo /etc/bind/named.conf.options y modifica el instructivo forwarders con las direcciones IP de los DNS del proveedor de Internet,

        forwarders {
                100.10.0.3;
                100.10.0.7;
        };

Para obtener las direcciones IP del DNS inspecciona el archivo /etc/resolv.conf. Este fue escrito automáticamente con los valores retornados por el servidor DHCP del proveedor.

Ahora edita /etc/resolv.conf para que lea,

nameserver 127.0.0.1

Remueve los instructivos "domain" y "search" si existen y los antiguos forwarders.

Reinicia el servidor DNS,

# /etc/init.d/bind9 restart

para que los cambios tomen efecto.

Esto transforma a localhost en servidor DNS, que vía BIND9 resuelve nombres haciendo requerimientos a los DNS del proveedor. En particular, 192.168.0.1 también es un servidor DNS.

Falta un pequeño detalle. Cada vez que el "lease" del servidor DHCP del proveedor se renueva, este reenvía los valores con que /etc/resolv.conf se reescribe automáticamente. Para evitar esto y de hecho borrar la nueva configuración, remueve la atribución de escritura sobre el archivo,

chattr +i /etc/resolv.conf

Falta redirigir eth1 a eth0 para que la red interna 192.168.1.0/24 del router inalámbrico pueda salir a Internet. Aquí debemos hacer dos cosas: 1) redirigir eth1 a eth0 y 2) reescribir los números IP 192.168.1.x con el número IP público del servidor Debian. Esto se llama enmascarar. Si no se enmascara, los paquetes de red salientes de la red interna tendrian IP 192.168.1.x y serían bloqueados ("IP spoofing").

En Debian, redirigir no es una opción por omisión. Para activarlo hay que modificar el valor de /proc/sys/net/ipv4/ip_forward de 0 a 1.

# echo 1 > /proc/sys/net/ipv4/ip_forward

Un,

$ cat /proc/sys/net/ipv4/ip_forward

debería retornar 1.

Falta otro pequeño detalle. Al reiniciar el computador, se reescribe /proc/sys/net/ipv4/ip_forward con el valor por omisión, que es 0, deshabilitando la redirección. Para evitar esto, edita /etc/sysctl.conf y descomenta,

net.ipv4.ip_forward=1

Ahora el valor de /proc/sys/net/ipv4/ip_forward se reescribe a 1.

En este punto puede ser ventajoso entrar a la administración del router inalámbrico, quizás con otro computador de la sub-red 192.168.1.0/24, y activar la administración remota desde la IP 192.168.0.1.

Queda un último detalle. El servidor Debian está conectado directamente a Internet y es aconsejable crearle un cortafuegos. La base de este cortafuegos es el descrito en http://man-es.debianchile.org/cortafuego.html, versión para un servidor, pero con unas pocas modificaciones necesarias, en particular, la existencia de una segunda interfaz de red (eth1), el emascaramiento de la red interna (reescribir las IP internas con la IP publica del servidor) y la posibilidad que la IP no sea fija, son tratadas explicitamente.

Primero, crea el archivo /etc/network/if-pre-up.d/firewall,

#!/bin/sh

# Author: Ricardo Yanez <ricardo.yanez@calel.org>

IPTABLES=/sbin/iptables

if [ ! -x $IPTABLES ]; then
  exit 0
fi

# loopback
LO_IP="127.0.0.0/8"

# red interna
LAN_IP_RANGE="192.168.0.0/24"

if [ "$IFACE" = "lo" ]; then

  $IPTABLES -F
  $IPTABLES -X
  $IPTABLES -t nat -F
  $IPTABLES -t nat -X

  $IPTABLES -P INPUT DROP
  $IPTABLES -P FORWARD DROP
  $IPTABLES -P OUTPUT ACCEPT

  ###############################################
  ############### cadena INPUT ##################
  ###############################################

  # 1) new not in syn
  $IPTABLES -A INPUT -p TCP -m state --state NEW ! --syn -j DROP

  # 2) Aceptar paquetes en estado establecido y relacionado
  $IPTABLES -A INPUT -i $IFACE -m state --state ESTABLISHED,RELATED -j ACCEPT

  # 3) loopback
  $IPTABLES -A INPUT -i $IFACE -s $LO_IP -j ACCEPT
  $IPTABLES -A INPUT -i $IFACE -s $LAN_IP_RANGE -j ACCEPT
  $IPTABLES -A INPUT -i $IFACE -j ACCEPT

  # 4) inserta reglas en este punto (ver más adelante)

  ###############################################
  ############## cadena FORWARD #################
  ###############################################

  # (Aquí van reglas si el servidor actua de router)

  ###############################################
  ############## cadena OUTPUT ##################
  ###############################################

  # new not in syn
  $IPTABLES -A OUTPUT -p TCP -m state --state NEW ! --syn -j DROP

  # establecido, relacionado
  $IPTABLES -A OUTPUT -o $IFACE -m state --state ESTABLISHED,RELATED -j ACCEPT

  # new
  $IPTABLES -A OUTPUT -o $IFACE -m state --state NEW -j ACCEPT

fi

Dale permisos de ejecución,

# chmod 755 /etc/network/if-pre-up.d/firewall

Luego crea el archivo /etc/network/if-up.d/firewall,

#!/bin/sh

# Author: Ricardo Yanez <ricardo.yanez@calel.org>

IPTABLES=/sbin/iptables

if [ ! -x $IPTABLES ]; then
  exit 0
fi

# interfaz de red externa
INET_IFACE="eth0"

# interfaz de red interna
LAN_IFACE="eth1"
LAN_IP="192.168.0.1"
LAN_IP_RANGE="192.168.0.0/24"

if [ "$IFACE" = "$INET_IFACE" ]; then

  # 5) Definir la cadena "bloquear-spoof"
  $IPTABLES -N bloquear-spoof
  $IPTABLES -A bloquear-spoof -i $IFACE -s 10.0.0.0/8 -j DROP
  $IPTABLES -A bloquear-spoof -i $IFACE -s 172.16.0.0/12 -j DROP
  $IPTABLES -A bloquear-spoof -i $IFACE -s 192.168.0.0/16 -j DROP

  # 6) Cadena "pqtes-icmp-permitidos"
  $IPTABLES -N pqtes-icmp-permitidos
#  $IPTABLES -A pqtes-icmp-permitidos -p ICMP --icmp-type 8 -m limit --limit 1/second --limit-burst 3 -j ACCEPT
  $IPTABLES -A pqtes-icmp-permitidos -p ICMP -j DROP

  # 7) Cadena "pqtes-udp-permitidos"
  $IPTABLES -N pqtes-udp-permitidos
#  $IPTABLES -A pqtes-udp-permitidos -p UDP -m state --state NEW --dport 53 -j ACCEPT
#  $IPTABLES -A pqtes-udp-permitidos -p UDP -m state --state NEW --dport 123 -j ACCEPT
  $IPTABLES -A pqtes-udp-permitidos -p UDP -m state --state NEW -j DROP

  # 8) Cadena "pqtes-tcp-permitidos"
  $IPTABLES -N pqtes-tcp-permitidos
#  $IPTABLES -A pqtes-tcp-permitidos -p TCP -m state --state NEW --dport 25 -j ACCEPT
#  $IPTABLES -A pqtes-tcp-permitidos -p TCP -m state --state NEW --dport 80 -j ACCEPT
#  $IPTABLES -A pqtes-tcp-permitidos -p TCP -m state --state NEW --dport 443 -j ACCEPT
#  $IPTABLES -A pqtes-tcp-permitidos -p TCP -m state --state NEW -m multiport --dports 110,995 -j ACCEPT
#  $IPTABLES -A pqtes-tcp-permitidos -p TCP -m state --state NEW -m multiport --dports 143,993 -j ACCEPT
#  $IPTABLES -A pqtes-tcp-permitidos -p TCP -m state --state NEW --dport 22 -s 100.10.2.0/24 -j ACCEPT
  $IPTABLES -A pqtes-tcp-permitidos -p TCP -m state --state NEW -j DROP

  # 9) Agregar cadenas a INPUT

  ###############################################
  ############### cadena INPUT ##################
  ###############################################

  # establecido, relacionado
  $IPTABLES -A INPUT -i $IFACE -m state --state ESTABLISHED,RELATED -j ACCEPT

  $IPTABLES -A INPUT -i $IFACE -j bloquear-spoof
  $IPTABLES -A INPUT -i $IFACE -p ICMP -j pqtes-icmp-permitidos
  $IPTABLES -A INPUT -i $IFACE -p UDP -j pqtes-udp-permitidos
  $IPTABLES -A INPUT -i $IFACE -p TCP -j pqtes-tcp-permitidos

  # 10) Optativo: Registrar paquetes que van a ser desechados
  #$IPTABLES -A INPUT -j LOG --log-level debug --log-prefix "Drop INPUT: "

  ###############################################
  ############## cadena FORWARD #################
  ###############################################

  # (Aquí van reglas si el servidor actua de router)

  ###############################################
  ############## cadena OUTPUT ##################
  ###############################################

  # establecido, relacionado
  $IPTABLES -A OUTPUT -o $IFACE -m state --state ESTABLISHED,RELATED -j ACCEPT

fi

if [ "$IFACE" = "$LAN_IFACE" ]; then

  ###############################################
  ############### cadena INPUT ##################
  ###############################################

  # establecido, relacionado
  $IPTABLES -A INPUT -i $IFACE -m state --state ESTABLISHED,RELATED -j ACCEPT

  $IPTABLES -A INPUT -i $IFACE -s $LAN_IP_RANGE -j ACCEPT

  ###############################################
  ############## cadena FORWARD #################
  ###############################################

  # established, related
  $IPTABLES -A FORWARD -i $INET_IFACE -o $LAN_IFACE -m state --state ESTABLISHED,RELATED -j ACCEPT
  $IPTABLES -A FORWARD -i $LAN_IFACE -o $INET_IFACE -m state --state ESTABLISHED,RELATED -j ACCEPT

  $IPTABLES -A FORWARD -i $INET_IFACE -o $IFACE -m state --state NEW -j DROP
  $IPTABLES -A FORWARD -i $IFACE -o $INET_IFACE -m state --state NEW -j ACCEPT

  ###############################################
  ############## cadena OUTPUT ##################
  ###############################################

  # establecido, relacionado
  $IPTABLES -A OUTPUT -o $IFACE -m state --state ESTABLISHED,RELATED -j ACCEPT

  ###############################################
  ############## cadena NAT #####################
  ###############################################

  INET_IP=`ifconfig $INET_IFACE | egrep "inet addr" | cut -d : -f2 | cut -d\  -f1`

  $IPTABLES -t nat -F POSTROUTING
  $IPTABLES -t nat -F PREROUTING

  # enmascarar
  $IPTABLES -t nat -A POSTROUTING -s $LAN_IP_RANGE -o $INET_IFACE -j SNAT --to-source $INET_IP

fi

Ahora el router inalámbrico rutea la sud-red privada 192.168.1.0/24, cuyo IP "externo" es 192.168.0.2 y el servidor Debian conectado a Internet rutea la red 192.168.0.0/24. Nota el particular que se debe enmascarar en algún punto. Lo mejor es hacerlo cuando se levanta eth1.

La segunda parte de este script protege la redirección en la cadena FORWARD.

Dale al script permisos de ejecución,

# chmod 755 /etc/network/if-up.d/firewall

y carga el cortafuegos en el núcleo,

# export IFACE=lo ; /etc/network/if-pre-up.d/firewall ; export IFACE=eth0 ; /etc/network/if-up.d/firewall ; export IFACE=eth1 ; /etc/network/if-up.d/firewall
Si la IP pública del servidor Debian es dinámica, el proveedor puede renovar el "lease" con una nueva IP cada 24 horas o menos. Para solucionar esto debemos crear un script que se corra cada vez que se levante la red externa en eth0,
#!/bin/sh
#
# masquerade: Script to masquerade an external network connection
#             (modem or ADSL) upon bringing the interface up. Name this
#             script masquerade.sh, put it in /etc/network/if-up.d/ and
#             make it executable (755).
#             Change INET_IFACE and LAN_IP_RANGE to suit your needs.
#             You will need to have packet filtering (iptables) enabled
#             in your kernel and module iptable_nat.

#             This script is intended for Debian systems. May not work on
#             other Linux distributions.

#             Author: Ricardo Yanez <ricardo.yanez@calel.org>, Mon May 30, 2011

# Define external interface
INET_IFACE="eth0"
 
# LAN IP range
LAN_IP_RANGE="192.168.0.0/24"
 
# Get IP number
INET_IP=`ifconfig $INET_IFACE | egrep "inet addr" | cut -d : -f2 | cut -d \  -f1`
# please note the extra space in the last cut, right after \ (very important).
 
# Clear all rules in POSTROUTING chain
iptables -t nat -F POSTROUTING
 
# Masquerade
echo -n "Masquerading interface $INET_IFACE to source $INET_IP... "
iptables -t nat -A POSTROUTING -s $LAN_IP_RANGE -o $INET_IFACE \
         -j SNAT --to-source $INET_IP
echo "done."

Descarga este script (masquerade.sh_.txt) y dale permisos de ejecución,

# chmod 755 masquerade.sh

Corre el script por primera vez,

# ./masquerade.sh
Masquerading interface eth0 to source 100.50.210.134... done.

Ahora muevelo a /etc/network/if-up.d/

# mv masquerade.sh /etc/network/if-up.d/

Las cadenas se pueden observar con,

# iptables -L -v

y la tabla NAT con,

# iptables -t nat -L -v
Tu voto: Nada Promedio: 7 (256 votos)

hola. te consulto, en ocasiones no se levanta el script masquerade, puede tener que ver el tema del if.up o if.preup?

Por otro lado, como podrá habilitar el ping a la interfaz WAN?

Muchas Gracias.

El script para enmascarar la red interna debe correrse despues que se levanten las interfaces de la red externa e interna. Debe ir en if.up/. Puede fallar si el orden en que se levantan las interfaces es diferente al orden implicito del script, que es eth0 seguido de eth1 (secuencia natural). Si las interfaces son eth0 (externa) y eth1 (interna), entonces es script deberia funcionar siempre. Si las interfaces tienen nombres diferentes, por ejemplo, ppp0 (externa) eth1 (interna) entonces hay que modificar el script firewall para que el script masquerade se corra luego que ambas interfaces hayan sido levantadas. Basta mover la linea

/etc/network/if-up.d/masquerade.sh

dentro del bloque condicional que levante la ultima interfaz.

En cuanto a ping, la linea comentada

# $IPTABLES -A pqtes-icmp-permitidos -p ICMP --icmp-type 8 -m limit --limit 1/second --limit-burst 3 -j ACCEPT

es un ejemplo que puede ser utilizada en cualquier interfaz. Basta descomentarla y llamar pqtes-icmp-permitidos en la cadena INPUT en el bloque condicional de la interfaz WAN. La regla no permite una tasa superior a 4 pings por segundo. Esto evita ataques DoS.

Muchas Gracias ^_^
yo estoy haciendo mi router debian en virtualbox para que mi otra maquina virtual con windows xp se conecte a el. En la maquina virtual debian tengo los adaptadores NAT, Host only adapter, y internal network; en la maquina virtual con Windows xp tengo los adaptadores Host only adapter, y internal network.
Aún asi no me funciona la conexión entre mi maquina windows xp y debian :(
Todo está bien configurado en el router debian, estoy casi seguro que el problema debe ser con los adaptadores de Virtualbox :(

Ya Solucioné lo de los adaptadores de virtualbox
Para Debian: Nat, y Red Interna
Para Windows XP: Red Interna

El rango de ip de dhcpd.conf está como:
range 192.168.0.2 192.168.0.2;
creo que debe ir:
range 192.168.0.2 192.168.0.20;

por lo menos.

Saludos.