@cryptotaxi247 / netdata-1 / commits / 01aaa9093

Fixing DNS-lookup performance issue on FreeBSD. (#7132)

Our default configuration includes: allow connections from = localhost * allow management from = localhost The problem occurs when a connection is received that passes the `allow connections` pattern match, but fails the ACL check for `allow management`. During the failure processing path the DNS lookup is triggered to allow the FQDN to be checked against the pattern. On a FreeBSD system this lookup fails more slowly than linux and causes a visible performance problem during stress-testing. The fix adds a heuristic to analyse the patterns and determine if it is possible to match a DNS name, or only match a numeric IP address (either IPv4 or IPv6), or only match a constant value. This heuristic is used to disable the DNS checks when they cannot produce anything that may match the pattern. Each heuristic is evaluated once, when the configuration is loaded, not per-connection to the agent. Because the heuristic is not exact it can be overridden using the new config options for each of the ACL connection filters to set it to "yes", "no" or "heuristic". The default for everything *except* the netdata.conf ACL is "heuristic". Because of the numeric-patterns in the netdata.conf ACL the default is set to "no".

Andrew Moss committed Oct 24, 2019 at 20:44 UTC 01aaa909393a48d9db83c22dc95fffdd1cc074c9
11 files changed +214 -34
collectors/statsd.plugin/statsd.c
+2 -1
@@ -1014,7 +1014,8 @@ void *statsd_collector_thread(void *ptr) {
1014 , statsd_rcv_callback
1015 , statsd_snd_callback
1016 , statsd_timer_callback
1017 - , NULL
1017 + , NULL // No access control pattern
1018 + , 0 // No dns lookups for access control pattern
1019 , (void *)d
1020 , 0 // tcp request timeout, 0 = disabled
1021 , statsd.tcp_idle_timeout // tcp idle timeout, 0 = disabled
daemon/main.c
+61 -14
@@ -96,22 +96,69 @@ void web_server_threading_selection(void) {
96 }
97 }
98
99 -void web_server_config_options(void) {
100 - web_client_timeout = (int) config_get_number(CONFIG_SECTION_WEB, "disconnect idle clients after seconds", web_client_timeout);
101 - web_client_first_request_timeout = (int) config_get_number(CONFIG_SECTION_WEB, "timeout for first request", web_client_first_request_timeout);
102 - web_client_streaming_rate_t = config_get_number(CONFIG_SECTION_WEB, "accept a streaming request every seconds", web_client_streaming_rate_t);
99 +int make_dns_decision(const char *section_name, const char *config_name, const char *default_value, SIMPLE_PATTERN *p)
100 +{
101 + char *value = config_get(section_name,config_name,default_value);
102 + if(!strcmp("yes",value))
103 + return 1;
104 + if(!strcmp("no",value))
105 + return 0;
106 + if(strcmp("heuristic",value))
107 + error("Invalid configuration option '%s' for '%s'/'%s'. Valid options are 'yes', 'no' and 'heuristic'. Proceeding with 'heuristic'",
108 + value, section_name, config_name);
109 + return simple_pattern_is_potential_name(p);
110 +}
111
104 - respect_web_browser_do_not_track_policy = config_get_boolean(CONFIG_SECTION_WEB, "respect do not track policy", respect_web_browser_do_not_track_policy);
112 +void web_server_config_options(void)
113 +{
114 + web_client_timeout =
115 + (int)config_get_number(CONFIG_SECTION_WEB, "disconnect idle clients after seconds", web_client_timeout);
116 + web_client_first_request_timeout =
117 + (int)config_get_number(CONFIG_SECTION_WEB, "timeout for first request", web_client_first_request_timeout);
118 + web_client_streaming_rate_t =
119 + config_get_number(CONFIG_SECTION_WEB, "accept a streaming request every seconds", web_client_streaming_rate_t);
120 +
121 + respect_web_browser_do_not_track_policy =
122 + config_get_boolean(CONFIG_SECTION_WEB, "respect do not track policy", respect_web_browser_do_not_track_policy);
123 web_x_frame_options = config_get(CONFIG_SECTION_WEB, "x-frame-options response header", "");
106 - if(!*web_x_frame_options) web_x_frame_options = NULL;
107 -
108 - web_allow_connections_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow connections from", "localhost *"), NULL, SIMPLE_PATTERN_EXACT);
109 - web_allow_dashboard_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow dashboard from", "localhost *"), NULL, SIMPLE_PATTERN_EXACT);
110 - web_allow_badges_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow badges from", "*"), NULL, SIMPLE_PATTERN_EXACT);
111 - web_allow_registry_from = simple_pattern_create(config_get(CONFIG_SECTION_REGISTRY, "allow from", "*"), NULL, SIMPLE_PATTERN_EXACT);
112 - web_allow_streaming_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow streaming from", "*"), NULL, SIMPLE_PATTERN_EXACT);
113 - 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.*"), NULL, SIMPLE_PATTERN_EXACT);
114 - web_allow_mgmt_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow management from", "localhost"), NULL, SIMPLE_PATTERN_EXACT);
124 + if(!*web_x_frame_options)
125 + web_x_frame_options = NULL;
126 +
127 + web_allow_connections_from =
128 + simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow connections from", "localhost *"),
129 + NULL, SIMPLE_PATTERN_EXACT);
130 + web_allow_connections_dns =
131 + make_dns_decision(CONFIG_SECTION_WEB, "allow connections by dns", "heuristic", web_allow_connections_from);
132 + web_allow_dashboard_from =
133 + simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow dashboard from", "localhost *"),
134 + NULL, SIMPLE_PATTERN_EXACT);
135 + web_allow_dashboard_dns =
136 + make_dns_decision(CONFIG_SECTION_WEB, "allow dashboard by dns", "heuristic", web_allow_dashboard_from);
137 + web_allow_badges_from =
138 + simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow badges from", "*"), NULL, SIMPLE_PATTERN_EXACT);
139 + web_allow_badges_dns =
140 + make_dns_decision(CONFIG_SECTION_WEB, "allow badges by dns", "heuristic", web_allow_badges_from);
141 + web_allow_registry_from =
142 + simple_pattern_create(config_get(CONFIG_SECTION_REGISTRY, "allow from", "*"), NULL, SIMPLE_PATTERN_EXACT);
143 + web_allow_registry_dns = make_dns_decision(CONFIG_SECTION_REGISTRY, "allow by dns", "heuristic",
144 + web_allow_registry_from);
145 + web_allow_streaming_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow streaming from", "*"),
146 + NULL, SIMPLE_PATTERN_EXACT);
147 + web_allow_streaming_dns = make_dns_decision(CONFIG_SECTION_WEB, "allow streaming by dns", "heuristic",
148 + web_allow_streaming_from);
149 + // Note the default is not heuristic, the wildcards could match DNS but the intent is ip-addresses.
150 + web_allow_netdataconf_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow netdata.conf from",
151 + "localhost fd* 10.* 192.168.* 172.16.* 172.17.* 172.18.*"
152 + " 172.19.* 172.20.* 172.21.* 172.22.* 172.23.* 172.24.*"
153 + " 172.25.* 172.26.* 172.27.* 172.28.* 172.29.* 172.30.*"
154 + " 172.31.*"), NULL, SIMPLE_PATTERN_EXACT);
155 + web_allow_netdataconf_dns =
156 + make_dns_decision(CONFIG_SECTION_WEB, "allow netdata.conf by dns", "no", web_allow_mgmt_from);
157 + web_allow_mgmt_from =
158 + simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow management from", "localhost"),
159 + NULL, SIMPLE_PATTERN_EXACT);
160 + web_allow_mgmt_dns =
161 + make_dns_decision(CONFIG_SECTION_WEB, "allow management by dns","heuristic",web_allow_mgmt_from);
162
163
164 #ifdef NETDATA_WITH_ZLIB
libnetdata/simple_pattern/simple_pattern.c
+71
@@ -260,3 +260,74 @@ void simple_pattern_free(SIMPLE_PATTERN *list) {
260
261 free_pattern(((struct simple_pattern *)list));
262 }
263 +
264 +/* Debugging patterns
265 +
266 + This code should be dead - it is useful for debugging but should not be called by production code.
267 + Feel free to comment it out, but please leave it in the file.
268 +*/
269 +extern void simple_pattern_dump(uint64_t debug_type, SIMPLE_PATTERN *p)
270 +{
271 + struct simple_pattern *root = (struct simple_pattern *)p;
272 + if(root==NULL) {
273 + debug(debug_type,"dump_pattern(NULL)");
274 + return;
275 + }
276 + debug(debug_type,"dump_pattern(%p) child=%p next=%p mode=%d match=%s", root, root->child, root->next, root->mode,
277 + root->match);
278 + if(root->child!=NULL)
279 + simple_pattern_dump(debug_type, (SIMPLE_PATTERN*)root->child);
280 + if(root->next!=NULL)
281 + simple_pattern_dump(debug_type, (SIMPLE_PATTERN*)root->next);
282 +}
283 +
284 +/* Heuristic: decide if the pattern could match a DNS name.
285 +
286 + Although this functionality is used directly by socket.c:connection_allowed() it must be in this file
287 + because of the SIMPLE_PATTERN/simple_pattern structure hiding.
288 + Based on RFC952 / RFC1123. We need to decide if the pattern may match a DNS name, or not. For the negative
289 + cases we need to be sure that it can only match an ipv4 or ipv6 address:
290 + * IPv6 addresses contain ':', which are illegal characters in DNS.
291 + * IPv4 addresses cannot contain alpha- characters.
292 + * DNS TLDs must be alphanumeric to distinguish from IPv4.
293 + Some patterns (e.g. "*a*" ) could match multiple cases (i.e. DNS or IPv6).
294 + Some patterns will be awkward (e.g. "192.168.*") as they look like they are intended to match IPv4-only
295 + but could match DNS (i.e. "192.168.com" is a valid name).
296 +*/
297 +static void scan_is_potential_name(struct simple_pattern *p, int *alpha, int *colon, int *wildcards)
298 +{
299 + while (p) {
300 + if (p->match) {
301 + if(p->mode == SIMPLE_PATTERN_EXACT && !strcmp("localhost", p->match)) {
302 + p = p->child;
303 + continue;
304 + }
305 + char const *scan = p->match;
306 + while (*scan != 0) {
307 + if ((*scan >= 'a' && *scan <= 'z') || (*scan >= 'A' && *scan <= 'Z'))
308 + *alpha = 1;
309 + if (*scan == ':')
310 + *colon = 1;
311 + scan++;
312 + }
313 + if (p->mode != SIMPLE_PATTERN_EXACT)
314 + *wildcards = 1;
315 + p = p->child;
316 + }
317 + }
318 +}
319 +
320 +extern int simple_pattern_is_potential_name(SIMPLE_PATTERN *p)
321 +{
322 + int alpha=0, colon=0, wildcards=0;
323 + struct simple_pattern *root = (struct simple_pattern*)p;
324 + while (root != NULL) {
325 + if (root->match != NULL) {
326 + scan_is_potential_name(root, &alpha, &colon, &wildcards);
327 + }
328 + if (root->mode != SIMPLE_PATTERN_EXACT)
329 + wildcards = 1;
330 + root = root->next;
331 + }
332 + return (alpha || wildcards) && !colon;
333 +}
libnetdata/simple_pattern/simple_pattern.h
+3
@@ -30,4 +30,7 @@ extern int simple_pattern_matches_extract(SIMPLE_PATTERN *list, const char *str,
30 // list can be NULL, in which case, this does nothing.
31 extern void simple_pattern_free(SIMPLE_PATTERN *list);
32
33 +extern void simple_pattern_dump(uint64_t debug_type, SIMPLE_PATTERN *p) ;
34 +extern int simple_pattern_is_potential_name(SIMPLE_PATTERN *p) ;
35 +
36 #endif //NETDATA_SIMPLE_PATTERN_H
libnetdata/socket/socket.c
+14 -10
@@ -1007,13 +1007,16 @@ int accept4(int sock, struct sockaddr *addr, socklen_t *addrlen, int flags) {
1007 * of *writable* bytes (i.e. be aware of the strdup used to compact the pollinfo).
1008 */
1009 extern int connection_allowed(int fd, char *client_ip, char *client_host, size_t hostsize, SIMPLE_PATTERN *access_list,
1010 - const char *patname) {
1010 + const char *patname, int allow_dns)
1011 +{
1012 + debug(D_LISTENER,"checking %s... (allow_dns=%d)", patname, allow_dns);
1013 if (!access_list)
1014 return 1;
1015 if (simple_pattern_matches(access_list, client_ip))
1016 return 1;
1017 // If the hostname is unresolved (and needed) then attempt the DNS lookups.
1016 - if (client_host[0]==0)
1018 + //if (client_host[0]==0 && simple_pattern_is_potential_name(access_list))
1019 + if (client_host[0]==0 && allow_dns)
1020 {
1021 struct sockaddr_storage sadr;
1022 socklen_t addrlen = sizeof(sadr);
@@ -1021,8 +1024,8 @@ extern int connection_allowed(int fd, char *client_ip, char *client_host, size_t
1024 if (err != 0 ||
1025 (err = getnameinfo((struct sockaddr *)&sadr, addrlen, client_host, (socklen_t)hostsize,
1026 NULL, 0, NI_NAMEREQD)) != 0) {
1024 - error("Incoming connection on '%s' does not match a numeric pattern, "
1025 - "and host could not be resolved (err=%s)", client_ip, gai_strerror(err));
1027 + error("Incoming %s on '%s' does not match a numeric pattern, and host could not be resolved (err=%s)",
1028 + patname, client_ip, gai_strerror(err));
1029 if (hostsize >= 8)
1030 strcpy(client_host,"UNKNOWN");
1031 return 0;
@@ -1074,9 +1077,8 @@ extern int connection_allowed(int fd, char *client_ip, char *client_host, size_t
1077
1078 // --------------------------------------------------------------------------------------------------------------------
1079 // accept_socket() - accept a socket and store client IP and port
1077 -
1080 int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *client_port, size_t portsize,
1079 - char *client_host, size_t hostsize, SIMPLE_PATTERN *access_list) {
1081 + char *client_host, size_t hostsize, SIMPLE_PATTERN *access_list, int allow_dns) {
1082 struct sockaddr_storage sadr;
1083 socklen_t addrlen = sizeof(sadr);
1084
@@ -1088,7 +1090,7 @@ int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *clien
1090 strncpyz(client_ip, "UNKNOWN", ipsize - 1);
1091 strncpyz(client_port, "UNKNOWN", portsize - 1);
1092 }
1091 - if(!strcmp(client_ip, "127.0.0.1") || !strcmp(client_ip, "::1")) {
1093 + if (!strcmp(client_ip, "127.0.0.1") || !strcmp(client_ip, "::1")) {
1094 strncpy(client_ip, "localhost", ipsize);
1095 client_ip[ipsize - 1] = '\0';
1096 }
@@ -1126,7 +1128,7 @@ int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *clien
1128 debug(D_LISTENER, "New UNKNOWN web client from %s port %s on socket %d.", client_ip, client_port, fd);
1129 break;
1130 }
1129 - if(!connection_allowed(nfd, client_ip, client_host, hostsize, access_list, "connection")) {
1131 + if (!connection_allowed(nfd, client_ip, client_host, hostsize, access_list, "connection", allow_dns)) {
1132 errno = 0;
1133 error("Permission denied for client '%s', port '%s'", client_ip, client_port);
1134 close(nfd);
@@ -1135,7 +1137,7 @@ int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *clien
1137 }
1138 }
1139 #ifdef HAVE_ACCEPT4
1138 - else if(errno == ENOSYS)
1140 + else if (errno == ENOSYS)
1141 error("netdata has been compiled with the assumption that the system has the accept4() call, but it is not here. Recompile netdata like this: ./configure --disable-accept4 ...");
1142 #endif
1143
@@ -1444,7 +1446,7 @@ static void poll_events_process(POLLJOB *p, POLLINFO *pi, struct pollfd *pf, sho
1446
1447 debug(D_POLLFD, "POLLFD: LISTENER: calling accept4() slot %zu (fd %d)", i, fd);
1448 nfd = accept_socket(fd, SOCK_NONBLOCK, client_ip, INET6_ADDRSTRLEN, client_port, NI_MAXSERV,
1447 - client_host, NI_MAXHOST, p->access_list);
1449 + client_host, NI_MAXHOST, p->access_list, p->allow_dns);
1450 if (unlikely(nfd < 0)) {
1451 // accept failed
1452
@@ -1562,6 +1564,7 @@ void poll_events(LISTEN_SOCKETS *sockets
1564 , int (*snd_callback)(POLLINFO * /*pi*/, short int * /*events*/)
1565 , void (*tmr_callback)(void * /*timer_data*/)
1566 , SIMPLE_PATTERN *access_list
1567 + , int allow_dns
1568 , void *data
1569 , time_t tcp_request_timeout_seconds
1570 , time_t tcp_idle_timeout_seconds
@@ -1592,6 +1595,7 @@ void poll_events(LISTEN_SOCKETS *sockets
1595 .checks_every = (tcp_idle_timeout_seconds / 3) + 1,
1596
1597 .access_list = access_list,
1598 + .allow_dns = allow_dns,
1599
1600 .timer_milliseconds = timer_milliseconds,
1601 .timer_data = timer_data,
libnetdata/socket/socket.h
+4 -2
@@ -73,9 +73,9 @@ extern int sock_enlarge_in(int fd);
73 extern int sock_enlarge_out(int fd);
74
75 extern int connection_allowed(int fd, char *client_ip, char *client_host, size_t hostsize,
76 - SIMPLE_PATTERN *access_list, const char *patname);
76 + SIMPLE_PATTERN *access_list, const char *patname, int allow_dns);
77 extern int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *client_port, size_t portsize,
78 - char *client_host, size_t hostsize, SIMPLE_PATTERN *access_list);
78 + char *client_host, size_t hostsize, SIMPLE_PATTERN *access_list, int allow_dns);
79
80 #ifndef HAVE_ACCEPT4
81 extern int accept4(int sock, struct sockaddr *addr, socklen_t *addrlen, int flags);
@@ -155,6 +155,7 @@ struct poll {
155 struct pollinfo *first_free;
156
157 SIMPLE_PATTERN *access_list;
158 + int allow_dns;
159
160 void *(*add_callback)(POLLINFO *pi, short int *events, void *data);
161 void (*del_callback)(POLLINFO *pi);
@@ -193,6 +194,7 @@ extern void poll_events(LISTEN_SOCKETS *sockets
194 , int (*snd_callback)(POLLINFO *pi, short int *events)
195 , void (*tmr_callback)(void *timer_data)
196 , SIMPLE_PATTERN *access_list
197 + , int allow_dns
198 , void *data
199 , time_t tcp_request_timeout_seconds
200 , time_t tcp_idle_timeout_seconds
registry/README.md
+17
@@ -122,6 +122,23 @@ Netdata v1.9+ support limiting access to the registry from given IPs, like this:
122
123 Keep in mind that connections to Netdata API ports are filtered by `[web].allow connections from`. So, IPs allowed by `[registry].allow from` should also be allowed by `[web].allow connection from`.
124
125 +The patterns can be matches over IP addresses or FQDN of the host.
126 +In order to check the FQDN of the connection without opening the Netdata agent to DNS-spoofing, a reverse-dns record
127 +must be setup for the connecting host. At connection time the reverse-dns of the peer IP address is resolved, and
128 +a forward DNS resolution is made to validate the IP address against the name-pattern.
129 +
130 +Please note that this process can be expensive on a machine that is serving many connections. The behaviour of
131 +the pattern matching can be controlled with the following setting:
132 +```
133 +[registry]
134 + allow by dns = heuristic
135 +```
136 +
137 +The settings are:
138 +* `yes` allows the pattern to match DNS names.
139 +* `no` disables DNS matching for the patterns (they only match IP addresses).
140 +* `heuristic` will estimate if the patterns should match FQDNs by the presence or absence of `:`s or alpha-characters.
141 +
142 ### Where is the registry database stored?
143
144 `/var/lib/netdata/registry/*.db`
web/server/README.md
+21 -1
@@ -149,7 +149,7 @@ Netdata supports access lists in `netdata.conf`:
149 allow management from = localhost
150 ```
151
152 -`*` does string matches on the IPs of the clients.
152 +`*` does string matches on the IPs or FQDNs of the clients.
153
154 - `allow connections from` matches anyone that connects on the Netdata port(s).
155 So, if someone is not allowed, it will be connected and disconnected immediately, without reading even
@@ -169,6 +169,26 @@ Netdata supports access lists in `netdata.conf`:
169
170 - `allow management from` checks the IPs to allow API management calls. Management via the API is currently supported for [health](../api/health/#health-management-api)
171
172 +In order to check the FQDN of the connection without opening the Netdata agent to DNS-spoofing, a reverse-dns record
173 +must be setup for the connecting host. At connection time the reverse-dns of the peer IP address is resolved, and
174 +a forward DNS resolution is made to validate the IP address against the name-pattern.
175 +
176 +Please note that this process can be expensive on a machine that is serving many connections. Each access list has an
177 +associated configuration option to turn off DNS-based patterns completely to avoid incurring this cost at run-time:
178 +
179 +```
180 + allow connections by dns = heuristic
181 + allow dashboard by dns = heuristic
182 + allow badges by dns = heuristic
183 + allow streaming by dns = heuristic
184 + allow netdata.conf by dns = no
185 + allow management by dns = heuristic
186 +```
187 +
188 +The three possible values for each of these options are `yes`, `no` and `heuristic`. The `heuristic` option disables
189 +the check when the pattern only contains IPv4/IPv6 addresses or `localhost`, and enables it when wildcards are
190 +present that may match DNS FQDNs.
191 +
192 ### Other netdata.conf [web] section options
193
194 |setting|default|info|
web/server/static/static-threaded.c
+1
@@ -396,6 +396,7 @@ void *socket_listen_main_static_threaded_worker(void *ptr) {
396 , web_server_snd_callback
397 , web_server_tmr_callback
398 , web_allow_connections_from
399 + , web_allow_connections_dns
400 , NULL
401 , web_client_first_request_timeout
402 , web_client_timeout
web/server/web_server.c
+13 -6
@@ -74,46 +74,53 @@ void api_listen_sockets_setup(void) {
74 // access lists
75
76 SIMPLE_PATTERN *web_allow_connections_from = NULL;
77 +int web_allow_connections_dns;
78
79 // WEB_CLIENT_ACL
80 SIMPLE_PATTERN *web_allow_dashboard_from = NULL;
81 +int web_allow_dashboard_dns;
82 SIMPLE_PATTERN *web_allow_registry_from = NULL;
83 +int web_allow_registry_dns;
84 SIMPLE_PATTERN *web_allow_badges_from = NULL;
85 +int web_allow_badges_dns;
86 SIMPLE_PATTERN *web_allow_mgmt_from = NULL;
87 +int web_allow_mgmt_dns;
88 SIMPLE_PATTERN *web_allow_streaming_from = NULL;
89 +int web_allow_streaming_dns;
90 SIMPLE_PATTERN *web_allow_netdataconf_from = NULL;
91 +int web_allow_netdataconf_dns;
92
93 void web_client_update_acl_matches(struct web_client *w) {
94 w->acl = WEB_CLIENT_ACL_NONE;
95
96 if (!web_allow_dashboard_from ||
97 connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
91 - web_allow_dashboard_from, "dashboard"))
98 + web_allow_dashboard_from, "dashboard", web_allow_dashboard_dns))
99 w->acl |= WEB_CLIENT_ACL_DASHBOARD;
100
101 if (!web_allow_registry_from ||
102 connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
96 - web_allow_registry_from, "registry"))
103 + web_allow_registry_from, "registry", web_allow_registry_dns))
104 w->acl |= WEB_CLIENT_ACL_REGISTRY;
105
106 if (!web_allow_badges_from ||
107 connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
101 - web_allow_badges_from, "badges"))
108 + web_allow_badges_from, "badges", web_allow_badges_dns))
109 w->acl |= WEB_CLIENT_ACL_BADGE;
110
111 if (!web_allow_mgmt_from ||
112 connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
106 - web_allow_mgmt_from, "management"))
113 + web_allow_mgmt_from, "management", web_allow_mgmt_dns))
114 w->acl |= WEB_CLIENT_ACL_MGMT;
115
116 if (!web_allow_streaming_from ||
117 connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
111 - web_allow_streaming_from, "streaming"))
118 + web_allow_streaming_from, "streaming", web_allow_streaming_dns))
119 w->acl |= WEB_CLIENT_ACL_STREAMING;
120
121 if (!web_allow_netdataconf_from ||
122 connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
116 - web_allow_netdataconf_from, "netdata.conf"))
123 + web_allow_netdataconf_from, "netdata.conf", web_allow_netdataconf_dns))
124 w->acl |= WEB_CLIENT_ACL_NETDATACONF;
125
126 w->acl &= w->port_acl;
web/server/web_server.h
+7
@@ -20,12 +20,19 @@ typedef enum web_server_mode {
20 } WEB_SERVER_MODE;
21
22 extern SIMPLE_PATTERN *web_allow_connections_from;
23 +extern int web_allow_connections_dns;
24 extern SIMPLE_PATTERN *web_allow_dashboard_from;
25 +extern int web_allow_dashboard_dns;
26 extern SIMPLE_PATTERN *web_allow_registry_from;
27 +extern int web_allow_registry_dns;
28 extern SIMPLE_PATTERN *web_allow_badges_from;
29 +extern int web_allow_badges_dns;
30 extern SIMPLE_PATTERN *web_allow_streaming_from;
31 +extern int web_allow_streaming_dns;
32 extern SIMPLE_PATTERN *web_allow_netdataconf_from;
33 +extern int web_allow_netdataconf_dns;
34 extern SIMPLE_PATTERN *web_allow_mgmt_from;
35 +extern int web_allow_mgmt_dns;
36
37 extern WEB_SERVER_MODE web_server_mode;
38