masque_udp_bind_proxy_handler (masque v0.7.0)
View SourceDefault 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. Defaultany.bind_port :: inet:port_number()- default0(kernel-assigned ephemeral).bind_socket_opts :: [gen_udp:option()]- merged on top of[binary, {active, true}].public_addresses :: [{ip_address(), port()}]- list emitted onProxy-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 unlessallow_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
-type ip_port() :: {inet:ip_address(), inet:port_number()}.
-type opts() :: map().
Functions
-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.
-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()}}.
-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()}.
-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.