Correct way of handling Node.js TLS server and C TLS client (openSSL) connections

am3

Goal: The client should send data to trusted server (through self-signed certificates) and the server the same.

I’m running a Node.js TLS server and have many embedded clients which run openSSL TLS client in C. I have the entire setup working and I can see the data is encrypted (through Wireshark) but I’m not convinced I’m doing it the right way (especially the way I'm handling certificates).

What I have so far

  1. On the Server, I generated a 2048 private key (private-key.pem) and a self-signed certificate (public-cert.pem)
  2. Copied over the self-signed certificate (public-cert.pem) to the client

Node.js server code snippet

var tls = require('tls');
var fs = require('fs');

var options = {
    key: fs.readFileSync('private-key.pem'),
    cert: fs.readFileSync('public-cert.pem')
};
tls.createServer(options, function (socket) {

socket.on('data', function(data) {
    // do something
});

socket.on('close', function() {
    socket.destroy();
});

}).listen(PORT);

C Client code snippet

     SSL_library_init(); 
     SSL_load_error_strings();
     ERR_load_BIO_strings();
     OpenSSL_add_all_algorithms();

     // create new context object
     ctx = SSL_CTX_new(TLSv1_2_client_method());

    //load trust cert

    if(! SSL_CTX_load_verify_locations(ctx, "public-cert.pem", NULL)){

          printf("sslInitialize() Error: Cannot load certificate\n");
          ERR_print_errors_fp(stderr);

          if(ctx != NULL) {

            SSL_CTX_free(ctx);

          }


          return;
    } 

    bio = BIO_new_ssl_connect(ctx);

    BIO_get_ssl(bio, & ssl);


    if (ssl == NULL) {

         printf("sslInitialize() Error: Can't locate SSL pointer\n");
         ERR_print_errors_fp(stderr);

         if(ctx != NULL){

            SSL_CTX_free(ctx);

        } 


        if(bio != NULL){

         BIO_free_all(bio);

        }
         return;
    }

    BIO_set_conn_hostname(bio, HOST);

   int connectStatus;                            

   if((connectStatus = BIO_do_connect(bio)) <= 0) {

    printf("Connect Status: %d",connectStatus);
     printf("sslInitialize() Error: Cannot connect to server\n");
     ERR_print_errors_fp(stderr);

    sslCloseConnection();

     return;
   }

Observations

  1. I changed the certificate on the client to same random certificate and it still works (the certificate the server sent during ServerHello TLS handhake and the client loaded using SSL_CTX_load_verify_locations() were different). The makes me wonder as to how the client is trusting the certificate. How can I sort this out?
  2. As of now I've setup it up in such a way that the client verifies the server (although it isn't working) and sends data and the server blindly accepts it. How can I make the client send a certificate (self-signed by client) and the server only accepts it if it has that particular certificate on file.
  3. On the client-end I use SSL_CTX_load_verify_locations(ctx, cert, NULL). The documentation says

specifies the locations for ctx, at which CA certificates for verification purposes are located. The certificates available via CAfile and CApath are trusted.

Does this mean the client checks this against the certificate received in ServerHello message of the TLS handshake? If so, is there another function I should call to do this check?

  1. As always, I've gone through a lot of resources online (SO posts and openSSL man page) before asking this question. Node.js_TLS,openSSL,SO_1, SO_2 to name a few. I've also omitted header files and other boiler-plate code.

Any help will be appreciated. Thanks!

Castaglia

For the C client, you may want to ensure that the client is verifying the server certificate by calling OpenSSL's SSL_CTX_set_verify() function explicitly:

SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);

before calling BIO_new_ssl_connect(). Note that this may not be necessary.

And yes, the certificates you set via SSL_CTX_load_verify_locations() are the ones used for verifying the server certificate (which is part of the ServerHello). The checking of the server certificate against those verification certificates happens as part of the default OpenSSL verification callback.

Per the Nodejs tls createServer docs, you might need to provide a couple more options for your TLS server, specially the ca array and the requestCert and rejectUnauthorized booleans:

