summaryrefslogtreecommitdiffstats
path: root/web/server
diff options
context:
space:
mode:
Diffstat (limited to 'web/server')
-rw-r--r--web/server/README.md16
-rw-r--r--web/server/static/static-threaded.c31
-rw-r--r--web/server/web_client.c8
-rw-r--r--web/server/web_client.h7
-rw-r--r--web/server/web_server.c24
5 files changed, 51 insertions, 35 deletions
diff --git a/web/server/README.md b/web/server/README.md
index 30cb00699..9f47cb8d9 100644
--- a/web/server/README.md
+++ b/web/server/README.md
@@ -33,7 +33,7 @@ The ports to bind are controlled via `[web].bind to`, like this:
```
[web]
default port = 19999
- bind to = 127.0.0.1=dashboard^SSL=optional 10.1.1.1:19998=management|netdata.conf hostname:19997=badges [::]:19996=streaming^SSL=force localhost:19995=registry *:http=dashboard unix:/tmp/netdata.sock
+ bind to = 127.0.0.1=dashboard^SSL=optional 10.1.1.1:19998=management|netdata.conf hostname:19997=badges [::]:19996=streaming^SSL=force localhost:19995=registry *:http=dashboard unix:/run/netdata/netdata.sock
```
Using the above, Netdata will bind to:
@@ -44,7 +44,7 @@ Using the above, Netdata will bind to:
- All IPv6 IPs at port 19996. Only metric streaming requests from other Netdata agents will be accepted on this port. Only encrypted streams will be allowed (i.e. slaves also need to be [configured for TLS](../../streaming).
- All the IPs `localhost` resolves to (both IPv4 and IPv6 depending the resolved IPs) at port 19996. This port will only accept registry API requests.
- All IPv4 and IPv6 IPs at port `http` as set in `/etc/services`. Only the UI (dashboard) and the read API will be accessible on this port.
-- Unix domain socket `/tmp/netdata.sock`. All requests are serviceable on this socket.
+- Unix domain socket `/run/netdata/netdata.sock`. All requests are serviceable on this socket. Note that in some OSs like Fedora, every service sees a different `/tmp`, so don't create a Unix socket under `/tmp`. `/run` or `/var/run` is suggested.
The option `[web].default port` is used when an entries in `[web].bind to` do not specify a port.
@@ -79,14 +79,14 @@ Both files must be readable by the `netdata` user. If either of these files do n
For test purposes, you can generate self-signed certificates with the following command:
```bash
-$ openssl req -newkey rsa:2048 -nodes -sha512 -x509 -days 365 -keyout key.pem -out cert.pem
+openssl req -newkey rsa:2048 -nodes -sha512 -x509 -days 365 -keyout key.pem -out cert.pem
```
!!! note
If you use 4096 bits for your key and the certificate, Netdata will need more CPU to process the communication. `rsa4096` can be up to 4 times slower than `rsa2048`, so we recommend using 2048 bits. You can verify the difference by running:
```sh
-$ openssl speed rsa2048 rsa4096
+openssl speed rsa2048 rsa4096
```
#### TLS/SSL enforcement
@@ -98,11 +98,11 @@ When the certificates are defined and unless any other options are provided, a N
To change this behavior, you need to modify the `bind to` setting in the `[web]` section of `netdata.conf`. At the end of each port definition, you can append `^SSL=force` or `^SSL=optional`. What happens with these settings differs, depending on whether the port is used for HTTP/S requests, or for streaming.
-|SSL setting|HTTP requests|HTTPS requests|Unencrypted Streams|Encrypted Streams|
+| SSL setting | HTTP requests|HTTPS requests|Unencrypted Streams|Encrypted Streams|
|:---------:|:-----------:|:------------:|:-----------------:|:----------------|
-|none|Redirected to HTTPS|Accepted|Accepted|Accepted|
-|`force`|Redirected to HTTPS|Accepted|Denied|Accepted|
-|`optional`|Accepted|Accepted|Accepted|Accepted|
+| none | Redirected to HTTPS|Accepted|Accepted|Accepted|
+| `force`| Redirected to HTTPS|Accepted|Denied|Accepted|
+| `optional`| Accepted|Accepted|Accepted|Accepted|
Example:
diff --git a/web/server/static/static-threaded.c b/web/server/static/static-threaded.c
index 5dda27000..c432b9bf3 100644
--- a/web/server/static/static-threaded.c
+++ b/web/server/static/static-threaded.c
@@ -7,23 +7,26 @@ int web_client_timeout = DEFAULT_DISCONNECT_IDLE_WEB_CLIENTS_AFTER_SECONDS;
int web_client_first_request_timeout = DEFAULT_TIMEOUT_TO_RECEIVE_FIRST_WEB_REQUEST;
long web_client_streaming_rate_t = 0L;
-// ----------------------------------------------------------------------------
-// high level web clients connection management
-
-static struct web_client *web_client_create_on_fd(int fd, const char *client_ip, const char *client_port, int port_acl) {
+/*
+ * --------------------------------------------------------------------------------------------------------------------
+ * Build web_client state from the pollinfo that describes an accepted connection.
+ */
+static struct web_client *web_client_create_on_fd(POLLINFO *pi) {
struct web_client *w;
w = web_client_get_from_cache_or_allocate();
- w->ifd = w->ofd = fd;
+ w->ifd = w->ofd = pi->fd;
- strncpyz(w->client_ip, client_ip, sizeof(w->client_ip) - 1);
- strncpyz(w->client_port, client_port, sizeof(w->client_port) - 1);
+ strncpyz(w->client_ip, pi->client_ip, sizeof(w->client_ip) - 1);
+ strncpyz(w->client_port, pi->client_port, sizeof(w->client_port) - 1);
+ strncpyz(w->client_host, pi->client_host, sizeof(w->client_host) - 1);
if(unlikely(!*w->client_ip)) strcpy(w->client_ip, "-");
if(unlikely(!*w->client_port)) strcpy(w->client_port, "-");
- w->port_acl = port_acl;
+ w->port_acl = pi->port_acl;
web_client_initialize_connection(w);
+ w->pollinfo_slot = pi->slot;
return(w);
}
@@ -76,7 +79,7 @@ static void *web_server_file_add_callback(POLLINFO *pi, short int *events, void
return w;
}
-static void web_werver_file_del_callback(POLLINFO *pi) {
+static void web_server_file_del_callback(POLLINFO *pi) {
struct web_client *w = (struct web_client *)pi->data;
debug(D_WEB_CLIENT, "%llu: RELEASE FILE READ ON FD %d", w->id, pi->fd);
@@ -138,7 +141,7 @@ static int web_server_file_write_callback(POLLINFO *pi, short int *events) {
// web server clients
static void *web_server_add_callback(POLLINFO *pi, short int *events, void *data) {
- (void)data;
+ (void)data; // Supress warning on unused argument
worker_private->connected++;
@@ -149,10 +152,9 @@ static void *web_server_add_callback(POLLINFO *pi, short int *events, void *data
*events = POLLIN;
debug(D_WEB_CLIENT_ACCESS, "LISTENER on %d: new connection.", pi->fd);
- struct web_client *w = web_client_create_on_fd(pi->fd, pi->client_ip, pi->client_port, pi->port_acl);
- w->pollinfo_slot = pi->slot;
+ struct web_client *w = web_client_create_on_fd(pi);
- if ( !strncmp(pi->client_port,"UNIX",4)){
+ if (!strncmp(pi->client_port, "UNIX", 4)) {
web_client_set_unix(w);
} else {
web_client_set_tcp(w);
@@ -270,8 +272,9 @@ static int web_server_rcv_callback(POLLINFO *pi, short int *events) {
, POLLINFO_FLAG_CLIENT_SOCKET
, "FILENAME"
, ""
+ , ""
, web_server_file_add_callback
- , web_werver_file_del_callback
+ , web_server_file_del_callback
, web_server_file_read_callback
, web_server_file_write_callback
, (void *) w
diff --git a/web/server/web_client.c b/web/server/web_client.c
index 908e3a6a9..53a5944ce 100644
--- a/web/server/web_client.c
+++ b/web/server/web_client.c
@@ -791,7 +791,7 @@ static inline char *http_header_parse(struct web_client *w, char *s, int parse_u
w->auth_bearer_token = strdupz(v);
}
else if(hash == hash_host && !strcasecmp(s, "Host")){
- strncpyz(w->host, v, (ve - v));
+ strncpyz(w->server_host, v, ((size_t)(ve - v) < sizeof(w->server_host)-1 ? (size_t)(ve - v) : sizeof(w->server_host)-1));
}
#ifdef NETDATA_WITH_ZLIB
else if(hash == hash_accept_encoding && !strcasecmp(s, "Accept-Encoding")) {
@@ -1147,8 +1147,8 @@ static inline void web_client_send_http_header(struct web_client *w) {
char headerbegin[8328];
if (w->response.code == HTTP_RESP_MOVED_PERM) {
memcpy(headerbegin,"\r\nLocation: https://",20);
- size_t headerlength = strlen(w->host);
- memcpy(&headerbegin[20],w->host,headerlength);
+ size_t headerlength = strlen(w->server_host);
+ memcpy(&headerbegin[20],w->server_host,headerlength);
headerlength += 20;
size_t tmp = strlen(w->last_url);
memcpy(&headerbegin[headerlength],w->last_url,tmp);
@@ -1212,7 +1212,7 @@ static inline void web_client_send_http_header(struct web_client *w) {
if(w->mode == WEB_CLIENT_MODE_OPTIONS) {
buffer_strcat(w->response.header_output,
"Access-Control-Allow-Methods: GET, OPTIONS\r\n"
- "Access-Control-Allow-Headers: accept, x-requested-with, origin, content-type, cookie, pragma, cache-control\r\n"
+ "Access-Control-Allow-Headers: accept, x-requested-with, origin, content-type, cookie, pragma, cache-control, x-auth-token\r\n"
"Access-Control-Max-Age: 1209600\r\n" // 86400 * 14
);
}
diff --git a/web/server/web_client.h b/web/server/web_client.h
index 38a433523..c785a7fda 100644
--- a/web/server/web_client.h
+++ b/web/server/web_client.h
@@ -154,13 +154,14 @@ struct web_client {
int ifd;
int ofd;
- char client_ip[NI_MAXHOST+1];
- char client_port[NI_MAXSERV+1];
+ char client_ip[INET6_ADDRSTRLEN]; // Defined buffer sizes include null-terminators
+ char client_port[NI_MAXSERV];
+ char server_host[NI_MAXHOST];
+ char client_host[NI_MAXHOST];
char decoded_url[NETDATA_WEB_REQUEST_URL_SIZE + 1]; // we decode the URL in this buffer
char decoded_query_string[NETDATA_WEB_REQUEST_URL_SIZE + 1]; // we decode the Query String in this buffer
char last_url[NETDATA_WEB_REQUEST_URL_SIZE+1]; // we keep a copy of the decoded URL here
- char host[256];
size_t url_path_length;
char separator; // This value can be either '?' or 'f'
char *url_search_path; //A pointer to the search path sent by the client
diff --git a/web/server/web_server.c b/web/server/web_server.c
index 9e51c81fe..b8b84bc36 100644
--- a/web/server/web_server.c
+++ b/web/server/web_server.c
@@ -86,22 +86,34 @@ SIMPLE_PATTERN *web_allow_netdataconf_from = NULL;
void web_client_update_acl_matches(struct web_client *w) {
w->acl = WEB_CLIENT_ACL_NONE;
- if(!web_allow_dashboard_from || simple_pattern_matches(web_allow_dashboard_from, w->client_ip))
+ if (!web_allow_dashboard_from ||
+ connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
+ web_allow_dashboard_from, "dashboard"))
w->acl |= WEB_CLIENT_ACL_DASHBOARD;
- if(!web_allow_registry_from || simple_pattern_matches(web_allow_registry_from, w->client_ip))
+ if (!web_allow_registry_from ||
+ connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
+ web_allow_registry_from, "registry"))
w->acl |= WEB_CLIENT_ACL_REGISTRY;
- if(!web_allow_badges_from || simple_pattern_matches(web_allow_badges_from, w->client_ip))
+ if (!web_allow_badges_from ||
+ connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
+ web_allow_badges_from, "badges"))
w->acl |= WEB_CLIENT_ACL_BADGE;
- if(!web_allow_mgmt_from || simple_pattern_matches(web_allow_mgmt_from, w->client_ip))
+ if (!web_allow_mgmt_from ||
+ connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
+ web_allow_mgmt_from, "management"))
w->acl |= WEB_CLIENT_ACL_MGMT;
- if(!web_allow_streaming_from || simple_pattern_matches(web_allow_streaming_from, w->client_ip))
+ if (!web_allow_streaming_from ||
+ connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
+ web_allow_streaming_from, "streaming"))
w->acl |= WEB_CLIENT_ACL_STREAMING;
- if(!web_allow_netdataconf_from || simple_pattern_matches(web_allow_netdataconf_from, w->client_ip))
+ if (!web_allow_netdataconf_from ||
+ connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
+ web_allow_netdataconf_from, "netdata.conf"))
w->acl |= WEB_CLIENT_ACL_NETDATACONF;
w->acl &= w->port_acl;