itsource

오류: nodejs의 첫 번째 인증서를 확인할 수 없습니다.

mycopycode 2023. 6. 6. 08:21
반응형

오류: nodejs의 첫 번째 인증서를 확인할 수 없습니다.

URL을 사용하여 jira 서버에서 파일을 다운로드하려고 하는데 오류가 발생합니다.어떻게 확인할 코드에 인증서를 포함합니까?

오류:

Error: unable to verify the first certificate in nodejs

at Error (native)
    at TLSSocket.<anonymous> (_tls_wrap.js:929:36)
   
  at TLSSocket.emit (events.js:104:17)

at TLSSocket._finishInit (_tls_wrap.js:460:8)

내 노드js 코드:

var https = require("https");
var fs = require('fs');
var options = {
    host: 'jira.example.com',
    path: '/secure/attachment/206906/update.xlsx'
};

https.get(options, function (http_res) {
    
    var data = "";

  
    http_res.on("data", function (chunk) {
       
        data += chunk;
    });

   
    http_res.on("end", function () {
      
        var file = fs.createWriteStream("file.xlsx");
        data.pipe(file);
      
    });
});

unable to verify the first certificate

인증서 체인이 불완전합니다.

연결 중인 웹 서버가 잘못 구성되어 있으며 사용자에게 보낸 인증서 체인에 중간 인증서가 포함되어 있지 않음을 의미합니다.

인증서 체인

대부분 다음과 같이 나타납니다.

  1. 서버 인증서 - 중간에서 서명한 인증서를 저장합니다.
  2. 중간 인증서 - 루트별로 서명된 인증서를 저장합니다.
  3. 루트 인증서 - 자체 서명된 인증서를 저장합니다.

중간 인증서는 서버 인증서와 함께 서버에 설치되어야 합니다.
루트 인증서는 소프트웨어 응용 프로그램, 브라우저 및 운영 체제에 내장되어 있습니다.

인증서를 제공하는 응용프로그램은 전체 체인을 전송해야 합니다. 이는 서버 인증서 자체와 모든 중간자를 의미합니다.루트 인증서는 클라이언트에서 알 수 있어야 합니다.

문제 다시 만들기

브라우저를 사용하여 https://incomplete-chain.badssl.com 으로 이동합니다.

오류가 나타나지 않습니다(주소 표시줄의 자물쇠가 녹색임).
서버에서 전송되지 않으면 브라우저가 체인을 완료하는 경향이 있기 때문입니다.

이제 노드를 사용하여 https://incomplete-chain.badssl.com 에 연결합니다.

// index.js
const axios = require('axios');

axios.get('https://incomplete-chain.badssl.com')
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

로그: "오류: 번째 인증서를 확인할 수 없습니다."

해결책

직접 인증서 체인을 완료해야 합니다.

실행 방법:

1: 누락된 중간 인증서를 에서 가져와야 합니다..pemformat을한 다음 , 음다

2a: 다음을 사용하여 노드의 기본 제공 인증서 저장소 확장NODE_EXTRA_CA_CERTS,

2b: 또는 다음을 사용하여 자체 인증서 번들(인증서 및 루트) 전달ca선택.

중급 자격증을 받으려면 어떻게 해야 합니까?

용사를 합니다.opensslGit for Windows와 함께 제공됩니다.

원격 서버의 인증서 세부 정보 저장:

openssl s_client -connect incomplete-chain.badssl.com:443 -servername incomplete-chain.badssl.com | tee logcertfile

발급자를 찾고 있습니다(중간 인증서는 서버 인증서의 발급자/서명자).

openssl x509 -in logcertfile -noout -text | grep -i "issuer"

그것은 당신에게 서명 인증서의 URI를 줄 것입니다.다운로드:

curl --output intermediate.crt http://cacerts.digicert.com/DigiCertSHA2SecureServerCA.crt

마막으로변환다니합지다로 변환합니다..pem:

openssl x509 -inform DER -in intermediate.crt -out intermediate.pem -text

