器 | 了解一下,使用python进行端口扫描

1,081 阅读2分钟

本文正在参加「Python主题月」,详情查看 活动链接

在服务器上,很多时候需要观察端口的使用情况,当然我们可以使用成熟的工具nmap完成这个事情,但我们是不是可以用pythonsocket原生完成这件事情呢?

一、socket概念

我们很清楚,socket又称"套接字",socket套接字在 Internet 通信上广泛使用,应用程序通常通过"套接字"向网络发出请求或者应答网络请求,完成主机间或者一台计算机上的进程间的通讯。

python中的套接字模块提供对 BSD 套接字接口的访问。它包括用于处理实际数据通道的套接字类,以及用于与网络相关的任务的函数,例如将服务器名称转换为地址并格式化要通过网络发送的数据。

下图表达了使用socket通信的过程。

socket.jpg

二、socket基本用法

我们先来熟悉一下socket函数的基本用法。在Python中,import socket后,用socket.socket()方法来创建套接字,语法格式如下:

socket = socket.socket([family[, type[, proto]]])

参数说明:

  • family: 套接字家族,可以使AF_UNIX或者AF_INET
  • type: 套接字类型,根据是面向连接的还是非连接分为SOCK_STREAMSOCK_DGRAM,也就是TCP和UDP的区别。
  • protocol: 一般不填默认为0。

直接使用socket.socket() ,则全部使用默认值。

创建一个TCP套接字(流式)

socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

创建一个UDP套接字(数据报式)

socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

将一个主机名翻译成IPv4地址格式

gethostbyname("host") 

将一个主机名翻译成IPv4地址格式,扩展接口

socket.gethostbyname_ex("host")  

获取完全限定域名

socket.getfqdn("8.8.8.8")  

获取机器的主机名

socket.gethostname()  

异常处理

Exception handling

三、扫描端口实战

#!/usr/bin/env python
import socket
import subprocess
import sys
import platform
from datetime import datetime
​
# 获取当前的系统类型,用不同的指令清空屏幕
if platform.system() == "Windows":
    subprocess.call('cls', shell=True)
else:
    subprocess.call('clear', shell=True)
​
# 获取输入内容host
remoteServer    = input("Enter a remote host to scan: ")
remoteServerIP  = socket.gethostbyname(remoteServer)
​
# 打印一个banner,打印格式如下
#------------------------------------------------------------
#Please wait, scanning remote host 110.242.68.3
#------------------------------------------------------------
print ("-" * 60)
print ("Please wait, scanning remote host", remoteServerIP)
print ("-" * 60)
​
# 获取一个时间t1
t1 = datetime.now()
​
# 使用范围函数range()来指定端口(这里将扫描1到1024之间的所有端口)
#针对异常,做了try..except 捕获处理try:
    for port in range(1,1025):  
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        result = sock.connect_ex((remoteServerIP, port))
        if result == 0:
            print ("Port {}:     Open".format(port))
        sock.close()
​
except KeyboardInterrupt:
    print ("You pressed Ctrl+C")
    sys.exit()
​
except socket.gaierror:
    print ('Hostname could not be resolved. Exiting')
    sys.exit()
​
except socket.error:
    print ("Couldn't connect to server")
    sys.exit()
​
# 再次获取时间t2
t2 = datetime.now()
​
# 获取脚本计算的时间差
total =  t2 - t1
​
# 打印时间差到控制台
print ('Scanning Completed in: ', total)