cURL 명령줄에서 자체 서명된 인증서를 신뢰하는 방법은 무엇입니까?

cURL 명령줄에서 자체 서명된 인증서를 신뢰하는 방법은 무엇입니까?

foo.localhost를 사용하여 자체 서명된 인증서를 만들었습니다.추천을 암호화하자이 Makefile을 사용하십시오:

include ../.env

configuration = csr.cnf
certificate = self-signed.crt
key = self-signed.key

.PHONY: all
all: $(certificate)

$(certificate): $(configuration)
    openssl req -x509 -out $@ -keyout $(key) -newkey rsa:2048 -nodes -sha256 -subj '/CN=$(HOSTNAME)' -extensions EXT -config $(configuration)

$(configuration):
    printf "[dn]\nCN=$(HOSTNAME)\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:$(HOSTNAME)\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth" > $@

.PHONY: clean
clean:
    $(RM) $(configuration)

그런 다음 웹 서버에 할당합니다. 서버가 관련 인증서를 반환했음을 확인했습니다.

$ openssl s_client -showcerts -connect foo.localhost:8443 < /dev/null
CONNECTED(00000003)
depth=0 CN = foo.localhost
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = foo.localhost
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
 0 s:/CN=foo.localhost
   i:/CN=foo.localhost
-----BEGIN CERTIFICATE-----
[…]
-----END CERTIFICATE-----
---
Server certificate
subject=/CN=foo.localhost
issuer=/CN=foo.localhost
---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 1330 bytes and written 269 bytes
Verification error: unable to verify the first certificate
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256
    Session-ID: […]
    Session-ID-ctx: 
    Master-Key: […]
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket:
    […]

    Start Time: 1529622990
    Timeout   : 7200 (sec)
    Verify return code: 21 (unable to verify the first certificate)
    Extended master secret: no
---
DONE

cURL을 신뢰하게 만드는 방법/etc에서 아무것도 수정하지 않습니까? --cacert하다아니요아마도 CA가 없기 때문에 작동합니다.

$ curl --cacert tls/foo.localhost.crt 'https://foo.localhost:8443/'
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

목표는 개발 중에 HTTPS를 활성화하는 것입니다.

  • 모든 개발 환경에서 DNS 확인을 활성화하기 위한 많은 작업 없이는 완전히 프로덕션과 유사한 인증서를 얻을 수 없습니다. 따라서 자체 서명된 인증서를 사용해야 합니다.
  • 물론, 저는 여전히 개발 환경을 프로덕션 환경과 최대한 유사하게 만들고 싶기 때문에 모든 인증서 문제를 단순히 무시할 수는 없습니다. 이 경우 curl -k와 마찬가지로 catch (Exception e) {}브라우저가 웹 서버와 통신하는 것과는 다릅니다.

즉, 내가 달릴 때 curl [something] https://project.local/api/foo나는 확신하고 싶다.

  1. TLS가 올바르게 구성된 경우자체 서명된 인증서를 보유하는 것 외에도명령이 성공하고
  2. 내 TLS 구성에 문제가 있는 경우자체 서명된 인증서를 보유하는 것 외에도명령이 실패합니다.

HTTP가 사용되거나 --insecure두 번째 기준이 충족되지 않습니다.

답변1

노력하다 -k:

curl -k https://yourhost/

자체 서명된 인증서를 "수락"해야 합니다.

답변2

아래 단계를 따르면 문제가 해결됩니다.

  1. 자체 서명된 인증서를 다운로드하고 저장합니다.echo quit | openssl s_client -showcerts -servername "${API_HOST}" -connect "${API_HOST}":443 > cacert.pem
  2. curl고객에게 다음과 같이 말하세요 .curl --cacert cacert.pem --location --silent https://${API_HOST}

wget을 사용하고 인증서를 무시할 수도 있습니다.wget --no-check-certificate https://${API_HOST}

답변3

이 문제는 정확히 동일한 문제와 오류 메시지에 부딪혔지만 Openssl 대신 GNUTLS의 certtool을 사용하여 인증서를 생성했습니다.

