0
点赞
收藏
分享

微信扫一扫

【netaddr系列】处理网络地址,你可能需要一个netaddr

诗远 2023-05-11 阅读 109

【netaddr系列】处理网络地址,你可能需要一个netaddr

网络运维中,我们永远也绕不开到的一个话题,就是网络地址(IP+MAC)

其中,尤以IP地址我们讨论的最多,因为在这个上面,有着太多的信息和话题值得我们去深究。

今天我们就为大家带来一个Python的网络地址工具包——netaddr。

它是一款功能非常强大的Python包,用于表示网络地址和处理网络地址。

它支持2层和3层地址。

我们今天先简单介绍一下3层地址的一些基础的定义和操作用法。

关于Python中的IP地址工具包,就笔者而言,我所知晓的几个包:

  1. Python内置的ipaddress包,功能简单,v4、v6的地址及网段操作基本都支持,但是API功能有限,有时候需要自己写一些逻辑辅助,偶尔略显鸡肋。随着笔者使用的不断深入,此包被逐渐弃用。
  2. IPy,功能已经很强大的IP地址处理工具类,GitHub上460+的star数,满足基本操作不在话下,同时API比较简单或者说非常简单,刚开始用还凑合,但是慢慢的,用的越来越拧巴,也许是想让网工上手难度低一些,封装的过于高度,IP地址和网段混着来(严重怀疑它和谷歌的ipaddr有着一些传承),恍惚间,个人觉得这个包这么做会丢失一些信息,有点得不偿失,同时身为一个在夹缝中的开发者和网络工程师,让我觉得这个包有时候怪怪的,不伦不类,面向对象的抽象不好。值得一提,最近更新到了1.0.1版本,对Python3.9兼容更好了。
  3. netaddr,功能强大,可以处理2、3层地址,2层地址支持很多手写格式,对于网段的计算、合并、子网、超网都非常简单,同时,数据结构的设计非常清晰,让我感觉很严谨,在不同场景下用不同的类,非常方便。GitHub上star数大约650+。个人认为,在笔者使用的范畴内,这个包,已经足够了,不需要再用其他的包了。我们本文也会着重介绍。更新的也不错,从2009年至今每年差不多都在更新。mac地址部分内置了一些厂家mac地址的oui信息,这块笔者也打算继续去挖掘一下。
  4. ipaddr,谷歌的一个IP地址工具类,但是功能略显单薄,也基本不更新。我看了看源代码,感觉IPy和它有点说不清得的关系。个人不太推荐。

以上四种工具包都是非常优秀的(至少前三种,笔者都实际使用过,第四种看了看源代码)。netaddr的更新频度也还ok,且是由一群人一起更新维护的,个人觉得非常值得一试。好了,言归正传,我们开始解开netaddr的神秘面纱。

本文估计也会写成一个系列,因为,netaddr的内涵非常宽广,浅浅深深,有很多可以挖掘的地方,在我们日常工作中都会有所帮助,这个大家都懂得,关于IP的相关需求层出不穷,曾经在一个群里,一个网工贴了一个ipv6的地址合不合法,我当时用了ipaddress的包,用字符串去构建一个IPv6的对象,成功就是合法,不成功就是非法,so easy。对于网络的划分等等也有类似的案例。

插播一句netadd的安装 ,确保你安装了Python和pip,建议使用3.8版本的Python,pip install netaddr即可。

用netaddr定义基本的IP对象

netaddr内置了很多的类,在不同的场景下有着不同的作用,有的时候感觉是守正出奇,中规中矩之下的外表,内核及其灵活多变,而底层又非常统一。

【netaddr系列】处理网络地址,你可能需要一个netaddr_Python

image-20210313083422261

我们安装完netaddr,导入包的时候会发现,它的一些基本的类和方法,上图红框部分,是个人觉得IP层面比较常用的。

谈起IP,我们最常见的就是IP地址和IP网段,我们今天主要就来介绍一下IP地址的基本操作。

IP地址的定义

*

【netaddr系列】处理网络地址,你可能需要一个netaddr_IP_02

IP地址的定义非常简单,我们用IPAddress这个类,初始化的时候传入IP地址字符串即可,它会根据v4 、v6的进行判断,自动返回一个IP地址对象给我们。

【netaddr系列】处理网络地址,你可能需要一个netaddr_IP_03

image-20210313085914291

IPv6也是没问题的,同时会自动帮助我们压缩一下地址。

错误的IP地址,netaddr会报错,并给我们提示

