@cryptotaxi247 / netdata / commits / 87db53814

Record proxy information when establishing ACLK (#20747)

* Additional logging for ACLK connections when proxy is used Add ACLK proxy info in aclk-state CLI command and api/v1/aclk * Code formatting * Remove unused includes and clean up command pipe logging * Disable socks for now; not working * Remove SOCKS proxy environment check

Stelios Fragkakis committed Aug 3, 2025 at 21:11 UTC 87db5381490a3d2f3bb2a84a0a4558c6ba6fa7bd
12 files changed +90 -68
src/aclk/aclk.c
+16 -5
@@ -747,8 +747,14 @@ static int aclk_attempt_to_connect(mqtt_wss_client client)
747
748 int ssl_flags = cloud_config_insecure_get() ? MQTT_WSS_SSL_ALLOW_SELF_SIGNED : MQTT_WSS_SSL_CERT_CHECK_FULL;
749
750 - struct mqtt_wss_proxy proxy_conf = { .host = NULL, .port = 0, .username = NULL, .password = NULL, .type = MQTT_WSS_DIRECT };
751 - aclk_set_proxy((char**)&proxy_conf.host, &proxy_conf.port, (char**)&proxy_conf.username, (char**)&proxy_conf.password, &proxy_conf.type);
750 + struct mqtt_wss_proxy proxy_conf = { .host = NULL, .port = 0, .username = NULL, .password = NULL, .proxy_destination = NULL, .type = MQTT_WSS_DIRECT };
751 + aclk_set_proxy(
752 + (char **)&proxy_conf.host,
753 + &proxy_conf.port,
754 + (char **)&proxy_conf.username,
755 + (char **)&proxy_conf.password,
756 + (char **)&proxy_conf.proxy_destination,
757 + &proxy_conf.type);
758
759 #ifdef ACLK_DISABLE_CHALLENGE
760 int mqtt_rc = mqtt_wss_connect(client, base_url.host, base_url.port, &mqtt_conn_params, ssl_flags, &proxy_conf);
@@ -836,7 +842,7 @@ void aclk_main(void *ptr)
842 worker_register_job_name(WORKER_ACLK_WAITING_TO_CONNECT, "conn wait");
843
844 ACLK_PROXY_TYPE proxy_type;
839 - aclk_get_proxy(&proxy_type);
845 + aclk_get_proxy(&proxy_type, false);
846 if (proxy_type == PROXY_TYPE_SOCKS5) {
847 netdata_log_error("ACLK: SOCKS5 proxy is not supported by ACLK-NG yet.");
848 static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
@@ -1073,7 +1079,8 @@ char *aclk_state(void)
1079 buffer_strcat(wb, "No\n");
1080 else {
1081 const char *cloud_base_url = cloud_config_url_get();
1076 - buffer_sprintf(wb, "Yes\nClaimed Id: %s\nCloud URL: %s\n", claim_id.str, cloud_base_url ? cloud_base_url : "null");
1082 + char *aclk_proxy = (char *)aclk_get_proxy(NULL, true);
1083 + buffer_sprintf(wb, "Yes\nClaimed Id: %s\nCloud URL: %s\nACLK Proxy: %s\n", claim_id.str, cloud_base_url ? cloud_base_url : "null", aclk_proxy ? aclk_proxy : "none");
1084 }
1085
1086 buffer_sprintf(wb, "Online: %s\nReconnect count: %d\nBanned By Cloud: %s\n", aclk_online() ? "Yes" : "No", aclk_connection_counter > 0 ? (aclk_connection_counter - 1) : 0, aclk_disable_runtime ? "Yes" : "No");
@@ -1200,6 +1207,10 @@ char *aclk_state_json(void)
1207 tmp = cloud_base_url ? json_object_new_string(cloud_base_url) : NULL;
1208 json_object_object_add(msg, "cloud-url", tmp);
1209
1210 + char *aclk_proxy = (char *)aclk_get_proxy(NULL, true);
1211 + tmp = aclk_proxy ? json_object_new_string(aclk_proxy) : NULL;
1212 + json_object_object_add(msg, "aclk_proxy", tmp);
1213 +
1214 tmp = json_object_new_boolean(aclk_online());
1215 json_object_object_add(msg, "online", tmp);
1216
@@ -1288,7 +1299,7 @@ void add_aclk_host_labels(void) {
1299 rrdlabels_add(labels, "_aclk_available", "true", RRDLABEL_SRC_AUTO|RRDLABEL_SRC_ACLK);
1300 ACLK_PROXY_TYPE aclk_proxy;
1301 char *proxy_str;
1291 - aclk_get_proxy(&aclk_proxy);
1302 + aclk_get_proxy(&aclk_proxy, false);
1303
1304 switch(aclk_proxy) {
1305 case PROXY_TYPE_SOCKS5:
src/aclk/aclk_otp.c
+11 -4
@@ -8,14 +8,21 @@ static https_client_resp_t aclk_https_request(https_req_t *request, https_req_re
8 https_client_resp_t rc;
9 // wrapper for ACLK only which loads ACLK specific proxy settings
10 // then only calls https_request
11 - struct mqtt_wss_proxy proxy_conf = { .host = NULL, .port = 0, .username = NULL, .password = NULL, .type = MQTT_WSS_DIRECT };
12 - aclk_set_proxy((char**)&proxy_conf.host, &proxy_conf.port, (char**)&proxy_conf.username, (char**)&proxy_conf.password, &proxy_conf.type);
11 + struct mqtt_wss_proxy proxy_conf = { .host = NULL, .port = 0, .username = NULL, .password = NULL, .proxy_destination = NULL, .type = MQTT_WSS_DIRECT };
12 + aclk_set_proxy(
13 + (char **)&proxy_conf.host,
14 + &proxy_conf.port,
15 + (char **)&proxy_conf.username,
16 + (char **)&proxy_conf.password,
17 + (char **)&proxy_conf.proxy_destination,
18 + &proxy_conf.type);
19
20 if (proxy_conf.type == MQTT_WSS_PROXY_HTTP) {
15 - request->proxy_host = (char*)proxy_conf.host; // TODO make it const as well
21 + request->proxy_host = (char *)proxy_conf.host;
22 request->proxy_port = proxy_conf.port;
23 request->proxy_username = proxy_conf.username;
24 request->proxy_password = proxy_conf.password;
25 + request->proxy = proxy_conf.proxy_destination;
26 }
27
28 rc = https_request(request, response, fallback_ipv4);
@@ -33,7 +40,7 @@ struct auth_data {
40
41 #define PARSE_ENV_JSON_CHK_TYPE(it, type, name) \
42 if (json_object_get_type(json_object_iter_peek_value(it)) != type) { \
36 - netdata_log_error("ACLK: value of key \"%s\" should be %s", name, #type); \
43 + netdata_log_error("ACLK: value of key \"%s\" should be %s", name, #type); \
44 goto exit; \
45 }
46
src/aclk/aclk_proxy.c
+19 -43
@@ -1,7 +1,5 @@
1 #include "aclk_proxy.h"
2
3 -#include "database/rrd.h"
4 -
3 #define ACLK_PROXY_ENV "env"
4 #define ACLK_PROXY_CONFIG_VAR "proxy"
5
@@ -44,6 +42,9 @@ ACLK_PROXY_TYPE aclk_verify_proxy(const char *string)
42 // for logging purposes
43 void safe_log_proxy_censor(char *proxy)
44 {
45 + if (!proxy)
46 + return;
47 +
48 size_t length = strlen(proxy);
49 char *auth = proxy + length - 1;
50 char *cur;
@@ -75,24 +76,6 @@ static inline void safe_log_proxy_error(char *str, const char *proxy)
76 freez(log);
77 }
78
78 -static inline int check_socks_enviroment(const char **proxy)
79 -{
80 - char *tmp = getenv("socks_proxy");
81 -
82 - if (!tmp || !*tmp)
83 - return 1;
84 -
85 - if (aclk_verify_proxy(tmp) == PROXY_TYPE_SOCKS5) {
86 - *proxy = tmp;
87 - return 0;
88 - }
89 -
90 - safe_log_proxy_error(
91 - "Environment var \"socks_proxy\" defined but of unknown format. Supported syntax: \"socks5[h]://[user:pass@]host:port\".",
92 - tmp);
93 - return 1;
94 -}
95 -
79 static inline int check_http_environment(const char **proxy)
80 {
81 const char *var = "http_proxy";
@@ -130,31 +113,15 @@ const char *aclk_lws_wss_get_proxy_setting(ACLK_PROXY_TYPE *type)
113 return proxy;
114
115 if (strcmp(proxy, ACLK_PROXY_ENV) == 0) {
133 - if (check_socks_enviroment(&proxy) == 0) {
134 -#ifdef LWS_WITH_SOCKS5
135 - *type = PROXY_TYPE_SOCKS5;
136 - return proxy;
137 -#else
138 - safe_log_proxy_error("socks_proxy environment variable set to use SOCKS5 proxy "
139 - "but Libwebsockets used doesn't have SOCKS5 support built in. "
140 - "Ignoring and checking for other options.",
141 - proxy);
142 -#endif
143 - }
116 if (check_http_environment(&proxy) == 0)
117 *type = PROXY_TYPE_HTTP;
118 + else
119 + proxy = NULL;
120 return proxy;
121 }
122
123 *type = aclk_verify_proxy(proxy);
150 -#ifndef LWS_WITH_SOCKS5
151 - if (*type == PROXY_TYPE_SOCKS5) {
152 - safe_log_proxy_error(
153 - "Config var \"" ACLK_PROXY_CONFIG_VAR
154 - "\" set to use SOCKS5 proxy but Libwebsockets used is built without support for SOCKS proxy. ACLK will be disabled.",
155 - proxy);
156 - }
157 -#endif
124 +
125 if (*type == PROXY_TYPE_UNKNOWN) {
126 *type = PROXY_DISABLED;
127 safe_log_proxy_error(
@@ -169,14 +136,23 @@ const char *aclk_lws_wss_get_proxy_setting(ACLK_PROXY_TYPE *type)
136 // helper function to read settings only once (static)
137 // as claiming, challenge/response and ACLK
138 // read the same thing, no need to parse again
172 -const char *aclk_get_proxy(ACLK_PROXY_TYPE *type)
139 +const char *aclk_get_proxy(ACLK_PROXY_TYPE *return_type, bool for_logging)
140 {
141 static const char *proxy = NULL;
142 + static const char *safe_proxy = NULL;
143 static ACLK_PROXY_TYPE proxy_type = PROXY_NOT_SET;
144
177 - if (proxy_type == PROXY_NOT_SET)
145 + if (proxy_type == PROXY_NOT_SET) {
146 proxy = aclk_lws_wss_get_proxy_setting(&proxy_type);
147 + char *log = NULL;
148 + if (proxy) {
149 + log = strdupz(proxy);
150 + safe_log_proxy_censor(log);
151 + }
152 + safe_proxy = log;
153 + }
154
180 - *type = proxy_type;
181 - return proxy;
155 + if (return_type)
156 + *return_type = proxy_type;
157 + return for_logging ? safe_proxy : proxy;
158 }
src/aclk/aclk_proxy.h
+2 -2
@@ -1,7 +1,7 @@
1 #ifndef ACLK_PROXY_H
2 #define ACLK_PROXY_H
3
4 -#include <config.h>
4 +#include "aclk.h"
5
6 #define ACLK_PROXY_PROTO_ADDR_SEPARATOR "://"
7
@@ -16,6 +16,6 @@ typedef enum aclk_proxy_type {
16 ACLK_PROXY_TYPE aclk_verify_proxy(const char *string);
17 const char *aclk_lws_wss_get_proxy_setting(ACLK_PROXY_TYPE *type);
18 void safe_log_proxy_censor(char *proxy);
19 -const char *aclk_get_proxy(ACLK_PROXY_TYPE *type);
19 +const char *aclk_get_proxy(ACLK_PROXY_TYPE *type, bool for_logging);
20
21 #endif /* ACLK_PROXY_H */
src/aclk/aclk_util.c
+4 -2
@@ -386,10 +386,12 @@ static inline int aclk_parse_userpass_pair(const char *src, const char c, char *
386 }
387
388 #define HTTP_PROXY_PREFIX "http://"
389 -void aclk_set_proxy(char **ohost, int *port, char **uname, char **pwd, enum mqtt_wss_proxy_type *type)
389 +void aclk_set_proxy(char **ohost, int *port, char **uname, char **pwd,
390 + char **log_proxy, enum mqtt_wss_proxy_type *type)
391 {
392 ACLK_PROXY_TYPE pt;
392 - const char *ptr = aclk_get_proxy(&pt);
393 + const char *ptr = aclk_get_proxy(&pt, false);
394 + *log_proxy = (char *) aclk_get_proxy(&pt, true);
395 char *tmp;
396
397 if (pt != PROXY_TYPE_HTTP)
src/aclk/aclk_util.h
+2 -1
@@ -106,6 +106,7 @@ extern volatile int aclk_conversation_log_counter;
106 unsigned long int aclk_tbeb_delay(int reset, int base, unsigned long int mins_ms, unsigned long int min_ms);
107 #define aclk_tbeb_reset(x) aclk_tbeb_delay(1, 0, 0, 0)
108
109 -void aclk_set_proxy(char **ohost, int *port, char **uname, char **pwd, enum mqtt_wss_proxy_type *type);
109 +void aclk_set_proxy(char **ohost, int *port, char **uname, char **pwd,
110 + char **log_proxy, enum mqtt_wss_proxy_type *type);
111
112 #endif /* ACLK_UTIL_H */
src/aclk/https_client.c
+22 -4
@@ -664,7 +664,6 @@ static https_client_resp_t handle_http_request(https_req_ctx_t *ctx) {
664
665 buffer_strcat(hdr, HTTP_1_1 HTTP_ENDL);
666
667 - //TODO Headers!
667 buffer_sprintf(hdr, "Host: %s\x0D\x0A", ctx->request->host);
668 buffer_strcat(hdr, "User-Agent: Netdata/rocks newhttpclient\x0D\x0A");
669
@@ -755,9 +754,22 @@ https_client_resp_t https_request(https_req_t *request, https_req_response_t *re
754 int ret;
755 char connect_port_str[PORT_STR_MAX_BYTES];
756
758 - const char *connect_host = request->proxy_host ? request->proxy_host : request->host;
759 - int connect_port = request->proxy_host ? request->proxy_port : request->port;
760 - struct timeval timeout = { .tv_sec = 10, .tv_usec = 0 };
757 + bool proxy_used = (request->proxy_host != NULL);
758 +
759 + // assume no proxy
760 + const char *connect_host;
761 + int connect_port;
762 + const char *proxy_used_str = " (no proxy)";
763 +
764 +
765 + if (unlikely(proxy_used)) {
766 + connect_host = request->proxy_host;
767 + connect_port = request->proxy_port;
768 + proxy_used_str = request->proxy;
769 + } else {
770 + connect_host = request->host;
771 + connect_port = request->port;
772 + }
773
774 https_req_ctx_t *ctx = callocz(1, sizeof(https_req_ctx_t));
775 ctx->req_start_time = now_realtime_sec();
@@ -771,6 +783,11 @@ https_client_resp_t https_request(https_req_t *request, https_req_response_t *re
783
784 snprintfz(connect_port_str, PORT_STR_MAX_BYTES, "%d", connect_port);
785
786 + nd_log_daemon(NDLP_INFO, "ACLK: Connecting to %s:%d%s%s",
787 + request->host, request->port,
788 + proxy_used ? " via proxy " : "", proxy_used_str);
789 +
790 + struct timeval timeout = { .tv_sec = 10, .tv_usec = 0 };
791 ctx->sock = connect_to_this_ip46(IPPROTO_TCP, SOCK_STREAM, connect_host, 0, connect_port_str, &timeout, fallback_ipv4);
792 if (ctx->sock < 0) {
793 rc = -ctx->sock;
@@ -887,6 +904,7 @@ https_client_resp_t https_request(https_req_t *request, https_req_response_t *re
904 // only exact data without affixed 0x00
905 ((char*)response->payload)[response->payload_size] = 0; // mallocz(response->payload_size + 1);
906 }
907 + errno_clear();
908 netdata_log_info("ACLK: HTTPS \"%s\" request to \"%s\" finished with HTTP code: %d", http_req_type_to_str(ctx->request->request_type), ctx->request->host, response->http_code);
909
910 rc = HTTPS_CLIENT_RESP_OK;
src/aclk/https_client.h
+2 -1
@@ -64,10 +64,11 @@ typedef struct {
64 void *payload;
65 size_t payload_size;
66
67 - char *proxy_host;
67 + const char *proxy_host;
68 int proxy_port;
69 const char *proxy_username;
70 const char *proxy_password;
71 + const char *proxy;
72 } https_req_t;
73
74 typedef struct {
src/aclk/mqtt_websockets/mqtt_ng.c
+5 -4
@@ -2063,24 +2063,25 @@ int handle_incoming_traffic(struct mqtt_ng_client *client)
2063 client->connect_msg = NULL;
2064
2065 if (client->client_state != MQTT_STATE_CONNECTING) {
2066 - nd_log(NDLS_DAEMON, NDLP_ERR, "Received unexpected CONNACK");
2066 + nd_log(NDLS_DAEMON, NDLP_ERR, "ACLK: Received unexpected CONNACK");
2067 client->client_state = MQTT_STATE_ERROR;
2068 return MQTT_NG_CLIENT_PROTOCOL_ERROR;
2069 }
2070
2071 if ((prop = get_property_by_id(client->parser.properties_parser.head, MQTT_PROP_MAX_PKT_SIZE)) != NULL) {
2072 - nd_log(NDLS_DAEMON, NDLP_INFO, "MQTT server limits message size to %" PRIu32, prop->data.uint32);
2072 + nd_log(NDLS_DAEMON, NDLP_INFO, "ACLK: MQTT server limits message size to %" PRIu32, prop->data.uint32);
2073 client->max_msg_size = prop->data.uint32;
2074 }
2075
2076 if (client->connack_callback)
2077 client->connack_callback(client->user_ctx, client->parser.mqtt_packet.connack.reason_code);
2078 if (!client->parser.mqtt_packet.connack.reason_code) {
2079 - nd_log(NDLS_DAEMON, NDLP_INFO, "MQTT Connection Accepted By Server");
2079 + nd_log(NDLS_DAEMON, NDLP_INFO, "ACLK: MQTT Connection Accepted By Server");
2080 client->client_state = MQTT_STATE_CONNECTED;
2081 break;
2082 }
2083 - client->client_state = MQTT_STATE_ERROR; return MQTT_NG_CLIENT_SERVER_RETURNED_ERROR;
2083 + client->client_state = MQTT_STATE_ERROR;
2084 + return MQTT_NG_CLIENT_SERVER_RETURNED_ERROR;
2085
2086 case MQTT_CPT_PUBACK:
2087 worker_is_busy(WORKER_ACLK_CPT_PUBACK);
src/aclk/mqtt_websockets/mqtt_wss_client.c
+6 -1
@@ -488,6 +488,12 @@ int mqtt_wss_connect(
488 char port_str[16];
489 snprintf(port_str, sizeof(port_str) -1, "%d", client->port);
490
491 + bool proxy_used = (proxy && proxy->proxy_destination != NULL);
492 +
493 + nd_log_daemon(NDLP_INFO, "ACLK: Connecting to %s:%d%s%s",
494 + client->target_host, client->target_port,
495 + proxy_used ? " via proxy " : " (no proxy)", proxy_used ? proxy->proxy_destination : "");
496 +
497 struct timeval timeout = { .tv_sec = 10, .tv_usec = 0 };
498 int fd = connect_to_this_ip46(IPPROTO_TCP, SOCK_STREAM, client->host, 0, port_str, &timeout, fallback_ipv4);
499 if (fd < 0) {
@@ -582,7 +588,6 @@ int mqtt_wss_connect(
588
589 client->mqtt_keepalive = (mqtt_params->keep_alive ? mqtt_params->keep_alive : 400);
590
585 - nd_log(NDLS_DAEMON, NDLP_INFO, "Going to connect using internal MQTT 5 implementation");
591 struct mqtt_auth_properties auth;
592 auth.client_id = (char*)mqtt_params->clientid;
593 auth.client_id_free = NULL;
src/aclk/mqtt_websockets/mqtt_wss_client.h
+1
@@ -95,6 +95,7 @@ struct mqtt_wss_proxy {
95 int port;
96 const char *username;
97 const char *password;
98 + const char *proxy_destination;
99 };
100
101 /* TODO!!! update the description
src/daemon/commands.c
-1
@@ -672,7 +672,6 @@ static void pipe_read_cb(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf
672 if (0 == nread) {
673 netdata_log_info("%s: Zero bytes read by command pipe.", __func__);
674 } else if (UV_EOF == nread) {
675 - netdata_log_info("EOF found in command pipe.");
675 parse_commands(cmd_ctx);
676 } else if (nread < 0) {
677 netdata_log_error("%s: %s", __func__, uv_strerror(nread));