xrdp网络协议分析工具:自定义Wireshark解析器

xrdp网络协议分析工具:自定义Wireshark解析器

【免费下载链接】xrdp xrdp: an open source RDP server 【免费下载链接】xrdp 项目地址: https://gitcode.com/gh_mirrors/xrd/xrdp

1. RDP协议分析痛点与解决方案

远程桌面协议(Remote Desktop Protocol,RDP)作为Windows系统默认的远程控制协议,在跨平台远程管理场景中被广泛使用。xrdp作为开源RDP服务器实现,其协议交互过程包含大量私有字段和扩展结构,使用标准Wireshark解析时往往面临以下问题:

  • 协议字段解析不全:Wireshark原生RDP解析器对xrdp私有扩展支持有限
  • 数据流关联困难:RDP会话中交织的控制流与数据流难以区分
  • 性能问题定位复杂:无法直观识别影响用户体验的协议瓶颈点

本文将详细介绍如何基于xrdp源码实现自定义Wireshark解析器,通过协议字段映射、PDU类型识别和数据流可视化,构建完整的RDP协议分析能力。

2. RDP协议结构与xrdp实现

2.1 RDP协议栈层次

RDP协议基于多层结构实现,从xrdp源码中可以梳理出清晰的协议栈层次:

mermaid

关键协议层解析

  • TPKT层:定义于libxrdp/xrdp_rdp.c,使用3字节头部(版本+长度)
  • X.224层:实现连接建立与释放,在libxrdp/xrdp_iso.c中处理
  • MCS层:提供多点通信服务,支持通道复用,对应libxrdp/xrdp_mcs.c

2.2 核心PDU类型与格式

通过分析common/ms-rdpbcgr.h头文件,xrdp支持的主要PDU类型包括:

PDU类型常量十六进制值功能描述
PDUTYPE_DEMANDACTIVEPDU0x1会话激活请求
PDUTYPE_CONFIRMACTIVEPDU0x3会话激活确认
PDUTYPE_DATAPDU0x7数据传输单元
PDUTYPE_SERVER_REDIR_PKT0xA服务器重定向包

每个PDU包含固定头部和可变数据部分,以Data PDU为例,其结构定义于xrdp_rdp_send_data函数:

// 简化自libxrdp/xrdp_rdp.c
out_uint16_le(s, len);               // 总长度
out_uint16_le(s, 0x10 | pdu_type);   // PDU类型(高4位为版本)
out_uint16_le(s, self->mcs_channel); // 通道号
// TS_SHAREDATAHEADER
out_uint32_le(s, self->share_id);    // 共享ID
out_uint8(s, 0);                     // 填充
out_uint8(s, 1);                     // 流ID
out_uint16_le(s, dlen);              // 未压缩长度
out_uint8(s, data_pdu_type);         // 数据PDU类型
out_uint8(s, ctype);                 // 压缩类型
out_uint16_le(s, clen);              // 压缩后长度

3. Wireshark解析器开发基础

3.1 解析器开发框架

Wireshark使用C语言插件架构,自定义解析器需要实现以下核心函数:

// 协议注册函数
void proto_register_rdp_xrdp(void) {
    static hf_register_info hf[] = {
        { &hf_rdp_pdu_type,
            { "PDU Type", "rdp.xrdp.pdu_type", FT_UINT16, BASE_HEX,
              VALS(pdu_type_vals), 0x000F, "PDU类型", HFILL }},
        // 其他字段注册...
    };
    
    static gint *ett[] = { &ett_rdp_xrdp, &ett_rdp_xrdp_pdu };
    proto_rdp_xrdp = proto_register_protocol("xrdp Extended RDP", "xrdp", "xrdp");
    proto_register_field_array(proto_rdp_xrdp, hf, array_length(hf));
    proto_register_subtree_array(ett, array_length(ett));
}

//  dissector函数
static int dissect_rdp_xrdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
    // 协议解析逻辑
    proto_item *ti = proto_tree_add_item(tree, proto_rdp_xrdp, tvb, 0, -1, ENC_NA);
    proto_tree *rdp_tree = proto_item_add_subtree(ti, ett_rdp_xrdp);
    
    // 解析PDU类型字段
    guint16 pdu_type = tvb_get_letohs(tvb, 2);
    proto_tree_add_item(rdp_tree, hf_rdp_pdu_type, tvb, 2, 2, ENC_LITTLE_ENDIAN);
    
    // 根据PDU类型调度不同解析逻辑
    switch(pdu_type & 0x000F) {
        case PDUTYPE_DATAPDU:
            dissect_rdp_datapdu(tvb, pinfo, rdp_tree);
            break;
        // 其他PDU类型处理...
    }
    return tvb_captured_length(tvb);
}

