Browse Source

Extend TLS Support (#8505)

* tls13: This commit brings TLS 1.3 to Netdata

* tls13: Update variables on slave side

* tls13: Fix compilation error for old libraries

* tls13: Fix compilation error for old libraries 2

* tls13 remove ciphers

* tls13: TLS versions

This commit brings the missing tls versions accpeted for Netdata
and it also brings documentation update related to these versions

* tls13: Remove dupplication

This commit removes wrong dupplication of code

* tls13: Documentation

This commit brings fix for the documentation

* tls13: Remove magic number

This commit removes the magic number to allow the code to be readable

* tls13: TLS version

Small adjust with TLS version

* tls13: Security Init

This commit removes array from the function and overwrite the magic number
with a string

* tls13: Remove new variable name from stream

* tls13: OpenSSL versions and old key name

This commit removes the new key names and also update the names
used to define openssl version
thiagoftsm 5 years ago
parent
commit
a12d4e56d7
5 changed files with 81 additions and 28 deletions
  1. 3 0
      daemon/main.c
  2. 53 25
      libnetdata/socket/security.c
  3. 8 1
      libnetdata/socket/security.h
  4. 1 0
      streaming/rrdpush.c
  5. 16 2
      web/server/README.md

+ 3 - 0
daemon/main.c

@@ -406,6 +406,9 @@ static void security_init(){
     snprintfz(filename, FILENAME_MAX, "%s/ssl/cert.pem",netdata_configured_user_config_dir);
     security_cert    = config_get(CONFIG_SECTION_WEB, "ssl certificate",  filename);
 
+    tls_version    = config_get(CONFIG_SECTION_WEB, "tls version",  "1.3");
+    tls_ciphers    = config_get(CONFIG_SECTION_WEB, "tls ciphers",  "none");
+
     security_openssl_library();
 }
 #endif

+ 53 - 25
libnetdata/socket/security.c

@@ -7,6 +7,8 @@ SSL_CTX *netdata_client_ctx=NULL;
 SSL_CTX *netdata_srv_ctx=NULL;
 const char *security_key=NULL;
 const char *security_cert=NULL;
+const char *tls_version=NULL;
+const char *tls_ciphers=NULL;
 int netdata_validate_server =  NETDATA_SSL_VALID_CERTIFICATE;
 
 /**
@@ -32,14 +34,12 @@ static void security_info_callback(const SSL *ssl, int where, int ret __maybe_un
  */
 void security_openssl_library()
 {
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
-# if (SSLEAY_VERSION_NUMBER >= 0x0907000L)
+#if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110
+# if (SSLEAY_VERSION_NUMBER >= OPENSSL_VERSION_097)
     OPENSSL_config(NULL);
 # endif
 
-# if OPENSSL_API_COMPAT < 0x10100000L
     SSL_load_error_strings();
-# endif
 
     SSL_library_init();
 #else
@@ -49,32 +49,60 @@ void security_openssl_library()
 #endif
 }
 
+#if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_110
+/**
+ * TLS version
+ *
+ * Returns the TLS version depending of the user input.
+ *
+ * @param lversion is the user input.
+ *
+ * @return it returns the version number.
+ */
+int tls_select_version(const char *lversion) {
+    if (!strcmp(lversion, "1") || !strcmp(lversion, "1.0"))
+        return TLS1_VERSION;
+    else if (!strcmp(lversion, "1.1"))
+        return TLS1_1_VERSION;
+    else if (!strcmp(lversion, "1.2"))
+        return TLS1_2_VERSION;
+#if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_111
+    else if (!strcmp(lversion, "1.3"))
+        return TLS1_3_VERSION;
+#endif
+
+    return TLS_MAX_VERSION;
+}
+#endif
+
 /**
  * OpenSSL common options
  *
  * Clients and SERVER have common options, this function is responsible to set them in the context.
  *
- * @param ctx
+ * @param ctx the initialized SSL context.
+ * @param side 0 means server, and 1 client.
  */
-void security_openssl_common_options(SSL_CTX *ctx) {
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
-    static char *ciphers = {"ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA"};
+void security_openssl_common_options(SSL_CTX *ctx, int side) {
+#if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_110
+    if (!side) {
+        int version =  tls_select_version(tls_version) ;
 #endif
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
-    SSL_CTX_set_options (ctx,SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_COMPRESSION);
+#if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110
+        SSL_CTX_set_options (ctx,SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_COMPRESSION);
 #else
-    SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
-    //We are avoiding the TLS v1.3 for while, because Google Chrome
-    //is giving the message net::ERR_SSL_VERSION_INTERFERENCE with it.
-    SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION);
-#endif
-    SSL_CTX_set_mode(ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+        SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
+        SSL_CTX_set_max_proto_version(ctx, version);
 
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
-    if (!SSL_CTX_set_cipher_list(ctx, ciphers)) {
-        error("SSL error. cannot set the cipher list");
+        if(tls_ciphers  && strcmp(tls_ciphers, "none") != 0) {
+            if (!SSL_CTX_set_cipher_list(ctx, tls_ciphers)) {
+                error("SSL error. cannot set the cipher list");
+            }
+        }
     }
 #endif
+
+    SSL_CTX_set_mode(ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
 }
 
 /**
@@ -86,13 +114,13 @@ void security_openssl_common_options(SSL_CTX *ctx) {
  */
 SSL_CTX * security_initialize_openssl_client() {
     SSL_CTX *ctx;
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110
     ctx = SSL_CTX_new(SSLv23_client_method());
 #else
     ctx = SSL_CTX_new(TLS_client_method());
 #endif
     if(ctx) {
-        security_openssl_common_options(ctx);
+        security_openssl_common_options(ctx, 1);
     }
 
     return ctx;
@@ -111,7 +139,7 @@ static SSL_CTX * security_initialize_openssl_server() {
 	static int netdata_id_context = 1;
 
     //TO DO: Confirm the necessity to check return for other OPENSSL function
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110
 	ctx = SSL_CTX_new(SSLv23_server_method());
     if (!ctx) {
 		error("Cannot create a new SSL context, netdata won't encrypt communication");
@@ -128,7 +156,7 @@ static SSL_CTX * security_initialize_openssl_server() {
 
     SSL_CTX_use_certificate_chain_file(ctx, security_cert);
 #endif
-    security_openssl_common_options(ctx);
+    security_openssl_common_options(ctx, 0);
 
     SSL_CTX_use_PrivateKey_file(ctx,security_key,SSL_FILETYPE_PEM);
 
@@ -142,7 +170,7 @@ static SSL_CTX * security_initialize_openssl_server() {
 	SSL_CTX_set_session_id_context(ctx,(void*)&netdata_id_context,(unsigned int)sizeof(netdata_id_context));
     SSL_CTX_set_info_callback(ctx,security_info_callback);
 
-#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
+#if (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_095)
 	SSL_CTX_set_verify_depth(ctx,1);
 #endif
     debug(D_WEB_CLIENT,"SSL GLOBAL CONTEXT STARTED\n");
@@ -207,7 +235,7 @@ void security_clean_openssl() {
         SSL_CTX_free(netdata_opentsdb_ctx);
     }
 
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110
     ERR_free_strings();
 #endif
 }

+ 8 - 1
libnetdata/socket/security.h

@@ -17,9 +17,14 @@
 
 # ifdef ENABLE_HTTPS
 
+#define OPENSSL_VERSION_095 0x00905100L
+#define OPENSSL_VERSION_097 0x0907000L
+#define OPENSSL_VERSION_110 0x10100000L
+#define OPENSSL_VERSION_111 0x10101000L
+
 #  include <openssl/ssl.h>
 #  include <openssl/err.h>
-#  if (SSLEAY_VERSION_NUMBER >= 0x0907000L) && (OPENSSL_VERSION_NUMBER < 0x10100000L)
+#  if (SSLEAY_VERSION_NUMBER >= OPENSSL_VERSION_097) && (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110)
 #   include <openssl/conf.h>
 #  endif
 
@@ -33,6 +38,8 @@ extern SSL_CTX *netdata_client_ctx;
 extern SSL_CTX *netdata_srv_ctx;
 extern const char *security_key;
 extern const char *security_cert;
+extern const char *tls_version;
+extern const char *tls_ciphers;
 extern int netdata_validate_server;
 extern int security_location_for_context(SSL_CTX *ctx,char *file,char *path);
 

+ 1 - 0
streaming/rrdpush.c

@@ -109,6 +109,7 @@ int rrdpush_init() {
     }
 
     char *invalid_certificate = appconfig_get(&stream_config, CONFIG_SECTION_STREAM, "ssl skip certificate verification", "no");
+
     if ( !strcmp(invalid_certificate,"yes")){
         if (netdata_validate_server == NETDATA_SSL_VALID_CERTIFICATE){
             info("Netdata is configured to accept invalid SSL certificate.");

+ 16 - 2
web/server/README.md

@@ -67,11 +67,11 @@ The API requests are serviced as follows:
 
 ### Enabling TLS support
 
-Since v1.16.0, Netdata supports encrypted HTTP connections to the web server, plus encryption of streaming data between a slave and its master, via the TLS 1.2 protocol.
+Since v1.16.0, Netdata supports encrypted HTTP connections to the web server, plus encryption of streaming data between a slave and its master, via the TLS protocol.
 
 Inbound unix socket connections are unaffected, regardless of the TLS settings.\
 ??? info "Differences in TLS and SSL terminology"
-    While Netdata uses Transport Layer Security (TLS) 1.2 to encrypt communications rather than the obsolete SSL protocol, it's still common practice to refer to encrypted web connections as `SSL`. Many vendors, like Nginx and even Netdata itself, use `SSL` in configuration files, whereas documentation will always refer to encrypted communications as `TLS` or `TLS/SSL`.
+    While Netdata uses Transport Layer Security (TLS) to encrypt communications rather than the obsolete SSL protocol, it's still common practice to refer to encrypted web connections as `SSL`. Many vendors, like Nginx and even Netdata itself, use `SSL` in configuration files, whereas documentation will always refer to encrypted communications as `TLS` or `TLS/SSL`.
 
 To enable TLS, provide the path to your certificate and private key in the `[web]` section of `netdata.conf`:
 
@@ -96,6 +96,20 @@ openssl req -newkey rsa:2048 -nodes -sha512 -x509 -days 365 -keyout key.pem -out
 openssl speed rsa2048 rsa4096
 ```
 
+### Select TLS version
+
+Beginning with version 1.21, you can also specify the TLS version and the ciphers that you want to use:
+
+```conf
+[web]
+    tls version = 1.3
+    tls ciphers = TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256
+```
+
+If you do not specify these options, Netdata will use the highest available protocol version on your system and the default cipher list for that protocol provided by your TLS implementation.
+
+While Netdata accepts all the TLS version as arguments (`1` or `1.0`, `1.1`, `1.2` and `1.3`), we recommend you use `1.3` for the most secure encryption.
+
 #### TLS/SSL enforcement
 
 When the certificates are defined and unless any other options are provided, a Netdata server will: