目标:客户端应将数据发送到受信任的服务器(通过自签名证书),并且服务器应相同。
我正在运行Node.js TLS服务器,并且有许多嵌入式客户端,它们在C中运行openSSL TLS客户端。我已经完成了整个设置,可以看到数据已加密(通过Wireshark),但是我不相信自己以正确的方式(尤其是我处理证书的方式)进行操作。
到目前为止我有什么
Node.js服务器代码段
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客户端代码段
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;
}
SSL_CTX_load_verify_locations(ctx, cert, NULL)
。该文件说指定ctx的位置,用于验证的CA证书位于该位置。通过CAfile和CApath可用的证书是受信任的。
这是否意味着客户端ServerHello
将根据TLS握手消息中收到的证书对它进行检查?如果是这样,我应该调用另一个函数来执行此检查吗?
任何帮助将不胜感激。谢谢!
对于C客户端,您可能希望通过显式调用OpenSSL的函数来确保客户端正在验证服务器证书SSL_CTX_set_verify()
:
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
打电话之前BIO_new_ssl_connect()
。请注意,这可能不是必需的。
是的,您通过设置的证书SSL_CTX_load_verify_locations()
是用于验证服务器证书的证书(属于的一部分ServerHello
)。根据这些验证证书检查服务器证书是默认的OpenSSL验证回调的一部分。
每对的NodeJS TLScreateServer
文档,您可能需要提供一对夫妇为你的TLS服务器更多的选择,特别是ca
阵列和在requestCert
与rejectUnauthorized
布尔值:
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) {
该requestCert
布尔指示服务器请求客户端的证书。在TLS中,服务器必须向客户端明确请求证书;除非服务器要求,否则客户端不会提供一个。如果不设置rejectUnauthorized
为true
,您的TLS服务器将请求证书,但忽略任何验证错误并允许连接继续进行,这是不希望的。然后,ca
阵列配置验证证书列表(类似于SSL_CTX_load_verify_locations()
Node.js用于验证客户端证书的OpenSSL )。
理想情况下,您将没有三个证书,而不是为服务器使用自签名证书,也不为客户端使用单独的自签名证书,而是拥有三个证书:CA证书(按定义是自签名的),服务器证书(即已定义的证书)。由该CA签发/签名),以及单独的客户端证书(也由CA签发/签名)。由于您同时控制客户端和服务器,因此不需要从公共CA购买这些证书。浏览器需要这些证书(因为公共CA的证书在浏览器的信任库中),但这听起来并不像您的用例所需要的(因此,您可以通过生成/使用自己的CA来节省一些钱)。这个网站 提供了用于执行此操作的示例命令。
这样,您的服务器将拥有其证书(和私钥)以及CA证书;您的客户将拥有其证书(和私钥)以及CA证书。那么,CA证书将是在SSL_CTX_load_verify_locations()
路径/文件中以及在ca
选项中配置的证书tls.createServer
。
作为奖励,描述你可以考虑添加支持TLS会话缓存,在这里。
希望这可以帮助!
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句