I've build a proxy with some logic on request headers.
I use sockets.
Before even any connect occurs, inside my proxy I parse headers, add authentification
and forward the request to target host.
And now I've stumbled upon following issues:
I have to relay https requests
I don't need any body manipulations, I just need to modify headers the same way, forward CONNECT to target, receive an answer and return to source socket.
Questions:
Do I need CA on the proxy side?
Do I need to use SSlStream to forward and receive request?
If so, what could be the algorithm?
The SSL handshake comes after the CONNECT request and its response. If you only need to manipulate the CONNECT request you can simply forward the data after the handshake between the peers, e.g. no SSL interception which means no SSLStream and no CA. But, if you need to manipulate the HTTP headers of the requests inside the HTTPS connection (GET, POST...) you have to do SSL interception (e.g. man-in-the-middle with your own proxy CA and SSLStream).
Related
I'm writing a basic HTTP proxy for a school project using HttpWebRequest HttpWebResponse. It's all working great for HTTP requests, but when it comes to receiving a HTTPS request it fails miserably.
I don't want the proxy to intercept and decrypt HTTPS traffic, merely just pass it along. I know I could just change the proxy server settings in windows to only handle HTTP traffic, but I'd really like to try and handle it some way. How can this be done?
Help appreciated.
I'm trying to write a Home Proxy Server in C# and I almost succeeded but I have problem to handle HTTPS requests (CONNECT).
I don't know really how to handle this type of requests.
In my studies I realized that for this requests we must to connect client to target host directly.
Steps for these requests (that I realized):
Receive first request from client (CONNECT https://www.example.ltd:443 HTTP/1.1) and send that to target host
Send HTTP/1.1 200 Connection Established\r\n\r\n to client
Listen to both sockets (client and target host) and send receives from each other to each other
Listen until one of sockets disconnected
Is this correct? If it ok, how handle this by c# ?
My understanding is that the
CONNECT www.example.com:443 HTTP/1.1
from the browser is asking you to establish a connection to example.com on port 443. Once this has been successfully achieved, you should THEN send the
HTTP/1.1 200 Connection established\r\n\r\n
string back to the browser. You do not send the CONNECT string to the server as I think you were doing. Also, this initial connection SHOULD NOT be encrypted.
From this point, the browser and end server will exchange data over the plain text connection which you must forward to the correct destination. To do this, the socket must remain open. However, the order of communication is not specified, so don't rely on the browser sending data followed by a response from server. Either could send data at any point. They will first establish their own secure connection, then begin to do the usual http requests.
Hope this helps.
References:
https://stackoverflow.com/a/24195792/1224132
https://datatracker.ietf.org/doc/html/draft-luotonen-ssl-tunneling-03
http://www.ietf.org/rfc/rfc2817.txt
I have custom tcp server listening on port 5888(dummy port). The proxy server listens for incoming connections. When the proxy receives a HTTP Request, it should relay the same request to a different server.
Eg:
Proxy receives: http://proxyserver.com/mypage.html
Proxy should Relay: http://MainServer.com/mypage.html
The response from the Main Server should be sent directly to the requesting client.
I have used sockets for accepting connections and parsing the raw HTTP Request before relaying the new HTTP request to the main server. This is becoming too complicated, since I have to send the Raw HTTP Request to the main server, get the response and send it to the client machine.The proxy is basically becoming a middle-man. I want the proxy only for the
one side of communication i.e to change the host address to the MainServer and then the main server should take care of sending the response to the requesting client.
How to achieve this ?
HTTP works over a TCP connection initiated from a client to a server. In presence of proxy you need at least two connections - one from client to the proxy, and one from proxy to the server. These two connections are sort of "independent" in a sense that both transmit standard HTTP requests and responses. Proxy here acts as a client to the end server.
What you want involves at least three TCP connections, and requires sending HTTP response on a different connection from the one where initiating HTTP request came on. That is outside of the HTTP proper - the client wouldn't know that it needs a second connection somewhere else, and how to match requests on one connection to responses on the other. The best you can do within HTTP is redirecting to a different server, say, with a special generated URL or something.
Just remember that HTTP response has to come on the same TCP connection as the original request.
I'd like to determine whether the proxy at a given IP address is transparent or anonymous. Transparent proxies connect to websites with your real IP in headers like HTTP_X_FORWARDED_FOR or HTTP_VIA. I would like to check these proxies, but all solutions I found are developed to work on server side, to test incoming connections for proxyness. My plan is to make a web request to an example page via the proxy. How do I check the headers sent by the proxy, preferably using the WebRequest class?
EDIT: So is there some free web API that will allow me to do this? I'm not keen on setting up a script on my own small server that will be bombarded with requests.
Simply you don't need that headers. I could check transparency of a proxy by sending request to any get-my-IP site, if it returns my IP then it is transparent. If not then the proxy is anonymous. So steps are:
send request to any get-my-IP site without proxies
extract the IP from response as my local IP address
send new request to any get-my-IP site with the proxy
extract the IP from response and compare it with my local IP (step 2)
if(LocalIp==ProxyIp) then the proxy is transparent else it is anonymous
That is technically impossible since the client only sees what the proxy returns back to the client - the proxy can do whatever it wants when communicating with the target server and transform your request and the answer from the server anyway it wants...
To really know what the proxy does you NEED see what the server gets and sends back without any interference from the proxy...
The reason all solutions are server side is that the headers you're talking about are only passed from the proxy to the server and never back to the client again in the response.
In other words, if you plan to check for HTTP headers in the request from the proxy to the server, you either need to check them server side (as the solutions you found do) or actively pass them right back in the response to the client to check.
Either way, you can't just make a request to a random page and check the headers the server gets, the server needs to be involved in some way.
I realize that you can use a Socks5 proxy with WebProxy. That being said, what I am trying to do is this:
Open Up TCPListener -> Create request with HttpWebRequest that sends request to TCPListener using HttpWebRequest.Proxy -> Use either the NetworkStream or Socket from TCPListener to then forward the request through socket connected to a remote Socks5 proxy -> Return the response all the way back up the chain.
I am using Socket.Receive(); to read the bytes from the socket I accept with TCPClient then write them to a socket I've connected to the Socks5 proxy server with. This works great when my requests are just plain HTTP requests. I seem to be having problems requesting SSL pages. They aren't returning responses. Is there something I am missing or maybe even an easier way to do this? At this point I might even consider a library for sending Http Requests with a socks5 proxy.
You're actually doing a man-in-the-middle-attack. HttpWebRequest fails to verify your SSL certificate check and won't accept the connection (aka it knows something fishy is going on).
You can try this to work around the SSL-checks if you really need this working (and understand the consequences)