MEDIUM: connection: Upstream SOCKS4 proxy support
Have "socks4" and "check-via-socks4" server keyword added.
Implement handshake with SOCKS4 proxy server for tcp stream connection.
See issue #82.
I have the "SOCKS: A protocol for TCP proxy across firewalls" doc found
at "https://www.openssh.com/txt/socks4.protocol". Please reference to it.
[wt: for now connecting to the SOCKS4 proxy over unix sockets is not
supported, and mixing IPv4/IPv6 is discouraged; indeed, the control
layer is unique for a connection and will be used both for connecting
and for target address manipulation. As such it may for example report
incorrect destination addresses in logs if the proxy is reached over
IPv6]
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index f595029..7ae28f0 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -294,6 +294,7 @@
struct proxy *be;
struct conn_src *src;
int use_fastopen = 0;
+ struct sockaddr_storage *addr;
conn->flags |= CO_FL_WAIT_L4_CONN; /* connection in progress */
@@ -514,7 +515,8 @@
if (global.tune.server_rcvbuf)
setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &global.tune.server_rcvbuf, sizeof(global.tune.server_rcvbuf));
- if (connect(fd, (struct sockaddr *)&conn->addr.to, get_addr_len(&conn->addr.to)) == -1) {
+ addr = (conn->flags & CO_FL_SOCKS4) ? &srv->socks4_addr : &conn->addr.to;
+ if (connect(fd, (const struct sockaddr *)addr, get_addr_len(addr)) == -1) {
if (errno == EINPROGRESS || errno == EALREADY) {
/* common case, let's wait for connect status */
conn->flags |= CO_FL_WAIT_L4_CONN;
@@ -567,10 +569,6 @@
conn->flags |= CO_FL_ADDR_TO_SET;
- /* Prepare to send a few handshakes related to the on-wire protocol. */
- if (conn->send_proxy_ofs)
- conn->flags |= CO_FL_SEND_PROXY;
-
conn_ctrl_init(conn); /* registers the FD */
fdtab[fd].linger_risk = 1; /* close hard if needed */
@@ -663,6 +661,7 @@
*/
int tcp_connect_probe(struct connection *conn)
{
+ struct sockaddr_storage *addr;
int fd = conn->handle.fd;
socklen_t lskerr;
int skerr;
@@ -701,7 +700,11 @@
* - connecting (EALREADY, EINPROGRESS)
* - connected (EISCONN, 0)
*/
- if (connect(fd, (struct sockaddr *)&conn->addr.to, get_addr_len(&conn->addr.to)) < 0) {
+ addr = &conn->addr.to;
+ if ((conn->flags & CO_FL_SOCKS4) && obj_type(conn->target) == OBJ_TYPE_SERVER)
+ addr = &objt_server(conn->target)->socks4_addr;
+
+ if (connect(fd, (const struct sockaddr *)addr, get_addr_len(addr)) == -1) {
if (errno == EALREADY || errno == EINPROGRESS) {
__conn_sock_stop_recv(conn);
fd_cant_send(fd);