Сокет TLS узла: ошибка DEPTH_ZERO_SELF_SIGNED_CERT - PullRequest
0 голосов
/ 15 октября 2019

Я пытаюсь настроить сервер и некоторые клиенты, использующие 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}/

Я также пытаюсь использовать Perfect Forward Secrecy, используя эфемерный обмен Диффи-Хеллмана. Параметры для клиентов и сервера создаются как 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, этот выглядит очень похоже на мою проблему. Но самый голосующий ответ от 2014 года, и я не смог найти слишком много информации о выдающемся имени в документах .
  • Я проверил сертификаты, используя openssl x509 -in *.cert -text, и они выглядели хорошо.

¿Я неправильно генерирую сертификаты? Любая помощь приветствуется. Спасибо!

РЕДАКТИРОВАТЬ. 16/10/2019 В коде была проблема, я не использовал resolve();, когда розетки работали. Та же проблема остается ... НО , несмотря на получение ошибки авторизации на клиенте, сервер запускает событие «secureConnection», и сообщения обмениваются. ¿Имеет ли это смысл? * Да, это имеет смысл, поскольку сервер принимает несанкционированные соединения. Если я настрою сервер на отклонение несертифицированных соединений, клиенты зависнут *

1 Ответ

0 голосов
/ 14 ноября 2019

Проблема была в том, что я использовал один и тот же файл конфигурации (./openssl/oid_file) для всех сертификатов. Использование разных файлов конфигурации и разных альтернативных имен решило эту проблему.

Я закончил с ошибкой «UNABLE_TO_VERIFY_LEAF_SIGNATURE». Сертификаты были сгенерированы правильно, но это не сработало. Я не смог найти работающий пример самозаверяющих сертификатов в nodejs. Большинство из них просто отказались от использования сертификатов, отключив SSL или приняв несанкционированные транзакции, что противоположно тому, что должен делать TLS.

Наконец, я использовал этот инструмент для генерации сертификатов: https://github.com/FiloSottile/mkcert. Лучший и самый простой способ создания самозаверяющих сертификатов в среде тестирования. Вам нужно только установить переменную узла NODE_EXTRA_CA_CERTS, чтобы указать корневой сертификат:

process.env.NODE_EXTRA_CA_CERTS = [os.homedir() + "/.local/share/mkcert/rootCA.pem"];

-

...