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.
InSkillCoach
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=Falsewhen 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.
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+
Comments
Comments are powered by GitHub Discussions
Sign in with GitHub to join the discussion