Consider this piece of code:
app.on("connection", (clientToProxySocket) => {
console.log("Client connected to proxy");
clientToProxySocket.once("data", (data) => {
let isConnectionTLS = data.toString().indexOf("CONNECT") !== -1;
let port= 80;
let host;
if (isConnectionTLS) {
serverPort = 443;
host= data
.toString().split("CONNECT")[1]
.split(" ")[1]
.split(":")[0];
} else {
serverAddress = data.toString().split("Host: ")[1].split("\n")[0];
}
let proxyToServerSocket = net.createConnection(
{host, port},
() => {}
)
if (isConnectionTLS) {
clientToProxySocket.write("HTTP/1.1 200 OKrnrn");
} else {
proxyToServerSocket.write(data);
}
const intermediatePipe = new stream.PassThrough();
intermediatePipe.on('data', (chunk) => {
console.log(chunk.toString());
});
clientToProxySocket.pipe(proxyToServerSocket);
proxyToServerSocket.pipe(clientToProxySocket);
// ... more events handling
})
})
//... more events handling
app.listen(
{
host: "0.0.0.0",
port: 8080,
},
() => {
console.log("Server listening on 0.0.0.0:8080");
}
);
My question is about the data
event of the clientToProxySocket
socket. What confuses me is that some data is consumed by the first listener (the one registered using once
), but this consumed data is still being seen in the pipe ( clientToProxySocket.pipe(proxyToServerSocket);
).
I tried this curl command:
curl https://httpbin.org/headers -x http://127.0.0.1:8080 -kv
And paused the code using the debugger to see what is in data
, I found:
CONNECT httpbin.org:443 HTTP/1.1
Host: httpbin.org:443
User-Agent: curl/8.7.1
Proxy-Connection: Keep-Alive
This lets me think that httpbin
will not see these headers because the are consumed in the first data
event and thus the piping will not include them, but curl shows this:
CONNECT httpbin.org:443 HTTP/1.1
Host: httpbin.org:443
User-Agent: curl/8.7.1
Proxy-Connection: Keep-Alive
Actually, httpbin.org
have recieved all the headers (the api I used just prints the request headers) while it shouldn’t: OK for the CONNECT
header to not be as it is performed by us in the net.createConnection
call.
My question goes in two parts:
- How could the headers be consumed in the first event but still included in piping?
- How could it be possible to see the headers plainly in an https connections while only
httpbin.org
who could decrypt the traffic?
yunus is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.