> Docs > Http Client > Proxy and Tunnels
By default, HttpClient
establishes a direct connection to the server for transmitting the request and response.
This can be changed by using proxy and tunnels.
If a proxy
is configured, requests will be sent to the proxy, instead of the servers. For example,
HttpClient client = new HttpClientConf() .proxy("some-http-proxy.com", 80) .newClient(); client.doGet( "https://example.com/path" );
The client establishes a TCP connection to some-http-proxy.com:80
, sends the request over this connection as
GET https://example.com/path HTTP/1.1 ...
A TcpTunnel
forwards TCP data blindly between clients and servers.
An HttpClient
can be configured to use TCP tunnels
. For example
// a local SOCKS5 tunnel created by PuTTY TcpTunnel tunnel = new Socks5Tunnel("localhost", 9876); HttpClient client = new HttpClientConf() .tunnels(tunnel) .newClient(); client.doGet( "https://example.com/path" );
The client connects to localhost:9876
, performs SOCKS5 handshake, instructs it to tunnel to example.com:443
. Now any data on this connection will be tunneled to/from example.com:443
. The client then performs SSL handshake (because of https
) over this connection with example.com
, before sending the request.
A chain of tunnels can be configured. Each request will go through every tunnel in the order specified. For example
TcpTunnel tunnelA = new Socks5Tunnel("socks-proxy-A.com", 1080); TcpTunnel tunnelB = new Socks5Tunnel("socks-proxy-B.com", 1080); HttpClient client = new HttpClientConf() .tunnels(tunnelA, tunnelB) .newClient(); client.doGet( "https://example.com/path" );
The request will go through socks-proxy-A.com
, then socks-proxy-B.com
, before reaching example.com
.
If both tunnels and proxy are specified for an HttpClient, the requests will be sent through the tunnels to the proxy.
"HTTPS proxy", as it's commonly called, is actually a TCP tunnel which forwards TCP data blindly. Do not confuse it with HTTP proxy which forwards HTTP messages. (Although, it is possible to run HTTP+HTTPS proxy on the same server:port.)
In bayou.io
, HTTPS proxy is known as ConnectTunnel
. For HttpClient
, it is a tunnel, not a proxy. For example
TcpTunnel tunnel = new ConnectTunnel("some-httpS-proxy.com", 8000); HttpClient client = new HttpClientConf() .tunnels( tunnel ) .newClient();
Although HTTPS proxy is typically used for tunnelling end-to-end HTTPS traffic, it can be used to tunnel any TCP traffic, including plain HTTP. In the previous example, every request will go though the tunnel, regardless of whether it's https
.
For simplicity, the proxy and tunnels in an HttpClient apply to all requests. This is different from common browser configuration practices, where an HTTP proxy is used for http
requests, and an HTTPS proxy is used for https
requests. If you need to mimic that behavior, you can use two HttpClient
instances, one with a proxy
, one with a ConnectTunnel
; send all http
requests to the 1st client, and all https
to the 2nd.
Usually, the communication between the client and the proxy is in clear text. This is vulnerable to eavesdroppers though. To counter that, the proxy may support SSL connections with clients. That is independent of whether the requests are https
. For example
TcpAddress proxyAddress = new TcpAddress(/*ssl*/true, "some-http-proxy.com", PORT); clientConf.proxy( new HttpProxy(proxyAddress, null) );
The same applies to tunnels. Even if a client does end-to-end SSL with a server over a tunnel, the initial tunneling handshake between the client and the tunnel may contain sensitive information (e.g. the server address) that requires protection too. For these reasons, a tunnel may support SSL connections with clients. For example
TcpAddress tunnelAddress = new TcpAddress(/*ssl*/true, "some-socks-proxy.com", PORT); clientConf.tunnels( new Socks5Tunnel(tunnelAddress, false, null) );
If hypothetically a very paranoid HttpClient is configured with 2 tunnels and a proxy, all requiring SSL, there will be 3 layers of SSL on the client end.