【netaddr系列】处理网络地址,你可能需要一个netaddr_IP_04

image-20210313090312948

这样的话,有时候我们可以用它来校验IP地址,不用写正则表达式了。当然这个开销会比正则要大一些。

同时,我们也可以显示的指定IP地址版本,在一些特殊情况下多一道加固。

【netaddr系列】处理网络地址,你可能需要一个netaddr_Python_05

image-20210314085021177

IP地址的多种表现形式

IP地址本质是二进制,我们用了点分十进制的方式来表示,方便我们阅读交流。

在不同的情况下,我们对于IP地址的表现形式会有很多的要求,netaddr也是支持的,我们来简单演示一下

二进制表示方法

ip = IPAddress('192.168.1.10')
print(ip)
print(bin(ip)) # 用内置函数转换
print(ip.bin) # 调取对象的属性,其实本质是一个property修饰过后的方法

【netaddr系列】处理网络地址,你可能需要一个netaddr_IP_06

image-20210314085125564

十进制表示方法

ip = IPAddress('192.168.1.10')
print(int(ip))

十进制可只有这一种方式方法了,只能用int来转换为整数,默认十进制。

【netaddr系列】处理网络地址,你可能需要一个netaddr_IP_07

image-20210314085923047

本质上是IPAdress的魔法函数实现了二、十、十六进制的转换,所以我们调用bin、int、hex就可以实现对应的进制了。

十六进制我们就不演示了,个人感觉用处不大。

点分二进制表示方法

ip = IPAddress('192.168.1.10')
    print(ip.bin)
    print(ip.bits()) # 注意,此处用的是一个bits的方法,一定要家"()",结果会返回一个点分二进制的字符串

【netaddr系列】处理网络地址,你可能需要一个netaddr_网络地址_08

image-20210314090339900

十进制的元组表示方法

这种表示方法,我取主机位的时候偶尔用。

【netaddr系列】处理网络地址,你可能需要一个netaddr_Python_09

image-20210314090556676

IP地址比较大小

IP地址也可以比较大小,实际意义,个人认为有两个场景

  1. 排序,各种情况下,我们需要按照IP地址排序的时候,可以考虑先转成IPAdress,然后比较
  2. 判断网络地址(网段地址)是否落在一个网段内,只要网络地址(或者网段地址的上下限)在待比较网段地址的上下限内即可。当然,实际netaddr有专门的比较网络地址和网段之间关系的函数或者方法。

【netaddr系列】处理网络地址,你可能需要一个netaddr_网络地址_10

image-20210314092033842

其他可能用到的

这些事内置的方法,笔者个人使用的并不是很多,大家可以根据自己情况取看看,看看是不是私网地址,是不是多播地址,是不是保留地址等等。

【netaddr系列】处理网络地址,你可能需要一个netaddr_IP_11

image-20210314091659924

补充说明

我们在比较网络地址和网段归属的时候,有时候会用for循环(多是嵌套),多在ACL或者路由的判断中。然后一个个的比较,实际上这种方法有时候比较暴力简单低效,在一台设备上计算都好,假如是全网去计算获取筛选,那效率应该及其低下,估计底下得算百万千万甚至上亿次,才可以。

笔者推荐的一个方法,是把相关网段地址解析后转成int类型,存储到数据库中,存储它的上下限,判断一个IP地址或者网段在整个ACL或者路由中的关系的时候,就变成了一个简单的数字比较,且大部分计算量都交给了数据库,无需过多的for循环,整体效率会更高,毕竟在数据库层面比较int的大小还是非常easy的。

所以我非常喜欢IPAddress的int转换,实际上我们自己写一个也非常简单,很多人上学的时候应该有在计算机网络这门课程观中学习过。

闲言碎语

本来想总结一下,感觉没啥必要,我们就是讲了一下为什么选择IP地址工具包netaddr,简单介绍了一下网络地址如何定义,一些表达方法。

下一节我们讲网段,本来打算一并写了的,但是发现工程量有点大,所以我给拆了一下,本系列就叫netaddr系列吧。预估3-5节。HW就要开始了,对于网络地址的归属和计算估计接踵而至,我也会尽快完成此系列,今年如果赶不上,大家明年也可以再回来看看。

最后

同名知乎专栏和微信公众号:NetDevOps加油站,欢迎你的加入!

【netaddr系列】处理网络地址,你可能需要一个netaddr_网络地址_12

image-20201219222006955


举报

相关推荐

0 条评论