2a. NODE_EXTRA_CA_CERTS

환경 변수를 설정하기 위해 교차 환경을 사용하고 있습니다.package.json파일 이름:

"start": "cross-env NODE_EXTRA_CA_CERTS=\"C:\\Users\\USERNAME\\Desktop\\ssl-connect\\intermediate.pem\" node index.js"

2b.ca

이 옵션은 노드의 기본 제공 루트 CA를 덮어씁니다.

그렇기 때문에 우리만의 루트 CA를 만들어야 합니다.ssl-root-cas를 사용합니다.

그런 다음 사용자 정의를 만듭니다.https에이전트가 인증서 번들(루트 및 중간)으로 구성되었습니다.를 이에전대로 합니다.axios청할 때는

// index.js
const axios = require('axios');
const path = require('path');
const https = require('https');
const rootCas = require('ssl-root-cas').create();

rootCas.addFile(path.resolve(__dirname, 'intermediate.pem'));
const httpsAgent = new https.Agent({ca: rootCas});

axios.get('https://incomplete-chain.badssl.com', { httpsAgent })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

정의를 https을 에전트전달에게 것.axios은 당은인신를놓수있다니습을에 를 넣을 수 .https글로벌 에이전트:

// Applies to ALL requests (whether using https directly or the request module)
https.globalAgent.options.ca = rootCas;

리소스:

  1. https://levelup.gitconnected.com/how-to-resolve-certificate-errors-in-nodejs-app-involving-ssl-calls-781ce48daded
  2. https://www.npmjs.com/package/ssl-root-cas
  3. https://github.com/nodejs/node/issues/16336
  4. https://www.namecheap.com/support/knowledgebase/article.aspx/9605/69/how-to-check-ca-chain-installation
  5. https://superuser.com/questions/97201/how-to-save-a-remote-server-ssl-certificate-locally-as-a-file/
  6. .crt를 .pem으로 변환하는 방법

당신의 모든 요청을 불안정하게 만드는 또 다른 더러운 해킹:

process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0

적절한 루트 인증서 추가 시도

이는 승인되지 않은 엔드포인트를 맹목적으로 수용하는 것보다 훨씬 안전한 옵션이며, 이는 결국 최후의 수단으로만 사용되어야 합니다.

이는 간단히 추가할 수 있습니다.

require('https').globalAgent.options.ca = require('ssl-root-cas/latest').create();

당신의 신청에.

SSL 루트 CA snmp 패키지(여기서 사용)는 이 문제와 관련하여 매우 유용한 패키지입니다.

