You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

桥接网络模式下UDP数据包无法路由问题排查求助

问题描述

我尝试通过主机向VirtualBox中的Windows Server 2019虚拟机发送UDP数据包,代码执行无报错,但虚拟机及主机的Wireshark均未捕获到数据包。主机与虚拟机可互相Ping通,采用桥接网络模式,且虚拟机防火墙已关闭。每次执行程序时会发送查询虚拟机IP的ARP包,但路由似乎失败导致UDP包无法到达目标。

原始代码

#include<stdio.h>
#include<stdlib.h>
#include<WinSock2.h>
#include<Ws2tcpip.h>
#include<iostream>
#include<tchar.h>
#define IN_PORT 8888
#define OUT_PORT 50

#pragma comment(lib,"ws2_32.lib") //Winsock Library
// 编译命令:gcc flood.cpp -lwsock32 -lstdc++
int main(){
    SOCKET s;
    struct sockaddr_in src,dst;
    WSADATA wsa;
    long long count = 0;
    const char* srcIP = "192.168.137.1";
    const char* dstIP = "192.168.137.71";
    const char* pkt = "This is a Probe";
    //Initialise winsock
    printf("\nInitialising Winsock...");
    if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
    {
        printf("Failed. Error Code : %d",WSAGetLastError());
        exit(EXIT_FAILURE);
    }
    src.sin_family = AF_INET;
    src.sin_addr.s_addr = inet_addr(srcIP);
    src.sin_port = htons(IN_PORT);
    
    dst.sin_family = AF_INET;
    dst.sin_addr.s_addr = inet_addr(dstIP);
    dst.sin_port = htons(OUT_PORT);

    if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR)
    {
        printf("socket() failed with error code : %d" , WSAGetLastError());
        exit(EXIT_FAILURE);
    }

    if( bind(s ,(struct sockaddr *)&src , sizeof(src)) == SOCKET_ERROR)
    {
        printf("Bind failed with error code : %d" , WSAGetLastError());
        exit(EXIT_FAILURE);
    }

    if (sendto(s, pkt, strlen(pkt), 0, (struct sockaddr*) &dst, sizeof(dst)) == SOCKET_ERROR)
    {
        printf("sendto() failed with error code : %d" , WSAGetLastError());
        exit(EXIT_FAILURE);
    }
    closesocket(s);
    WSACleanup();
    return 0;
}

编译命令

gcc flood.cpp -lwsock32 -lstdc++

排查与解决思路

1. 绑定的源IP不匹配通信网卡

你手动绑定了源IP 192.168.137.1,但主机桥接模式对应的物理网卡IP可能并非这个地址。绑定错误的源IP会导致系统无法正确选择出口网卡发送数据包。

  • 解决方式:
    • 直接删除代码中的bind相关逻辑,让系统自动选择合适的源地址和端口;
    • 或在主机上通过ipconfig确认桥接网卡的实际IP,替换代码中的srcIP。

2. 目标端口50的特殊性

UDP端口50是ESP(封装安全载荷)协议的默认端口,部分系统底层网络栈或设备会默认拦截该端口的流量,即使关闭防火墙也可能生效。

  • 解决方式:将目标端口更换为非特权常用端口(如8080、9000),修改代码中的OUT_PORT宏定义。

3. Wireshark抓包配置错误

  • 主机抓包时,确保选择桥接对应的物理网卡,而非WiFi、VPN等其他网卡;
  • 虚拟机抓包时,选择虚拟机的本地网卡,抓包过滤器直接用udp,避免误过滤目标流量。

4. VirtualBox桥接网络异常

  • 重启VirtualBox的网络服务,或重新配置桥接网络,确认选择了正确的物理网卡;
  • 临时切换虚拟机网络模式为NAT测试,验证UDP包是否能正常发送,排除桥接模式的特殊问题。

优化后的代码示例

移除不必要的绑定操作,让系统自动处理源地址:

#include<stdio.h>
#include<stdlib.h>
#include<WinSock2.h>
#include<Ws2tcpip.h>
#include<iostream>
#include<tchar.h>
#define OUT_PORT 8080 // 更换为非特权端口

#pragma comment(lib,"ws2_32.lib") //Winsock Library
// 编译命令:gcc flood.cpp -lwsock32 -lstdc++
int main(){
    SOCKET s;
    struct sockaddr_in dst;
    WSADATA wsa;
    const char* dstIP = "192.168.137.71";
    const char* pkt = "This is a Probe";
    
    printf("\nInitialising Winsock...");
    if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
    {
        printf("Failed. Error Code : %d",WSAGetLastError());
        exit(EXIT_FAILURE);
    }

    dst.sin_family = AF_INET;
    dst.sin_addr.s_addr = inet_addr(dstIP);
    dst.sin_port = htons(OUT_PORT);

    if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR)
    {
        printf("socket() failed with error code : %d" , WSAGetLastError());
        exit(EXIT_FAILURE);
    }

    if (sendto(s, pkt, strlen(pkt), 0, (struct sockaddr*) &dst, sizeof(dst)) == SOCKET_ERROR)
    {
        printf("sendto() failed with error code : %d" , WSAGetLastError());
        exit(EXIT_FAILURE);
    }
    printf("\nPacket sent successfully");
    closesocket(s);
    WSACleanup();
    return 0;
}

内容的提问来源于stack exchange,提问作者anonymous bear

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 05:37:44