文章目录
- TCP协议
- [1. 简介](#1. 简介)
- [2. 报文格式](#2. 报文格式)
- [3. 连接,三次握手](#3. 连接,三次握手)
- [4. 断开连接,四次挥手](#4. 断开连接,四次挥手)
- [5. 基于TCP的应用层协议](#5. 基于TCP的应用层协议)
- [6. 基于TCP的主机探活 python实现](#6. 基于TCP的主机探活 python实现)
TCP协议
1. 简介
TCP(Transmission Control Protocol)传输控制协议,提供了一种面向连接
、可靠
的字节流
服务。属于传输层协议。
2. 报文格式
- 序号: TCP传输过程,在发送端发出的字节流中,传输报文中的数据部分的每个字节都有它的编号。占32位,发送方发送数据都需要标记序号。
TCP协议通过序号对上层提供有序的字节流
.序号的语义与SYN控制标识有关,根据SYN是否为1,序号表达不同的含义:- SYN=1,当前为连接建立阶段,此时的序号为初始序号ISN(Initial Sequence Number),通过算法随机生成序号
- SYN=0,数据传输开始,第一个报文的序号为ISN+1,后面的序号为前一个SN的值 + TCP报文的静载荷字节数。
- 确认序号: 标识报文接收端期望接收的字节序列。如果设置了ACK控制位,确认序号的值表示一个准备接收的包的序列码。
- 头部长度: 占四位,表示TCP报文首部的长度,单位4字节。
- 保留字段:预留的字段长度为6位
- 控制标志:
- URG: 1位,表示紧急指针字段有效。,此标志用通知接收方,紧急数据需要优先处理。
- ACK:1位,表示确认字段有效。确认接受到了之前发送的数据。
- PSH: 提示接收端应立即处理并推送接收到的数据到应用层,而不必等待缓冲区填满。
- RST: 重置连接,用于强制关闭连接或拒绝连接。当出现不正常通信情况。
- SYN: 初始化连接,在TCP握手的第一个步骤发出,用于同步序列号。
- FIN: 表示发送方已经发送完数据,并希望关闭连接。
- 窗口大小:长度为16位。用来进行流量控制,流量控制单位为字节数,值是本端期望一次接收的字节数。
- 校验和:16位,对整个TCP报文段,即TCP头部和TCP数据进行检验和计算,接收端用于对数据进行校验。
- 紧急指针:16位,一个偏移量,和SN序号值相加表示紧急数据最后一个字节的序号。
- 选项和填充: 在这部分可以增加可选项, 填充需要确保Tcp头是32位的整数倍,
3. 连接,三次握手
三次握手的目的:让双方能够同步各自的序列号和确认号,确保双向通信的可靠性。
步骤解释:
- 第一次握手:SYN
- 客户端主动向服务端发送一个SYN请求,主动建立TCP连接,包中设置seq为a
- 第二次握手:SYN-ACK
- 服务端准许建立这个连接的情况下,向客户端返回一个SYN-ACK(同步-确认)包.
- 返回包包含两个信息: ack=a+1,表示确认收到客户端seq为a的包。seq=b表示自己的初始序列号为b
- 第三次握手: ACK
- 客户端在接收端到服务端的SYN-ACK响应之后,发送一个 ACK(确认)包给服务器。
- 这个包确认号为 ack = b + 1,表示已接收到服务器的 SYN 包。
三次握手各步骤作用:
- 确保双方的可用性: 第一次握手(SYN)让服务端知道客户端主动想建立TCP连接,第二次(SYN-ACK)让客户端确认服务器的存在。
- 序列号同步: 第一次握手和第二次握手过程中交换了双方在进行数据传输时的起始序列号。可以确保后续传递数据包的排序正确性。
- 避免半开放连接:如果不进行第三次握手,可能导致连接客户端或者服务端认为连接已经建立,但另一方断开了。这种情况会导致存在潜在的半开放连接,导致资源浪费。
4. 断开连接,四次挥手
目的: 确保在数据完整传输前提下,安全的断开连接。
各步骤解释:
- 第一次挥手:FIN
- 主动断开方主动发送方发送一个FIN包,表示它已经没有数据要发送了,想要关闭连接。
- 发送完FIN包之后,主动段开放进行FIN_WAITE_1状态。
- 第二次挥手: ACK
- 被动断开方收到FIN包之后,发送一个ACK包,表示确认收到关闭请求。
- 发送完ACK包之后,被动断开方进入CLOSE_WAIT的状态。
- 第三次挥手: FIN
- 被动断开方在处理所有未完成的数据传输之后,会主动发送一个FIN包,表示自己已经准备好关闭连接请求了。
- 被动断开方会进入LAST_ACK状态,等待客户端的ACK请求。
- 第四次挥手: ACK
- 主动断开方在接受到 对方法来的FIN包时,会立即发送一个ACK包,确保让对方知道已经接受到对方的关闭请求。
- 发送ACK之后,主动断开方进入TIME_WAIT状态,等待一段时间以确保对方已经ACK,之后完全关闭连接。等待时间一般为2 * MSL(最大报文段存活时间),确保被动断开方能够收到ACK包(没有收到ACK包,被动断开方会重发FIN请求, 在2*MSL时间范围内)。
5. 基于TCP的应用层协议
- HTTP: 超文本传输协议,web
- HTTPS: 安全数据传输协议,web
- SSH: 安全外壳协议, Linux远程连接的协议
- Telnet:远程终端协议
- FTP:文件传输协议。
- SMTP:电子邮件传输协议
6. 基于TCP的主机探活 python实现
原理:TCP连接建立需要进行三次握手,直接向目标主机发送ACK数据包,目标 存活,会返回一个RST数据包终止这个不正常的TCP连接。也可以使用正常的三次握手步骤去探测主机存活。主要依据目标主机响应数据包中flags字段,如果flags字段有值,则表示主机存活。
flags字段值的范围和含义:
- SYN: 建立连接 0x02
- FIN: 关闭连接 0x10
- ACK: 应答 0x10
- PSH: 包含DATA数据传输 0x08
- RST: 连接重置 0x04
- URG: 紧急指针 0x20
python
from optparse import OptionParser
from random import randint
from scapy.layers.inet import *
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()
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 Scan(ip):
try:
# 随机目的端口可能会存在目标主机端口未开放
dport = randint(1, 65535)
packet = IP(dst=ip) / TCP(flags="S", dport=dport) # 构建标志为ACK的数据
response = sr1(packet, timeout=10.0, verbose=0)
if response:
if "SA" in response.getlayer(TCP).sprintf("%flags%"):
time.sleep(0.5)
print(ip + " is up")
else:
print(ip + " is down")
else:
print(ip + " connect fail")
except Exception as e:
print(e)
"""
发送TCP数据包 ACK包
"""
def send_tcp_data(address):
ip = IP(dst=address)
tcp = TCP()
r = (ip / tcp)
r[TCP].flags = "A"
r[TCP].dport = 21
a = sr1(r)
a.display()
if __name__ == "__main__":
main()