var options = {
    key: fs.readFileSync('private-key.pem'),
    cert: fs.readFileSync('public-cert.pem'),
    ca: [ fs.readFileSync('ca-cert.pem') ],
    requestCert: true,
    rejectUnauthorized: true
};
tls.createServer(options, function (socket) {

The requestCert boolean instructs the server to request the client's certificate. In TLS, the server has to explicitly request a cert from the client; the client does not supply one unless asked by the server. And without setting rejectUnauthorized to true, your TLS server would request the cert, but ignore any validation error and allow the connection to proceed, which is not desirable. And the ca array configures the list of verification certificates (similar to OpenSSL's SSL_CTX_load_verify_locations() that Nodejs will use for verifying the client certificate).

Ideally, rather than using a self-signed certificate for the server, and a separate self-signed certificate for the client, you would have three certificates: a CA certificate (which is self-signed by definition), a server certificate (which was issued/signed by that CA), and a separate client certificate (also issued/signed by the CA). Since you control both the clients and the server, there is no particular need for you to buy these certificates from a public CA; those are needed for browsers (since the public CA's certificates are in the browsers' trust stores), but that doesn't sound like it's needed for your use case (and thus you can save some money by generating/using your own CA). This site provides example commands for doing just this.

This way, your server would have its certificate (and private key), and the CA cert; your client would have its certificate (and private key), and the CA cert. The CA cert, then, would be the certificate configured in the SSL_CTX_load_verify_locations() paths/files, and in the ca option for tls.createServer.

As a bonus, you might consider adding support TLS session caching, as described here.

Hope this helps!

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

正确处理Node.js TLS服务器和C TLS客户端(openSSL)连接的方法

来自分类Dev

正确处理Node.js TLS服务器和C TLS客户端(openSSL)连接的方法

来自分类Dev

使用Node的HTTPS / TLS与OpenSSL s_client时的不同证书链顺序

来自分类Dev

用于客户端TLS连接的OpenSSL或LibreSSL C ++示例

来自分类Dev

用于客户端TLS连接的OpenSSL或LibreSSL C ++示例

来自分类Dev

使用“ openssl s_client”获取服务器的SSL / TLS证书

来自分类Dev

如何在Node.js请求中禁用Tls 1.3

来自分类常见问题

SSL / TLS保护需要openssl扩展

来自分类Dev

如何使用openssl进行TLS 1.3 PSK?

来自分类Dev

在apache-tomcat中禁用了tls1,但仍然可以与openssl s_client连接,为什么?

来自分类Dev

节点js TLS双工流

来自分类Dev

Node.JS错误-process.env.NODE_TLS_REJECT_UNAUTHORIZED。这是什么意思?

来自分类Dev

端口443(HTTPS TLS / SSL)上的Node.js + Express.js + Socket.io

来自分类Dev

端口443(HTTPS TLS / SSL)上的Node.js + Express.js + Socket.io

来自分类Dev

https ssl / tls在Node.js中的本地主机上不起作用

来自分类Dev

TLS1.2支持的node.js客户端

来自分类Dev

Node.JS Thrift服务器示例给出“无法读取未定义的属性'tls'”

来自分类Dev

通过SSL / TLS连接访问Vagrant上的Node.js应用

来自分类Dev

Node.js,简单的TLS客户端/服务器

来自分类Dev

从Node.JS向DocuSign发送请求时强制设置TLS vresion 1.2

来自分类Dev

Node.js axios错误:tls_process_ske_dhe:dh密钥太小

来自分类Dev

结合使用Node.js和TLS获取HTTP主机名错误错误

来自分类Dev

列出特定OpenSSL版本支持的SSL / TLS版本

来自分类Dev

使用 openssl 以编程方式查找已协商的 TLS 版本

来自分类Dev

是否接受带有http-client-tls或tls的特定证书?

来自分类Dev

Is there a way to get client connections count in AWS ELB

来自分类Dev

Java exception client authentication TLS: password must not be null

来自分类Dev

FreeBSD 11端口acme-client的tls握手失败

来自分类Dev

建立安全TLS连接之前客户端网络套接字已断开连接Node.js v13.0.1

Related 相关文章

  1. 1

    正确处理Node.js TLS服务器和C TLS客户端(openSSL)连接的方法

  2. 2

    正确处理Node.js TLS服务器和C TLS客户端(openSSL)连接的方法

  3. 3

    使用Node的HTTPS / TLS与OpenSSL s_client时的不同证书链顺序

  4. 4

    用于客户端TLS连接的OpenSSL或LibreSSL C ++示例

  5. 5

    用于客户端TLS连接的OpenSSL或LibreSSL C ++示例

  6. 6

    使用“ openssl s_client”获取服务器的SSL / TLS证书

  7. 7

    如何在Node.js请求中禁用Tls 1.3

  8. 8

    SSL / TLS保护需要openssl扩展

  9. 9

    如何使用openssl进行TLS 1.3 PSK?

  10. 10

    在apache-tomcat中禁用了tls1,但仍然可以与openssl s_client连接,为什么?

  11. 11

    节点js TLS双工流

  12. 12

    Node.JS错误-process.env.NODE_TLS_REJECT_UNAUTHORIZED。这是什么意思?

  13. 13

    端口443(HTTPS TLS / SSL)上的Node.js + Express.js + Socket.io

  14. 14

    端口443(HTTPS TLS / SSL)上的Node.js + Express.js + Socket.io

  15. 15

    https ssl / tls在Node.js中的本地主机上不起作用

  16. 16

    TLS1.2支持的node.js客户端

  17. 17

    Node.JS Thrift服务器示例给出“无法读取未定义的属性'tls'”

  18. 18

    通过SSL / TLS连接访问Vagrant上的Node.js应用

  19. 19

    Node.js,简单的TLS客户端/服务器

  20. 20

    从Node.JS向DocuSign发送请求时强制设置TLS vresion 1.2

  21. 21

    Node.js axios错误:tls_process_ske_dhe:dh密钥太小

  22. 22

    结合使用Node.js和TLS获取HTTP主机名错误错误

  23. 23

    列出特定OpenSSL版本支持的SSL / TLS版本

  24. 24

    使用 openssl 以编程方式查找已协商的 TLS 版本

  25. 25

    是否接受带有http-client-tls或tls的特定证书?

  26. 26

    Is there a way to get client connections count in AWS ELB

  27. 27

    Java exception client authentication TLS: password must not be null

  28. 28

    FreeBSD 11端口acme-client的tls握手失败

  29. 29

    建立安全TLS连接之前客户端网络套接字已断开连接Node.js v13.0.1

热门标签

归档