DEV Community

Ashish R Bhandari
Ashish R Bhandari

Posted on

What All Things are Possible in a Proxy(Forward Proxy)

Hello All,
I am Trying to Express, Expand and Explain My Thoughts and Learning Through these Posts

> Feel Free to Point Out If I have made any mistakes

Beginning With Proxy(If Said Only Proxy then it mostly means Forward Proxy)

There are Lots of Explanation Covered Already about this and I will add links and resources that I have read and found very interesting.

Coming Back as to what am I going to add in this post.
It going to be all about
What a Forward Proxy is

Capable of doing,
What it can do,
What it cannot do (depending on Configuration, Use and Functionality)

So Long Story Short, Since You have Gone Through My Above Links (^)
Let's Start it

Now The Proxy Works and Provides Features depends on where it is Placed.

Let's Break this down
1) If the Proxy is inside the Network(Basically a Scenario of a School, Institute, Office(Could be Any Office)), Then the Reason it is used is to Let the Client Use the Proxy and do

Caching

Website Access Blocking (Well it Fall inside Filtering But There is a Reason Why I kept it over here)

Filtering

Identification (Basically Knowing Which User and Based on that Filtering)

Other Activity (Logging, Alerting)

........

2) If the Proxy is Outside the Network(Basically a Scenario of a Online Proxy, Free Proxy Server, Browser Proxy Extension(like Hola , HotSpotShield), Browser VPN Extension(* More Here) ), Then the Reason it is used is to Make the Client Anonymous Over the Internet.
Which Means that This Proxy will provide me Anonymity and Let me Access what is Blocked by My ISP.
[Now This is a Bit Contradictory of the Above that is the reason why I Said the Above Punch line.]

So we are Clear here About Proxy and How it Differs based on where it is Placed.

Let's Go To the Other

How Easy it is for a Proxy to determine the Host the user is trying to Connect to ?

Based on the Host Header
For Plain HTTP Website it is Easy to Get the Host Header because anybody can see that, same ways even Proxy can see it Very Easily

For HTTPS Website, The Browser will First Send a CONNECT Request to indicate that it is going to initiate a SSL Connection with the Remote Website.
It Looks Like This

CONNECT b.config.skype.com:443 HTTP/1.1
Host: b.config.skype.com:443
Proxy-Connection: keep-alive
User-Agent: curl/7.58.0
Enter fullscreen mode Exit fullscreen mode

The Important Headers are Only Below one, Rest Proxy-Connection, User-Agent are Important But not Compulsory/Mandatory for CONNECT Request [Well For User-Agent it can create problem accessing websites]

CONNECT b.config.skype.com:443 HTTP/1.1
Host: b.config.skype.com:443
Enter fullscreen mode Exit fullscreen mode

The Connect Also specifies Port, indicating whether to connect on Standard or any other Port.

So, In Simple It works This Way

In Below Scenario, Imagine it This Way, We are Using Firefox and There is a Setting in browser: The Proxy Setting

Alt Text

I am Running a Proxy on My Machine Locally [I will Later Update which proxy I am running]

Plain HTTP Site

We will connect to: http://example.com/

The Browser Will Send a HTTP Request to The Proxy as Follows:

