masque_udp_bind_proxy_handler (masque v0.7.0)

View Source

Default Connect-UDP-Bind handler. Owns the per-session upstream gen_udp socket, computes the Proxy-Public-Address list for the response, gates inbound packets via peer_filter_fun, and emits actions for the bind session to put on the wire.

This module ships a masque_handler-shaped callback set (init/2, handle_info/2, terminate/2) plus the handle_bind_packet/3 entry the bind session calls when a datagram arrives from the client. handle_bind_packet/3 is not on the existing masque_handler behaviour because no other protocol uses it; the bind sessions invoke it directly.

Configurable via handler_opts:

  • bind_address :: inet:ip_address() | any - which interface to bind to. Default any.
  • bind_port :: inet:port_number() - default 0 (kernel-assigned ephemeral).
  • bind_socket_opts :: [gen_udp:option()] - merged on top of [binary, {active, true}].
  • public_addresses :: [{ip_address(), port()}] - list emitted on Proxy-Public-Address. Required if the socket is bound to a wildcard address; otherwise sockname is the fallback.
  • public_address_fun :: fun((sockname()) -> [{ip, port}]) - alternative to the static list. Takes precedence when set.
  • peer_filter_fun :: fun((ip(), port()) -> ok | {drop, atom()}) - per-packet egress policy. Default rejects RFC 1918, link-local, and multicast unless allow_private => true; loopback is allowed by default for testability.
  • scrub_fun :: fun((Packet, State) -> {pass, Packet, State} | {drop, Reason, State}) - data-plane policy hook for DDoS scrubbing or other per-packet filtering. Default identity.

Summary

Functions

The bind session calls this with the decoded peer tuple and the inner UDP payload. Returns either an ok continuation or a drop with a reason that the session can attribute via metrics.

Types

ip_port/0

-type ip_port() :: {inet:ip_address(), inet:port_number()}.

opts/0

-type opts() :: map().

Functions

handle_bind_packet(_, Payload, State)

-spec handle_bind_packet(ip_port(),
                         binary(),
                         #state{socket :: gen_udp:socket(),
                                public_addresses :: [{inet:ip_address(), inet:port_number()}],
                                advertised_families :: [4 | 6],
                                peer_filter_fun ::
                                    fun((inet:ip_address(), inet:port_number()) -> ok | {drop, atom()}),
                                scrub_fun ::
                                    fun((binary(), term()) ->
                                            {pass, binary(), term()} | {drop, atom(), term()}),
                                user_state :: term()}) ->
                            {ok,
                             #state{socket :: gen_udp:socket(),
                                    public_addresses :: [{inet:ip_address(), inet:port_number()}],
                                    advertised_families :: [4 | 6],
                                    peer_filter_fun ::
                                        fun((inet:ip_address(), inet:port_number()) ->
                                                ok | {drop, atom()}),
                                    scrub_fun ::
                                        fun((binary(), term()) ->
                                                {pass, binary(), term()} | {drop, atom(), term()}),
                                    user_state :: term()}} |
                            {drop,
                             atom(),
                             #state{socket :: gen_udp:socket(),
                                    public_addresses :: [{inet:ip_address(), inet:port_number()}],
                                    advertised_families :: [4 | 6],
                                    peer_filter_fun ::
                                        fun((inet:ip_address(), inet:port_number()) ->
                                                ok | {drop, atom()}),
                                    scrub_fun ::
                                        fun((binary(), term()) ->
                                                {pass, binary(), term()} | {drop, atom(), term()}),
                                    user_state :: term()}}.

The bind session calls this with the decoded peer tuple and the inner UDP payload. Returns either an ok continuation or a drop with a reason that the session can attribute via metrics.

handle_info(Other, State)

-spec handle_info(term(),
                  #state{socket :: gen_udp:socket(),
                         public_addresses :: [{inet:ip_address(), inet:port_number()}],
                         advertised_families :: [4 | 6],
                         peer_filter_fun ::
                             fun((inet:ip_address(), inet:port_number()) -> ok | {drop, atom()}),
                         scrub_fun ::
                             fun((binary(), term()) -> {pass, binary(), term()} | {drop, atom(), term()}),
                         user_state :: term()}) ->
                     {ok,
                      #state{socket :: gen_udp:socket(),
                             public_addresses :: [{inet:ip_address(), inet:port_number()}],
                             advertised_families :: [4 | 6],
                             peer_filter_fun ::
                                 fun((inet:ip_address(), inet:port_number()) -> ok | {drop, atom()}),
                             scrub_fun ::
                                 fun((binary(), term()) ->
                                         {pass, binary(), term()} | {drop, atom(), term()}),
                             user_state :: term()}} |
                     {ok,
                      #state{socket :: gen_udp:socket(),
                             public_addresses :: [{inet:ip_address(), inet:port_number()}],
                             advertised_families :: [4 | 6],
                             peer_filter_fun ::
                                 fun((inet:ip_address(), inet:port_number()) -> ok | {drop, atom()}),
                             scrub_fun ::
                                 fun((binary(), term()) ->
                                         {pass, binary(), term()} | {drop, atom(), term()}),
                             user_state :: term()},
                      [term()]} |
                     {stop,
                      term(),
                      #state{socket :: gen_udp:socket(),
                             public_addresses :: [{inet:ip_address(), inet:port_number()}],
                             advertised_families :: [4 | 6],
                             peer_filter_fun ::
                                 fun((inet:ip_address(), inet:port_number()) -> ok | {drop, atom()}),
                             scrub_fun ::
                                 fun((binary(), term()) ->
                                         {pass, binary(), term()} | {drop, atom(), term()}),
                             user_state :: term()}}.

init(Req, Opts)

-spec init(masque_handler:req(), opts()) ->
              {ok,
               #state{socket :: gen_udp:socket(),
                      public_addresses :: [{inet:ip_address(), inet:port_number()}],
                      advertised_families :: [4 | 6],
                      peer_filter_fun ::
                          fun((inet:ip_address(), inet:port_number()) -> ok | {drop, atom()}),
                      scrub_fun ::
                          fun((binary(), term()) -> {pass, binary(), term()} | {drop, atom(), term()}),
                      user_state :: term()},
               [term()]} |
              {stop, term()}.

terminate(Reason, State)

-spec terminate(term(),
                #state{socket :: gen_udp:socket(),
                       public_addresses :: [{inet:ip_address(), inet:port_number()}],
                       advertised_families :: [4 | 6],
                       peer_filter_fun ::
                           fun((inet:ip_address(), inet:port_number()) -> ok | {drop, atom()}),
                       scrub_fun ::
                           fun((binary(), term()) -> {pass, binary(), term()} | {drop, atom(), term()}),
                       user_state :: term()}) ->
                   ok.