proxy_header_SUITE.erl 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. %% Copyright (c) 2018, Loïc Hoguin <essen@ninenines.eu>
  2. %%
  3. %% Permission to use, copy, modify, and/or distribute this software for any
  4. %% purpose with or without fee is hereby granted, provided that the above
  5. %% copyright notice and this permission notice appear in all copies.
  6. %%
  7. %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  10. %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  12. %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  13. %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  14. -module(proxy_header_SUITE).
  15. -compile(export_all).
  16. -compile(nowarn_export_all).
  17. -import(ct_helper, [doc/1]).
  18. -import(ct_helper, [name/0]).
  19. %% ct.
  20. all() ->
  21. ct_helper:all(?MODULE).
  22. %% Tests.
  23. recv_v1_proxy_header_tcp(_) ->
  24. doc("Confirm we can read the proxy header at the start of the connection."),
  25. Name = name(),
  26. ProxyInfo = #{
  27. version => 1,
  28. command => proxy,
  29. transport_family => ipv4,
  30. transport_protocol => stream,
  31. src_address => {127, 0, 0, 1},
  32. src_port => 444,
  33. dest_address => {192, 168, 0, 1},
  34. dest_port => 443
  35. },
  36. do_proxy_header_tcp(Name, ProxyInfo, <<>>, <<"TCP Ranch is working!">>).
  37. recv_v1_proxy_header_tcp_extra_data(_) ->
  38. doc("Confirm we can read the proxy header at the start of the connection "
  39. "and that the extra data in the first packet can be read afterwards."),
  40. Name = name(),
  41. ProxyInfo = #{
  42. version => 1,
  43. command => proxy,
  44. transport_family => ipv4,
  45. transport_protocol => stream,
  46. src_address => {127, 0, 0, 1},
  47. src_port => 444,
  48. dest_address => {192, 168, 0, 1},
  49. dest_port => 443
  50. },
  51. do_proxy_header_tcp(Name, ProxyInfo, <<"HELLO">>, <<"TCP Ranch is working!">>).
  52. recv_v2_proxy_header_tcp(_) ->
  53. doc("Confirm we can read the proxy header at the start of the connection."),
  54. Name = name(),
  55. ProxyInfo = #{
  56. version => 2,
  57. command => proxy,
  58. transport_family => ipv4,
  59. transport_protocol => stream,
  60. src_address => {127, 0, 0, 1},
  61. src_port => 444,
  62. dest_address => {192, 168, 0, 1},
  63. dest_port => 443
  64. },
  65. do_proxy_header_tcp(Name, ProxyInfo, <<>>, <<"TCP Ranch is working!">>).
  66. recv_v2_proxy_header_tcp_extra_data(_) ->
  67. doc("Confirm we can read the proxy header at the start of the connection "
  68. "and that the extra data in the first packet can be read afterwards."),
  69. Name = name(),
  70. ProxyInfo = #{
  71. version => 2,
  72. command => proxy,
  73. transport_family => ipv4,
  74. transport_protocol => stream,
  75. src_address => {127, 0, 0, 1},
  76. src_port => 444,
  77. dest_address => {192, 168, 0, 1},
  78. dest_port => 443
  79. },
  80. do_proxy_header_tcp(Name, ProxyInfo, <<"HELLO">>, <<"TCP Ranch is working!">>).
  81. recv_v2_local_header_tcp(_) ->
  82. doc("Confirm we can read the proxy header at the start of the connection."),
  83. Name = name(),
  84. ProxyInfo = #{
  85. version => 2,
  86. command => local
  87. },
  88. do_proxy_header_tcp(Name, ProxyInfo, <<>>, <<"TCP Ranch is working!">>).
  89. recv_v2_local_header_tcp_extra_data(_) ->
  90. doc("Confirm we can read the proxy header at the start of the connection "
  91. "and that the extra data in the first packet can be read afterwards."),
  92. Name = name(),
  93. ProxyInfo = #{
  94. version => 2,
  95. command => local
  96. },
  97. do_proxy_header_tcp(Name, ProxyInfo, <<"HELLO">>, <<"TCP Ranch is working!">>).
  98. do_proxy_header_tcp(Name, ProxyInfo, Data1, Data2) ->
  99. {ok, _} = ranch:start_listener(Name,
  100. ranch_tcp, #{},
  101. proxy_protocol, []),
  102. Port = ranch:get_port(Name),
  103. {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]),
  104. ok = gen_tcp:send(Socket, [ranch_proxy_header:header(ProxyInfo), Data1]),
  105. receive
  106. {proxy_protocol, ProxyInfo} ->
  107. ok
  108. after 2000 ->
  109. error(timeout)
  110. end,
  111. ok = gen_tcp:send(Socket, Data2),
  112. Len1 = byte_size(Data1),
  113. Len2 = byte_size(Data2),
  114. {ok, <<Data1:Len1/binary, Data2/binary>>} = gen_tcp:recv(Socket, Len1 + Len2, 1000),
  115. ok = ranch:stop_listener(Name),
  116. ok.
  117. recv_v1_proxy_header_ssl(_) ->
  118. doc("Confirm we can read the proxy header at the start of the connection."),
  119. Name = name(),
  120. ProxyInfo = #{
  121. version => 1,
  122. command => proxy,
  123. transport_family => ipv4,
  124. transport_protocol => stream,
  125. src_address => {127, 0, 0, 1},
  126. src_port => 444,
  127. dest_address => {192, 168, 0, 1},
  128. dest_port => 443
  129. },
  130. do_proxy_header_ssl(Name, ProxyInfo, <<>>, <<"TCP Ranch is working!">>).
  131. recv_v1_proxy_header_ssl_extra_data(_) ->
  132. doc("Confirm we can read the proxy header at the start of the connection "
  133. "and that the extra data in the first packet can be read afterwards."),
  134. Name = name(),
  135. ProxyInfo = #{
  136. version => 1,
  137. command => proxy,
  138. transport_family => ipv4,
  139. transport_protocol => stream,
  140. src_address => {127, 0, 0, 1},
  141. src_port => 444,
  142. dest_address => {192, 168, 0, 1},
  143. dest_port => 443
  144. },
  145. do_proxy_header_ssl(Name, ProxyInfo, <<"HELLO">>, <<"TCP Ranch is working!">>).
  146. recv_v2_proxy_header_ssl(_) ->
  147. doc("Confirm we can read the proxy header at the start of the connection."),
  148. Name = name(),
  149. ProxyInfo = #{
  150. version => 2,
  151. command => proxy,
  152. transport_family => ipv4,
  153. transport_protocol => stream,
  154. src_address => {127, 0, 0, 1},
  155. src_port => 444,
  156. dest_address => {192, 168, 0, 1},
  157. dest_port => 443
  158. },
  159. do_proxy_header_ssl(Name, ProxyInfo, <<>>, <<"TCP Ranch is working!">>).
  160. recv_v2_proxy_header_ssl_extra_data(_) ->
  161. doc("Confirm we can read the proxy header at the start of the connection "
  162. "and that the extra data in the first packet can be read afterwards."),
  163. Name = name(),
  164. ProxyInfo = #{
  165. version => 2,
  166. command => proxy,
  167. transport_family => ipv4,
  168. transport_protocol => stream,
  169. src_address => {127, 0, 0, 1},
  170. src_port => 444,
  171. dest_address => {192, 168, 0, 1},
  172. dest_port => 443
  173. },
  174. do_proxy_header_ssl(Name, ProxyInfo, <<"HELLO">>, <<"TCP Ranch is working!">>).
  175. recv_v2_local_header_ssl(_) ->
  176. doc("Confirm we can read the proxy header at the start of the connection."),
  177. Name = name(),
  178. ProxyInfo = #{
  179. version => 2,
  180. command => local
  181. },
  182. do_proxy_header_ssl(Name, ProxyInfo, <<>>, <<"TCP Ranch is working!">>).
  183. recv_v2_local_header_ssl_extra_data(_) ->
  184. doc("Confirm we can read the proxy header at the start of the connection "
  185. "and that the extra data in the first packet can be read afterwards."),
  186. Name = name(),
  187. ProxyInfo = #{
  188. version => 2,
  189. command => local
  190. },
  191. do_proxy_header_ssl(Name, ProxyInfo, <<"HELLO">>, <<"TCP Ranch is working!">>).
  192. do_proxy_header_ssl(Name, ProxyInfo, Data1, Data2) ->
  193. Opts = ct_helper:get_certs_from_ets(),
  194. {ok, _} = ranch:start_listener(Name,
  195. ranch_ssl, Opts,
  196. proxy_protocol, []),
  197. Port = ranch:get_port(Name),
  198. {ok, Socket0} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]),
  199. ok = gen_tcp:send(Socket0, [ranch_proxy_header:header(ProxyInfo)]),
  200. {ok, Socket} = ssl:connect(Socket0, [], 1000),
  201. ok = ssl:send(Socket, Data1),
  202. receive
  203. {proxy_protocol, ProxyInfo} ->
  204. ok
  205. after 2000 ->
  206. error(timeout)
  207. end,
  208. ok = ssl:send(Socket, Data2),
  209. Len1 = byte_size(Data1),
  210. Len2 = byte_size(Data2),
  211. {ok, <<Data1:Len1/binary, Data2/binary>>} = ssl:recv(Socket, Len1 + Len2, 1000),
  212. ok = ranch:stop_listener(Name),
  213. ok.