CIDR 是无类别域间路由的意思,以前会用A类、B类、C类地址来表示一个网段。在 CIDR 的概念里没有ABC类地址的概念,所有地址段都可以用 a.b.c.d/m 的形式来表示。其中 a.b.c.d 是 IP 地址,m 是子网掩码。这类IP段的表示法就叫 CIDR 表示法。
如何将 IP 地址范围(以开始和结束 IP 地址的形式)转换成 CIDR 表示法,这是一个常见需求。有些防火墙和 ipset 操作不支持使用不连续的网段来表示一个集合,比如 192.168.1.1-192.168.1.10 是没法转换成单一的 CIDR 的,它如果转换成 CIDR 格式,会转换成多个 CIDR 地址段,比如:
python3 ip_merge2.py -t ip 192.168.1.1-192.168.1.10
192.168.1.1/32
192.168.1.2/31
192.168.1.4/30
192.168.1.8/31
192.168.1.10/32
即一个 IP 段是由多个 CIDR 段组成。Github 上有一个 Go 语言写的工具可以处理这种 IP 段到 CIDR 的转换,项目地址为:
https://github.com/zhanhb/cidr-merger
之前也写过文章介绍过这款工具,文章地址:
这里介绍一种在 Python 下的解决方案,这样就不需要调用第三方工具了,直接在代码中即可处理 IP 段到 CIDR 的转换。后面会贴出代码,将函数包装成命令行工具后,使用方法下:
python3 ip_merge2.py
usage: ip_merge2.py [-h] -t {cidr,ip} input
ip_merge2.py: error: the following arguments are required: input, -t/--type
$ python3 ip_merge2.py -t ip 0.0.0.0-9.255.255.255
0.0.0.0/5
8.0.0.0/7
使用前要先安装 netaddr 模块:
$ pip install netaddr
用到的关键函数如下:
> from netaddr import IPRange
def ip_range_to_cidr(ip_start, ip_end): >
... cidr_list = IPRange(ip_start, ip_end)
... return cidr_list
...
'192.168.1.1', '192.168.1.10') > ip_range_to_cidr(
IPRange('192.168.1.1', '192.168.1.10')
> from netaddr import IPSet
'192.168.1.1', '192.168.1.10')) > IPSet(ip_range_to_cidr(
IPSet(['192.168.1.1/32', '192.168.1.2/31', '192.168.1.4/30', '192.168.1.8/31', '192.168.1.10/32'])
>
Python 代码如下:
import argparse
import ipaddress
from netaddr import IPSet, IPRange
def debug(func):
def wrapper(*args, **kwargs):
print(f"Function: {func.__name__}")
print(f"Arguments: {args}")
print(f"Keyword Arguments: {kwargs}")
print()
result = func(*args, **kwargs)
return result
return wrapper
def ip_to_cidr(ip):
ip_network = ipaddress.ip_network(ip, strict=False)
return str(ip_network)
# @debug
def ip_range_to_cidr(ip_start, ip_end):
cidr_list = IPRange(ip_start, ip_end)
return cidr_list
def cidr_to_ip_range(cidr):
ip_network = ipaddress.ip_network(cidr, strict=False)
ip_range = (str(ip_network.network_address), str(ip_network.broadcast_address))
return ip_range
def main():
parser = argparse.ArgumentParser(description="Convert between CIDR and IP range")
parser.add_argument("input", help="Input CIDR, IP address, or IP range")
parser.add_argument("-t", "--type", choices=["cidr", "ip"], help="Specify input type (cidr or ip)", required=True)
args = parser.parse_args()
if args.type == "cidr":
if "/" not in args.input:
print("Error: Invalid CIDR input. Make sure to include the subnet mask.")
return
result = cidr_to_ip_range(args.input)
print(f"CIDR to IP Range: {args.input} -> {result}")
elif args.type == "ip":
if "-" in args.input:
ip_start, ip_end = map(str.strip, args.input.split("-"))
result = ip_range_to_cidr(ip_start, ip_end)
# print(f"IP Range to CIDR: {args.input} -> {IPSet(result)}")
for i in result.cidrs():
print(i)
elif "/" in args.input:
print("Error: Invalid IP input. Remove the subnet mask for IP address input.")
return
else:
result = ip_to_cidr(args.input)
print(f"IP to CIDR: {args.input} -> {result}")
if __name__ == "__main__":
main()
全文完。
如果转发本文,文末务必注明:“转自微信公众号:生有可恋”。
原文始发于微信公众号(生有可恋):IP 地址段到 CIDR 格式的转换
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论