发送自定义ICMP回显响应

3
我已经编写了一个ICMP客户端和一个ICMP监听程序。我可以向监听程序发送自定义的回显请求,并且监听程序可以正确地解包它们。现在,我希望监听程序响应不是精确的回显,而是使用不同的数据集进行响应。这是我目前尝试过的方法:
ICMP客户端:
    static void Main(string[] args)
    {
        Ping icmpClient = new Ping();
        PingOptions options = new PingOptions();
        options.DontFragment = true;
        byte[] msg = Encoding.UTF8.GetBytes("howdy pilgrim");

        while (true)
        {
            PingReply reply = icmpClient.Send("192.168.0.3", 60 * 1000, msg, options);
            string responseReceived = Encoding.UTF8.GetString(reply.Buffer);
            Console.WriteLine(DateTime.Now.ToString() + "    Response from server: " + responseReceived);
            Thread.Sleep(500);
        }
    }

ICMP监听器:
    static void Main(string[] args)
    {
        while (true)
        {
            Socket icmpListener = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
            icmpListener.Bind(new IPEndPoint(IPAddress.Parse("192.168.0.3"), 0));
            icmpListener.IOControl(IOControlCode.ReceiveAll, new byte[] { 1, 0, 0, 0 }, null);

            byte[] buffer = new byte[1024*1024];
            EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);               

            int bytesRead = icmpListener.ReceiveFrom(buffer, ref remoteEndPoint);
            string receivedMsg = Encoding.UTF8.GetString(buffer, 28, bytesRead);
            Console.WriteLine(DateTime.Now.ToString() + ": Received " + bytesRead + "B from " + remoteEndPoint + ": " + receivedMsg);

            byte[] customResponse = Encoding.UTF8.GetBytes("good day");
            int bytesSent = icmpListener.SendTo(customResponse, remoteEndPoint);        
        }
    }

这是监听器上出现的内容: enter image description here 这是客户端上出现的内容: enter image description here 因此,尽管向客户端发送了“good day”,但仍然收到“howdy pilgrim”。如何将“good day”发送回客户端?
3个回答

1

Fidel,你尝试过禁用系统上的ICMP回复吗?Linux有一个类似的参数来禁用这个功能,叫做“icmp_echo_ignore_all”,启用它可能会防止系统IP堆栈进行回复,如果您完全使用程序来制作icmp回复,则该回复可能不会被目标计算机视为重复。我知道你在使用Windows,但可能有替代方案,而且我从未尝试过这样做,但如果你必须使用icmp,我认为值得一试。


谢谢Moz!我得再调查一下Windows的情况——已经快10年没用了! - Fidel

1
我认为这可能与底层TCP/IP架构有关。 我认为在您的程序接收数据之前,ICMP层会回显ping数据包。 尝试注释发送回复的行,并查看客户端是否仍然收到回复。 如果是这种情况,我的建议是不要使用Ping-而是在特定端口上发送TCP数据包,并让监听器回复。
在.NET中,ICMP数据包非常棘手。 微软希望为您处理所有这些内容,因此与许多.NET实现一样,他们不想为您提供对底层协议的控制。

谢谢Zero。是的,如果我注释掉这行代码,响应仍然会被发送回来。所以你是对的 - 必须是操作系统的某个较低层在处理ping请求之前。我可以很容易地在TCP中做同样的事情,但我正在尝试组建一个ICMP隧道。 - Fidel
1
这是完全不同的IP协议。ICMP!= TCP。 - Martin James
确实,马丁。隧道的想法是将一个协议通过另一个协议传输... - Fidel
@Fidel,嘿,你解决问题了吗? - rudolfninja

0

当你ping远程主机时,你会自动收到响应。发送和接收的数据包之间的区别仅在于消息类型,在ping的情况下,消息类型可以是8、3或0。8是回显请求,0是回显回复,而类型3是目标不可达,这意味着没有找到响应。

要接收自定义响应,您需要实现类似于服务器上的监听器,并且摆脱PingReply。

您还需要创建一个类来生成自定义ICMP数据包,并可能更改其头(消息类型和代码),以便服务器不会自动响应回显请求。然后,当它接收到消息时,检查它是否具有正确的类型(由您在发送方声明)并发送响应。

但是-由于ICMP类型已经定义,可能没有真正的解决方案。(远程将始终根据请求发送回复。因此,发送另一条消息只是)

编辑

ICMP消息类型15(信息请求)不会从服务器中自动弹出响应。尝试将其用作您在服务器上侦听的ICMP消息类型,并且在客户端上,您也必须侦听ICMP。

顺便提一下,当您尝试从无法到达的目标获取响应时使用Ping.Send()方法,在进程等待远程响应时停止调试可能会导致蓝屏。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接