From 4a8d40b55353c58d0a7d70dc3211543e33189edb Mon Sep 17 00:00:00 2001 From: gongqianye241 Date: Wed, 13 Sep 2023 14:45:18 -0400 Subject: [PATCH 1/4] Add connection status feedback for socks proxy connections. Adds feedbacks for socks proxy connections to explain if connection succeed or refuse. Ports now can be determined open/close for scanning using proxychains nmap -sT ... This fixes bug where all ports are determined open when scanning. --- common.h | 11 +++- handler.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++------- message.c | 14 +++++ protocol.h | 4 +- proxy.c | 37 ++++++++++++ 5 files changed, 205 insertions(+), 25 deletions(-) diff --git a/common.h b/common.h index ba9900d..04126cd 100644 --- a/common.h +++ b/common.h @@ -112,11 +112,13 @@ #define CON_DORMANT 4 /* Apparently reply strings for socks requests are static in the modern era. */ -#define SOCKS_V4_REPLY "\x00\x5a\x00\x00\x00\x00\x00\x00" +#define SOCKS_V4_REPLY_OK "\x00\x5a\x00\x00\x00\x00\x00\x00" +#define SOCKS_V4_REPLY_ERR "\x00\x5b\x00\x00\x00\x00\x00\x00" #define SOCKS_V4_REPLY_LEN 8 #define SOCKS_V5_AUTH_REPLY "\x05\x00" #define SOCKS_V5_AUTH_REPLY_LEN 2 -#define SOCKS_V5_REPLY "\x05\x00\x00\x01\x00\x00\x00\x00\x00\x00" +#define SOCKS_V5_REPLY_OK "\x05\x00\x00\x01\x00\x00\x00\x00\x00\x00" +#define SOCKS_V5_REPLY_ERR "\x05\x01\x00\x01\x00\x00\x00\x00\x00\x00" #define SOCKS_V5_REPLY_LEN 10 /* Maximum possible size of a socks request. */ @@ -203,6 +205,8 @@ int handle_message_dt_connection_ht_create_tun_tap(); int handle_message_dt_connection_ht_response(); int handle_connection_activate(struct connection_node *cur_connection_node); int handle_message_dt_connection_ht_active_dormant(); +int handle_message_dt_connection_ht_connected(); +int handle_message_dt_connection_ht_refused(); int handle_message_dt_connection_ht_data(); int handle_proxy_read(struct proxy_node *cur_proxy_node); int handle_connection_write(struct connection_node *cur_connection_node); @@ -213,6 +217,8 @@ int handle_send_dt_proxy_ht_create(char *proxy_string, int proxy_type); int handle_send_dt_proxy_ht_report(struct proxy_node *cur_proxy_node); int handle_send_dt_connection_ht_destroy(unsigned short origin, unsigned short id, unsigned short header_errno); int handle_send_dt_connection_ht_create(struct connection_node *cur_connection_node); +int handle_send_dt_connection_ht_connected(unsigned short origin, unsigned short id); +int handle_send_dt_connection_ht_refused(unsigned short origin, unsigned short id); int handle_send_dt_nop(); struct connection_node *handle_tun_tap_init(int ifr_flag); @@ -253,6 +259,7 @@ struct connection_node *connection_node_create(); void connection_node_delete(struct connection_node *); struct connection_node *connection_node_find(unsigned short origin, unsigned short id); void connection_node_queue(struct connection_node *cur_connection_node); +void connection_node_socks_reply(struct connection_node *, int ok); int parse_socks_request(struct connection_node *cur_connection_node); char *addr_to_string(int atype, char *addr, char *port, int len); diff --git a/handler.c b/handler.c index 324df1d..155b2d8 100644 --- a/handler.c +++ b/handler.c @@ -445,6 +445,7 @@ int handle_message_dt_connection_ht_create(){ cur_connection_node->origin = message->header_origin; cur_connection_node->id = message->header_id; cur_connection_node->proxy_type = message->header_proxy_type; + cur_connection_node->socks_type = message->header_socks_type; if((cur_connection_node->rhost_rport = (char *) calloc(message->data_len + 1, sizeof(char))) == NULL){ report_error("handle_message_dt_connection_ht_create(): calloc(%d, %d): %s", message->data_len + 1, (int) sizeof(char), strerror(errno)); @@ -581,6 +582,11 @@ int handle_connection_activate(struct connection_node *cur_connection_node){ fprintf(stderr, "\rConnection failed: %s, %s\n", cur_connection_node->rhost_rport, strerror(optval)); } + if(handle_send_dt_connection_ht_refused(cur_connection_node->origin, cur_connection_node->id) == -1){ + report_error("handle_connection_activate(): handle_send_dt_connection_ht_refused(%d, %d, 0): %s", cur_connection_node->origin, cur_connection_node->id, strerror(errno)); + return(-1); + } + if(handle_send_dt_connection_ht_destroy(cur_connection_node->origin, cur_connection_node->id, 0) == -1){ report_error("handle_connection_activate(): handle_send_dt_connection_ht_destroy(%d, %d, 0): %s", cur_connection_node->origin, cur_connection_node->id, strerror(errno)); return(-1); @@ -592,6 +598,8 @@ int handle_connection_activate(struct connection_node *cur_connection_node){ cur_connection_node->state = CON_ACTIVE; + handle_send_dt_connection_ht_connected(cur_connection_node->origin, cur_connection_node->id); + return(0); } @@ -730,6 +738,64 @@ int handle_message_dt_connection_ht_data(){ } +/****************************************************************************** + * + * handle_message_dt_connection_ht_connected() + * + * Inputs: None, but we will leverage the global io struct. + * Outputs: 0 for success. -1 on fatal error. -2 on non-fatal error. + * + * Purpose: Handle the broker case where a connection has succeeded. + * + ******************************************************************************/ +int handle_message_dt_connection_ht_connected(){ + struct connection_node *cur_connection_node; + + + if((cur_connection_node = connection_node_find(message->header_origin, message->header_id)) == NULL){ + + if(handle_send_dt_connection_ht_destroy(message->header_origin, message->header_id, 0) == -1){ + report_error("handle_message_dt_connection(): handle_send_dt_connection_ht_destroy(%d, %d, 0): %s", message->header_origin, message->header_id, strerror(errno)); + return(-1); + } + return(-2); + } + + connection_node_socks_reply(cur_connection_node, 1); + + return(0); +} + + +/****************************************************************************** + * + * handle_message_dt_connection_ht_refused() + * + * Inputs: None, but we will leverage the global io struct. + * Outputs: 0 for success. -1 on fatal error. -2 on non-fatal error. + * + * Purpose: Handle the broker case where a connection was refused. + * + ******************************************************************************/ +int handle_message_dt_connection_ht_refused(){ + struct connection_node *cur_connection_node; + + + if((cur_connection_node = connection_node_find(message->header_origin, message->header_id)) == NULL){ + + if(handle_send_dt_connection_ht_destroy(message->header_origin, message->header_id, 0) == -1){ + report_error("handle_message_dt_connection(): handle_send_dt_connection_ht_destroy(%d, %d, 0): %s", message->header_origin, message->header_id, strerror(errno)); + return(-1); + } + return(-2); + } + + connection_node_socks_reply(cur_connection_node, 0); + + return(0); +} + + /****************************************************************************** * * handle_proxy_read() @@ -995,32 +1061,24 @@ int handle_connection_socks_init(struct connection_node *cur_connection_node){ if(new_state == CON_SOCKS_V5_AUTH){ reply_buff = SOCKS_V5_AUTH_REPLY; reply_buff_len = SOCKS_V5_AUTH_REPLY_LEN; - }else if(new_state == CON_ACTIVE){ - if(cur_connection_node->state == CON_SOCKS_INIT){ - reply_buff = SOCKS_V4_REPLY; - reply_buff_len = SOCKS_V4_REPLY_LEN; - }else if(cur_connection_node->state == CON_SOCKS_V5_AUTH){ - reply_buff = SOCKS_V5_REPLY; - reply_buff_len = SOCKS_V5_REPLY_LEN; - } - } - - retval = write(cur_connection_node->fd, reply_buff, reply_buff_len); + retval = write(cur_connection_node->fd, reply_buff, reply_buff_len); - if(retval == -1){ - report_error("handle_connection_socks_init(): write(%d, %lx, %d): %s", cur_connection_node->fd, (unsigned long) reply_buff, reply_buff_len, strerror(errno)); - return(-1); - } - - if(retval != reply_buff_len){ - report_error("handle_connection_socks_init(): write(%d, %lx, %d): Unable to send SOCKS reply.", cur_connection_node->fd, (unsigned long) reply_buff, reply_buff_len); - if(handle_send_dt_connection_ht_destroy(cur_connection_node->origin, cur_connection_node->id, 0) == -1){ - report_error("handle_connection_socks_init(): handle_send_dt_connection_ht_destroy(%d, %d, 0): %s", cur_connection_node->origin, cur_connection_node->id, strerror(errno)); + if(retval == -1){ + report_error("handle_connection_socks_init(): write(%d, %lx, %d): %s", cur_connection_node->fd, (unsigned long) reply_buff, reply_buff_len, strerror(errno)); return(-1); } - connection_node_delete(cur_connection_node); + + if(retval != reply_buff_len){ + report_error("handle_connection_socks_init(): write(%d, %lx, %d): Unable to send SOCKS reply.", cur_connection_node->fd, (unsigned long) reply_buff, reply_buff_len); + if(handle_send_dt_connection_ht_destroy(cur_connection_node->origin, cur_connection_node->id, 0) == -1){ + report_error("handle_connection_socks_init(): handle_send_dt_connection_ht_destroy(%d, %d, 0): %s", cur_connection_node->origin, cur_connection_node->id, strerror(errno)); + return(-1); + } + connection_node_delete(cur_connection_node); + } } + cur_connection_node->state = new_state; // Handle the case where we have a rude client that doesn't wait for data and just fills our buffer with both halves of the @@ -1179,7 +1237,6 @@ int handle_send_dt_proxy_ht_report(struct proxy_node *cur_proxy_node){ return(0); } - /****************************************************************************** * * handle_send_dt_connection_ht_destroy() @@ -1242,6 +1299,7 @@ int handle_send_dt_connection_ht_create(struct connection_node *cur_connection_n message->header_origin = cur_connection_node->origin; message->header_id = cur_connection_node->id; message->header_proxy_type = cur_connection_node->proxy_type; + message->header_socks_type = cur_connection_node->socks_type; memset(message->data, 0, io->message_data_size); count = strlen(cur_connection_node->rhost_rport); @@ -1288,6 +1346,68 @@ int handle_send_dt_nop(){ } +/****************************************************************************** + * + * handle_send_dt_connection_ht_connected() + * + * Inputs: The origin and id tuple that identify the related connection. + * We will also leverage the global io struct. + * Outputs: 0 for success. -1 on fatal error. + * + * Purpose: Handle the broker case where we need to notify the remote node + * that a connection has been successfully connected. + * + ******************************************************************************/ +int handle_send_dt_connection_ht_connected(unsigned short origin, unsigned short id){ + + int retval; + + message->data_type = DT_CONNECTION; + message->header_type = DT_CONNECTION_HT_CONNECTED; + message->header_origin = origin; + message->header_id = id; + message->data_len = 0; + + if((retval = message_push()) == -1){ + report_error("handle_send_dt_connection_ht_connected(): message_push(): %s", strerror(errno)); + return(-1); + } + + return(0); +} + + +/****************************************************************************** + * + * handle_send_dt_connection_ht_refused() + * + * Inputs: The origin and id tuple that identify the related connection. + * We will also leverage the global io struct. + * Outputs: 0 for success. -1 on fatal error. + * + * Purpose: Handle the broker case where we need to notify the remote node + * that a connection has been refused. + * + ******************************************************************************/ +int handle_send_dt_connection_ht_refused(unsigned short origin, unsigned short id){ + + int retval; + + message->data_type = DT_CONNECTION; + message->header_type = DT_CONNECTION_HT_REFUSED; + message->header_origin = origin; + message->header_id = id; + message->data_len = 0; + + if((retval = message_push()) == -1){ + report_error("handle_send_dt_connection_ht_refused(): message_push(): %s", strerror(errno)); + return(-1); + } + + return(0); +} + + /****************************************************************************** * * handle_tun_tap_init() diff --git a/message.c b/message.c index c701aba..8f75971 100644 --- a/message.c +++ b/message.c @@ -25,6 +25,7 @@ int message_push(){ header_len += sizeof(message->header_type) + sizeof(message->header_origin) + sizeof(message->header_id); if(message->header_type == DT_PROXY_HT_CREATE || message->header_type == DT_PROXY_HT_REPORT || message->header_type == DT_CONNECTION_HT_CREATE){ header_len += sizeof(message->header_proxy_type); + header_len += sizeof(message->header_socks_type); } } @@ -92,6 +93,12 @@ int message_push(){ (unsigned long) &tmp_short, (int) sizeof(tmp_short), strerror(errno)); return(-1); } + tmp_short = htons(message->header_socks_type); + if(io->remote_write(&tmp_short, sizeof(tmp_short)) == -1){ + report_error("message_push(): remote_write(%lx, %d): %s", \ + (unsigned long) &tmp_short, (int) sizeof(tmp_short), strerror(errno)); + return(-1); + } } } @@ -188,6 +195,13 @@ int message_pull(){ } message->header_proxy_type = ntohs(message->header_proxy_type); header_len -= sizeof(message->header_proxy_type); + if((retval = io->remote_read(&message->header_socks_type, sizeof(message->header_socks_type))) == -1){ + report_error("message_pull(): remote_read(%lx, %d): %s", \ + (unsigned long) &message->header_socks_type, (int) sizeof(message->header_socks_type), strerror(errno)); + return(-1); + } + message->header_socks_type = ntohs(message->header_socks_type); + header_len -= sizeof(message->header_socks_type); } } diff --git a/protocol.h b/protocol.h index b1848a2..0330b6a 100644 --- a/protocol.h +++ b/protocol.h @@ -10,7 +10,7 @@ */ #define PROTOCOL_MAJOR_VERSION 1 -#define PROTOCOL_MINOR_VERSION 0 +#define PROTOCOL_MINOR_VERSION 1 /********************************************************************************************************************** * @@ -167,6 +167,8 @@ // As such, this reporting is typically handled as a best effort without guarantee of delivery. #define DT_ERROR 6 +#define DT_CONNECTION_HT_CONNECTED 7 +#define DT_CONNECTION_HT_REFUSED 8 /* * Other protocol constants used in messaging. */ diff --git a/proxy.c b/proxy.c index 169286c..5d0273c 100644 --- a/proxy.c +++ b/proxy.c @@ -410,6 +410,41 @@ struct connection_node *connection_node_create(){ return(cur_connection_node); } +/****************************************************************************** + * + * connection_node_socks_reply() + * + * Inputs: A pointer to the connection_node and the socks reply type to send (0 + * for error. 1 for ok). + * + * Outputs: None. + * + * Purpose: Report back to the socks client whether the requested connection + * request succeeded or not. + * + ******************************************************************************/ +void connection_node_socks_reply(struct connection_node *cur_connection_node, int ok){ + char *reply_buff = NULL; + int reply_buff_len = 0; + if (cur_connection_node->socks_type == 4) { + if(ok) { + reply_buff = SOCKS_V4_REPLY_OK; + } + else { + reply_buff = SOCKS_V4_REPLY_ERR; + } + reply_buff_len = SOCKS_V4_REPLY_LEN; + } else if (cur_connection_node->socks_type == 5) { + if(ok) { + reply_buff = SOCKS_V5_REPLY_OK; + } + else { + reply_buff = SOCKS_V5_REPLY_ERR; + } + reply_buff_len = SOCKS_V5_REPLY_LEN; + } + write(cur_connection_node->fd, reply_buff, reply_buff_len); +} /****************************************************************************** * @@ -555,6 +590,7 @@ int parse_socks_request(struct connection_node *cur_connection_node){ // Socks 4 or 4a. if(head[index] == 4){ + cur_connection_node->socks_type = 4; /* * +----+----+----+----+----+----+----+----+----+----+....+----+ @@ -641,6 +677,7 @@ int parse_socks_request(struct connection_node *cur_connection_node){ // SOCKS 5 }else if(head[index] == 5){ + cur_connection_node->socks_type = 5; if(cur_connection_node->state == CON_SOCKS_INIT){ index += 1; From 84f03b8ee9f9ddb889fdebbd54e96bc0ab877e07 Mon Sep 17 00:00:00 2001 From: gongqianye241 Date: Wed, 22 Nov 2023 23:11:23 -0500 Subject: [PATCH 2/4] Add missing fields --- helper_objects.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/helper_objects.h b/helper_objects.h index 99530ac..f634946 100644 --- a/helper_objects.h +++ b/helper_objects.h @@ -20,6 +20,8 @@ struct message_helper { // Proxy types are defined in the protocol.h file. unsigned short header_proxy_type; + unsigned short header_socks_type; + char *data; struct message_helper *next; @@ -122,6 +124,7 @@ struct connection_node { unsigned short origin; unsigned short id; unsigned short proxy_type; + unsigned short socks_type; int fd; // A copy of the original rhost_rport string in the related proxy_node struct, to simplify retry requests. From 8b44be7dc7cd6477ae7d8526968f123067d6579a Mon Sep 17 00:00:00 2001 From: gongqianye241 Date: Wed, 22 Nov 2023 23:12:12 -0500 Subject: [PATCH 3/4] Fix warning --- proxy.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/proxy.c b/proxy.c index 5d0273c..31716a4 100644 --- a/proxy.c +++ b/proxy.c @@ -443,7 +443,9 @@ void connection_node_socks_reply(struct connection_node *cur_connection_node, in } reply_buff_len = SOCKS_V5_REPLY_LEN; } - write(cur_connection_node->fd, reply_buff, reply_buff_len); + if(write(cur_connection_node->fd, reply_buff, reply_buff_len) == -1) { + report_error("connection_node_socks_reply(): write(%d, %lx, %d): %s", cur_connection_node->fd, (unsigned long) reply_buff, reply_buff_len, strerror(errno)); + } } /****************************************************************************** From 8de5a6dc50dd205afd1a94eff736a0d6663a35a5 Mon Sep 17 00:00:00 2001 From: gongqianye241 Date: Fri, 1 Dec 2023 01:51:21 -0500 Subject: [PATCH 4/4] Fix missing handling in broker --- broker.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/broker.c b/broker.c index c787abf..613fdc9 100644 --- a/broker.c +++ b/broker.c @@ -352,6 +352,20 @@ int broker(){ goto RETURN; } + }else if(message->header_type == DT_CONNECTION_HT_CONNECTED){ + + if((retval = handle_message_dt_connection_ht_connected()) == -1){ + report_error("broker(): handle_message_dt_connection_ht_connected(): %s", strerror(errno)); + goto RETURN; + } + + }else if(message->header_type == DT_CONNECTION_HT_REFUSED){ + + if((retval = handle_message_dt_connection_ht_refused()) == -1){ + report_error("broker(): handle_message_dt_connection_ht_refused(): %s", strerror(errno)); + goto RETURN; + } + }else{ // Unknown connection type. Report but soldier on. report_error("broker(): Unknown Connection Header Type: %d: Ignoring.", message->header_type);