桥接网络模式下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
相关产品推荐
相关产品推荐

