0%
Check Whether an IP Address Belongs to a Network in Python

Check Whether an IP Address Belongs to a Network in Python

Learn how to check whether an IP address belongs to a network using the ipaddress module. Practical examples for firewalls, allowlists, and network filtering.

I

InSkillCoach

· min

Check Whether an IP Address Belongs to a Network in Python

A common task in network administration and application security is determining whether a given IP address belongs to a specific network. Python’s ipaddress module provides elegant, robust tools for this check. Whether you’re implementing an allowlist, an application firewall, or access validation, this guide will show you how to master this feature.

1. The ipaddress Module

The ipaddress module has been included in the Python standard library since version 3.3. It provides classes for representing and manipulating IP addresses and networks.

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. Checking Membership with the in Operator

The in operator tests whether an IP address belongs to a network.

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)

Reusable Function

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. Error Handling

User input can be invalid, so you need to catch exceptions.

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

The strict=False Parameter

By default, ip_network requires the network address to sit exactly on the CIDR block boundary. With strict=False, the network address is automatically recalculated.

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. Comparing Networks

The module provides functions for comparing networks.

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

The module also handles IPv6. The syntax is identical.

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. Practical Use Cases

Allowlist for an 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

Filtering in an Application Firewall

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. Best Practices

  • Catch ValueError: network input can always be invalid.
  • Use strict=False when accepting user input and you want to be lenient.
  • Create network objects once and reuse them (they’re cheap in memory).
  • Test edge cases: network address, broadcast address, special addresses (localhost, link-local, etc.).
  • Log rejections for auditing and security purposes.

Conclusion

The ipaddress module greatly simplifies checking whether an IP belongs to a network. With the in operator, the strict=False parameter, and robust error handling, you have all the tools you need to implement allowlists, network filters, and access policies. Whether you’re securing an API, managing an application firewall, or filtering traffic, this skill is essential for any Python developer working with networks.

InSkillCoach

About InSkillCoach

Training and technology expert

Coach specializing in advanced technologies and AI, backed by GNeurone Inc.

Certifications:

  • AWS Certified Solutions Architect – Professional
  • Google Cloud certifications
  • Microsoft Certified: DevOps Engineer Expert
  • Certified Kubernetes Administrator (CKA)
  • CompTIA Security+
2.0k
200

Comments

Comments are powered by GitHub Discussions

Sign in with GitHub to join the discussion

Link copied!