aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2019-09-20 19:26:15 +0200
committerLoïc Hoguin <[email protected]>2019-09-22 16:46:44 +0200
commit0a5879ceffa3a96666ed8406c1557759811d8a16 (patch)
tree6faf0dfa49ae04520470df915915c5cb31878e37
parent4664da8703d4a1d5225fd71e1fc3164f9441ff36 (diff)
downloadgun-0a5879ceffa3a96666ed8406c1557759811d8a16.tar.gz
gun-0a5879ceffa3a96666ed8406c1557759811d8a16.tar.bz2
gun-0a5879ceffa3a96666ed8406c1557759811d8a16.zip
Add CONNECT->Socks5->HTTP tests
Also fix the multiple TLS proxies tests from the previous commit.
-rw-r--r--src/gun.erl4
-rw-r--r--test/socks_SUITE.erl94
2 files changed, 90 insertions, 8 deletions
diff --git a/src/gun.erl b/src/gun.erl
index c1a8be5..e576b61 100644
--- a/src/gun.erl
+++ b/src/gun.erl
@@ -957,7 +957,7 @@ tls_handshake(internal, {tls_handshake, HandshakeEvent, Protocols},
%% TLS over TLS.
tls_handshake(internal, {tls_handshake,
HandshakeEvent0=#{tls_opts := TLSOpts0, timeout := TLSTimeout}, Protocols},
- State=#state{socket=Socket, transport=gun_tls, origin_host=OriginHost, origin_port=OriginPort,
+ State=#state{socket=Socket, transport=Transport, origin_host=OriginHost, origin_port=OriginPort,
event_handler=EvHandler, event_handler_state=EvHandlerState0}) ->
TLSOpts = ensure_alpn(Protocols, TLSOpts0),
HandshakeEvent = HandshakeEvent0#{
@@ -966,7 +966,7 @@ tls_handshake(internal, {tls_handshake,
},
EvHandlerState = EvHandler:tls_handshake_start(HandshakeEvent, EvHandlerState0),
{ok, ProxyPid} = gun_tls_proxy:start_link(OriginHost, OriginPort,
- TLSOpts, TLSTimeout, Socket, gun_tls, {HandshakeEvent, Protocols}),
+ TLSOpts, TLSTimeout, Socket, Transport, {HandshakeEvent, Protocols}),
commands([{switch_transport, gun_tls_proxy, ProxyPid}], State#state{
socket=ProxyPid, transport=gun_tls_proxy, event_handler_state=EvHandlerState});
%% When using gun_tls_proxy we need a separate message to know whether
diff --git a/test/socks_SUITE.erl b/test/socks_SUITE.erl
index 80a2796..060c89f 100644
--- a/test/socks_SUITE.erl
+++ b/test/socks_SUITE.erl
@@ -262,27 +262,27 @@ socks5_tcp_through_multiple_tcp_proxies(_) ->
doc("Gun can be used to establish a TCP connection "
"to an HTTP/1.1 server via a tunnel going through "
"two separate TCP Socks5 proxies."),
- do_socks5_through_multiple_proxies(tcp, tcp).
+ do_socks5_through_multiple_proxies(<<"http">>, tcp, tcp).
socks5_tcp_through_multiple_tls_proxies(_) ->
doc("Gun can be used to establish a TCP connection "
"to an HTTP/1.1 server via a tunnel going through "
"two separate TLS Socks5 proxies."),
- do_socks5_through_multiple_proxies(tcp, tls).
+ do_socks5_through_multiple_proxies(<<"http">>, tcp, tls).
socks5_tls_through_multiple_tcp_proxies(_) ->
doc("Gun can be used to establish a TLS connection "
"to an HTTP/1.1 server via a tunnel going through "
"two separate TCP Socks5 proxies."),
- do_socks5_through_multiple_proxies(tcp, tcp).
+ do_socks5_through_multiple_proxies(<<"https">>, tls, tcp).
socks5_tls_through_multiple_tls_proxies(_) ->
doc("Gun can be used to establish a TLS connection "
"to an HTTP/1.1 server via a tunnel going through "
"two separate TLS Socks5 proxies."),
- do_socks5_through_multiple_proxies(tcp, tls).
+ do_socks5_through_multiple_proxies(<<"https">>, tls, tls).
-do_socks5_through_multiple_proxies(OriginTransport, ProxyTransport) ->
+do_socks5_through_multiple_proxies(OriginScheme, OriginTransport, ProxyTransport) ->
{ok, OriginPid, OriginPort} = init_origin(OriginTransport, http),
{ok, Proxy1Pid, Proxy1Port} = do_proxy_start(ProxyTransport, none),
{ok, Proxy2Pid, Proxy2Port} = do_proxy_start(ProxyTransport, none),
@@ -322,7 +322,7 @@ do_socks5_through_multiple_proxies(OriginTransport, ProxyTransport) ->
#{
transport := OriginTransport,
protocol := http,
- origin_scheme := <<"http">>,
+ origin_scheme := OriginScheme,
origin_host := "localhost",
origin_port := OriginPort,
intermediaries := [#{
@@ -339,3 +339,85 @@ do_socks5_through_multiple_proxies(OriginTransport, ProxyTransport) ->
protocol := socks
}]} = gun:info(ConnPid),
gun:close(ConnPid).
+
+socks5_tcp_through_connect_tcp_to_tcp_origin(_) ->
+ doc("CONNECT can be used to establish a TCP connection "
+ "to an HTTP/1.1 server via a tunnel going through "
+ "an HTTP proxy followed by a Socks5 proxy."),
+ do_socks5_through_connect_proxy(<<"http">>, tcp, tcp).
+
+socks5_tls_through_connect_tls_to_tcp_origin(_) ->
+ doc("CONNECT can be used to establish a TCP connection "
+ "to an HTTP/1.1 server via a tunnel going through "
+ "an HTTPS proxy followed by a TLS Socks5 proxy."),
+ do_socks5_through_connect_proxy(<<"http">>, tcp, tls).
+
+socks5_tcp_through_connect_tcp_to_tls_origin(_) ->
+ doc("CONNECT can be used to establish a TCP connection "
+ "to an HTTP/1.1 server via a tunnel going through "
+ "an HTTP proxy followed by a Socks5 proxy."),
+ do_socks5_through_connect_proxy(<<"https">>, tls, tcp).
+
+socks5_tls_through_connect_tls_to_tls_origin(_) ->
+ doc("CONNECT can be used to establish a TCP connection "
+ "to an HTTP/1.1 server via a tunnel going through "
+ "an HTTPS proxy followed by a TLS Socks5 proxy."),
+ do_socks5_through_connect_proxy(<<"https">>, tls, tls).
+
+do_socks5_through_connect_proxy(OriginScheme, OriginTransport, ProxyTransport) ->
+ {ok, OriginPid, OriginPort} = init_origin(OriginTransport, http),
+ {ok, Proxy1Pid, Proxy1Port} = rfc7231_SUITE:do_proxy_start(ProxyTransport),
+ {ok, Proxy2Pid, Proxy2Port} = do_proxy_start(ProxyTransport, none),
+ {ok, ConnPid} = gun:open("localhost", Proxy1Port, #{
+ transport => ProxyTransport
+ }),
+ %% We receive a gun_up first. This is the HTTP proxy.
+ {ok, http} = gun:await_up(ConnPid),
+ Authority1 = iolist_to_binary(["localhost:", integer_to_binary(Proxy2Port)]),
+ StreamRef = gun:connect(ConnPid, #{
+ host => "localhost",
+ port => Proxy2Port,
+ transport => ProxyTransport,
+ protocols => [{socks, #{
+ host => "localhost",
+ port => OriginPort,
+ transport => OriginTransport
+ }}]
+ }),
+ {request, <<"CONNECT">>, Authority1, 'HTTP/1.1', _} = receive_from(Proxy1Pid),
+ {response, fin, 200, _} = gun:await(ConnPid, StreamRef),
+ %% We receive a gun_socks_connected afterwards. This is the origin HTTP server.
+ {ok, http} = gun:await_up(ConnPid),
+ %% The second proxy receives a Socks5 auth/connect request.
+ {auth_methods, 1, [none]} = receive_from(Proxy2Pid),
+ {connect, <<"localhost">>, OriginPort} = receive_from(Proxy2Pid),
+ handshake_completed = receive_from(OriginPid),
+ Authority2 = iolist_to_binary(["localhost:", integer_to_binary(OriginPort)]),
+ _ = gun:get(ConnPid, "/proxied"),
+ Data = receive_from(OriginPid),
+ Lines = binary:split(Data, <<"\r\n">>, [global]),
+ [<<"host: ", Authority2/bits>>] = [L || <<"host: ", _/bits>> = L <- Lines],
+ Proxy2Transport = case ProxyTransport of
+ tcp -> tcp;
+ tls -> tls_proxy
+ end,
+ #{
+ transport := OriginTransport,
+ protocol := http,
+ origin_scheme := OriginScheme,
+ origin_host := "localhost",
+ origin_port := OriginPort,
+ intermediaries := [#{
+ type := connect,
+ host := "localhost",
+ port := Proxy1Port,
+ transport := ProxyTransport,
+ protocol := http
+ }, #{
+ type := socks5,
+ host := "localhost",
+ port := Proxy2Port,
+ transport := Proxy2Transport,
+ protocol := socks
+ }]} = gun:info(ConnPid),
+ gun:close(ConnPid).