nodejs에서 첫 번째 인증서를 확인할 수 없기 때문에 승인되지 않은 인증서 거부가 필요합니다.

 request({method: "GET", 
        "rejectUnauthorized": false, 
        "url": url,
        "headers" : {"Content-Type": "application/json",
        function(err,data,body) {
    }).pipe(
       fs.createWriteStream('file.html'));

다운로드하려는 서버가 잘못 구성되었을 수 있습니다.브라우저에서 작동하더라도 캐시가 없는 클라이언트가 확인하는 데 필요한 모든 공용 인증서가 체인에 포함되어 있지 않을 수 있습니다.

SSL labs 도구에서 사이트를 확인하는 것이 좋습니다. https://www.ssllabs.com/ssltest/

다음 오류를 찾습니다.

이 서버의 인증서 체인이 불완전합니다.

그리고 이것은:

체인 문제...미완성

devenv에서 설정:

process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

또는 먼저 환경 변수를 설정합니다.

export NODE_TLS_REJECT_UNAUTHORIZED=0   

그런 다음 응용 프로그램을 시작합니다.

node index.js

제품 서비스에 적합하지 않습니다.

https://www.npmjs.com/package/ssl-root-cas 에서 이 문제를 해결했습니다.

// INCORRECT (but might still work)
var server = https.createServer({
  key: fs.readFileSync('privkey.pem', 'ascii'),
  cert: fs.readFileSync('cert.pem', 'ascii') // a PEM containing ONLY the SERVER certificate
});

// CORRECT (should always work)
var server = https.createServer({
  key: fs.readFileSync('privkey.pem', 'ascii'),
  cert: fs.readFileSync('fullchain.pem', 'ascii') // a PEM containing the SERVER and ALL INTERMEDIATES
});

이를 해결하기 위한 또 다른 방법은 다음 모듈을 사용하는 것입니다.

node_module_ca_certs_module_module

이 모듈은 Mozilla에서 신뢰하는 모든 루트 및 중간 인증서를 포함하는 PEM 파일을 생성하여 코드 수정 없이 작동할 수 있습니다.다음 환경 변수(Nodejs v7.3+와 함께 작동)를 사용할 수 있습니다.

NODE_EXTRA_CA_CERTS

위 환경 변수와 함께 사용할 PEM 파일을 생성합니다.다음을 사용하여 모듈을 설치할 수 있습니다.

npm install --save node_extra_ca_certs_mozilla_bundle

그런 다음 환경 변수를 사용하여 노드 스크립트를 시작합니다.

NODE_EXTRA_CA_CERTS=node_modules/node_extra_ca_certs_mozilla_bundle/ca_bundle/ca_intermediate_root_bundle.pem node your_script.js

생성된 PEM 파일을 사용하는 다른 방법은 다음 사이트에서 사용할 수 있습니다.

https://github.com/arvind-agarwal/node_extra_ca_certs_mozilla_bundle

참고: 저는 위 모듈의 작성자입니다.

아래와 같이 요청 옵션을 수정하여 이 작업을 수행할 수 있습니다.자체 서명된 인증서를 사용하거나 누락된 중개자를 사용하는 경우 엄격하게 설정SSL을 false로 설정하면 요청 패키지가 인증서의 유효성을 검사하지 않습니다.

var options = {
   host: 'jira.example.com',
   path: '/secure/attachment/206906/update.xlsx',
   strictSSL: false
}

GoDaddy SSL 인증서

GoDaddy 인증서를 사용하여 백엔드 API 서버에 연결하려고 시도하는 동안 이 문제를 해결하기 위해 사용한 코드가 있습니다.

var rootCas = require('ssl-root-cas/latest').create();

rootCas
  .addFile(path.join(__dirname, '../config/ssl/gd_bundle-g2-g1.crt'))
  ;

// will work with all https requests will all libraries (i.e. request.js)
require('https').globalAgent.options.ca = rootCas;

PS:

를 설치하는을 잊지 .npm install ssl-root-cas

이 작업이 완료되었습니다 => 에이전트 및 'rejectUnauthorized'가 false로 설정된 에이전트 추가

const https = require('https'); //Add This
const bindingGridData = async () => {
  const url = `your URL-Here`;
  const request = new Request(url, {
    method: 'GET',
    headers: new Headers({
      Authorization: `Your Token If Any`,
      'Content-Type': 'application/json',
    }),
    //Add The Below
    agent: new https.Agent({
      rejectUnauthorized: false,
    }),
  });
  return await fetch(request)
    .then((response: any) => {
      return response.json();
    })
    .then((response: any) => {
      console.log('response is', response);
      return response;
    })
    .catch((err: any) => {
      console.log('This is Error', err);
      return;
    });
};

다음과 같이 요청에 사용하는 패키지에 관계없이 전체적으로 인증서 검사를 비활성화할 수 있습니다.

// Disable certificate errors globally
// (ES6 imports (eg typescript))
//
import * as https from 'https'
https.globalAgent.options.rejectUnauthorized = false

또는

// Disable certificate errors globally
// (vanilla nodejs)
//
require('https').globalAgent.options.rejectUnauthorized = false

물론 이렇게 하면 안 됩니다. 하지만 디버깅 및/또는 매우 기본적인 스크립팅에서 인증서의 정확한 유효성을 전혀 신경 쓰지 않는 경우에 유용합니다.

저는 며칠 전에 이 문제에 직면했고 이것이 제가 추구한 접근 방식이며 저에게 효과가 있습니다.

나에게 있어 이것은 내가 회사 방화벽 아래 있는 것처럼 axios를 사용하여 데이터를 가져오거나 라이브러리를 가져오려고 할 때 발생했습니다. 그래서 우리는 노드 js 인증서 저장소가 가리킬 수 없는 특정 인증서를 가지고 있었습니다.

그래서 저는 제 지역 호스트를 위해 이 접근법을 따랐습니다.프로젝트에 폴더를 만들고 전체 인증서 체인을 폴더에 보관하고 dev-server(package.json)용 스크립트에 서버 스크립트와 함께 추가하여 노드 J가 경로를 참조할 수 있도록 했습니다.

"dev-server":set NODE_EXTRA_CA_CERTS=certificates/certs-bundle.crt

서버(다른 환경)의 경우아래와 같이 새로운 환경변수를 생성하여 추가하였습니다.Openshift를 사용하고 있었지만, 다른 사람들도 마찬가지일 것 같습니다.

"name":NODE_EXTRA_CA_CERTS
"value":certificates/certs-bundle.crt

이 경우 전체 인증서 체인을 이미 사용할 수 있기 때문에 인증서를 생성하지 않았습니다.

사용하고 있습니까?axios요청을 보내고 이 오류를 받으시겠습니까?

" 그다면오고를시십오하려류렇오▁error시▁the▁if▁that십고▁consider"를 고려해 보세요.unable to verify the first certificate에서 나올수있다니습에서 나올 수 .axios서버와 관련이 없습니다.이 문제를 해결하려면 다음을 구성해야 합니다.axios(또는 다른 요청 작성 앱) 무단 요청을 허용합니다.를 합니다.https.Agent설정하는rejectUnauthorized: false요청 구성:

import axios from "axios"
import https from "https"

const getCities = async () => {
    try {
        const result = await axios.get("https://your-site/api/v1/get-cities", {
            httpsAgent: new https.Agent({
              rejectUnauthorized: false // set to false
            })
        })

        console.log(result.data)
    } catch(err) {
        console.log(err?.message||err)
    }
}

지정을 사용자 지정을 사용합니다.axios then 예를 들어 다음과 .

import axios from "axios"
import https from "https"

export const request = axios.create({
  baseURL: process.env.BASE_URL,
  headers: {
    Authorization: cookies.YOUR_ACCESS_TOKEN,
  },
  httpsAgent: new https.Agent({
    rejectUnauthorized: false //set to false
  })
})

@sch에서 제공한 답변은 저에게 큰 도움이 되었습니다.몇 가지 추가 사항이 있습니다. 된 인증서 중 인증서가) 이 입니다.NODE_EXTRA_CA_CERTS환경 변수입니다.자체 서명된 인증서는 PEM 형식으로 저장해야 합니다.인증서를 내보낸 후 다음 작업을 수행했습니다.

set NODE_EXTRA_CA_CERTS=C:\rootCert.pem

(Windows에서 노드를 실행하고 있으며 PEM 경로는 따옴표로 묶이지 않았습니다.)

명령줄에서 {{node}}을(를) 사용하여 다음 전화로 문제를 해결했는지 확인할 수 있었습니다.

https.get("https://my.dev-domain.local")

저는 매우 드문 사례를 만났지만, 누군가에게 도움이 될 수 있기를 바랍니다: 다른 서비스로 요청을 프록시하는 프록시 서비스를 만들었습니다.그리고 모든 요청의 오류는 모든 예상 인증서를 추가할 때도 "첫 번째 인증서를 확인할 수 없습니다"였습니다.

이유는 매우 간단했습니다. 실수로 "호스트" 헤더도 다시 보냈습니다."host" 헤더를 명시적으로 보내지 마십시오.

모질라나 크롬 같은 브라우저를 통해 인증서 체인을 얻을 수 있었습니다.

  1. 웹 사이트를 열고 웹 페이지의 인증서 설정으로 이동하여 인증서 체인을 파일 이름(first-chain.pem, second-chain.pem)으로 다운로드합니다. 다음과 같은 pem 형식이어야 합니다.
----BEGIN CERTIFICATE-----
MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB
......
-----END CERTIFICATE-----
----BEGIN CERTIFICATE-----
MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB
......
-----END CERTIFICATE-----
  1. 그러면 당신의 nodejs 코드에서, 나는 그것을 typescript에서 했고, 나는 2개의 웹 서버 요청이 있기 때문에 2개의 cas를 추가했습니다.
import https from 'https'
import cas from 'ssl-root-cas'

......

 interface CaList extends Buffer {
  addFile(file: string): Buffer[]
 }
 const caList = cas.create() as CaList
 caList.addFile(process.env.PROJECT_PATH + 'certs/first-chain.pem')
 caList.addFile(process.env.PROJECT_PATH + 'certs/second-chain.pem')

그리고 나서 웹소켓 wss 연결을 만들어야 하기 때문에, 나는 요청에 새로운 케이스 목록이 있는 에이전트를 추가합니다.

this.client.connect(KtUrl, undefined, undefined, undefined, {
    agent: new https.Agent({
      ca: caList
    })
})

또한 typescript가 불평하지 않도록 ssl-root-cas 파일 이름 ssl-root-cas.d.ts에 대한 정의 파일을 추가해야 했습니다.

declare module 'ssl-root-cas' {
  function create(): string | Buffer | (string | Buffer)[] | undefined
}

우리는 유효한 것을 제공했습니다.Root.pem and Intermediate.pem에한자격증에 있는 .agentOptions입니다.

ex:

   agentOptions: {
        ca: [
            fs.readFileSync("./ROOT.pem"),
            fs.readFileSync("./Intermediate.pem"),
        ],
    },

자세한 내용은 https://stackoverflow.com/a/72582263/4652706 에서 확인하시기 바랍니다.

Axios 요청: 이 문제의 근본 원인은 코드가 인증서 관리를 처리할 수 없다는 것입니다.이 문제를 해결하려면 아래 코드를 추가합니다.

import * as https from "https";

...

const httpsAgent = new https.Agent({
  rejectUnauthorized: false,
});

이제 httpsAgent를 axios에 전달합니다.아래와 같이.

const { data } = await axios.get(url, { httpsAgent });

제3자가 제 HTTPS 웹 서버를 호출할 때 플라스크에서 이 문제가 발생했습니다. 이 문제는 포스트맨을 통해 쉽게 재현되어 메시지가 표시됩니다.

오류: 첫 번째 인증서를 확인할 수 없습니다.

또는 경유로

openssl s_client -connect www.rc8.net:443 -servername www.rc8.com | tee logcertfile

많은 검색과 다른 해결책을 시도한 후에, 나는 해결책을 찾았다, 문제를 암호화하자,fullchain.pem확실한

cert.pem이 아닌 Flask Run -cert 옵션에서 사용합니다.

이것이 누군가에게 시간을 절약해 주기를 바랍니다.

효과가 있었습니다.

다음을 수행합니다.

이러한 패키지가 없는 경우 https 및 axios

npm install --save axios https로 설치할 수 있습니다.

import axios from 'axios';
import https from 'https';
const httpsAgent = new https.Agent({
    rejectUnauthorized: false,
})

axios.defaults.httpsAgent = httpsAgent

그렇게 하면 응답을 얻을 수 있습니다.

나는 nodemailer npm 모듈을 사용하고 있었습니다.아래 코드는 문제를 해결했습니다.

     tls: {
     // do not fail on invalid certs
     rejectUnauthorized: false
     }

언급URL : https://stackoverflow.com/questions/31673587/error-unable-to-verify-the-first-certificate-in-nodejs

반응형