使用WinSock侦听任意ICMP超时(TTL = 0)报文
Listening for arbitrary ICMP Time Exceeded (TTL = 0) packets with WinSock
所以我的目标是使用WinSock和原始套接字来侦听所有ICMP超时数据包(当IP数据包的TTL达到0时由网关生成)。
我的第一种方法涉及2套接字,一个是UDP与TTL设置为2(几乎保证TTL达到0;wireshark确认了这一点),另一个是带有IPPROTO_ICMP的SOCK_RAW。
这种方法不起作用——我假设ICMP套接字只会返回与发送的数据包匹配的数据包(即,echo request -> echo reply)。将此方法进一步推进,我打开SIO_RCVALL(混杂模式-套接字接收所有内容)。几乎言出必行,我开始接收该套接字上的所有入站和出站数据包,除了ICMP超时(可能还有其他)。这可以通过让一个线程每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;
}
什么类型的机器监听你的UDP数据包?有些主机防火墙拒绝发送ICMP消息
相关文章:
- libcurl 和 DNS ttl 中的内部连接管理
- 自己的C++网络协议:如何定义唯一的二进制报文值
- 如何使用C++驱动程序在 mongodb 中设置 TTL
- 使用 TTL 的数据结构
- TTL::变体,放置新
- 32位二进制报文的异或反值
- 提振.ASIO UDP socket:接收所有报文
- c++不能接收udp报文(Socket)
- 如何重组TCP报文
- 本地套接字建立连接后,等待指定报文
- 发送IP报文
- 使用NS3协议通过UdpL4Protocol发送报文
- 使用Boost-ASIO协议搭建服务器,供Wireshark连接和接收报文
- 正在设置传出UDP数据包的TTL
- 为支持CNAME记录的记录配置TTL
- 在同一端口上发送和接收udp报文
- 将多种数据类型组合成一个报文
- XOR加密报文不能正常解密
- 发送udp报文到本地网络异常
- 使用WinSock侦听任意ICMP超时(TTL = 0)报文