节点 TLS 套接字:DEPTH_ZERO_SELF_SIGNED_CERT 错误
Node TLS socket : DEPTH_ZERO_SELF_SIGNED_CERT error
我正在尝试在节点中使用 TLS 设置服务器和一些客户端。我在客户端和服务器上使用自签名证书。服务器 运行 没问题,但是当我尝试连接客户端时,客户端出现以下错误:
Error: DEPTH_ZERO_SELF_SIGNED_CERT
证书生成
CA 证书:
# Create key to sign our own certs. Act like as our own a CA.
echo "SecuresPassphrase" > ./tls/passphrase.txt
openssl ecparam -name secp521r1 -genkey -noout -out ./tls/certs/ca/ca.plain.key # Generate private key
openssl pkcs8 -topk8 -passout file:./tls/passphrase.txt -in ./tls/certs/ca/ca.plain.key -out ./tls/certs/ca/ca.key # Generate encrypted private key
rm ./tls/certs/ca/ca.plain.key; # Remove unencrypted private key
# Generate CA cert
openssl req -config ./openssl/oid_file -passin file:./tls/passphrase.txt -new -x509 -days 365 -key ./tls/certs/ca/ca.key -out ./tls/certs/ca/ca.crt
服务器证书:
openssl ecparam -name secp521r1 -genkey -noout -out ./tls/certs/servers/server.key # Generate server private key
openssl req -config ./openssl/oid_file -new -key ./tls/certs/servers/server.key -out ./tls/certs/servers/server.csr # Generate signing request
openssl x509 -passin file:./tls/passphrase.txt -req -days 365 -in ./tls/certs/servers/server.csr -CA ./tls/certs/ca/ca.crt -CAkey ./tls/certs/ca/ca.key -CAcreateserial -out ./tls/server.crt
mv ./tls/server.crt ./tls/certs/servers/
客户端证书:
客户端的证书在 bash 循环中创建,变量 ${name}
包含客户端的名称并在每次迭代时更改。
openssl ecparam -name secp521r1 -genkey -noout -out ./tls/certs/clients/${name}/client.key
openssl req -config ./openssl/oid_file -new -key ./tls/certs/clients/${name}/client.key -out ./tls/certs/clients/${name}/client.csr
openssl x509 -passin file:./tls/passphrase.txt -req -days 365 -in ./tls/certs/clients/${name}/client.csr -CA ./tls/certs/ca/ca.crt -CAkey ./tls/certs/ca/ca.key -CAcreateserial -out ./tls/client.crt
mv ./tls/client.crt ./tls/certs/clients/${name}/
我也在尝试通过使用短暂的 Diffie-Hellman 交换来使用完美前向保密。客户端和服务器的参数创建为 openssl dhparam -outform PEM -out ./tls/params/servers/server/dhparams.pem 2048
服务器代码:
return new Promise(resolve => {
// Define parameters of TLS socket
const options = {
rejectUnauthorized: false,
requestCert: true,
// Secure Context Parameters
ca: [fs.readFileSync("tls/certs/ca/ca.crt")],
cert: fs.readFileSync("tls/certs/servers/server.crt"),
key: fs.readFileSync("tls/certs/servers/server.key"),
ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:!RC4:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!SRP:!CAMELLIA",
dhparam: fs.readFileSync("tls/params/servers/server/dhparams.pem"),
ecdhCurve: tls.DEFAULT_ECDH_CURVE,
minVersion: "TLSv1.2"
};
// Iniciar servidor TLS
this.SERVIDOR = tls.createServer(options, function (socket) {
console.log("Server created.");
});
this.SERVIDOR.listen(this.puerto, this.direccion, function () {
console.log("Listening");
});
this.SERVIDOR.on("secureConnection", (socket) => this.handleRequest(socket));
this.SERVIDOR.on("tlsClientError", (error) => console.log("Error client TLs. %s", error));
});
客户代码:
return new Promise(resolve => {
// Define parameters of TLS socket
const options = {
host: this.NODE,
port: this.NODE_PORT,
rejectUnauthorized: false,
secureContext: tls.createSecureContext({
ca: [fs.readFileSync("tls/certs/ca/ca.crt")],
cert: fs.readFileSync("tls/certs/clients/" + this.NAME + "/client.crt"),
key: fs.readFileSync("tls/certs/clients/" + this.NAME + "/client.key"),
ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:!RC4:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!SRP:!CAMELLIA",
dhparam: fs.readFileSync("tls/params/clients/" + this.NAME + "/dhparams.pem"),
ecdhCurve: tls.DEFAULT_ECDH_CURVE,
minVersion: "TLSv1.2"
})
};
// Initialize TLS socket
this.WEB_SOCKET = tls.connect(options, function () {
// Check if TLS auth worked
if (this.authorized) {
console.log("Connection authorized by a Cert. Authority ");
} else {
console.log("Authorization not granted. Error: " + this.authorizationError);
}
});
我试过的:
- 将 rejectUnauthorized 设置为
false
。
- 尝试 运行 代码
NODE_TLS_REJECT_UNAUTHORIZED = "0";
。它没有用,我认为这不是生产的好选择。
- 检查了关于 SO 的类似问题,this one it looks pretty similar to my problem. But the most upvoted answer is from 2014 and I couldn't find too much information about Distinguished name on the docs。
- 我使用
openssl x509 -in *.cert -text
检查了证书,它们看起来不错。
¿我是否错误地生成了证书?任何帮助表示赞赏。
谢谢!
编辑。 16/10/2019
代码有问题,套接字打开时我没有使用 resolve();
。同样的问题仍然存在... BUT 尽管客户端出现授权错误,服务器仍会触发 "secureConnection" 事件并交换消息。 ¿这有意义吗? *是的,这是有道理的,因为服务器接受未经授权的连接。如果我将服务器设置为拒绝未经认证的连接,客户端就会挂断 *
问题是我对所有证书使用了相同的配置文件 (./openssl/oid_file)。使用不同的配置文件和不同的替代名称解决了这个问题。
我以 "UNABLE_TO_VERIFY_LEAF_SIGNATURE" 错误结束。证书已正确生成,但没有用。我在 nodejs 中找不到 working 自签名证书的示例。他们中的大多数人只是通过禁用 SSL 或接受未经授权的交易来弃用证书的使用,这与 TLS 应该做的相反。
最后,我使用了这个工具来生成证书:https://github.com/FiloSottile/mkcert。在测试环境中生成自签名证书的最好和最简单的方法。只需要设置节点变量NODE_EXTRA_CA_CERTS指向根证书:
process.env.NODE_EXTRA_CA_CERTS = [os.homedir() + "/.local/share/mkcert/rootCA.pem"];
-
我正在尝试在节点中使用 TLS 设置服务器和一些客户端。我在客户端和服务器上使用自签名证书。服务器 运行 没问题,但是当我尝试连接客户端时,客户端出现以下错误:
Error: DEPTH_ZERO_SELF_SIGNED_CERT
证书生成
CA 证书:
# Create key to sign our own certs. Act like as our own a CA.
echo "SecuresPassphrase" > ./tls/passphrase.txt
openssl ecparam -name secp521r1 -genkey -noout -out ./tls/certs/ca/ca.plain.key # Generate private key
openssl pkcs8 -topk8 -passout file:./tls/passphrase.txt -in ./tls/certs/ca/ca.plain.key -out ./tls/certs/ca/ca.key # Generate encrypted private key
rm ./tls/certs/ca/ca.plain.key; # Remove unencrypted private key
# Generate CA cert
openssl req -config ./openssl/oid_file -passin file:./tls/passphrase.txt -new -x509 -days 365 -key ./tls/certs/ca/ca.key -out ./tls/certs/ca/ca.crt
服务器证书:
openssl ecparam -name secp521r1 -genkey -noout -out ./tls/certs/servers/server.key # Generate server private key
openssl req -config ./openssl/oid_file -new -key ./tls/certs/servers/server.key -out ./tls/certs/servers/server.csr # Generate signing request
openssl x509 -passin file:./tls/passphrase.txt -req -days 365 -in ./tls/certs/servers/server.csr -CA ./tls/certs/ca/ca.crt -CAkey ./tls/certs/ca/ca.key -CAcreateserial -out ./tls/server.crt
mv ./tls/server.crt ./tls/certs/servers/
客户端证书:
客户端的证书在 bash 循环中创建,变量 ${name}
包含客户端的名称并在每次迭代时更改。
openssl ecparam -name secp521r1 -genkey -noout -out ./tls/certs/clients/${name}/client.key
openssl req -config ./openssl/oid_file -new -key ./tls/certs/clients/${name}/client.key -out ./tls/certs/clients/${name}/client.csr
openssl x509 -passin file:./tls/passphrase.txt -req -days 365 -in ./tls/certs/clients/${name}/client.csr -CA ./tls/certs/ca/ca.crt -CAkey ./tls/certs/ca/ca.key -CAcreateserial -out ./tls/client.crt
mv ./tls/client.crt ./tls/certs/clients/${name}/
我也在尝试通过使用短暂的 Diffie-Hellman 交换来使用完美前向保密。客户端和服务器的参数创建为 openssl dhparam -outform PEM -out ./tls/params/servers/server/dhparams.pem 2048
服务器代码:
return new Promise(resolve => {
// Define parameters of TLS socket
const options = {
rejectUnauthorized: false,
requestCert: true,
// Secure Context Parameters
ca: [fs.readFileSync("tls/certs/ca/ca.crt")],
cert: fs.readFileSync("tls/certs/servers/server.crt"),
key: fs.readFileSync("tls/certs/servers/server.key"),
ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:!RC4:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!SRP:!CAMELLIA",
dhparam: fs.readFileSync("tls/params/servers/server/dhparams.pem"),
ecdhCurve: tls.DEFAULT_ECDH_CURVE,
minVersion: "TLSv1.2"
};
// Iniciar servidor TLS
this.SERVIDOR = tls.createServer(options, function (socket) {
console.log("Server created.");
});
this.SERVIDOR.listen(this.puerto, this.direccion, function () {
console.log("Listening");
});
this.SERVIDOR.on("secureConnection", (socket) => this.handleRequest(socket));
this.SERVIDOR.on("tlsClientError", (error) => console.log("Error client TLs. %s", error));
});
客户代码:
return new Promise(resolve => {
// Define parameters of TLS socket
const options = {
host: this.NODE,
port: this.NODE_PORT,
rejectUnauthorized: false,
secureContext: tls.createSecureContext({
ca: [fs.readFileSync("tls/certs/ca/ca.crt")],
cert: fs.readFileSync("tls/certs/clients/" + this.NAME + "/client.crt"),
key: fs.readFileSync("tls/certs/clients/" + this.NAME + "/client.key"),
ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:!RC4:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!SRP:!CAMELLIA",
dhparam: fs.readFileSync("tls/params/clients/" + this.NAME + "/dhparams.pem"),
ecdhCurve: tls.DEFAULT_ECDH_CURVE,
minVersion: "TLSv1.2"
})
};
// Initialize TLS socket
this.WEB_SOCKET = tls.connect(options, function () {
// Check if TLS auth worked
if (this.authorized) {
console.log("Connection authorized by a Cert. Authority ");
} else {
console.log("Authorization not granted. Error: " + this.authorizationError);
}
});
我试过的:
- 将 rejectUnauthorized 设置为
false
。 - 尝试 运行 代码
NODE_TLS_REJECT_UNAUTHORIZED = "0";
。它没有用,我认为这不是生产的好选择。 - 检查了关于 SO 的类似问题,this one it looks pretty similar to my problem. But the most upvoted answer is from 2014 and I couldn't find too much information about Distinguished name on the docs。
- 我使用
openssl x509 -in *.cert -text
检查了证书,它们看起来不错。
¿我是否错误地生成了证书?任何帮助表示赞赏。 谢谢!
编辑。 16/10/2019
代码有问题,套接字打开时我没有使用 resolve();
。同样的问题仍然存在... BUT 尽管客户端出现授权错误,服务器仍会触发 "secureConnection" 事件并交换消息。 ¿这有意义吗? *是的,这是有道理的,因为服务器接受未经授权的连接。如果我将服务器设置为拒绝未经认证的连接,客户端就会挂断 *
问题是我对所有证书使用了相同的配置文件 (./openssl/oid_file)。使用不同的配置文件和不同的替代名称解决了这个问题。
我以 "UNABLE_TO_VERIFY_LEAF_SIGNATURE" 错误结束。证书已正确生成,但没有用。我在 nodejs 中找不到 working 自签名证书的示例。他们中的大多数人只是通过禁用 SSL 或接受未经授权的交易来弃用证书的使用,这与 TLS 应该做的相反。
最后,我使用了这个工具来生成证书:https://github.com/FiloSottile/mkcert。在测试环境中生成自签名证书的最好和最简单的方法。只需要设置节点变量NODE_EXTRA_CA_CERTS指向根证书:
process.env.NODE_EXTRA_CA_CERTS = [os.homedir() + "/.local/share/mkcert/rootCA.pem"];
-