programmatically handling ICMP packets

19 views
Skip to first unread message

Kōshin

unread,
Dec 26, 2024, 8:54:51 AM12/26/24
to gVisor Users [Public]
Is there any way that I can handle ICMP packets programmatically, bypassing gvisor's automatic processing (e.g. replying to ICMP echo requests)? What I have is this:

    mystack.SetTransportProtocolHandler(icmp.ProtocolNumber4, func(id stack.TransportEndpointID, pb *stack.PacketBuffer) bool {
        return true
    })

I was expecting that this would eliminate gvisor's automatic ICMP replies, but it so far as I can tell, gvisor still responds to echo requests with echo replies. What I'd like is to parse the packet buffer myself and formulate echo replies conditional on some business logic (specifically, I plan to proxy the ICMP messages over to a separate connection).

Lucas Manning

unread,
Dec 30, 2024, 1:50:16 PM12/30/24
to Kōshin, gVisor Users [Public]
Hi Kōshin,

If there is a valid ICMP endpoint in the stack, then gVisor will forward the packets to that endpoint, even if you've set up a custom transport handler. Transport layer delivery logic happens in the  DeliverTransportPacket method defined here, The method checks if there's an endpoint to deliver to first, and if there is it passes the packet off to it and returns. Only if there is not an endpoint to deliver to does it invoke the custom handler which is set here.

I'm not sure of your setup, but if you can prevent other ICMP endpoints from being created you should be able to receive and process packets from your custom handler reliably.

Hope that helps.

- Lucas



--
You received this message because you are subscribed to the Google Groups "gVisor Users [Public]" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gvisor-users...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/gvisor-users/CAPhZ8geJ5K9auNVGao%2B3TyGcmDommcf-K4tw%3DM-DWqKSyyVaKQ%40mail.gmail.com.

Kōshin

unread,
Dec 31, 2024, 10:59:26 AM12/31/24
to Lucas Manning, gVisor Users [Public]
Ah - very helpful to know where to find that code. Thanks.

Is it possible that the stack creates ICMP endpoints automatically? I don't create any ICMP endpoints in the code I've written, but I still get replies to ICMP echo requests.

Lucas Manning

unread,
Jan 2, 2025, 2:42:18 PMJan 2
to Kōshin, gVisor Users [Public]
> Is it possible that the stack creates ICMP endpoints automatically?

I don't think so. Also, my initial response was slightly incorrect. Yes, those handlers will pass your ICMP packets to a transport endpoint (if it exists) and your custom handler otherwise. But the code also falls through to generate an echo reply at the network layer, which you can see here and here. The reply is generated outside the view of your custom handler.

To implement the behavior you're looking for you could fork gVisor, rip up all that ICMP handling code in tcpip/network/ipv4/icmp.go, and add your own implementation. Or, if you are inclined, you could extend the IPv4 protocol to allow for a custom ICMP handler, configured by an option that you add here. The latter would be something that could be upstreamed into gVisor.

- Lucas

Kōshin

unread,
Jan 3, 2025, 8:15:12 AMJan 3
to Lucas Manning, gVisor Users [Public]
Thanks Lucas, very helpful.

Would it just be a matter of adding a field "HandleICMP func(*stack.PacketBuffer)" to ipv4.Options and hooking it up in the right place? Or does ipv4.Options need to be serializable?

Lucas Manning

unread,
Jan 3, 2025, 12:50:17 PMJan 3
to Kōshin, gVisor Users [Public]
I would try to follow roughly the same pattern as `stack.SetTransportProtocolHandler(...)`. So something like `stack.SetICMPHandler(tcpip.NetworkProtocolNumber, func(*stack.PacketBuffer))` with all the necessary plumbing to get that method to where the ICMP handling currently is.
Reply all
Reply to author
Forward
0 new messages