add streaming access lists and fix unix domain sockets access lists; now 127.0.0.1, ::1 and unix domain sockets are matched with localhost; fixes #2636
Costa Tsaousis (ktsaou) committed
Sep 19, 2017 at 22:53 UTC
4abf0eb9ee37d76de2405b1c286e15757a8d5a0f
6 files changed
+86
-33
conf.d/stream.conf
+25
-10
@@ -21,13 +21,13 @@
21
#
22
# If many are given, the first available will get the metrics.
23
#
24
- # PROTOCOL = tcp or udp (only tcp is supported by masters)
25
- # HOST = an IPv4, IPv6 IP, or a hostname.
24
+ # PROTOCOL = tcp, udp, or unix (only tcp and unix are supported by masters)
25
+ # HOST = an IPv4, IPv6 IP, or a hostname, or a unix domain socket path.
26
# IPv6 IPs should be given with brackets [ip:address]
27
- # INTERFACE = the network interface to use
27
+ # INTERFACE = the network interface to use (only for IPv6)
28
# PORT = the port number or service name (/etc/services)
29
#
30
- # This communication is not HTTP (cannot be proxied by web proxies).
30
+ # This communication is not HTTP (it cannot be proxied by web proxies).
31
destination =
32
33
# The API_KEY to use (as the sender)
@@ -56,26 +56,34 @@
56
# -----------------------------------------------------------------------------
57
# 2. ON MASTER NETDATA - THE ONE THAT WILL BE RECEIVING METRICS
58
59
-# You can have one API key per slave, or the same API key for all slaves.
59
+# You can have one API key per slave,
60
+# or the same API key for all slaves.
61
#
62
# netdata searches for options in this order:
63
#
63
-# a) [MACHINE_GUID] section (settings for each machine)
64
-# b) [API_KEY] section (settings for the API key)
65
-# c) master netdata settings (netdata.conf)
64
+# a) master netdata settings (netdata.conf)
65
+# b) [API_KEY] section (below, settings for the API key)
66
+# c) [MACHINE_GUID] section (below, settings for each machine)
67
#
68
# You can combine the above (the more specific setting will be used).
69
70
# API key authentication
70
-# If the key is not listed here, it will not be able to connect.
71
+# If the key is not listed here, it will not be able to push metrics.
72
73
+# [API_KEY] is [YOUR-API-KEY], i.e [11111111-2222-3333-4444-555555555555]
74
[API_KEY]
73
- # Default settings for the API key
75
+ # Default settings for this API key
76
77
# You can disable the API key, by setting this to: no
78
# The default (for unknown API keys) is: no
79
enabled = no
80
81
+ # A list of simple patterns matching the IPs of the servers that
82
+ # will be pushing metrics using this API key.
83
+ # The metrics are received via the API port, so the same IPs
84
+ # should also be matched at netdata.conf [web].allow connections from
85
+ allow from = *
86
+
87
# The default history in entries, for all hosts using this API key.
88
# You can also set it per host below.
89
# If you don't set it here, the history size of the central netdata
@@ -132,6 +140,13 @@
140
# Use only the API key for security.
141
enabled = no
142
143
+ # A list of simple patterns matching the IPs of the servers that
144
+ # will be pushing metrics using this MACHINE GUID.
145
+ # The metrics are received via the API port, so the same IPs
146
+ # should also be matched at netdata.conf [web].allow connections from
147
+ # and at stream.conf [API_KEY].allow from
148
+ allow from = *
149
+
150
# The number of entries in the database
151
history = 3600
152
src/main.c
+2
-2
@@ -83,11 +83,11 @@ void web_server_config_options(void) {
83
web_x_frame_options = config_get(CONFIG_SECTION_WEB, "x-frame-options response header", "");
84
if(!*web_x_frame_options) web_x_frame_options = NULL;
85
86
- web_allow_connections_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow connections from", "127.* ::1 *"), SIMPLE_PATTERN_EXACT);
86
+ web_allow_connections_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow connections from", "localhost *"), SIMPLE_PATTERN_EXACT);
87
web_allow_badges_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow badges from", "*"), SIMPLE_PATTERN_EXACT);
88
web_allow_registry_from = simple_pattern_create(config_get(CONFIG_SECTION_REGISTRY, "allow from", "*"), SIMPLE_PATTERN_EXACT);
89
web_allow_streaming_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow streaming from", "*"), SIMPLE_PATTERN_EXACT);
90
- web_allow_netdataconf_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow netdata.conf from", "::1 fd* 127.* 10.* 192.168.* 172.16.* 172.17.* 172.18.* 172.19.* 172.20.* 172.21.* 172.22.* 172.23.* 172.24.* 172.25.* 172.26.* 172.27.* 172.28.* 172.29.* 172.30.* 172.31.*"), SIMPLE_PATTERN_EXACT);
90
+ web_allow_netdataconf_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow netdata.conf from", "localhost fd* 10.* 192.168.* 172.16.* 172.17.* 172.18.* 172.19.* 172.20.* 172.21.* 172.22.* 172.23.* 172.24.* 172.25.* 172.26.* 172.27.* 172.28.* 172.29.* 172.30.* 172.31.*"), SIMPLE_PATTERN_EXACT);
91
92
#ifdef NETDATA_WITH_ZLIB
93
web_enable_gzip = config_get_boolean(CONFIG_SECTION_WEB, "enable gzip compression", web_enable_gzip);
src/rrdpush.c
+41
-21
@@ -781,6 +781,14 @@ static void rrdpush_sender_thread_spawn(RRDHOST *host) {
781
rrdhost_unlock(host);
782
}
783
784
+int rrdpush_receiver_permission_denied(struct web_client *w) {
785
+ // we always respond with the same message and error code
786
+ // to prevent an attacker from gaining info about the error
787
+ buffer_flush(w->response.data);
788
+ buffer_sprintf(w->response.data, "You are not permitted to access this. Check the logs for more info.");
789
+ return 401;
790
+}
791
+
792
int rrdpush_receiver_thread_spawn(RRDHOST *host, struct web_client *w, char *url) {
793
(void)host;
794
@@ -819,57 +827,69 @@ int rrdpush_receiver_thread_spawn(RRDHOST *host, struct web_client *w, char *url
827
if(!key || !*key) {
828
log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (hostname && *hostname)?hostname:"-", "ACCESS DENIED - NO KEY");
829
error("STREAM [receive from [%s]:%s]: request without an API key. Forbidding access.", w->client_ip, w->client_port);
822
- buffer_flush(w->response.data);
823
- buffer_sprintf(w->response.data, "You need an API key for this request.");
824
- return 401;
830
+ return rrdpush_receiver_permission_denied(w);
831
}
832
833
if(!hostname || !*hostname) {
834
log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (hostname && *hostname)?hostname:"-", "ACCESS DENIED - NO HOSTNAME");
835
error("STREAM [receive from [%s]:%s]: request without a hostname. Forbidding access.", w->client_ip, w->client_port);
830
- buffer_flush(w->response.data);
831
- buffer_sprintf(w->response.data, "You need to send a hostname too.");
832
- return 400;
836
+ return rrdpush_receiver_permission_denied(w);
837
}
838
839
if(!machine_guid || !*machine_guid) {
840
log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (hostname && *hostname)?hostname:"-", "ACCESS DENIED - NO MACHINE GUID");
841
error("STREAM [receive from [%s]:%s]: request without a machine GUID. Forbidding access.", w->client_ip, w->client_port);
838
- buffer_flush(w->response.data);
839
- buffer_sprintf(w->response.data, "You need to send a machine GUID too.");
840
- return 400;
842
+ return rrdpush_receiver_permission_denied(w);
843
}
844
845
if(regenerate_guid(key, buf) == -1) {
846
log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (hostname && *hostname)?hostname:"-", "ACCESS DENIED - INVALID KEY");
847
error("STREAM [receive from [%s]:%s]: API key '%s' is not valid GUID (use the command uuidgen to generate one). Forbidding access.", w->client_ip, w->client_port, key);
846
- buffer_flush(w->response.data);
847
- buffer_sprintf(w->response.data, "Your API key is invalid.");
848
- return 401;
848
+ return rrdpush_receiver_permission_denied(w);
849
}
850
851
if(regenerate_guid(machine_guid, buf) == -1) {
852
log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (hostname && *hostname)?hostname:"-", "ACCESS DENIED - INVALID MACHINE GUID");
853
error("STREAM [receive from [%s]:%s]: machine GUID '%s' is not GUID. Forbidding access.", w->client_ip, w->client_port, machine_guid);
854
- buffer_flush(w->response.data);
855
- buffer_sprintf(w->response.data, "Your machine GUID is invalid.");
856
- return 404;
854
+ return rrdpush_receiver_permission_denied(w);
855
}
856
857
if(!appconfig_get_boolean(&stream_config, key, "enabled", 0)) {
858
log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (hostname && *hostname)?hostname:"-", "ACCESS DENIED - KEY NOT ENABLED");
859
error("STREAM [receive from [%s]:%s]: API key '%s' is not allowed. Forbidding access.", w->client_ip, w->client_port, key);
862
- buffer_flush(w->response.data);
863
- buffer_sprintf(w->response.data, "Your API key is not permitted access.");
864
- return 401;
860
+ return rrdpush_receiver_permission_denied(w);
861
+ }
862
+
863
+ {
864
+ SIMPLE_PATTERN *key_allow_from = simple_pattern_create(appconfig_get(&stream_config, key, "allow from", "*"), SIMPLE_PATTERN_EXACT);
865
+ if(key_allow_from) {
866
+ if(!simple_pattern_matches(key_allow_from, w->client_ip)) {
867
+ simple_pattern_free(key_allow_from);
868
+ log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (hostname && *hostname) ? hostname : "-", "ACCESS DENIED - KEY NOT ALLOWED FROM THIS IP");
869
+ error("STREAM [receive from [%s]:%s]: API key '%s' is not permitted from this IP. Forbidding access.", w->client_ip, w->client_port, key);
870
+ return rrdpush_receiver_permission_denied(w);
871
+ }
872
+ simple_pattern_free(key_allow_from);
873
+ }
874
}
875
876
if(!appconfig_get_boolean(&stream_config, machine_guid, "enabled", 1)) {
877
log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (hostname && *hostname)?hostname:"-", "ACCESS DENIED - MACHINE GUID NOT ENABLED");
878
error("STREAM [receive from [%s]:%s]: machine GUID '%s' is not allowed. Forbidding access.", w->client_ip, w->client_port, machine_guid);
870
- buffer_flush(w->response.data);
871
- buffer_sprintf(w->response.data, "Your machine guide is not permitted access.");
872
- return 404;
879
+ return rrdpush_receiver_permission_denied(w);
880
+ }
881
+
882
+ {
883
+ SIMPLE_PATTERN *machine_allow_from = simple_pattern_create(appconfig_get(&stream_config, machine_guid, "allow from", "*"), SIMPLE_PATTERN_EXACT);
884
+ if(machine_allow_from) {
885
+ if(!simple_pattern_matches(machine_allow_from, w->client_ip)) {
886
+ simple_pattern_free(machine_allow_from);
887
+ log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (hostname && *hostname) ? hostname : "-", "ACCESS DENIED - MACHINE GUID NOT ALLOWED FROM THIS IP");
888
+ error("STREAM [receive from [%s]:%s]: Machine GUID '%s' is not permitted from this IP. Forbidding access.", w->client_ip, w->client_port, machine_guid);
889
+ return rrdpush_receiver_permission_denied(w);
890
+ }
891
+ simple_pattern_free(machine_allow_from);
892
+ }
893
}
894
895
struct rrdpush_thread *rpt = mallocz(sizeof(struct rrdpush_thread));
src/socket.c
+12
@@ -873,6 +873,13 @@ int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *clien
873
client_port[portsize - 1] = '\0';
874
875
switch (((struct sockaddr *)&sadr)->sa_family) {
876
+ case AF_UNIX:
877
+ debug(D_LISTENER, "New UNIX domain web client from %s on socket %d.", client_ip, fd);
878
+ // set the port - certain versions of libc return garbage on unix sockets
879
+ strncpy(client_port, "UNIX", portsize);
880
+ client_port[portsize - 1] = '\0';
881
+ break;
882
+
883
case AF_INET:
884
debug(D_LISTENER, "New IPv4 web client from %s port %s on socket %d.", client_ip, client_port, fd);
885
break;
@@ -892,6 +899,11 @@ int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *clien
899
}
900
901
if(access_list) {
902
+ if(!strcmp(client_ip, "127.0.0.1") || !strcmp(client_ip, "::1")) {
903
+ strncpy(client_ip, "localhost", ipsize);
904
+ client_ip[ipsize - 1] = '\0';
905
+ }
906
+
907
if(unlikely(!simple_pattern_matches(access_list, client_ip))) {
908
errno = 0;
909
debug(D_LISTENER, "Permission denied for client '%s', port '%s'", client_ip, client_port);
src/web_client.h
+1
@@ -77,6 +77,7 @@ typedef enum web_client_flags {
77
78
#define web_client_set_tcp(w) web_client_flag_set(w, WEB_CLIENT_FLAG_TCP_CLIENT)
79
#define web_client_set_unix(w) web_client_flag_set(w, WEB_CLIENT_FLAG_UNIX_CLIENT)
80
+#define web_client_check_unix(w) web_client_flag_check(w, WEB_CLIENT_FLAG_UNIX_CLIENT)
81
82
#define web_client_is_corkable(w) web_client_flag_check(w, WEB_CLIENT_FLAG_TCP_CLIENT)
83
src/web_server.c
+5
@@ -168,6 +168,11 @@ void *socket_listen_main_multi_threaded(void *ptr) {
168
continue;
169
}
170
171
+ if(api_sockets.fds_families[i] == AF_UNIX)
172
+ web_client_set_unix(w);
173
+ else
174
+ web_client_set_tcp(w);
175
+
176
if(pthread_create(&w->thread, NULL, web_client_main, w) != 0) {
177
error("%llu: failed to create new thread for web client.", w->id);
178
WEB_CLIENT_IS_OBSOLETE(w);