Browse Source

Add support for the UNIQUE_ID proxy protocol header TLV

Loïc Hoguin 1 year ago
parent
commit
cb75e10c99
2 changed files with 16 additions and 0 deletions
  1. 6 0
      doc/src/manual/ranch_proxy_header.asciidoc
  2. 10 0
      src/ranch_proxy_header.erl

+ 6 - 0
doc/src/manual/ranch_proxy_header.asciidoc

@@ -37,6 +37,7 @@ proxy_info() = #{
     %% Extra TLV-encoded data.
     alpn      => binary(), %% US-ASCII.
     authority => binary(), %% UTF-8.
+    unique_id => binary(), %% Opaque byte sequence of up to 128 bytes.
     netns     => binary(), %% US-ASCII.
     ssl       => #{
         client   := [ssl | cert_conn | cert_sess],
@@ -105,6 +106,10 @@ authority::
 The host name serving as authority for the connection.
 This is typically passed using the SNI extension for TLS.
 
+unique_id::
+An opaque byte sequence of up to 128 bytes generated
+by the upstream proxy that uniquely identifies the connection.
+
 netns::
 
 The namespace's name for the original connection.
@@ -158,6 +163,7 @@ The non-standard TLVs that Ranch was not able to parse.
 
 == Changelog
 
+* *2.2*: The `unique_id` TLV was added.
 * *1.7*: Module introduced.
 
 == See also

+ 10 - 0
src/ranch_proxy_header.erl

@@ -33,6 +33,7 @@
 	%% Extra TLV-encoded data.
 	alpn => binary(), %% US-ASCII.
 	authority => binary(), %% UTF-8.
+	unique_id => binary(), %% Opaque byte sequence of up to 128 bytes.
 	ssl => #{
 		client := [ssl | cert_conn | cert_sess],
 		verified := boolean(),
@@ -520,6 +521,12 @@ parse_tlv(<<16#3, TLVLen:16, CRC32C:32, Rest/bits>>, Len0, Info, Header) when TL
 %% PP2_TYPE_NOOP.
 parse_tlv(<<16#4, TLVLen:16, _:TLVLen/binary, Rest/bits>>, Len, Info, Header) ->
 	parse_tlv(Rest, Len - TLVLen - 3, Info, Header);
+%% PP2_TYPE_UNIQUE_ID.
+parse_tlv(<<16#5, TLVLen:16, UniqueID:TLVLen/binary, Rest/bits>>, Len, Info, Header)
+		when TLVLen =< 128 ->
+	parse_tlv(Rest, Len - TLVLen - 3, Info#{unique_id => UniqueID}, Header);
+parse_tlv(<<16#5, _/bits>>, _, _, _) ->
+	{error, 'Invalid TLV length in the PROXY protocol binary header. (PP 2.2, PP 2.2.5)'};
 %% PP2_TYPE_SSL.
 parse_tlv(<<16#20, TLVLen:16, Client, Verify:32, Rest0/bits>>, Len, Info, Header) ->
 	SubsLen = TLVLen - 5,
@@ -682,6 +689,7 @@ tlvs(ProxyInfo, Opts) ->
 	[
 		binary_tlv(ProxyInfo, alpn, 16#1),
 		binary_tlv(ProxyInfo, authority, 16#2),
+		binary_tlv(ProxyInfo, unique_id, 16#5),
 		ssl_tlv(ProxyInfo),
 		binary_tlv(ProxyInfo, netns, 16#30),
 		raw_tlvs(ProxyInfo),
@@ -849,6 +857,8 @@ v2_tlvs_test() ->
 	]},
 	Test5Out = Test5In#{raw_tlvs => lists:reverse(RawTLVs)},
 	{ok, Test5Out, <<>>} = parse(iolist_to_binary(header(Test5In))),
+	Test6 = Common#{unique_id => rand:bytes(rand:uniform(128))},
+	{ok, Test6, <<>>} = parse(iolist_to_binary(header(Test6))),
 	ok.
 
 v2_checksum_test() ->