miércoles, 1 de octubre de 2025

Router 4G y WiFi con NetworkManager

Si queremos interconectar varias redes podemos utilizar un ordenador con múltiples interfaces de red para que haga de router entre las redes. Dependiendo de lo que necesitemos es posible usar diferentes configuraciones de hardware y software. En este artículo utilizo una placa Raspberry Pi 4B, un módem/router 4G USB Huawei E8372h-320 y el software NetworkManager para conectar una red local Ethernet y una red local WiFi a Internet mediante fibra óptica y conexión móvil 4G. Solo se muestra la configuración para IPv4.

La placa Raspberry Pi 4B tiene un interfaz WiFi con el que podemos conectar a un router de fibra óptica y a la vez crear un punto de acceso al que se pueden conectar otros dispositivos. El comando iw permite listar los interfaces WiFi y ver sus características. Entre ellas se encuentra las combinaciones de modos que se pueden hacer. El interfaz de la Raspberry Pi 4B puede funcionar a la vez en modo managed (cliente) y AP (punto de acceso) con la limitación de que tiene que ser en el mismo canal.

# iw list

Wiphy phy0

..........

valid interface combinations:
		 * #{ managed } <= 2, #{ P2P-device } <= 1, #{ P2P-client, P2P-GO } <= 1,
		   total <= 3, #channels <= 2
		 * #{ managed } <= 1, #{ AP } <= 1, #{ P2P-client } <= 1, #{ P2P-device } <= 1,
		   total <= 4, #channels <= 1

..........

Cada interfaz físico, con nombre phy seguido de un número, puede tener varios interfaces virtuales con distintos modos. Con iw dev es posible ver un listado de estos interfaces. Seguramente tendremos por defecto al menos un interfaz en modo managed. Su nombre puede variar dependiendo de la distribución de Linux. En la Raspberry Pi 4B es wlan0.

Para crear el punto de acceso es necesario añadir otro interfaz virtual en modo AP usando el comando iw. Podemos ejecutarlo con una regla de udev para que se añada automáticamente el interfaz al iniciar el sistema operativo.

# iw dev

phy#0
	
..........
	
	Interface wlan0
		ifindex 3
		wdev 0x1
		addr e4:5f:01:e7:9b:f8
		type managed
		txpower 31.00 dBm

# vi /etc/udev/rules.d/90-wifi.rules

ACTION=="add", SUBSYSTEM=="ieee80211", KERNEL=="phy0", RUN+="/usr/sbin/iw phy phy0 interface add ap0 type __ap"

# reboot

Una vez que tenemos el interfaz preparado, podemos utilizar el comando nmcli para configurar el punto de acceso en NetworkManager. Con el comando device wifi hotspot se le ordena la creación de un punto de acceso WiFi. El parámetro con-name es el nombre que recibirá la conexión internamente. Puede ser igual o distinto al SSID, que se indica con el parámetro ssid. Con ifname se le dice el nombre del interfaz, en este caso ap0. Por último el parámetro band fija la frecuencia a utilizar, 5 GHz (a) o 2,4 GHz (bg). Después de crear el punto de acceso es posible modificar alguno de sus parámetros. Por ejemplo podemos activar la autoconexión o deshabilitar WPS.

# nmcli device wifi hotspot con-name router ssid router password xxxxxxxxxx ifname ap0 band bg

Device 'ap0' successfully activated with '52bd6c59-5014-42a5-a658-8df478bed236'.

# nmcli con mod router connection.autoconnect yes
# nmcli con mod router wifi-sec.wps-method disabled

NetworkManager guarda la configuración del punto de acceso en un archivo del directorio /etc/NetworkManager/system-connections/. El nombre del archivo es el valor del parámetro con-name más ".nmconnection". Para modificar el punto de acceso podemos utilizar el comando nmcli o editar el archivo de configuración. Por defecto se activa el servidor DHCP para IPv4 con method=shared y se desactiva IPv6 con method=ignore. NetworkManager utiliza dnsmasq como servidor DHCP.

