前言
之前在编写端口扫描的代码时都是使用TCP/UDP协议,
但是看了很多的代码都是用socket来完成的,所以就
来学习一下socket编程
什么是socket
网络中的两台主机之间进行通信,本质上是主机中所
运行的进程之间的通信,两个进程如果需要进行通信
,最基本的前提是每一个进程要有一个唯一的标识。
在本地进程通信中可以使用PID来唯一标识一个程,
但PID在 本地是唯一,可以用 "IP地+ 协议+端口号"
来组成唯一标识的网络进程,这就是socket
无论使用何种网络协议,最本质上都是在进行数据
的收发,发和收,这两个动作就是socket处理数据
的主要方式
socket的工作流程
socket 采用C/S 模式,分为服务端和客户端
服务端数据处理流程
创建socket -> 绑定到地址和端口 -> 等待连接 -> 开始通信-> 关闭连接
客户端数据处理流程
创建socket -> 等待连接 -> 开始通信-> 关闭连接
客户端没有绑定地址和端口,是由于客户端进程采用的是随机端口,当客户端要去连接目标时,会由系统自定分配一个端口号和自身ip地址去组合
实现端口扫描原理
通过与目标端口进行socket连接,如果能连接的上则端口为开放,反之就是关闭。
1
代码部分
扫描模块
功能
与目标主机端口创建socket连接
1
判断是否能够连接
1
输出开放端口
1
def connect(ip,port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 实例化socket类
try:
s.connect((ip,int(port)))# 连接目标主机,能连接的上即端口开放
time.sleep(0.1)
print(ip,port,"is open")
except:
pass# 连接不上直接放弃
finally:
s.close()# 不管是否能连接目标主机都关闭连接
主函数
功能
接收用户输入的参数
1
扫描单个ip
1
扫描整个网段
1
def main():
parser = OptionParser("Usage:-i -p -n network")# 输出帮助信息
parser.add_option("-i","--host",type="string",dest="tgtIP",help="specify target ip")# 接收ip参数
parser.add_option("-p",'--port',type='string',dest='tgtPort',help="specify target port")# 接收端口参数
parser.add_option('-n','--network',type='string',dest='tgtNetwork',help='speify tartget segment') # 接收网段参数
options, args = parser.parse_args()# 实例化对象输入的参数
tgtip = options.tgtIP
tgtnetwork = options.tgtNetwork
tgtport = options.tgtPort
if tgtip is None and tgtnetwork is None:# 判断用户是否输入参数
print(parser.usage)
sys.exit()
if tgtip:
port = tgtport.split(",")# 将端口以逗号为分隔符转换成列表
for p in port:#遍历列表获取单个端口
connect(tgtip,p)
if tgtnetwork:
for i in range(1, 255):
port = tgtport.split(",")# 将端口以逗号为分隔符转换成列表
prefix = tgtnetwork.split(".")[0] + '.' + tgtnetwork.split(".")[1] + '.' + tgtnetwork.split(".")[2] + '.'# 通过切片的方式获取网段地址前缀
ip = prefix + str(i)# 与ip地址前缀向结合构造网段扫描所需ip
for p in port:
t = Thread(target=connect,args=(ip, p))# 调用多线程去扫描
t.start()
time.sleep(0.1)
整体代码
import socket
import time
import sys
from optparse import OptionParser
from threading import Thread
def connect(ip,port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 实例化socket类
try:
s.connect((ip,int(port)))# 连接目标主机,能连接的上即端口开放
time.sleep(0.1)
print(ip,port,"is open")
except:
pass# 连接不上直接停止
finally:
s.close()# 不管是否能连接目标主机都关闭连接
def main():
parser = OptionParser("Usage:-i -p -n network")# 输出帮助信息
parser.add_option("-i","--host",type="string",dest="tgtIP",help="specify target ip")# 接收ip参数
parser.add_option("-p",'--port',type='string',dest='tgtPort',help="specify target port")# 接收端口参数
parser.add_option('-n','--network',type='string',dest='tgtNetwork',help='speify tartget segment') # 接收网段参数
options, args = parser.parse_args()# 实例化对象输入的参数
tgtip = options.tgtIP
tgtnetwork = options.tgtNetwork
tgtport = options.tgtPort
if tgtip is None and tgtnetwork is None:# 判断用户是否输入参数
print(parser.usage)
sys.exit()
if tgtip:
port = tgtport.split(",")# 将端口以逗号为分隔符转换成列表
for p in port:#遍历列表获取单个端口
connect(tgtip,p)
if tgtnetwork:
for i in range(1, 255):
port = tgtport.split(",")# 将端口以逗号为分隔符转换成列表
prefix = tgtnetwork.split(".")[0] + '.' + tgtnetwork.split(".")[1] + '.' + tgtnetwork.split(".")[2] + '.'# 通过切片的方式获取网段地址前缀
ip = prefix + str(i)# 与ip地址前缀向结合构造网段扫描所需ip
for p in port:
t = Thread(target=connect,args=(ip, p))# 调用多线程去扫描
t.start()
time.sleep(0.1)
if __name__ == '__main__':
main()
运行效果