hmmm@demo:~# curl -vk "http://example.com/" -x 127.0.0.1:8080
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
> GET http://example.com/ HTTP/1.1
> Host: example.com
> User-Agent: curl/7.58.0
> Accept: */*
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 200 OK
< Age: 341302
< Cache-Control: max-age=604800
< Content-Type: text/html; charset=UTF-8
< Date: Fri, 01 Jan 2021 13:50:29 GMT
< Etag: "3147526947+ident"
< Expires: Fri, 08 Jan 2021 13:50:29 GMT
< Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
< Server: ECS (nyb/1D2C)
< Vary: Accept-Encoding
< X-Cache: HIT
< Content-Length: 1256
Enter fullscreen mode Exit fullscreen mode

and Then the Proxy will make a Request to Remote Server (Gathered From Host Header, well it can be extracted from Request Line But Host Header is the Standard)

Let's Look at
A Simple DIRECT Request Looks as Follows

hmmm@demo:~# curl -vk "http://example.com/"
*   Trying 2606:2800:220:1:248:1893:25c8:1946...
* TCP_NODELAY set
*   Trying 93.184.216.34...
> GET / HTTP/1.1
> Host: example.com
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Age: 341302
< Cache-Control: max-age=604800
< Content-Type: text/html; charset=UTF-8
< Date: Fri, 01 Jan 2021 13:50:31 GMT
< Etag: "3147526947+ident"
< Expires: Fri, 08 Jan 2021 13:50:31 GMT
< Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
< Server: ECS (nyb/1D2C)
< Vary: Accept-Encoding
< X-Cache: HIT
< Content-Length: 1256

Enter fullscreen mode Exit fullscreen mode

HTTPS Request

We will connect to: https://example.com/


hmmm@demo:~# curl -vk "https://example.com/" -x 127.0.0.1:8080
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
* allocate connect buffer!
* Establish HTTP proxy tunnel to example.com:443
> CONNECT example.com:443 HTTP/1.1
> Host: example.com:443
> User-Agent: curl/7.58.0
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 200 Connection Established
< Connection: Keep-Alive
< Proxy-Connection: Keep-Alive
<
* Proxy replied 200 to CONNECT request
* CONNECT phase completed!
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* CONNECT phase completed!
* CONNECT phase completed!
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (OUT), TLS change cipher, Client hello (1):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Unknown (8):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS Unknown, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: C=US; ST=California; L=Los Angeles; O=Internet Corporation for Assigned Names and Numbers; CN=www.example.org
*  start date: Nov 24 00:00:00 2020 GMT
*  expire date: Dec 25 23:59:59 2021 GMT
*  issuer: C=US; O=DigiCert Inc; CN=DigiCert TLS RSA SHA256 2020 CA1
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
* Using Stream ID: 1 (easy handle 0x56435e5025c0)
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
> GET / HTTP/2
> Host: example.com
> User-Agent: curl/7.58.0
> Accept: */*
>
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS Unknown, Unknown (23):
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
* TLSv1.3 (IN), TLS Unknown, Unknown (23):
* TLSv1.3 (IN), TLS Unknown, Unknown (23):
* TLSv1.3 (IN), TLS Unknown, Unknown (23):
< HTTP/2 200
< age: 87233
< cache-control: max-age=604800
< content-type: text/html; charset=UTF-8
< date: Fri, 01 Jan 2021 14:04:25 GMT
< etag: "3147526947+ident"
< expires: Fri, 08 Jan 2021 14:04:25 GMT
< last-modified: Thu, 17 Oct 2019 07:18:26 GMT
< server: ECS (nyb/1D0D)
< vary: Accept-Encoding
< x-cache: HIT
< content-length: 1256
<
* TLSv1.3 (IN), TLS Unknown, Unknown (23):
* TLSv1.3 (IN), TLS Unknown, Unknown (23):
<!doctype html>
<html>
<head>
    <title>Example Domain</title>

    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style type="text/css">
    body {
        background-color: #f0f0f2;
        margin: 0;
        padding: 0;
        font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;

    }
    div {
        width: 600px;
        margin: 5em auto;
        padding: 2em;
        background-color: #fdfdff;
        border-radius: 0.5em;
        box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
    }
    a:link, a:visited {
        color: #38488f;
        text-decoration: none;
    }
    @media (max-width: 700px) {
        div {
            margin: 0 auto;
            width: auto;
        }
    }
    </style>
</head>

<body>
<div>
    <h1>Example Domain</h1>
    <p>This domain is for use in illustrative examples in documents. You may use this
    domain in literature without prior coordination or asking for permission.</p>
    <p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>
* Connection #0 to host 127.0.0.1 left intact

Enter fullscreen mode Exit fullscreen mode

As you can see above Curl Sends a Connect Request Prior.

So, we found that it is Very Easy for a Proxy to identify which remote server the user wants to connect to.

and based on that, The Proxy can have add a Condition whether to let users to access Remote Server or do not allow it.
How Efficiently, Easy, Useful depends on the Proxy

Quick Example: Inorder to Block a Domain in Squid, we need to restart Squid Service.
Same if we do that in Any Other Proxy it will Provide you a Dashboard to add domains and BLOCK it in Realtime

........... Post Will be Updated Soon.........

Top comments (0)