# cat /etc/NetworkManager/system-connections/router.nmconnection 

[connection]
id=router
uuid=52bd6c59-5014-42a5-a658-8df478bed236
type=wifi
interface-name=ap0
timestamp=1749917395

[wifi]
band=bg
channel=1
mode=ap
ssid=router

[wifi-security]
group=ccmp;
key-mgmt=wpa-psk
pairwise=ccmp;
proto=rsn;
psk=xxxxxxxxxx
wps-method=1

[ipv4]
method=shared

[ipv6]
addr-gen-mode=default
method=ignore

[proxy]

A continuación podemos conectar al router de fibra óptica con el comando device wifi connect y el nombre de su red wifi. Al igual que con el punto de acceso, el interfaz a utilizar se indica con el parámetro ifname. Se debe usar el interfaz virtual en modo managed. Si es necesario que el punto de acceso y la conexión al router de fibra óptica utilicen el mismo canal, tenemos que modificar la conexión para que use la misma banda que el punto de acceso.

# nmcli device wifi connect router-fibra password xxxxxxxxxx ifname wlan0

Device 'wlan0' successfully activated with '2a9becd5-07ac-459c-8555-18886e15ccf8'.

# nmcli con mod router-fibra wifi.band bg

# cat /etc/NetworkManager/system-connections/router-fibra.nmconnection

[connection]
id=router-fibra
uuid=2a9becd5-07ac-459c-8555-18886e15ccf8
type=wifi
interface-name=wlan0
timestamp=1749917444

[wifi]
band=bg
mode=infrastructure
ssid=router-fibra

[wifi-security]
auth-alg=open
key-mgmt=wpa-psk
psk=xxxxxxxxxx

[ipv4]
method=auto

[ipv6]
addr-gen-mode=default
method=auto

[proxy]

Por último se configura una conexión Ethernet en el interfaz eth0 con servidor DHCP. De esta forma podemos conectar al puerto Ethernet un dispositivo, o varios a través de un switch, y recibirán automáticamente una dirección IP, puerta de enlace y servidores DNS.

# nmcli con add type ethernet ifname eth0 ipv4.method shared ipv6.method ignore

Connection 'ethernet-eth0' (d1a0eb66-1212-419f-91a9-526549f05dc3) successfully added.

# cat /etc/NetworkManager/system-connections/ethernet-eth0.nmconnection 

[connection]
id=ethernet-eth0
uuid=d1a0eb66-1212-419f-91a9-526549f05dc3
type=ethernet
interface-name=eth0

[ethernet]

[ipv4]
method=shared

[ipv6]
addr-gen-mode=default
method=ignore

[proxy]

En el interfaz usb0 del módem/router 4G no es necesario hacer nada. Si vuelvo a ejecutar iw dev puedo ver como el interfaz wlan0 está conectado a la red "router-fibra" y el interfaz ap0 está en modo "AP" con nombre de red "router". Los dos interfaces utilizan el canal 1 de 2,4 GHz. Si ejecutamos ip link show se muestran todos los interfaces de red. Con ip address show podremos ver las direcciones IP asignadas a cada uno de los interfaces en formato dirección/bits máscara. Con el parámetro -4 se muestran solo las direcciones IPv4. También podemos usar nmcli para listar las conexiones.

# iw dev

phy#0

..........
	
	Interface wlan0
		ifindex 4
		wdev 0x2
		addr e4:5f:01:e7:9b:f8
		ssid router-fibra
		type managed
		channel 1 (2412 MHz), width: 20 MHz, center1: 2412 MHz
		txpower 31.00 dBm
	Interface ap0
		ifindex 3
		wdev 0x1
		addr e6:5f:01:47:9b:f8
		ssid router
		type AP
		channel 1 (2412 MHz), width: 20 MHz, center1: 2412 MHz
		txpower 31.00 dBm
