0%
Comprobar si una dirección IP pertenece a una red en Python

Comprobar si una dirección IP pertenece a una red en Python

Aprende a comprobar si una dirección IP pertenece a una red con el módulo ipaddress. Ejemplos prácticos para cortafuegos, listas de permitidos y filtrado de red.

I

InSkillCoach

· min

Comprobar si una dirección IP pertenece a una red en Python

Una tarea habitual en la administración de redes y en la seguridad de aplicaciones es determinar si una dirección IP dada pertenece a una red concreta. El módulo ipaddress de Python ofrece herramientas elegantes y robustas para esta comprobación. Tanto si implementas una lista de permitidos, un cortafuegos de aplicación o una validación de acceso, esta guía te mostrará cómo dominar esta funcionalidad.

1. El módulo ipaddress

El módulo ipaddress está incluido en la biblioteca estándar de Python desde la versión 3.3. Proporciona clases para representar y manipular direcciones IP y redes.

import ipaddress

# Créer une adresse IP
ip = ipaddress.ip_address("192.168.1.100")
print(ip)                 # 192.168.1.100
print(type(ip))           # <class 'ipaddress.IPv4Address'>

# Créer un réseau
reseau = ipaddress.ip_network("192.168.1.0/24")
print(reseau)             # 192.168.1.0/24
print(type(reseau))       # <class 'ipaddress.IPv4Network'>

2. Comprobar la pertenencia con el operador in

El operador in comprueba si una dirección IP pertenece a una red.

import ipaddress

reseau = ipaddress.ip_network("192.168.1.0/24")

# Tester si des adresses appartiennent au réseau
print("192.168.1.50" in reseau)      # True
print("192.168.2.50" in reseau)      # False
print("10.0.0.1" in reseau)          # False

# Note : l'adresse réseau et l'adresse broadcast font partie du réseau
print("192.168.1.0" in reseau)       # True  (adresse réseau)
print("192.168.1.255" in reseau)     # True  (adresse broadcast)

Función reutilizable

import ipaddress

def is_ip_in_network(ip_string, network_string):
    """
    Vérifie si une adresse IP appartient à un réseau.
    
    Args:
        ip_string (str): Adresse IP à vérifier (ex: "192.168.1.50")
        network_string (str): Réseau CIDR (ex: "192.168.1.0/24")
    
    Returns:
        bool: True si l'IP est dans le réseau, False sinon
    """
    try:
        ip = ipaddress.ip_address(ip_string)
        reseau = ipaddress.ip_network(network_string)
        return ip in reseau
    except ValueError as e:
        print(f"Erreur : {e}")
        return False

# Tests
print(is_ip_in_network("192.168.1.100", "192.168.1.0/24"))   # True
print(is_ip_in_network("192.168.2.100", "192.168.1.0/24"))   # False
print(is_ip_in_network("10.0.0.5", "10.0.0.0/8"))            # True

3. Gestión de errores

La entrada del usuario puede ser inválida. Hay que capturar las excepciones.

import ipaddress

def verifier_ip_securisee(ip_string, network_string):
    """Vérification robuste avec gestion d'erreur."""
    try:
        ip = ipaddress.ip_address(ip_string)
        reseau = ipaddress.ip_network(network_string, strict=False)
        return ip in reseau
    except ValueError as e:
        print(f"Entrée invalide : {e}")
        return False

# Tests d'erreur
print(verifier_ip_securisee("999.999.999.999", "192.168.1.0/24"))     # ValueError
print(verifier_ip_securisee("192.168.1.a", "192.168.1.0/24"))         # ValueError
print(verifier_ip_securisee("192.168.1.100", "192.168.1.0/999"))      # ValueError
print(verifier_ip_securisee("192.168.1.100", "invalid"))              # ValueError

# Résultat : tous affichent un message d'erreur et retournent False

Parámetro strict=False

Por defecto, ip_network exige que la red esté exactamente en el límite del bloque CIDR. Con strict=False, la dirección de red se recalcula automáticamente.

import ipaddress

# Strict (par défaut)
try:
    # 192.168.1.100 n'est pas l'adresse réseau de /24
    reseau = ipaddress.ip_network("192.168.1.100/24")
except ValueError as e:
    print(f"Erreur (strict=True) : {e}")
    # Erreur (strict=True) : 192.168.1.100/24 does not have the correct netmask

# Non-strict
reseau = ipaddress.ip_network("192.168.1.100/24", strict=False)
print(reseau)                      # 192.168.1.0/24 (corrigé automatiquement)

4. Comparación de redes

El módulo ofrece funciones para comparar redes.

import ipaddress

