You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Linux环境下USB端口流量重定向、直通及数据修改的技术咨询

Linux环境下USB端口流量重定向、直通及数据修改的技术咨询

当然可以实现!你的需求本质上是让Linux机器充当一个USB中间代理——一端作为USB Host连接目标设备,另一端以USB Gadget身份模拟该设备,同时在中间层拦截、修改传输的数据。下面我会从硬件要求、核心实现思路到具体操作步骤给你拆解清楚:

一、硬件前提检查

首先得确认你的Linux机器具备同时运行USB Host和USB Gadget的硬件条件:

  • 你的机器需要至少两个独立的USB控制器:一个用于Host模式(连接外部USB设备),另一个支持Gadget模式(作为模拟设备对外连接)。可以用lsusb -tlspci命令查看控制器信息,比如树莓派4B的部分USB端口支持模式切换,x86机器通常有多个独立控制器。
  • 确保内核已启用USB Gadget相关模块:一般需要libcompositeusb_f_generic等模块,可通过modprobe libcomposite加载,或者在/etc/modules中配置开机自动加载。

二、核心技术栈与实现思路

你的需求需要三个核心环节:

  1. Gadget端模拟Host设备:通过Linux USB Gadget子系统,完全镜像Host端设备的硬件描述符(包括vendor ID、product ID、设备类、接口描述符等),让下游设备误以为连接的是原USB设备。
  2. Host端流量捕获:通过libusbusbmon捕获Host端与目标设备之间的所有USB传输数据包(控制、批量、中断等类型)。
  3. 数据转发与修改:在中间层对捕获到的数据包进行修改(增删改),再将处理后的数据包转发到Gadget端,同时反向处理Gadget端的请求并转发回Host端。

三、具体操作步骤

1. 捕获Host端设备的硬件信息

先连接目标USB设备到Host端口,用usb-devices命令获取设备的关键信息:

usb-devices

找到目标设备的idVendoridProductbcdDevice、设备类(bDeviceClass)等参数,这些是配置Gadget的核心依据。

2. 配置USB Gadget模拟原设备

以模拟一个通用USB设备为例,创建Gadget配置:

# 创建Gadget目录
mkdir -p /sys/kernel/config/usb_gadget/my_usb_proxy
cd /sys/kernel/config/usb_gadget/my_usb_proxy

# 设置设备ID(对应Host端设备的信息)
echo 0x1234 > idVendor  # 替换为实际的vendor ID
echo 0x5678 > idProduct # 替换为实际的product ID
echo 0x0100 > bcdDevice

# 配置字符串描述符
mkdir -p strings/0x409
echo "My USB Proxy" > strings/0x409/manufacturer
echo "Proxy Device" > strings/0x409/product

# 配置功能函数(这里用通用函数,根据设备类型调整,比如HID、存储等)
mkdir -p functions/generic.0
ln -s functions/generic.0 configs/c.1/

# 绑定到Gadget端口(替换为你的USB控制器,比如usb1)
echo "usb1" > UDC

3. 编写流量拦截与修改程序

libusb编写C程序(或Python的pyusb库)实现双向转发与修改,核心逻辑如下:

#include <libusb-1.0/libusb.h>

// 全局变量:Host端设备句柄、Gadget端设备句柄
libusb_device_handle *host_dev = NULL;
libusb_device_handle *gadget_dev = NULL;

// 处理Host端数据包的回调函数
int host_transfer_cb(struct libusb_transfer *transfer) {
    // 这里可以修改transfer->buffer中的数据
    if (transfer->endpoint == 0x01) { // 批量输出端点
        modify_data(transfer->buffer, transfer->actual_length);
    }

    // 将修改后的数据发送到Gadget端对应端点
    libusb_bulk_transfer(gadget_dev, transfer->endpoint, 
                        transfer->buffer, transfer->actual_length,
                        NULL, 0);

    // 重新提交传输,持续监听
    libusb_submit_transfer(transfer);
    return 0;
}

// 主函数:初始化设备、监听传输
int main() {
    libusb_init(NULL);
    // 打开Host端设备(替换为实际的VID/PID)
    host_dev = libusb_open_device_with_vid_pid(NULL, 0x1234, 0x5678);
    // 打开Gadget端设备(这里假设Gadget已配置为对应VID/PID)
    gadget_dev = libusb_open_device_with_vid_pid(NULL, 0x1234, 0x5678);

    // 配置Host端端点监听(以批量端点为例)
    struct libusb_transfer *host_xfer = libusb_alloc_transfer(0);
    unsigned char buffer[512];
    libusb_fill_bulk_transfer(host_xfer, host_dev, 0x81, // 批量输入端点
                            buffer, sizeof(buffer), host_transfer_cb,
                            NULL, 0);
    libusb_submit_transfer(host_xfer);

    // 事件循环,持续处理传输
    while (1) {
        libusb_handle_events(NULL);
    }

    libusb_close(host_dev);
    libusb_close(gadget_dev);
    libusb_exit(NULL);
    return 0;
}

(注:实际使用时需要根据设备的端点配置、传输类型调整代码,同时实现Gadget端到Host端的反向转发逻辑)

四、注意事项与兼容性问题

  • 权限问题:操作USB设备需要root权限,或者通过udev规则给普通用户授予USB设备的访问权限。
  • 复杂设备适配:对于加密狗、带自定义协议的工业外设等,可能需要更细致地处理控制传输的交互逻辑,确保设备枚举和正常工作。
  • 内核版本:建议使用4.14以上的Linux内核,USB Gadget子系统在新版本中功能更完善,兼容性更好。

备注:内容来源于stack exchange,提问作者Dennis Solomon

火山引擎 最新活动