# nat_discory **Repository Path**: wu_qz/nat_discovery ## Basic Information - **Project Name**: nat_discory - **Description**: 局域网内物理机和宿主机内的NAT网络的VMware虚拟机之间NAT UDP打洞 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-05-31 - **Last Updated**: 2026-05-31 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # NAT设备发现工具 一个基于Qt的局域网设备发现工具,支持NAT穿透,可用于WebRTC P2P连接。 ## 功能特性 ### 1. 设备发现 - 自动发现局域网内的设备 - 获取设备的IP地址和端口 - 支持设备ID标识 ### 2. NAT穿透 - 自动检测NAT映射地址 - 支持对称型NAT穿透 - 向NAT映射端口发送数据,实现双向通信 ### 3. 网络信息获取 - 获取本机所有局域网IPv4地址 - 自动过滤虚拟网卡(VMware、VirtualBox、Hyper-V等) - 过滤虚拟网卡IP段(192.168.56.x、192.168.229.x等) - 显示详细的网卡信息 ### 4. WebRTC集成支持 - 发现的NAT映射地址可直接用于生成srflx ICE候选 - 提高WebRTC P2P连接成功率 ## 编译要求 - Qt 5.x 或 Qt 6.x - CMake 3.16+ - C++11 或更高版本 ## 编译 ```bash mkdir build cd build cmake .. cmake --build . --config Debug ``` ## 使用方法 ### 基本用法 ```bash # 物理机 LANDiscovery.exe --id physical_pc --target 192.168.31.140 # 虚拟机(NAT模式) LANDiscovery.exe --id virtual_machine --target 192.168.31.62 ``` ### 命令行参数 | 参数 | 说明 | 必需 | |------|------|------| | `--id ` | 设备唯一标识 | 是 | | `--target ` | 目标设备IP地址 | 是 | | `--interval ` | 发送间隔(毫秒),默认5000 | 否 | | `--help` | 显示帮助信息 | 否 | ## 工作原理 ### NAT穿透流程 ``` ┌─────────────────────────────────────────────────────────────────────┐ │ NAT穿透流程 │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ 1. 虚拟机发送数据包 │ │ 内部: 192.168.229.128:44556 → NAT → 192.168.31.140:56072 │ │ 目标: 192.168.31.62:44556 │ │ │ │ 2. 物理机收到数据包,获取NAT映射地址 │ │ senderIP = 192.168.31.140 │ │ senderPort = 56072 ← NAT映射端口 │ │ │ │ 3. 物理机向NAT映射端口回复 │ │ 发送到: 192.168.31.140:56072 │ │ │ │ 4. NAT转发给虚拟机 │ │ 192.168.31.140:56072 → NAT → 192.168.229.128:44556 │ │ │ │ ✅ 双向通信成功! │ │ │ └─────────────────────────────────────────────────────────────────────┘ ``` ### 关键点 1. **对称型NAT特性**:NAT映射端口与目标地址绑定 2. **端口发现**:通过接收数据包获取NAT映射端口 3. **正确回复**:向NAT映射端口发送数据,而非默认端口 ## 输出示例 ``` ======================================== NAT设备发现工具 ======================================== 设备ID: "physical_pc" 目标IP: "192.168.31.140" 发送间隔: 5000 ms ======================================== ========== 本机网络信息 ========== 网卡名称: "wireless_32768" 友好名称: "WLAN" 类型: 物理网卡 IPv4地址: ("192.168.31.62") ---------------------------------- 有效局域网IPv4地址: - "192.168.31.62" ================================== 开始监听端口: 44556 发送成功,79 字节到 "192.168.31.140":44556 ========== 收到消息 ========== 设备ID: "virtual_machine" IP: "192.168.31.140" 端口: 56072 ============================== *** 检测到NAT映射 *** 对方NAT地址: 192.168.31.140:56072 重要:必须向此端口发送才能穿透NAT! >>> 向端口 56072 发送回复 <<< 发送成功,79 字节到 "192.168.31.140":56072 ``` ## API接口 ### NATDiscovery类 ```cpp // 启动服务 void start(const QString &deviceId, const QString &targetIP, int interval = 5000); // 获取本机首选IP QString getLocalIP() const; // 获取所有局域网IPv4地址 QStringList getAllLocalIPs() const; // 打印网络信息 void printNetworkInfo() const; // 发送数据 void sendData(const QString &targetIP, quint16 targetPort); // 发现设备信号 void deviceFound(const QString &ipAddress, quint16 port, const QString &deviceId); ``` ## WebRTC集成 发现的NAT映射地址可用于生成ICE候选: ```cpp // 获取NAT映射地址 QString natIP = "192.168.31.140"; // 从deviceFound信号获取 quint16 natPort = 56072; // 从deviceFound信号获取 // 生成srflx ICE候选 QString candidate = QString( "candidate:1 1 udp 1685987071 %1 %2 typ srflx" ).arg(natIP).arg(natPort); // 添加到PeerConnection peerConnection->AddIceCandidate(candidate); ``` ## 支持的虚拟网卡 自动识别并过滤以下虚拟网卡: - VMware (VMnet1, VMnet8) - VirtualBox (Host-Only, NAT) - Hyper-V - Docker - 其他虚拟网络接口 ## 许可证 MIT License