reseau_grand = ipaddress.ip_network("10.0.0.0/8")
reseau_petit = ipaddress.ip_network("10.1.0.0/16")

# Vérifier si un réseau est contenu dans un autre
print(reseau_petit.subnet_of(reseau_grand))      # True
print(reseau_grand.supernet_of(reseau_petit))    # True

# Vérifier l'égalité
reseau_copy = ipaddress.ip_network("10.0.0.0/8")
print(reseau_grand == reseau_copy)               # True

5. IPv6

El módulo también gestiona IPv6. La sintaxis es idéntica.

import ipaddress

# IPv6
reseau_ipv6 = ipaddress.ip_network("2001:db8::/32")
print(reseau_ipv6)                                        # 2001:db8::/32

# Tester l'appartenance
print("2001:db8::1" in reseau_ipv6)               # True
print("2001:db9::1" in reseau_ipv6)               # False

# Adresse link-local (spéciale)
ip_link_local = ipaddress.ip_address("fe80::1")
print(ip_link_local.is_link_local)                # True

6. Casos de uso prácticos

Lista de permitidos para una API

import ipaddress
from flask import Flask, request, abort

app = Flask(__name__)

# IPs autorisées (interne + partenaires)
ALLOWED_NETWORKS = [
    ipaddress.ip_network("192.168.0.0/16"),     # Réseau interne
    ipaddress.ip_network("10.0.0.0/8"),         # Réseau principal
    ipaddress.ip_network("203.0.113.0/24"),     # Partenaire A
]

def is_ip_authorized(ip_string):
    """Vérifie si une IP est autorisée."""
    try:
        ip = ipaddress.ip_address(ip_string)
        return any(ip in network for network in ALLOWED_NETWORKS)
    except ValueError:
        return False

@app.before_request
def check_ip():
    """Middleware : bloquer les IPs non autorisées."""
    client_ip = request.remote_addr
    if not is_ip_authorized(client_ip):
        abort(403)  # Accès refusé

@app.route("/api/data")
def get_data():
    return {"data": "Secret"}

# Résultat : seules les IPs dans ALLOWED_NETWORKS accèdent à l'API

Filtrado en un cortafuegos de aplicación

import ipaddress

class SimpleFirewall:
    def __init__(self):
        self.blocked_networks = [
            ipaddress.ip_network("203.0.113.0/24"),     # Pays bloqué
            ipaddress.ip_network("198.51.100.0/24"),    # Spam connu
        ]
    
    def is_blocked(self, ip_string):
        """Vérifie si une IP est bloquée."""
        try:
            ip = ipaddress.ip_address(ip_string)
            return any(ip in network for network in self.blocked_networks)
        except ValueError:
            return False
    
    def log_connection(self, ip_string, allowed):
        status = "ALLOWED" if allowed else "BLOCKED"
        print(f"{ip_string} : {status}")

firewall = SimpleFirewall()

test_ips = [
    "192.168.1.1",        # OK
    "203.0.113.50",       # Bloquée
    "198.51.100.100",     # Bloquée
]

for ip in test_ips:
    allowed = not firewall.is_blocked(ip)
    firewall.log_connection(ip, allowed)

7. Buenas prácticas

  • Captura ValueError: la entrada de red siempre puede ser inválida.
  • Utiliza strict=False cuando aceptes entradas del usuario y quieras ser tolerante.
  • Crea los objetos de red una sola vez y reutilízalos (cuestan poca memoria).
  • Prueba los casos límite: dirección de red, dirección de broadcast, direcciones especiales (localhost, link-local, etc.).
  • Registra los rechazos con fines de auditoría y seguridad.

Conclusión

El módulo ipaddress simplifica enormemente la comprobación de pertenencia de una IP a una red. Gracias al operador in, al parámetro strict=False y a una gestión de errores robusta, dispones de todas las herramientas necesarias para implementar listas de permitidos, filtros de red y políticas de acceso. Ya sea para proteger una API, gestionar un cortafuegos de aplicación o filtrar tráfico, esta competencia es esencial para cualquier desarrollador Python que trabaje con redes.

InSkillCoach

Acerca de InSkillCoach

Experto en formación y tecnologías

Coach especializado en tecnologías avanzadas e IA, impulsado por GNeurone Inc.

Certificaciones:

  • AWS Certified Solutions Architect – Professional
  • Certificaciones de Google Cloud
  • Microsoft Certified: DevOps Engineer Expert
  • Certified Kubernetes Administrator (CKA)
  • CompTIA Security+
1.5k
277

Comentarios

Los comentarios funcionan con GitHub Discussions

Inicia sesión con GitHub para participar en la discusión

¡Enlace copiado!