Interface UdpInterceptor

Functional Interface:
This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.

@FunctionalInterface public interface UdpInterceptor
Sees, rewrites, drops and adds the datagrams of UDP flows the proxy relays: the UDP counterpart of TcpInterceptor, as mitmproxy's udp_message hooks. Configure one per proxy with HttpProxyServerBootstrap.withUdpInterceptor(UdpInterceptor).

 bootstrap.withUdpInterceptor((message, ctx) -> message.fromClient() && message.length() > 1200
         ? null                                                        // drop
         : message.data());                                            // pass on
 

Which flows

Every CONNECT-UDP flow (MASQUE, RFC 9298) a client of the forward proxy's HTTP/3 listener opens: the client's UDP payloads, which arrive in HTTP Datagrams (QUIC DATAGRAM frames, or DATAGRAM capsules on the request stream), go to the target from a UDP socket of the flow's own, and the target's datagrams come back to the client the same way.

Messages

Unlike TCP, UDP keeps message boundaries: a UdpMessage is one datagram's payload, and what the hook returns is sent as one datagram. UDP is unreliable: the proxy drops datagrams when a flow's queue is full, as a network would, and so may the hook.

Each direction is handled by a thread of its own, so the hooks of one flow are called from two threads at once, and those of many flows concurrently: the interceptor must be thread-safe. Within a direction, calls come in order, and the direction waits for each one.

Every flow gets udpStart(org.microproxy.udp.UdpContext) first, then its messages, then udpEnd(org.microproxy.udp.UdpContext). A hook that throws is logged; a throwing udpMessage(org.microproxy.udp.UdpMessage, org.microproxy.udp.UdpContext) passes the datagram on unchanged.

  • Method Summary

    Modifier and Type
    Method
    Description
    default void
    udpEnd(UdpContext context)
    The flow ended: the client closed or reset its stream, the flow was idle for the idle timeout, or its socket failed.
    byte[]
    udpMessage(UdpMessage message, UdpContext context)
    A datagram from one side, before it is passed on.
    default void
    A flow opened: the client's CONNECT-UDP was accepted and the proxy's socket to the target is ready, nothing has been relayed yet.
  • Method Details

    • udpStart

      default void udpStart(UdpContext context)
      A flow opened: the client's CONNECT-UDP was accepted and the proxy's socket to the target is ready, nothing has been relayed yet. UdpContext.send(boolean, byte[]) may already send datagrams.
      Parameters:
      context - the flow
    • udpMessage

      byte[] udpMessage(UdpMessage message, UdpContext context)
      A datagram from one side, before it is passed on.
      Parameters:
      message - the payload, which side sent it and when
      context - the flow, and UdpContext.send(boolean, byte[]) to add datagrams
      Returns:
      the payload to send on as one datagram: message.data() as it is or changed in place, or other bytes (possibly empty, an empty datagram); null to drop it
    • udpEnd

      default void udpEnd(UdpContext context)
      The flow ended: the client closed or reset its stream, the flow was idle for the idle timeout, or its socket failed.
      Parameters:
      context - the flow