3.2 关键数据结构映射

从xrdp源码提取的核心数据结构需要映射为Wireshark字段:

  1. RDP头部结构(定义于libxrdp/xrdp_rdp.cxrdp_rdp_send函数):

    • 总长度(2字节,小端序)
    • PDU类型(2字节,低4位有效)
    • 通道号(2字节)
  2. 安全层标志common/ms-rdpbcgr.h):

    #define SEC_EXCHANGE_PKT 0x0001
    #define SEC_ENCRYPT 0x0008
    #define SEC_INFO_PKT 0x0040
    
  3. 快速路径更新头部xrdp_rdp_send_fastpath函数):

    updateHeader = (updateCode & 15) | ((fragmentation & 3) << 4) | ((compression & 3) << 6);
    

4. 自定义解析器实现步骤

4.1 协议字段定义

基于xrdp源码中的协议常量,在Wireshark解析器中定义对应的字段解析规则。以PDU类型解析为例:

// PDU类型值表,对应ms-rdpbcgr.h中的定义
static const value_string pdu_type_vals[] = {
    { PDUTYPE_DEMANDACTIVEPDU, "Demand Active PDU" },
    { PDUTYPE_CONFIRMACTIVEPDU, "Confirm Active PDU" },
    { PDUTYPE_DATAPDU, "Data PDU" },
    { PDUTYPE_SERVER_REDIR_PKT, "Server Redirect PDU" },
    { 0, NULL }
};

// 注册PDU类型字段
{ &hf_rdp_pdu_type,
    { "PDU Type", "rdp.xrdp.pdu_type", FT_UINT16, BASE_HEX,
      VALS(pdu_type_vals), 0x000F, "RDP PDU类型", HFILL }},

4.2 PDU解析逻辑实现

针对不同PDU类型实现专项解析逻辑,以Data PDU为例:

