Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

error connecting with SSL #183

Closed
adobeturchenko opened this issue Mar 10, 2021 · 9 comments
Closed

error connecting with SSL #183

adobeturchenko opened this issue Mar 10, 2021 · 9 comments

Comments

@adobeturchenko
Copy link

adobeturchenko commented Mar 10, 2021

I'm trying to connect to SSL Redis server and getting connection error.
(I tried to connect to the same server using redis-cli with hostname and a password and it works fine)

ConnectionOptions opts;
opts.host = <some_hostname>;
opts.port = 6380;
opts.tls.enabled = true;
opts.password = <some_password>;

Error I got is not very informative:
redis error: Failed to initialize TLS connection: SSL_connect failed: (null)

After modifying hiredis it gave me something better:
redis error: Failed to initialize TLS connection: SSL_connect failed: certificate verify failed

It looks like the code (SSL_get_verify_result(ssl) == 20) refers to:
20 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: unable to get local issuer certificate
the issuer certificate could not be found: this occurs if the issuer certificate of an untrusted certificate cannot be found.

I'm likely doing something wrong. But what? (again, redis-cli works fine)

@sewenew
Copy link
Owner

sewenew commented Mar 10, 2021

Since you enabled ConnectionOptions::tls::enable, you need to specify other TLS options, e.g. certification file, key file. Please check the doc for detail.

I tried to connect to the same server using redis-cli with hostname and a password and it works fine

Did you connect Redis with TLS enabled? If you did, you should set TLS options with command line arguments. For example:

./src/redis-cli --tls \
        --cert ./tests/tls/redis.crt \
        --key ./tests/tls/redis.key \
        --cacert ./tests/tls/ca.crt

You can use these command line arguments to set ConnectionOptions::tls

Regards

@adobeturchenko
Copy link
Author

Actually I connected in redis-cli without specifying certificates:
redis-cli --tls -h < some_hostname > -p 6380
and after authentication was able to set/get values.

Also jedis (Java client) connects and all tests pass without certificates on the same host.
Redis++ documentation states that those certificates are optional:
opts.tls.enabled = true; // Required. false by default.
opts.tls.cert = "/path/to/client/certificate"; // Optional
opts.tls.key = "/path/to/private/key/file"; // Optional
opts.tls.cacert = "/path/to/CA/certificate/file"; // Optional
opts.tls.sni = "server-name-indication"; // Optional

@adobeturchenko
Copy link
Author

I think I've figured it out...
redis-cli has an option to skip certificate verification:
SSL_CTX_set_verify(ssl_ctx, config.skip_cert_verify ? SSL_VERIFY_NONE : SSL_VERIFY_PEER, NULL);
I don't see such option in redis-plus-plus but maybe I need to look again.

@sewenew
Copy link
Owner

sewenew commented Mar 11, 2021

@adobeturchenko Thanks for pointing it out!

It seems that this is a new feature for redis-cli, and it has not been supported by hiredis:

    SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, NULL);

So redis-plus-plus cannot skip the verification so far.

Sorry for that. I'll keep an eye on this hiredis' progress on this problem, and if hiredis fixes it, I'll make redis-plus-plus supports this feature.

Regards

@adobeturchenko
Copy link
Author

adobeturchenko commented Mar 11, 2021

After another round of research I've found actual missing code in hiredis:

diff --git a/ssl.c b/ssl.c
index c856bbc..726706a 100644
--- a/ssl.c
+++ b/ssl.c
@@ -273,6 +273,11 @@ redisSSLContext *redisCreateSSLContext(const char *cacert_filename, const char *
             if (error) *error = REDIS_SSL_CTX_CA_CERT_LOAD_FAILED;
             goto error;
         }
+    } else {
+        if (!SSL_CTX_set_default_verify_paths(ctx->ssl_ctx)) {
+            printf( "!!!!   Failed to use default CA paths\n");
+            goto error;
+        }
     }
 
     if (cert_filename) {

According to OpenSSL:
SSL_CTX_set_default_verify_paths() specifies that the default locations from which CA certificates are loaded should be used. There is one default directory and one default file. The default CA certificates directory is called "certs" in the default OpenSSL directory.

It can be fixed in hiredis or maybe in redis++ similar to how redis-cli is doing it (they also have dependency on hiredis) - construct SSL object inside redis++ and pass it with redisInitiateSSL() (redis++ uses redisInitiateSSLWithContext() and relies on hiredis to deal with SSL as I understand).

@sewenew
Copy link
Owner

sewenew commented Mar 13, 2021

I think it's better to make hiredis to support it, so that redis-plus-plus can be consistent with it.

I've created a pull request to hiredis: #927. When it's done, I'll port it to redis-plus-plus.

Regards

@sewenew
Copy link
Owner

sewenew commented Mar 22, 2023

Since hiredis already supports skipping certificate verification, I added this support for redis-plus-plus. In order to use this feature, you need to install hiredis v1.1.0 or above with TSL support.

ConnectionOptions opts;
opts.host = "127.0.0.1";
opts.port = 6379;
opts.tls.enabled = true;
opts.tls.verify_mode = REDIS_SSL_VERIFY_NONE;   // DO NOT verify certificate.
auto r = Redis(opts);
std::cout << r.ping() << std::endl;

Regards

@sewenew sewenew closed this as completed Mar 22, 2023
@sewenew
Copy link
Owner

sewenew commented Apr 28, 2023 via email

@sewenew
Copy link
Owner

sewenew commented May 4, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants