本篇基于赖明星的Python Linux系统管理与自动化运维.本书以Linux系统管理为线索,以Python语言为载体,介绍了大量Python语言的应用案例。通过学习本书,读者不但可以使用Python语言管理Linux系统,而且,也为Python解决其他领域问题打下了坚实的基础。
python的应用领域已经是众所周知的非常广泛,那么在网络上它是怎么大展神通的呢。
本次主要会介绍:
-
用python列出网络上活跃的所有主机。
-
python中的端口扫描工具
-
进行ip管理
-
一个DNS工具包
-
网络嗅探
-
<!--more-->
列出网络上活跃的所有主机
和网络相关,你接触到的第一个命令一定是ping命令,它可以探测到主机到主机之间是否能够通信。ping命令可以通过网络设备的回复得知两台主机的连通性以及主机之间的网络延迟。
使用案例:
$ping www.baidu.com
#得到结果如下:
#正在 Ping www.a.shifen.com [14.215.177.39] 具有 32 字节的数据:
#来自 14.215.177.39 的回复: 字节=32 时间=37ms TTL=54
#来自 14.215.177.39 的回复: 字节=32 时间=37ms TTL=54
#来自 14.215.177.39 的回复: 字节=32 时间=38ms TTL=54
#来自 14.215.177.39 的回复: 字节=32 时间=37ms TTL=54
#14.215.177.39 的 Ping 统计信息:
# 数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
#往返行程的估计时间(以毫秒为单位):
# 最短 = 37ms,最长 = 38ms,平均 = 37ms
如果主机不可达:则会返回Destination Host Unreachable
的错误信息。
注:ping发送的数据是互联网控制协议(ICMP)中的ECHO_REQUEST数据报
ping的控制选项:
-
-c:限制发送的ECHO_REQUEST数据报的数量,默认是无限制。
那么如何使用ping命令在shell脚本中获得网络上活跃的主机列表。
分析:
在程序中可以通过ping命令的返回码判断主机是否可达,主机活跃时返回码为0,主机不可达时返回码非零。
shell程序如下:
for ip in 'cat ips.txt'
do
if ping $ip -c 2 &> /dev/null
then
echo "$ip is alive"
else
echo "$ip is unreachable"
fi
done
以上例子中,主机地址以每行一个地址的形式保存到ips.txt文件中,然后使用cat命令读取文件中内容,使用for迭代ips.txt中保存的主机。
同时,if ping $ip -c 2 &> /dev/null
的操作使ping输出信息输出到/dev/null中,以免信息在终端上打印。
接下来使用python实现以上功能:
from __future__ import print_function
import subprocess
import threading
def is_reacheable(ip):
if not subprocess.call(["ping",ip,"-n","1"],shell=True):
print("{} is alive".format(ip))
else:
print("{} is unreacheable".format(ip))
def main():
with open("ips.txt") as f:
lines = f.readlines()
threads = []
for line in lines:
thr = threading.Thread(target=is_reacheable, args=(line,))
thr.start()
threads.append(thr)
for thr in threads:
thr.join()
if __name__ == '__main__':
main()
以上案例中使用线程的方法,给每个IP创建一个线程,由于线程之间不共享任何数据,因此不需要进行并发控制。在python中要判断两台主机是否可达主要有两种方式,一种时在python中调用ping命令,另一种是使用socket编程发送icmp数据。
使用python的区别在于python程序使用并发加快了程序的执行效率,同时实现并发的代码量也较少很便捷。
生产者消费者模型
当然上面的例子也存在一定的问题,当ip数较多时会有频繁的上下文切换。因此需要对于线程的数目进行限制。这里使用生产者和消费者模型就可以解决问题。
生产者消费者问题简单的说,就是增加缓存机制和等待机制。生产者放入缓存商品,放满后等待,消费者获取商品,没有商品则等待。
from __future__ import print_function
import subprocess
import threading
import queue
def call_ping(ip):
x = subprocess.call(["ping", ip, "-n", "1"], shell=True)
if not x:
print("{} is alive".format(ip))
else:
print("{} is unreacheable".format(ip))
def is_reacheable(q):
try:
while True:
ip = q.get_nowait()
call_ping(ip)
except Exception:
pass
def main():
q = queue.Queue()
with open("ips.txt") as f:
for line in f:
q.put(line)
threads = []
for i in range(10):
thr = threading.Thread(target=is_reacheable, args=(q,))
thr.start()
threads.append(thr)
for thr in threads:
thr.join()
if __name__ == '__main__':
main()
这里使用了队列的方法,队列是先进先出的数据结构。所有的ip读入内存并放入Queue中,消费者不断从中获取商品,当没有商品时线程将会阻塞,直到有新的ip进入。
端口扫描
端口扫描是为了我们能够快速了解主机打开了哪些不必要的端口,以便及时消灭隐患。
首先判断一个端口是否能打开,可以使用telent命令。直接参照上一个例子在python代码中调用telnet命令判断一个端口是否打开。
这里我们会使用到socket模块,该模块为操作系统的socket连接提供了一个python接口。默认情况下socket函数会返回一个使用tcp协议的socket对象。如下:
import socket
s=socket.socket()
s.connect(('123.56.80.63',80))
s.send("GET / HTTP/1.0 \r\n")
print(s.recv(200))
#输出的结果不是重点,,,我没得出来
再来一个端口扫描器,看能不能跑
emm不能
未完待续