static void dissect_rdp_datapdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
    // 跳过已解析的基础头部(6字节)
    int offset = 6;
    
    // 解析TS_SHAREDATAHEADER(18字节)
    guint32 share_id = tvb_get_letohl(tvb, offset);
    proto_tree_add_item(tree, hf_rdp_share_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
    offset += 4;
    
    // 跳过填充字节
    offset += 1;
    
    // 流ID
    guint8 stream_id = tvb_get_guint8(tvb, offset);
    proto_tree_add_item(tree, hf_rdp_stream_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
    offset += 1;
    
    // 未压缩长度
    guint16 uncompressed_len = tvb_get_letohs(tvb, offset);
    proto_tree_add_item(tree, hf_rdp_uncompressed_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
    offset += 2;
    
    // 数据PDU类型
    guint8 data_pdu_type = tvb_get_guint8(tvb, offset);
    proto_tree_add_item(tree, hf_rdp_data_pdu_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
    offset += 1;
    
    // 根据数据PDU类型进一步解析负载
    switch(data_pdu_type) {
        case PDUTYPE2_UPDATE:
            dissect_rdp_update_pdu(tvb, pinfo, tree, offset);
            break;
        case PDUTYPE2_INPUT:
            dissect_rdp_input_pdu(tvb, pinfo, tree, offset);
            break;
        // 其他数据PDU类型处理...
    }
}

4.3 快速路径解析

xrdp中的快速路径(Fast-Path)协议处理在xrdp_rdp_send_fastpath函数中实现,对应的Wireshark解析逻辑:

static void dissect_rdp_fastpath(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
    int offset = 0;
    guint8 update_header = tvb_get_guint8(tvb, offset);
    offset += 1;
    
    // 解析updateHeader字段
    guint8 update_code = update_header & 0x0F;
    guint8 fragmentation = (update_header >> 4) & 0x03;
    guint8 compression = (update_header >> 6) & 0x03;
    
    proto_tree_add_item(tree, hf_rdp_fastpath_update_code, tvb, offset-1, 1, ENC_LITTLE_ENDIAN);
    proto_tree_add_item(tree, hf_rdp_fragmentation, tvb, offset-1, 1, ENC_LITTLE_ENDIAN);
    proto_tree_add_item(tree, hf_rdp_compression, tvb, offset-1, 1, ENC_LITTLE_ENDIAN);
    
    // 压缩标志存在时解析
    if (compression != 0) {
        guint8 comp_type = tvb_get_guint8(tvb, offset);
        proto_tree_add_item(tree, hf_rdp_comp_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
        offset += 1;
    }
    
    // 数据长度
    guint16 data_len = tvb_get_letohs(tvb, offset);
    proto_tree_add_item(tree, hf_rdp_data_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
    offset += 2;
    
    // 根据update_code解析后续数据
    switch(update_code) {
        case FASTPATH_UPDATETYPE_BITMAP:
            dissect_rdp_fastpath_bitmap(tvb, pinfo, tree, offset);
            break;
        case FASTPATH_UPDATETYPE_ORDERS:
            dissect_rdp_fastpath_orders(tvb, pinfo, tree, offset);
            break;
        // 其他更新类型处理...
    }
}

4.4 协议解析器注册

完成字段定义和解析逻辑后,将自定义解析器注册到Wireshark框架:

// 协议处理函数表
static dissector_handle_t rdp_xrdp_handle;

void proto_register_rdp_xrdp(void) {
    // 字段和子树注册...
    
    rdp_xrdp_handle = create_dissector_handle(dissect_rdp_xrdp, proto_rdp_xrdp);
}

void proto_reg_handoff_rdp_xrdp(void) {
    // 将自定义解析器附加到RDP协议
    dissector_add_for_decode_as_with_preference("tcp", rdp_xrdp_handle);
    
    // 或者替换默认RDP解析器
    dissector_add("rdp", proto_rdp_xrdp, rdp_xrdp_handle);
}

5. 解析器测试与验证

5.1 测试环境搭建

  1. 抓包环境配置

    # 安装xrdp测试环境
    sudo apt install xrdp wireshark
    
    # 启动xrdp服务
    sudo systemctl start xrdp
    
    # 使用tcpdump抓取RDP流量
    sudo tcpdump -i any port 3389 -w xrdp_traffic.pcap
    
  2. 测试会话建立: 使用Windows远程桌面客户端连接xrdp服务器,执行典型操作(如文件传输、窗口调整)以生成多样化的RDP流量。

5.2 解析效果验证

使用开发的自定义解析器打开捕获文件,验证以下关键功能:

  1. PDU类型识别:确认所有xrdp支持的PDU类型都能正确识别
  2. 字段解析完整性:检查common/ms-rdpbcgr.h中定义的关键字段是否都能解析
  3. 数据流关联:验证MCS通道与PDU的正确对应关系

预期解析效果

xrdp Extended RDP
    PDU Type: Data PDU (0x7)
    Share ID: 66538
    Stream ID: 1
    Uncompressed Length: 148
    Data PDU Type: Update (0x2)
    Compression Type: 0x8000
    Compressed Length: 96
    Update Type: Orders (0x0)
    ...

6. 高级功能扩展

6.1 性能分析扩展

基于解析器实现RDP会话性能指标提取:

// 计算平均PDU大小
static void calculate_pdu_metrics(packet_info *pinfo, guint pdu_len) {
    static guint total_pdu = 0;
    static guint total_bytes = 0;
    
    total_pdu++;
    total_bytes += pdu_len;
    
    // 每100个包更新一次统计信息
    if (total_pdu % 100 == 0) {
        double avg_size = (double)total_bytes / total_pdu;
        expert_add_info_format(pinfo, NULL, PI_NOTE, PI_RESPONSE_TIME,
                              "RDP Performance: Average PDU size %.2f bytes", avg_size);
    }
}

6.2 异常检测实现

基于xrdp协议规范实现异常检测逻辑:

// 检测异常PDU大小
if (uncompressed_len > 1024*1024) {
    expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR,
                          "异常PDU大小: %d bytes (超过1MB阈值)", uncompressed_len);
}

// 检测不支持的PDU类型
if (!try_val_to_str(pdu_type, pdu_type_vals)) {
    expert_add_info_format(pinfo, tree, PI_UNDECODED, PI_WARN,
                          "未知PDU类型: 0x%04x", pdu_type);
}

7. 总结与展望

通过本文介绍的方法,我们基于xrdp源码实现了完整的RDP协议自定义解析器,解决了开源RDP服务器协议分析的关键痛点。该解析器不仅能够解析标准RDP协议字段,还能正确识别xrdp特有的私有扩展,为xrdp开发和运维提供了强大的协议分析工具。

未来扩展方向

  1. 虚拟通道解析:实现对cliprdrrdpsnd等虚拟通道的深度解析
  2. 性能可视化:开发Wireshark统计插件,直观展示RDP会话质量指标
  3. 动态协议更新:设计基于xrdp源码自动生成解析规则的工具链

通过持续优化解析器,可进一步提升xrdp协议调试效率,加速问题定位,为开源远程桌面生态的发展提供有力支持。

【免费下载链接】xrdp xrdp: an open source RDP server 【免费下载链接】xrdp 项目地址: https://gitcode.com/gh_mirrors/xrd/xrdp

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值