> Docs > Http Client > Proxy and Tunnels

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.

Proxy

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
    ...

Tunnels

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:80. Now any data on this connection will be tunneled to/from example.com:80. 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"

"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.

SSL to Proxy and Tunnels

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.