# ip link show

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether e4:5f:01:e7:9b:f7 brd ff:ff:ff:ff:ff:ff
3: ap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DORMANT group default qlen 1000
    link/ether e6:5f:01:47:9b:f8 brd ff:ff:ff:ff:ff:ff
4: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DORMANT group default qlen 1000
    link/ether e4:5f:01:e7:9b:f8 brd ff:ff:ff:ff:ff:ff
5: usb0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 42:a6:05:aa:ae:89 brd ff:ff:ff:ff:ff:ff
# ip -4 address show

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    inet 10.42.0.1/24 brd 10.42.0.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
3: ap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 10.42.1.1/24 brd 10.42.1.255 scope global noprefixroute ap0
       valid_lft forever preferred_lft forever
4: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 192.168.1.100/24 brd 192.168.1.255 scope global dynamic noprefixroute wlan0
       valid_lft 31640sec preferred_lft 31640sec
5: usb0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 192.168.8.100/24 brd 192.168.8.255 scope global dynamic noprefixroute usb0
       valid_lft 53211sec preferred_lft 53211sec
# nmcli con

NAME                UUID                                  TYPE      DEVICE 
ethernet-eth0       d1a0eb66-1212-419f-91a9-526549f05dc3  ethernet  eth0   
router              52bd6c59-5014-42a5-a658-8df478bed236  wifi      ap0    
Wired connection 1  d827c35a-971b-3d3a-bb02-b34c32ba3088  ethernet  usb0   
router-fibra        2a9becd5-07ac-459c-8555-18886e15ccf8  wifi      wlan0  
lo                  e19283e0-8088-4e28-8f90-61c19f71bdf2  loopback  lo

El router de fibra óptica tiene la dirección 192.168.1.1, es la puerta de enlace de la red 192.168.1.0/24 y al interfaz wlan0 de la placa Raspberry Pi le asigna por DHCP la dirección 192.168.1.100. El módem/router 4G tiene la dirección IP 192.168.8.1, es la puerta de enlace de la red 192.168.8.1/24 y al interfaz usb0 de la placa le asigna la dirección 192.168.8.100. El interfaz eth0 de la placa tiene la dirección 10.42.0.1 y es la puerta de enlace de la red 10.42.0.0/24. El interfaz ap0 de la placa tiene la dirección 10.42.1.1 y es la puerta de enlace de la red 10.42.1.1/24. En total tenemos cuatro redes locales con direcciones privadas.

Router                  Red              Puerta de Enlace   Interfaz
---------------------   --------------   ----------------   --------
Router Fibra Óptica     192.168.1.0/24   192.168.1.1        wlan0
Módem/Router 4G         192.168.8.0/24   192.168.8.1        usb0
Raspberry Pi Ethernet     10.42.0.0/24     10.42.0.1        eth0
Raspberry Pi WiFi         10.42.1.0/24     10.42.1.1        ap0

El comando ip también nos permite ver las rutas que ha creado NetworkManager. En primer lugar hay dos rutas por defecto que envían a Internet todos los paquetes IP que no vayan dirigidos a direcciones de las redes locales. A continuación están las rutas de las cuatro redes locales. Las rutas tienen el parámetro metric, que marca su prioridad para el envío de paquetes. Entre dos rutas que apuntan hacia el mismo sitio, como las dos primeras por defecto, se elige la que tenga un valor de metric menor. En mi caso la ruta por defecto a través del módem/router 4G tiene prioridad. Esto se puede cambiar en la configuración de las conexiones.

# ip route show

default via 192.168.8.1 dev usb0 proto dhcp src 192.168.8.100 metric 101 
default via 192.168.1.1 dev wlan0 proto dhcp src 192.168.1.100 metric 601 
10.42.0.0/24 dev eth0 proto kernel scope link src 10.42.0.1 metric 100 
10.42.1.0/24 dev ap0 proto kernel scope link src 10.42.1.1 metric 600 
192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.100 metric 601 
192.168.8.0/24 dev usb0 proto kernel scope link src 192.168.8.100 metric 101
               | 4G (usb0)     |        | WiFi (ap0)      |
