文章目录
- 1. 简介
- 2. 特点
- 3. UDP数据报结构
- 4. 基于UDP的应用层协议
- 5. UDP安全性问题
- 6. 使用udp传输数据的系统就一定不可靠吗?
- 7. 基于UDP的主机探活 python实现
1. 简介
User Datagram Protocol,用户数据报协议,基于IP协议提供面向无连接的网络通信服务。特点:简单
,不可靠
,面向数据报
。 UDP协议位于ISO网络模型的传输层
。
2. 特点
特点解释:
- 无连接: 两台主机在使用UDP进行数据传输时,不需要建立连接,只需要知道对方端的IP和端口号即可把数据发送过去。
- 不可靠:UDP协议没有确认重传机制,如果因为网络故障导致报文无法发到对方,或者对方接收到了报文,但是传输过程中乱序了,对方检验失败后把乱序的包丢了,UDP协议层也不给应用层任何错误反馈信息。
- 面向数据报:以数据报文为单位一个个发出去,然后一个个接收的,导致上面的应用层无法灵活控制数据的读写次数和数量。
3. UDP数据报结构
- 源端口号: 发送方的端口,用于唯一确认发送方主机的一个进程。 大小范围
1-65535
。 - 目的端口: 接收方的端口,用于唯一确认接收方主机的一个进程。大小范围
1-65535
。 - UDP长度:一个UDP报文所能传输的最大长度是64K,包含UDP首部。
- UDP校验和: 为了确保数据包在传送过程中,数据检测数据是否被篡改和丢失的一种手段。通过二进制补码求和进行校验,校验和的内容包括:
- 伪首部(IP数据包的一部分):
源IP地址(32位)
,目的IP地址(32位)
,保留字段(8位, 0)
,协议号(8位, 指定为17,代表udp)
,UDP长度(16) UDP数据报的总长度,包括头部和数据
- UDP首部:源端口号、目的端口号、长度字段、校验和字段(初始值为0)
- UDP数据: 实际传输的应用层数据。
- 伪首部(IP数据包的一部分):
端口和应用程序的关系: 1. 主机运行的一个进程可以绑定多个端口号。2.一个主机的某一个端口只能被一个进程所绑定。 可以推导出
一个主机上的端口可以唯一确认主机上的一个进程,
4. 基于UDP的应用层协议
- DNS协议: 域名解析协议, 域名 => IP.
- DHCP协议:动态主机配置协议, 为设备动态分配IP地址、网关、DNS服务器等网络参数。
- NTP协议: 用于同步网络中的设备时钟。
- SNMP协议: 用于网络设置的监控和管理,如路由器、交换机等。
- RIP协议: 路由信息协议,是一种距离向量路由协议,用于在网络设备间交换路由信息。
上述协议的几个明显的特点:
- 传输数据一般都比较小。
- 对速度要求较高,延迟时间低
- 不需要或者无法进行连接.(例如dhcp初次启动时,设备根本就没有ip地址)
- 由于网络问题丢失数据也不会非常严重,重新发起请求即可。
如果实际开发需求中,如果你的需求任务满足上述几种要求时,可以考虑使用udp去实现。
5. UDP安全性问题
- 易受攻击性问题(微造身份):udp本身是无连接的,数据包在发送之前不需要建立连接,攻击者可以轻易伪造源地址发送UDP数据,进行
IP欺骗
攻击。 - 反射攻击和放大攻击:
- udp反射攻击: 攻击者伪造受害者的 IP 地址,向网络上的其他服务器发送大量UDP 请求。由于很多服务器会自动回复请求,这些回复数据将被发送到受害者的地址,从而导致大量流量集中到受害者一侧,形成 DDoS 攻击。
- udp放大攻击:基于udp的应用层协议(DNS,NTP)返回的响应包含较大的数据包。攻击者利用伪造的 IP 地址发送小请求,目标服务器返回的大量数据包会直接被发送给受害者,放大了攻击效果。
- udp未加密传输: 数据以明文形式传输,容易被窃听。中间人可以劫持udp流量,监听内容,进行功能流量重放等攻击手段。
- 利用防火墙漏洞传输有害信息: UDP 是无连接的协议,某些情况下可以绕过防火墙的状态检测。攻击者可以通过精心设计的数据包,穿透防火墙,访问内部的网络资源。
6. 使用udp传输数据的系统就一定不可靠吗?
先说结论: 虽然udp本身不提供可靠性保证,但在实际应用中,
通过应用层协议的设计,可以使得基于UDP的通信具备可靠性
。
常见例子:
- DNS: 通过使用超时重传机制来保证查询的可靠性。
- TFTP: 通过应用层的确认和重传机制来保证文件传输的可靠性。
- RTP(用于传输音视频的协议): 通过结合RTCP提供的一些保障机制,例如 序列号和时间戳、丢包检测、RTCP反馈。来实现可靠传输。
7. 基于UDP的主机探活 python实现
实现原理:当向目标发送一个UDP数据包之后,目标是不会发回任何UDP数据包的。不过如果目标主机处于活跃状态,但是目标端口是关闭状态时,会返回一个ICMP数据包,这个包的含义是unreachable.如果目标主机处于不活跃状态,这时接收不到任务响应数据。
挑选目标主机的目标端口也是一个比较重要的步骤。一般思路是设置不太可能被开放端口,例如65535
这种不常用的端口。我下面这个脚本通过随机数去生成一个目标端口,不一定适用所有情况,可以根据要扫描网段或机器的环境设置目标端口。
from scapy.layers.inet import *
from optparse import OptionParser
import nmap
import sys
"""
发送udp数据包
"""
def main():
usage = "Usage: %prog -i <ip adress>"
parse = OptionParser(usage=usage)
# 获取网段地址
parse.add_option("-i", "--ip", type="string", dest="IP", help="specify the IP address")
options, args = parse.parse_args()
# check
if options.IP is None:
parse.print_help()
sys.exit(1)
if "-" in options.IP:
start = int(options.IP.split("-")[0].split(".")[3])
end = int(options.IP.split("-")[1])
ipPrefix = ".".join(options.IP.split(".")[:3])
for i in range(start, end + 1):
Scan(ipPrefix + "." + str(i))
else:
Scan(options.IP)
def sent_udp_message(address):
ip = IP()
udp = UDP()
r = (ip / udp)
r[IP].dst = address
r[UDP].dport = random.randint(1024, 65535)
a = sr1(r)
a.display()
"""
通过UDP探测包探测主机存活
"""
def Scan(ip):
dport = random.randint(1, 65535)
try:
packet = IP(dst=ip) / UDP(dport=dport)
response = sr1(packet, timeout=10, verbose=0)
if response:
if int(response[IP].proto) == 1:
print(ip + " is up")
else:
print(ip + " is down")
else:
print(ip + " is down")
except Exception as e:
print(e)
"""
借助nmap实现udp探测
"""
def NmapScan(targetIp):
nm = nmap.PortScanner()
try:
result = nm.scan(hosts=targetIp, arguments="-PU")
state = result["scan"][targetIp]["status"]["state"]
print("[{}] is [{}]".format(targetIp, state))
except Exception as e:
print(e)
if __name__ == "__main__":
main()