I am trying to write a C code to open an SSL connection with a remote server via a SOCKS5 proxy server.
I have successfully opened a tcp connection with the SOCKS5 proxy server. However, I do not know how to make an SSL connection with the remote server (different from proxy server).
// p->ai_addr has the SOCKS5 proxy address
m_sock_fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
connect(m_sock_fd, p->ai_addr, p->ai_addrlen);
char socks5_request[256] = {0}, response[256] = {0};
sprintf(socks5_request, "\5\1\0");
send(m_sock_fd, socks5_request, 4, 0);
recv(m_sock_fd, response, 256, 0);
assert(response[0] == '\5' && response[1] == '\0'); // OK
m_ssl_ctx = SSL_CTX_new(SSLv23_client_method());
m_ssl = SSL_new(m_ssl_ctx);
SSL_set_fd(m_ssl, m_sock_fd);
SSL_connect(m_ssl); // returns -1
SSL_connect failed and gave error:1408F10B:SSL routines:ssl3_get_record:wrong version number:ssl/record/ssl3_record.c:332:
I have two questions.
Update 4/2/2019
Code below is for sending connect request to proxy server. The last call for CheckConnectivity() found the connection closed.
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("*.*.*.*");
addr.sin_port = htons(443);
SOCKSRequest connect_request;
// 5: protocol number, 1: connect, 0: reserved, 1: ipv4
connect_request.m_version = '\5';
connect_request.m_type = '\1';
connect_request.m_reserved = '\0';
connect_request.m_addr_type = '\1';
connect_request.m_ip = addr.sin_addr.s_addr;
connect_request.m_port = addr.sin_port;
CheckConnectivitiy();
if (!send(m_sock_fd, &connect_request, 4, 0))
return 0;
CheckConnectivitiy();
if (!send(m_sock_fd, &connect_request.m_ip, sizeof(in_addr), 0))
return 0;
CheckConnectivitiy();
if (!send(m_sock_fd, &connect_request.m_port, 2, 0))
return 0;
CheckConnectivitiy(); // connection was closed by peer here!
Implementation of CheckConnectivity.
int CheckConnectivitiy() const
{
int error = 0;
socklen_t len = sizeof (error);
int retval = getsockopt (m_sock_fd, SOL_SOCKET, SO_ERROR, &error, &len);
if (retval != 0)
{
/* there was a problem getting the error code */
fprintf(stderr, "error getting socket error code: %s\n", strerror(retval));
return 0;
}
if (error != 0)
{
/* socket has a non zero error status */
fprintf(stderr, "socket error: %s\n", strerror(error));
return 0;
}
return 1;
}
You need only 1 connection, you to the proxy. You tell the proxy where it should connect to next (you are not doing that!). Only if the proxy successfully connects will you have a valid connection to the target server. Only then can you send the SSL/TLS handshake, as if you had connected to the target server directly.
I suggest you read RFC 1928 for the SOCKS v5 protocol. You are sending an Authentication request and reading its response, but you are not sending a Connect request and reading is response, before you attempt to use SSL/TLS. That is why the handshake is failing. You are not connected to the target server yet.