How to add additional headers in https proxy? - http

I created on golang double HTTP proxy server. Server receives request, adds additional headers in this request and sends this changed request to another proxy server, which read this headers, remove it from request, and finally make request into destination.
With HTTP it works perfect. But how create this with HTTPS ?!
In HTTPS request browser send http CONNECT request, and then send encrypted data. Can i decrypted this data with CA signed server certificate, then add headers, send HTTPS request to another server, and then send HTTPS request to destination !?

Related

Do servers send responses back to proxy servers or directly to clients?

Given a client sending requests to a proxy server. The proxy server forwards the requests to another server.
Does this "other" server send the response directly back to the client like so
or does it send the response to the proxy server and the proxy server sends the response back to the client like so

Is there an HTTP response code for a proxy to make browser directly connect to target?

I want to set up a custom proxy that proxies connections to some destinations (inside a network) but not other destinations (in the global internet). Is there any HTTP response the proxy server can send to make the browser connect directly to the requested destination?
For example, I request redirection to Google to my proxy server. The proxy server decides not to proxy, so I get this HTTP response, and my browser connects directly to Google.
You could send a redirect http response code like 302 to redirect the client directly to the website. See: https://moz.com/learn/seo/redirection

How http proxy clients work

if an HTTP client reaches a website through a proxy (not reverse proxy) server, what are the actual HTTP request and its parameters that are sent from this client host to the internet?
for example:
Proxy Server: www.proxy.com:80
Target website: www.website.com:8081
Does the HTTP client send the following Get request?
Get http://www.proxy.com:80
Host: www.proxy.com:80
OR
Get http://www.website.com:8081
Host: www.website.com:8081
if the first case is true, How can the proxy know what is the actual destination to forward this request?
otherwise, if the second is true, how can the request actually reach the proxy host machine?
When you want to issue a GET request to http://www.example.com:8081/index.html, the browser connects to www.example.com:8081 and sends the following request:
GET /index.html HTTP/1.1
Host: www.example.com:8081
Now when a proxy is configured, say www.proxy.com:80, the browser will connect to www.proxy.com:80 instead, and issue the following request:
GET http://www.example.com:8081/index.html HTTP/1.1
Host: www.example.com:8081
So when a proxy is configured, the HTTP client connects to the proxy instead of to the target server, and sends the request using the absolute URI.
The client doesn't have to change the HTTP request for it to be sent to a proxy. It has to change the TCP headers.
The screenshot below shows a HTTP request sent from my browser to a proxy, as you can see nothing in the HTTP request itself specifies the proxy.
How this works is the browser/client will issue a HTTP GET request, which will then be forwarded to the TCP/IP stack and wrapped in a TCP header. The TCP header is where the destination is specified (proxy or otherwise).
Http proxy server can read http headers.
Whenever we use http proxy the destination address in the tcp packet(originating from client) has destination address of proxy server..
When the proxy server receives the tcp packet it can read the http headers(which is present in tcp packet payload) the http headers contains the actual destination for the packet.. using this information the http proxy server can forward the packet to actual destination.
Source : https://www.ibm.com/support/knowledgecenter/SSBLQQ_9.1.0/com.ibm.rational.ritpp.install.doc/topics/c_ritpp_advanced_proxy.html

Which changes do a browser make when using an HTTP Proxy?