Internet <---> |               | Router |                 | <--> Red Local              
               | Fibra (wlan0) |        | Ethernet (eth0) |
                 Óptica

Si se desconecta la conexión 4G los paquetes IP se enviarán por la conexión al router de fibra óptica. Pero puede suceder que aunque no se pierda la conexión 4G, los paquetes no se envíen por algún otro problema. Para estos casos NetworkManager permite comprobar la conectividad cada varios segundos conectando a un URI de un servidor HTTP de Internet que responda con la cabecera X-NetworkManager-Status igual a online o el contenido "NetworkManager is online". Si falla la conexión a través de una ruta, se aumenta su metric para que las otras rutas tengan prioridad.

# apt-get install network-manager-config-connectivity-debian

# vi /usr/lib/NetworkManager/conf.d/20-connectivity-debian.conf

[connectivity]
uri=http://network-test.debian.org/nm
interval=60

NetworkManager también nos permite ejecutar scripts cuando se realiza alguna acción sobre un interfaz de red. Los scrips se crean en el directorio /etc/NetworkManager/dispatcher.d/ y se ejecutan por orden alfabético. Los scripts reciben como parámetros el interfaz y la acción realizada. Si la acción es connectivity-change, en la variable $CONNECTIVITY_STATE se encuentra el estado de la conectividad. Es conveniente ignorar las acciones dhcp4-change y dhcp6-change ya que informan continuamente de la actividad DHCP. Una vez que tengamos todo configurado podemos reiniciar NetworkManager con systemctl.

# vi /etc/NetworkManager/dispatcher.d/00-router

#!/usr/bin/bash

. /usr/local/lib/notifications.sh

interface=$1
action=$2

if [ $action = "connectivity-change" ]
then

    send_notification "Router Network Connectivity Change: $CONNECTIVITY_STATE"

elif [[ ! $action =~ "dhcp" ]]
then

    send_notification "Router Network Action: $interface $action"
fi

# systemctl restart NetworkManager

NetworkManager activa el reenvío de paquetes y utiliza nftables para realizar NAT (Network Address Translation) en las conexiones desde ap0 y eth0 a Internet. También aplica reglas de cortafuegos para bloquear el tráfico entrante. Con sysctl podemos ver si está activado el reenvío de paquetes y con nft las reglas de nftables.

# sysctl net.ipv4.ip_forward

net.ipv4.ip_forward = 1

# nft list ruleset

table ip nm-shared-eth0 {
    chain nat_postrouting {
        type nat hook postrouting priority srcnat; policy accept;
        ip saddr 10.42.0.0/24 ip daddr != 10.42.0.0/24 masquerade
    }

    chain filter_forward {
        type filter hook forward priority filter; policy accept;
        ip daddr 10.42.0.0/24 oifname "eth0" ct state { established, related } accept
        ip saddr 10.42.0.0/24 iifname "eth0" accept
        iifname "eth0" oifname "eth0" accept
        iifname "eth0" reject
        oifname "eth0" reject
    }
}
table ip nm-shared-ap0 {
    chain nat_postrouting {
        type nat hook postrouting priority srcnat; policy accept;
        ip saddr 10.42.1.0/24 ip daddr != 10.42.1.0/24 masquerade
    }

    chain filter_forward {
        type filter hook forward priority filter; policy accept;
        ip daddr 10.42.1.0/24 oifname "ap0" ct state { established, related } accept
        ip saddr 10.42.1.0/24 iifname "ap0" accept
        iifname "ap0" oifname "ap0" accept
        iifname "ap0" reject
        oifname "ap0" reject
    }
}

Con esta configuración se realiza NAT dos veces. Primero con nftables y después en los routers de acceso a Internet. La primera traducción de direcciones es innecesaria, basta con hacer NAT en los routers de acceso a Internet. Por otro lado las reglas de cortafuegos bloquean la comunicación entre redes locales.

