unable to verify the first certificate
인증서 체인이 불완전합니다.
연결하려는 웹 서버가 잘못 구성되어 전송 한 인증서 체인에 중간 인증서가 포함되지 않았 음을 의미합니다.
인증서 체인
다음과 같이 보입니다.
- 서버 인증서-중간에서 서명 한 인증서를 저장합니다.
- 중간 인증서-루트가 서명 한 인증서를 저장합니다.
- 루트 인증서-자체 서명 된 인증서를 저장합니다.
중간 인증서는 서버 인증서와 함께 서버에 설치해야합니다.
루트 인증서는 소프트웨어 응용 프로그램, 브라우저 및 운영 체제에 포함되어 있습니다.
인증서를 제공하는 응용 프로그램은 완전한 체인을 보내야합니다. 이는 서버 인증서 자체와 모든 중간체를 의미합니다. 루트 인증서는 클라이언트가 알고 있어야합니다.
문제를 재현
https://incomplete-chain.badssl.com으로 이동브라우저를 사용하여 하십시오.
오류가 표시되지 않습니다 (주소 표시 줄의 자물쇠가 녹색 임). 브라우저가 체인을 완성하는 경향이
있기 때문입니다 가 서버에서 전송되지 않으면 입니다.
이제 Node를 사용하여 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 : 누락 된 중간 인증서를 .pem
형식으로 가져와야합니다.
A : 확장 노드에 내장 된 인증서 저장소를 사용 NODE_EXTRA_CA_CERTS
,
2b : 또는 ca
옵션을 사용하여 고유 한 인증서 번들 (중간체 및 루트)을 전달하십시오 .
1. 중간 증명서는 어떻게 받습니까?
사용 openssl
( Git 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_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;
자원:
- https://levelup.gitconnected.com/how-to-resolve-certificate-errors-in-nodejs-app-involving-ssl-calls-781ce48daded
- https://www.npmjs.com/package/ssl-root-cas
- https://github.com/nodejs/node/issues/16336
- https://www.namecheap.com/support/knowledgebase/article.aspx/9605/69/how-to-check-ca-chain-installation
- /superuser/97201/how-to-save-a-remote-server-ssl-certificate-locally-as-a-file/
- .crt를 .pem로 변환하는 방법