通过wireshark简单了解S7协议
一方面本着学习wireshark的使用,一方面对S7协议想有一个更深入一点的了解。
1.建立连接过程:
一边是IPC,一边是PLC。
本着学习的态度,这里简单说明一下S7通信协议簇在ISO模型中的一个示意:
OSI layers | Protocol |
---|---|
7 APPlication Layer | S7 communication |
6 Presentation Layer | COTP(S7 communication) |
5 Session Layer | TPKT(S7 communication) |
4 Transport Layer | ISO-on-TCP |
3 Network Layer | IP |
2 Data Link Layer | Ethernet |
1 Physical Layer | Ethernet |
第1-4层是由计算机自己完成的(底层驱动)。
现在从Frame2-Frame4开始逐帧分析:
物理层数据帧:
这一行给出了物理层信息,其中没有中括号的是数据报文本身提取的一些信息,带有中括号的是根据报文整体的分析给出的辅助信息,虽然报文本身并不包含这些字段信息。.Frame 2: 66 bytes on wire (528 bits), 66 bytes captured (528bits) 2号帧,线路66字节,实际捕获528bits
.Encapsulation type: Ethernet (1) #封装类型,表示以太网的链路
.Arrival Time: 捕获日期和时间(中国标准时间)
.[Time shift for this packet: 0.000000000 seconds]
.Epoch Time: 绝对时间秒数(和前一种是不同的表达方式)
.[Time delta from previous captured frame: xx seconds] 此包与前一包时间间隔
.[Time delta from previous displayed frame: xx seconds]
.[Time since reference or first frame: xx seconds] 此包与第一个帧的时间间隔
.Frame Number: 2 帧序号
.Frame Length: 66 bytes (528 bits) 帧长度,数据的长度,是根据协议这种类格式中length所得到的长度,和后面的Capture Length长度是不同的。
.Capture Length: 66 bytes (528 bits) 在网卡上实际捕获的数据帧长度。通常情况下Frame Length和Capture Length 是相同的,但是如果Capture Length所捕获的数据有缺失,则Capture Length要比Frame Length要小一些。
.[Frame is marked: False] 此帧是否做了标记:否
.[Frame is ignored: False]
.[Protocols in frame: eth:ethertype:ip:tcp] 帧内封装的协议层次结构
.[Coloring Rule Name: HTTP] 用不同颜色的染色标记的协议名称:HTTP
.[Coloring Rule String: http || tcp.port == 80 || http2] 染色显示规则字符串Transmisssion control protocol
这一行描述的传输控制协议,这里主要做一下名词解释
.Source port:源端口51664
.Destination port:目的端口102
.Flags:0x002(SYN):表示表示建立连接。拓展一下,FIN表示关闭连接,ACK表示响应,PSH表示由DATA数据传输,RST表示连接重置。
- TCP connect
这三行,注意右边的info,他们表示经典的了TCP的三次握手过程。.Seq为序号,等下描述握手的时候会再讲到它
.Ack为确认号,也是个重要参数
.Win=64240表示窗口大小,理解为允许对方发送的最大数据量
.Len=0表示TCP数据部分长度
.MSS=1460表示最大报文长度
.WS=256表示窗口的放大倍数
.SACK_PERM表示通信双方均支持SACK机制
TCP采用三次握手来建立一个连接,其过程如下:第一次握手:主机A发送标志位SYN=1,主机B由SYN状态知道A要求建立连接,当前主机A的Sequence number=0,Acknowledgment number=0
第二次握手:主机B收到请求后,Sequence number=0,Acknowledgment number=1,主机B的SYN=1,ACK=1
第三次握手:主机A检查Acknowledgment number=1是否正确,以及ACK=1是否正确。主机B收到Seq值和Ack=1时表示连接建立成功
完成三次握手,主机A和主机B开始传数据
2. COTP协议
COTP协议的全称是connection-Oriented Transport Protocol,面向连接的传输协议。顾名思义,他必然是依赖连接的,所以在传输之前必然要先有类似TCP握手建立连接的过程的。
这里还是直接截图逐帧分析,概念光说太抽象:
注意看,两个COTP包里面,wireshark已经为我们标注出CR和CC,其实这里的CR就是connect request,CC就是connect confirm。一个表示请求连接,一个表示确认连接。这就是一个建立连接的过程。
其实在建立连接之后,还跟一个DT包,这个就是DATA的意思,表示在发送数据。
对于COTP而已,它的包有两种形态,叫做COTP连接包(COTP connection package)和COTP功能包(COTP function package)。
先来看看COTP连接包的几个关键参数:
.Length:数据的长度,不包括length这个字段本身(和profinet里面定义字段长度的风格一样)
.PDU type:这里是标志类型,0x0e就表示连接请求,我会在后面把PDU的常见类型码例举出来。
.Destination reference:目标的引用,可以认为是用来唯一标志目标的
.Source reference:源的引用,可以认为是用来唯一标志目标的
.Option:占用1byte,高4位是标志类别class,倒数第二位是拓展样式,倒数第一位表示是否有明确的指定流控制。
.Parameter:附加的参数字段,每个参数又有几个字段构成。字段code=0xC0表示tpdu-size,就是数传数据的大小;code=0xC1表示src-tsap;code=0xC2表示dst-tsap
.TSAP:一般在西门子里面,TSAP表示的是连接资源的地址,有两个,一个是Local tsap,表示采集程序的地址,一个是Remote tsap,大概相当于PLC的地址。所以从这个解释来看,code的tsap参数可能是表示的源和目标的地址。
对于COTP功能包而已,其实好像没啥看的,具体也就那么些东西:
.length:长度
.PDU type:标志类型
.Option:第一位标志是否是最后一个包(从这看出来COPT协议当数据较多的时候会拆开来做单元传输),后面7个位表示的是TPDU的number.
现在开始分别贴一下COTP连接包和功能包的PDU TYPE吧:
- COTP连接包
Code | info |
---|---|
0x1 | ED Expedited data,加急数据 |
0x2 | EA Expedited data acknowledgement,加急数据确认 |
0x4 | UD,用户数据 |
0x5 | RJ Reject,拒绝 |
0x6 | AK Data acknowledgement,数据确认 |
0x7 | ER TPDU Error,TPDU错误 |
0x8 | DR Disconnect Request,断开请求 |
0xC | DC Disconnect Confirm,断开确认 |
0xD | CC Connect Confirm,连接确认 |
0xE | CR Connect Request,连接请求 |
0xF | DT data,数据传输 |
- COTP功能包(其实和上面是一样的)
Code | info |
---|---|
0x1 | ED Expedited data,加急数据 |
0x2 | EA Expedited data acknowledgement,加急数据确认 |
0x4 | UD,用户数据 |
0x5 | RJ Reject,拒绝 |
0x6 | AK Data acknowledgement,数据确认 |
0x7 | ER TPDU Error,TPDU错误 |
0x8 | DR Disconnect Request,断开请求 |
0xC | DC Disconnect Confirm,断开确认 |
0xD | CC Connect Confirm,连接确认 |
0xE | CR Connect Request,连接请求 |
0xF | DT data,数据传输 |
3. TPKT协议
TPKT叫做transport service ontop of the TCP。顾名思义,就是在TCP之上的传输服务,它是为了在TCP和COTP之间建立桥梁的。其实在讲COTP之前应该先讲TPKT的。
TPKT一般和COTP一起发送,当作COTP的header段。
下面贴个图,这个结构很简单没什么好讲的:
.version:版本号
.reserved:保留
.length:总长度
4. S7 communication协议
终于讲到S7COMN了,这对于我来说是个很神奇的黑科技。因为我就是通过它直接读到了PLC数据的绝对地址。
S7COMM协议包含3个部分:
- Header
- Parameter
- Data
先讲Header,格式如下:
Protocol ID | PDU TYPE | reserved | PDU reference | param length | data length | error class | error code |
---|
贴图如下,逐一解释:
.Protocol ID:协议ID,通常就是0x32
.ROSCTR:常用的几个:=0x01,表示JOB,作业请求;=0x02,表示ACK,确认响应;=0x03,表示ACK_DATA,确认数据响应;=0x07,表示USERDATA,原始协议的拓展(像啥安全功能,时间设置,循环读取..);
.Redundancy identification(reserved):冗余数据,通常就是0x0000
.Protocol data unit reference:协议数据单元参考,通过请求时间增加
.param length:参数长度
.data length:数据长度,如果是PLC内部数据就是0x0000,对于其他功能,就是Data部分的长度。
其中最重要的就是ROSCTR,它决定了后续参数的结构。
比如在Job中的结构:
又比如在ACK_Data中的结构:
你看出区别来了吗?
继续讲Parameter,这个比较复杂多变。在PDU类型是Job和ACK时格式如下:
function code | reserved | Max AmQ calling | Max AmQ called | PDU length |
---|
job:
ack_data:
当PDU类型是Job时参数为Read Var[0x40]格式如下:
function | item count | item 1 | … | item n |
---|
其中item的格式又如下:
specification type | length | syntax ID | transport sizes | request data length | DB number | Area | Adderss |
---|
还是截图说吧,看格式有点抽象:
.Variable specification:确定项目结构的主要类型,通常就是0x12
.Length of following address specification,本Item其余部分的长度
.Syntax Ids of variable specification,确定寻址模式和其余项目结构的格式
.Transport sizes in item data,确定变量的类型和长度
.Request data length,请求的数据长度
. DB number,DB模块的编号,如果访问的不是DB区域,此处为0x0000
.Area,区域类型
上面说的是当PDU为Job时,S7COMMN的结构,那当PDU为ACK_DATA时结构又是怎么样的呢?我们不说虚的,直接截图:
是的,其Parameter只有function、item count两个字段。
继续,那么接下来的是Data啦!
.Return code,返回代码
.Transport size,数据的传输尺寸
. Length,数据的长度
当值写入Write Var[0x50]的时候,其实情况和Read Var的时候差不多。这里就不多赘述了,用wireshark一抓就知道了。
5. 小结
对于整个S7协议簇在ISO七层网络架构里面的分类其实很简单了,格式如下:
Ethernet | Ip | TCP | TPKT | ISO-COTP | S7COMM |
---|
截图说明会更直观:
我的S7协议简单分析就到这里就结束了,全当是个人学习和总结记录。本文讲的都是走马观花,往深了讲的话每一个参数和功能码类型都有很多的东西,这个时候就需要去看S7的手册和文档了。
我比较喜欢一个看法,对技术要有敬畏之心,每一门技术都是无数聪明的脑子共同呈现的结果,我们站在巨人的肩膀上,我们无时无刻不在追逐前人的步伐。
学无止境。