抓包分析DSCP字段在FTP协议中的应用
简介
本文介绍DSCP字段的作用,以及抓包分析DSCP字段在FTP协议中的应用。最后通过实验证明有可能DSCP字段实际上对普通用户没啥用,原因是运营商可能会将用户设置的DSCP字段重置。
DSCP
IP报文中有个TOS字段 ,TOS字段(Type of Service)是IP报文头部中的一个8位字段,用于指定IP数据包的服务类型或优先级。它可以用来指定数据包的延迟、吞吐量、可靠性或成本等方面的要求,以支持网络质量的不同需求。TOS字段已经被DSCP字段(Differentiated Services Code Point)所取代。
DSCP(Differentiated Services Code Point)是IP报文头部中的一个6位字段,用于指定IP数据包的服务类型或优先级。它可以用来指定数据包的延迟、吞吐量、可靠性或成本等方面的要求,以支持网络质量的不同需求。
DSCP字段可以组合成不同的服务等级(Service Level Agreement,SLA),以满足不同应用的需求。例如,视频应用需要低延迟和高带宽,而文件传输应用则需要高吞吐量和较低的成本。DSCP可以通过路由器、交换机等网络设备进行流量分析和分类,以实现不同服务等级的流量控制和优先级处理。
FTP协议中的DSCP
FTP协议中一般使用21端口传输控制指令,20端口传输数据。虽然FTP协议标准本身并没有规定各种数据包的优先级,但是按道理将传输指令的优先级应该较高,而传输数据的优先级较低,所以笔者猜想可能部分FTP实现会将传输控制的DSCP优先级设置得高一些。下面通过具体抓包分析验证下这个猜想。
下述实验所抓数据可在这里下载:linux和windows下分别wireshark抓包ftp协议
Linux下抓包
- 服务端:vsftpd
- 客户端: ftp命令
通过实际抓包发现,FTP request的DSCP为4,FTP data的DSCP为2,FTP Response的DSCP为0。
看起来像是印证了笔者的猜想:指令的优先级的确比数据优先级高。
但是,真的是所有的FTP实现都是如此吗?我们接下来再看windows下的抓包情况。
windows下抓包
- 服务端: windows自带的FTP服务
- 客户端: MobaXterm
通过抓包发现,windows下FTP的各种报文中的DSCP值都为默认值0。
RSTP协议中的DSCP
笔者又抓包发现RSTP协议中的指令等各种报文的DSCP的值也都是0.
真实场景下的DSCP
进一步地想,DSCP在实际用户场景中真的有作用吗?如果有作用的话,那我将我所有业务数据报文中的DSCP值都设为最高,是不是就可以保证我的数据在互联网中都以最高的优先级传输?那岂不是所有人都会将自己的数据包的优先级设置得很高?怀着这些疑问,笔者又进行了以下实验。
- 在腾讯云服务器上启动一个服务端,用于接收数据。代码如下:
python
import socket
HOST = '0.0.0.0' # 绑定所有可用的网络接口
PORT = 8080 # 监听的端口号
# 创建一个 TCP 套接字
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
# 绑定到指定的地址和端口
s.bind((HOST, PORT))
# 开始监听传入的连接
s.listen()
print(f'正在监听 {HOST}:{PORT}')
while True:
# 等待连接
conn, addr = s.accept()
print(f'已连接 {addr}')
with conn:
while True:
# 接收数据
data = conn.recv(1024)
if not data:
break # 如果没有数据了,退出循环
# 处理数据
print(f'接收到的数据: {data}')
response = b'Hello, client!'
# 发送响应
conn.sendall(response)
- 在本地机器启动一个客户端,设置DSCP值并向上述服务端传送数据,代码如下:
rust
use std::os::unix::prelude::AsRawFd;
use tokio::io::AsyncWriteExt;
use tokio::net::TcpStream;
#[tokio::main]
async fn main() {
let mut client = TcpStream::connect("118.24.148.33:8080").await.unwrap();
let dscp = 0x2E << 2; // DSCP为46(EF)
nix::sys::socket::setsockopt(client.as_raw_fd(), nix::sys::socket::sockopt::IpTos, &dscp)
.unwrap();
let buf = [0; 10];
// 发送
client.write_all(&buf[..10]).await.unwrap();
}
- 抓包分析
从上述代码中可以发现,客户端发出去时DSCP设置的是46,而笔者在服务端进行抓包却发现收到的报文中DSCP值却是26.
由此可见,用户设置的DSCP可能根本没啥用。在中间的网络节点中会被重置为其他值。笔者猜测为运营商的路由器之类的会将所有出口流量的DSCP重置为某些值,毕竟你没有额外花钱,凭什么优先传输的你的消息?