所以我的目标是使用WinSock和原始套接字来侦听所有ICMP Time Exceeded数据包(当IP数据包的TTL达到0时由网关生成)。
我的第一个方法涉及2个套接字,一个是UDP,TTL设置为2(几乎保证TTL达到0; wireshark证实了这一点),另一个是SOCK_RAW和IPPROTO_ICMP。
这种方法不起作用 - 我假设ICMP套接字只返回与发送数据包匹配的数据包(即echo请求 - > echo回复)。 推进这个方法,我打开了SIO_RCVALL(混杂模式 - socket接收所有)。 几乎是真的,我开始接收该套接字上的所有入站和出站数据包,但ICMP Time Exceeded(可能还有其他数据)除外。这通过让一个线程每5秒发送一个TTL 2的UDP数据包来显示,但是没有返回ICMP数据包。为了证明ICMP实际上已经出现,我能够观察到cmd中简单ping的ICMP数据包。
我的第二种方法是将UDP和ICMP放在同一个套接字上。这涉及到我制作IP和UDP标头。 Wireshark显示UDP正在运行,正如预期的那样,没有创建数据包的问题(校验和等),并且还显示返回的ICMP超时数据包,但是我再也看不到任何ICMP流量来自我的套接字(除此之外,当我测试ICMP正在使用简单的ping时。)
所以我的问题是,你怎么能得到这些数据包?我已经看过一个简单的tracert程序源代码,但是我在那里看不到任何我做得太差异的东西了。
SOCKET s;
if((s = socket(AF_INET, SOCK_RAW, 0)) == SOCKET_ERROR)
{
cout << "socket(AF_INET, SOCK_RAW, 0) failed with error code: " << WSAGetLastError() << endl;
return 1;
}
sockaddr_in source;
memset(&source, 0, sizeof(source));
source.sin_family = AF_INET;
source.sin_port = 0;
source.sin_addr.S_un.S_addr = inet_addr("10.64.0.8");
if(bind(s, (sockaddr*) &source, sizeof(source)) == SOCKET_ERROR)
{
cout << "bind failed with error: " << WSAGetLastError() << endl;
return 1;
}
uint32_t optval = 1;
DWORD bytesReturned;
if (WSAIoctl(s, SIO_RCVALL, &optval, sizeof(optval), NULL, 0, &bytesReturned, NULL, NULL) == SOCKET_ERROR)
{
cout << "WSAIotcl() failed with error code " << WSAGetLastError() << endl;
return 1;
}
if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char*) &optval, sizeof(optval)) == SOCKET_ERROR)
{
cout << "Failed to remove IP header. Error code: " << WSAGetLastError() << endl;
return 1;
}
if(WSARecvFrom(s, &buffer, 1, &in, &flags, (sockaddr*) &from, &fromSize, &ol, NULL) == SOCKET_ERROR)
{
int error = WSAGetLastError();
if(error != WSA_IO_PENDING)
{
cout << "WSARecvFrom Failed with error code: " << error << endl;
return;
}
}
int rc = WaitForSingleObject(ol.hEvent, INFINITE);
if(rc == WAIT_FAILED)
{
cout << "Wait for object failed" << endl;
return;
}
WSAGetOverlappedResult(s, &ol, &in, false, &flags);
ipv4_header_t* ipHeader = (ipv4_header_t*) buf;
if(ipHeader->dest == addr)
{
cout << "Received Protocol: " << (uint32_t) ipHeader->protocol << endl;
}
答案 0 :(得分:0)
什么是收听UDP数据包的机器类型?一些主机防火墙拒绝发送ICMP消息