내 문제는 CA로서 자체 서명된 인증서가 없다는 것입니다. 웹 서버 인증서로만 작동하도록 구성됩니다. 이것이 제가 하고 싶은 전부입니다. 다른 인증서에 서명하기 위해 CA로 사용할 계획은 없습니다.

그러나 다른 인증서의 발급자로 신뢰 체인에 인증서를 추가하려는 경우 인증서는 CA여야 합니다. 그렇지 않으면 openssl에 의해 거부됩니다!

의 경우 certtool -i < mycert.crt다음을 확인해야 합니다.

    Extensions:
            Basic Constraints (critical):
                    Certificate Authority (CA): TRUE

-addext basicConstraints=critical,CA:TRUE,pathlen:1동일한 효과를 얻으려면 openssl 명령을 추가하거나 cnf 파일을 수정해 보십시오 .

또는 certtool을 사용하면 일회성 인증서 생성이 훨씬 쉽습니다.

certtool -p --outfile localhost.key
certtool -s --load-privkey localhost.key --outfile localhost.crt

그런 다음 프롬프트에 따라 인증서의 CN을 제공합니다. 인증 기관에 대한 것인지 물으면 "예"라고 대답하세요!

답변4

제공된 솔루션을 사용하면 trustme문제가 없었지만 학습 목적으로 인증서를 만드는 데 관심이 있는 사람이라면 다음 단계를 따르세요.

  1. 루트 CA를 만듭니다.

    openssl req -x509 -sha256 -days 1825 -newkey rsa:2048 -keyout rootCA.key -out rootCA.crt
    
  2. 서버 개인 키를 생성합니다:

    openssl genrsa -out localhost.key 2048
    
  3. 인증서 서명 요청을 생성합니다.

    openssl req -key localhost.key -new -out localhost.csr
    
  4. localhost.ext다음 내용으로 파일을 만듭니다 .

    authorityKeyIdentifier=keyid,issuer
    basicConstraints=CA:FALSE
    subjectAltName = @alt_names
    [alt_names]
    DNS.1 = localhost
    

    이 파일에는 인증서에 대한 DNS 구성이 있습니다. URL의 이름이 인증서의 DNS와 일치하지 않으면 TLS 확인이 실패하므로 이는 중요합니다.

  5. 이전에 생성한 루트 CA를 사용하여 서버 인증서에 서명합니다.

    openssl x509 -req -CA rootCA.crt -CAkey rootCA.key -in localhost.csr -out localhost.crt -days 365 -CAcreateserial -extfile localhost.ext
    
  6. 파일을 crt다음 pem형식으로 변환합니다:

    openssl x509 -in localhost.crt -out localhost.pem
    openssl x509 -in rootCA.crt -out rootCA.pem
    

이제 서버에서 및 를 사용할 수 있습니다 localhost.pem. localhost.key클라이언트는 rootCA.pem서버에 연결하는 데 사용해야 합니다.

내 경우에는 파일을 사용해야 합니다 jks. 파일 은 다음 pem과 같이 변환될 수 있습니다 jks:

//first convert it to pkcs12
openssl pkcs12 -export -in localhost.pem -inkey localhost.key -out serverCertificate.p12 -name "serverCertificate"

//then convert it from pkcs12 to jks
keytool -importkeystore -srckeystore serverCertificate.p12 -srcstoretype pkcs12 -destkeystore localhost.jks

다음 명령을 사용하여 키 저장소의 항목을 볼 수 있습니다.

keytool -keystore localhost.jks -list

localhost.jks서버에서 사용해야 하며 다음을 사용하여 연결을 테스트할 수 있습니다.

curl --cacert rootCA.pem https://localhost:<port>

인용하다:

  1. https://www.baeldung.com/openssl-self-signed-cert
  2. https://www.digicert.com/kb/ssl-support/openssl-quick-reference-guide.htm
  3. https://www.baeldung.com/convert-pem-to-jks

관련 정보