Si esto nos causa problemas, podemos desactivar la creación de reglas de nftables por parte de NetworkManager y crear nosotros las reglas que necesitemos. Para ello debemos editar el archivo de configuración /etc/NetworkManager/NetworkManager.conf y dar al parámetro firewall-backend el valor de none. También debemos activar el reenvío de paquetes en un archivo de configuración de sysctl.

# vi /etc/NetworkManager/NetworkManager.conf

[main]
firewall-backend=none

# vi /etc/sysctl.d/00-networkmanager.conf

net.ipv4.ip_forward = 1

# systemctl restart systemd-sysctl

Si queremos desactivar NAT en NetworkManager es necesario que los routers de acceso a Internet hagan NAT de las redes 10.42.0.0/24 y 10.42.1.0/24. Para ello tenemos que dar direcciones IP estáticas a los interfaces wlan0 y usb0 e indicar a los routers que estas direcciones son las puertas de enlace de las redes 10.42.0.0/24 y 10.42.1.0/24.

Se pueden asignar direcciones estáticas a los interfaces en NetworkManager o configurar los routers para que asignen una dirección estática a la dirección MAC del interfaz a través de DHCP. Para informar a los routers de las puertas de enlace se pueden usar rutas estáticas o algún protocolo de enrutamiento como RIP. Si queremos que también haya comunicación entre las redes 192.168.1.0/24 y 192.168.8.0/24 es necesario añadir las rutas necesarias.

Router Fibra Óptica
-------------------

DHCP - Dirección IP Estática
----------------------------

e4:5f:01:e7:9b:f8 -> 192.168.1.2

Rutas Estáticas
---------------

  10.42.0.0/24 -> 192.168.1.2  	
  10.42.1.0/24 -> 192.168.1.2
192.168.8.0/24 -> 192.168.1.2
Módem/Router 4G
---------------

DHCP - Dirección IP Estática
----------------------------

42:a6:05:aa:ae:89 -> 192.168.8.2

Rutas Estáticas
---------------

  10.42.0.0/24 -> 192.168.8.2  	
  10.42.1.0/24 -> 192.168.8.2
192.168.1.0/24 -> 192.168.8.2

Mi módem/router 4G no permite la creación de rutas estáticas o el uso de protocolos de enrutamiento, por lo que no es posible prescindir de NAT en NetworkManager. El router de fibra óptica sí lo permite, pero aun añadiendo las rutas no realiza NAT de las redes 10.42.0.0/24 y 10.42.1.0/24. Por lo tanto, si desactivo NAT/cortafuegos en NetworkManager, tengo que añadir las reglas NAT necesarias por otro lado.

En Debian tenemos el servicio nftables para gestionar las reglas. En su archivo de configuración /etc/nftables.conf podemos incluir nuestras reglas. Yo por ejemplo mantengo las reglas de NAT pero quito las de cortafuegos para permitir el tráfico entre todas las redes locales. También añado una regla para hacer NAT desde la red 192.168.1.0/24 a la red 192.168.8.0/24. Una vez configurado tenemos que activar el servicio e iniciarlo. Con flush ruleset se eliminan todas las reglas antes de cargar las nuevas reglas.

# vi /etc/nftables.conf

#!/usr/sbin/nft -f

flush ruleset

table ip nm-shared {
    chain nat_postrouting {
        type nat hook postrouting priority srcnat; policy accept;
        ip saddr 10.42.0.0/24 ip daddr != 10.42.0.0/24 masquerade
        ip saddr 10.42.1.0/24 ip daddr != 10.42.1.0/24 masquerade
        ip saddr 192.168.1.0/24 ip daddr != 192.168.1.0/24 masquerade
    }
}

# systemctl enable nftables
# systemctl start nftables

Se pueden usar los comandos ip, iw y nft para configurar manualmente lo que no permita NetworkManager. Cuando disponga de IPv6 en la conexión de fibra óptica actualizaré el artículo para utilizar este protocolo en el router.

No hay comentarios:

Publicar un comentario