My proxy HTTPS, dealing with `CONNECT` HTTP requests from client, manages to connect immediately to the requested remote server after:
1. opening a socket to remote server;
2. setting the socket to non blocking mode;
3. attempting `connect()` checking for `if ((connect_res == -1) && (errno != EINPROGRESS))`;
4. looping with `select()` checking if server socket is ready to send or receive data in the following way:
if ((conn_res == -1) && (errno != EINPROGRESS)) {
do {
FD_ZERO(&rdset);
FD_SET(sockfd_server, &rdset);
wrset = rdset;
tv.tv_sec = 0;
tv.tv_usec = 0;
select_res = select(sockfd_server+1, &rdset, &wrset, NULL, &tv);
} while ((select_res == -1) && (errno == EINTR));
printf("connection OK\n");
} else {
printf("connected immediately\n");
}
5. setting socket back to blocking mode;
6. sending `"HTTP/1.1 200 Connection established\r\n"`to the client after successfull `connect()`.
Now I should be ready to forward data from client to server and from server to client when data are available from one of the two sides of connection, but it never succeeds.
Here's the code that should forward data from both sides of connection:
void proxyHTTPS(int new_sockfd_client, int sockfd_server) {
printf("starting proxyHTTPS\n");
fd_set fdset;
int maxp1 = sockfd_server > new_sockfd_client ? sockfd_server+1 : new_sockfd_client+1;
int r;
int read_from_client = 0;
int read_from_server = 0;
int send_to_client = 0;
int send_to_server = 0;
struct timeval timeout;
char https_buf[4096];
int https_buf_size = sizeof(https_buf);
memset(https_buf, 0, https_buf_size);
// tried 0, 5, 10, 20, 30, 60 seconds timeout,
// still got this problem
timeout.tv_sec = 10;
timeout.tv_usec = 0;
while (true) {
FD_ZERO(&fdset);
FD_SET(new_sockfd_client, &fdset);
FD_SET(sockfd_server, &fdset);
timeout.tv_sec = 10;
timeout.tv_usec = 0;
r = select(maxp1, &fdset, NULL, NULL, &timeout);
if (r == -1) {
perror("select()");
break;
}
if (r == 0) { // select timed out
printf("proxyHTTPS: select() request timeout 408\n");
break;
}
if ((!FD_ISSET(new_sockfd_client, &fdset)) && ((!FD_ISSET(sockfd_server, &fdset)))) {
printf("proxyHTTPS: SELECT sockfd not responding\n");
break;
}
else if (FD_ISSET(new_sockfd_client, &fdset)) {
printf("proxyHTTPS: reading from client and sending to server\n");
do {
read_from_client = recv(new_sockfd_client, https_buf, https_buf_size, 0);
if (read_from_client > 0) {
send_to_server = send(sockfd_server, https_buf, read_from_client, 0);
if (send_to_server <= 0) {
printf("proxyHTTPS: failed sending to server\n");
perror("proxyHTTPS send to server:");
break;
}
} else if (read_from_client == 0) {
printf("proxyHTTPS client sent 0 bytes\n");
} else {
perror("proxyHTTPS read from client:");
}
} while (read_from_client > 0);
break;
}
else if (FD_ISSET(sockfd_server, &fdset)) {
printf("proxyHTTPS: reading from server and sending to client\n");
do {
read_from_server = recv(sockfd_server, https_buf, https_buf_size, 0);
if (read_from_server > 0) {
send_to_client = send(new_sockfd_client, https_buf, read_from_server, 0);
if (send_to_client <= 0) {
printf("proxyHTTPS: failed sending to client\n");
perror("proxyHTTPS send to client:");
break;
}
} else if (read_from_server == 0) {
printf("proxyHTTPS server sent 0 bytes\n");
} else {
perror("proxyHTTPS read from server:");
}
} while (read_from_server > 0);
break;
}
}
printf("quitting proxyHTTPS\n");
}
This is, e.g., a `CONNECT` request the proxy gets from client:
CONNECT
www.youtube.com:443 HTTP/1.1
Host:
www.youtube.com:443
Proxy-Connection: keep-alive
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36
/r/n
If client sends `CONNECT
www.netflix.com:443 HTTP/1.1`, my proxy fails and on terminal prints:
setting non block socket
connected immediately
setting block socket
54.228.227.144:443 OK
CONNECT: send to client HTTP/1.1 200 Connection established
starting proxyHTTPS
proxyHTTPS: reading from server and sending to client
proxyHTTPS read from server: Connection refused
quitting proxyHTTPS
If clients sends `CONNECT
www.youtube.com:443 HTTP/1.1`, my proxy fails again and shows:
setting non block socket
connected immediately
setting block socket
216.58.201.238:443 OK
CONNECT: send to client HTTP/1.1 200 Connection established
starting proxyHTTPS
select(): Operation now in progress
proxyHTTPS: select() request timeout 408
quitting proxyHTTPS
I think i did all the steps I was told to do in order to establish a tunnel between client and server, `connect()` is always ok, so mistakes must be in my `proxyHTTPS`. I have no clue!