Imagine a webbrowser that makes an HTTP request to a remote server, such as site.example.com
If the browser is then configured to use a proxy server, let's call it proxy.example.com using port 8080, in which ways are the request now different?
Obviously the request is now sent to proxy.example.com:8080, but there must surely be other changes to enable the proxy to make a request to the original url?
RFC 7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing, Section 5.3.2. absolute-form:
When making a request to a proxy, other than a CONNECT or server-wide
OPTIONS request (as detailed below), a client MUST send the target
URI in absolute-form as the request-target.
absolute-form = absolute-URI
The proxy is requested to either service that request from a valid
cache, if possible, or make the same request on the client's behalf
to either the next inbound proxy server or directly to the origin
server indicated by the request-target. Requirements on such
"forwarding" of messages are defined in Section 5.7.
An example absolute-form of request-line would be:
GET http://www.example.org/pub/WWW/TheProject.html HTTP/1.1
So, without proxy, the connection is made to www.example.org:80:
GET /pub/WWW/TheProject.html HTTP/1.1
Host: www.example.org
With proxy it is made to proxy.example.com:8080:
GET http://www.example.org/pub/WWW/TheProject.html HTTP/1.1
Host: www.example.org
Where in the latter case the Host header is optional (for HTTP/1.0 clients), and must be recalculated by the proxy anyway.
The proxy simply makes the request on behalf of the original client. Hence the name "proxy", the same meaning as in legalese. The browser sends their request to the proxy, the proxy makes a request to the requested server (or not, depending on whether the proxy wants to forward this request or deny it), the server returns a response to the proxy, the proxy returns the response to the original client. There's no fundamental difference in what the server will see, except for the fact that the originating client will appear to be the proxy server. The proxy may or may not alter the request, and it may or may not cache it; meaning the server may not receive a request at all if the proxy decides to deliver a cached version instead.

HTTP Spec: Proxy-Authorization and Authorization headers

So I'm trying to implement the following scenario:
An application is protected by Basic Authentication. Let's say it is hosted on app.com
An HTTP proxy, in front of the application, requires authentication as well. It is hosted on proxy.com
The user must therefore provide credentials for both the proxy and the application in the same request, thus he has different username/password pairs: one pair to authenticate himself against the application, and another username/password pair to authenticate himself against the proxy.
After reading the specs, I'm not really sure on how I should implement this. What I was thinking to do is:
The user makes an HTTP request to the proxy without any sort of authentication.
The proxy answers 407 Proxy Authentication Required and returns a Proxy-Authenticate header in the format of: "Proxy-Authenticate: Basic realm="proxy.com".Question: Is this Proxy-Authenticate header correctly set?
The client then retries the request with a Proxy-Authorization header, that is the Base64 representation of the proxy username:password.
This time the proxy authenticates the request, but then the application answers with a 401 Unauthorized header. The user was authenticated by the proxy, but not by the application. The application adds a WWW-Authenticate header to the response like WWW-Authenticate: Basic realm="app.com". Question: this header value is correct right?
The client retries again the request with both a Proxy-Authorization header, and a Authorization header valued with the Base64 representation of the app's username:password.
At this point, the proxy successfully authenticates the request, forwards the request to the application that authenticates the user as well. And the client finally gets a response back.
Is the whole workflow correct?
Yes, that looks like a valid workflow for the situation you described, and those Authenticate headers seem to be in the correct format.
It's interesting to note that it's possible, albeit unlikely, for a given connection to involve multiple proxies that are chained together, and each one can itself require authentication. In this case, the client side of each intermediate proxy would itself get back a 407 Proxy Authentication Required message and itself repeat the request with the Proxy-Authorization header; the Proxy-Authenticate and Proxy-Authorization headers are single-hop headers that do not get passed from one server to the next, but WWW-Authenticate and Authorization are end-to-end headers that are considered to be from the client to the final server, passed through verbatim by the intermediaries.
Since the Basic scheme sends the password in the clear (base64 is a reversible encoding) it is most commonly used over SSL. This scenario is implemented in a different fashion, because it is desirable to prevent the proxy from seeing the password sent to the final server:
the client opens an SSL channel to the proxy to initiate the request, but instead of submitting a regular HTTP request it would submit a special CONNECT request (still with a Proxy-Authorization header) to open a TCP tunnel to the remote server.
The client then proceeds to create another SSL channel nested inside the first, over which it transfers the final HTTP message including the Authorization header.
In this scenario the proxy only knows the host and port the client connected to, not what was transmitted or received over the inner SSL channel. Further, the use of nested channels allows the client to "see" the SSL certificates of both the proxy and the server, allowing the identity of both to be authenticated.

Resources