본문 바로가기

Study/IT 분야 연구

[curl] (60) server certificate verification failed. 문제 해결 방법

반응형

글로벌 회사에 다니다 보니 외주업체도 글로벌합니다. 캐나다 밴쿠버에 있는 외주업체와 새벽 3시에 zoom으로 통화하면서 API 서버 접속 장애의 원인을 살펴봤습니다. 기존의 API 스크립트로 HTTP 프로토콜(8080 PORT)로 통신하는 것은 문제가 없었습니다. 하지만 최근에 보안성 향상을 위해서 HTTPS 프로토콜(8443 PORT)로 변경한 이후로는 curl 명령을 통해서 기본적인 접속 자체가 불가능하더군요. 구글링과 여러 번의 시행착오 끝에 문제를 해결할 수 있었습니다. 기쁜 마음으로 어떻게 해결했는지에 대해서 기록하고자 합니다.

 

[문제 현상]

curl 명령을 통해서 API 통신을 수행하는데, HTTP 프로토콜로는 정상적인 응답이 오지만, HTTPS 프로토콜로는 기본적인 접속 자체가 불가능했습니다. 아래는 사용했던 curl 명령과 에러 메시지입니다.

 

아래와 같이 curl 명령을 수행했고, 원하는 결과를 얻지 못하여 -v(verbose) 옵션을 붙여서 로그가 더 많이 출력되도록 하였습니다. 

curl -v -H "X-Requested-With: XMLHttpRequest" "https://(URL)"

 

위와 같이 curl 명령을 수행했더니 아래와 같은 메시지가 나왔습니다. 

*   Trying ABC.DEF.GHI.JKL...
* Connected to (URL) (ABC.DEF.GHI.JKL) port 8080 (#0)
* Establish HTTP proxy tunnel to (URL):8443
> CONNECT (URL):8443 HTTP/1.1
> Host: (URL):8443
> User-Agent: curl/7.47.0
> Proxy-Connection: Keep-Alive
> 
< HTTP/1.1 200 Connection established
< 
* Proxy replied OK to CONNECT request
* found 129 certificates in /etc/ssl/certs/ca-certificates.crt
* found 527 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ECDHE_RSA_AES_128_GCM_SHA256
* server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none
* Closing connection 0
curl: (60) server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

 

 

문제 상황의 에러 메시지를 자세히 살펴보면 "curl: (60) server certificate verification failed."라는 메시지가 보입니다. 처음에는 API 통신을 위한 ID/PW 또는 Token 인증의 문제인 줄 알았는데, 나중에 알고 보니 인증서의 문제도 있었고, Ubuntu 16.04의 최신 curl 버전이 TLS 1.3을 지원하지 않아서 발생한 문제도 있었습니다. 

 

 

[문제에 대한 접근, 문제 원인 진단]

문제의 원인을 찾기 위해서 외주업체 직원이 C#으로 작성한 Windows 실행 파일을 저에게 보내왔고, 제 PC에서 정상적으로 접속이 되는 것을 확인하였습니다. 외주업체 직원이 C#으로 작성한 실행파일을 제대로 실행되는데, VMware 내부에 있는 Linux에서 작성한 제 스크립트는 왜 접속이 안 되는 것인지 도무지 이해가 되지 않았습니다. 

 

결론부터 말씀드리자면, Host PC인 Windows에서는 해당 서버에 대한 인증서가 존재했기 때문에 문제가 없었고, VMware 내부에서 가상 머신으로 동작하는 Linux에서는 해당 서버에 대한 인증서가 존재하지 않았기 때문에 문제가 발생했던 것입니다. 

 

 

 

[임시조치 방법]

임시로 조치하는 방법은 curl 명령 시에 -k 옵션을 붙이는 것입니다. 하지만 이 경우 보안성에 취약할 수 있으므로 급한 경우에만 사용하시기 바랍니다.

 

curl -v -k -H "X-Requested-With: XMLHttpRequest" "https://(URL)"

 

위와 같이 -k 옵션을 붙여주면 curl 명령이 수행되지만 insecure 하므로 절대 권장되지 않습니다. man curl 명령을 통해서 curl 명령의 매뉴얼을 살펴보면 -k 옵션이 안전하지 못하다는 것을 알 수 있습니다. 동작은 --insecure 옵션과 equivalent 합니다.

 

 

절대 안전하지 않으므로 시간을 들여서라도 아래의 근본 해결 방법으로 진행하시기 바랍니다. 

 

 

[문제 근본 해결 1. 해당 서버의 인증서 다운로드]

curl 명령으로 접속이 안된다면, 웹브라우저로 접속해보기로 했습니다.

curl로 입력했던 URL을 Firefox로 접속해봤더니 아래와 같은 화면이 표시되었고, 인증서를 다운로드할 수 있었습니다. 하나씩 단계별로 설명드리면 아래와 같습니다.

 

1. curl로 입력했던 URL을 firefox 브라우저에 입력하고 접속합니다.

 

2. "Advanced" 버튼을 누르면 아래와 같이 인증서를 볼 수 있는 링크가 표시됩니다.

 

3. 인증서(pem 확장자)를 다운로드합니다.

이제부터는 다운로드한 .pem 확장자의 인증서를 .crt 확장자의 인증서로 변환한 후에 인증서를 추가하는 절차입니다.

 

 

4. 다운로드한 .pem 확장자의 인증서를 .crt 확장자의 인증서로 변환합니다.

$ openssl x509 -in ABC.pem -inform pem -out ABC.crt

위의 명령을 수행하면 ABC.crt 파일이 생성됩니다. 이 상황에서 --cacert 옵션을 통해서 crt 인증서 파일을 지정해주는 방법도 있습니다. 

$ curl -v --cacert ABC.crt -H "X-Requested-With: XMLHttpRequest" "https://(URL)"

위와 같이 --cacert 옵션을 통해서 인증서를 지정해주면 해당 인증서를 통해서 정상적으로 인증되게 됩니다. 앞으로도 지속적으로 사용하 것이라면 '신뢰할 수 있는 인증서'로 등록해주면 따로 --cacert 옵션을 지정해줄 필요가 없어 편리합니다. 아래 5번 단계부터는 '신뢰할 수 있는 인증서'에 해당 인증서를 추가해주는 작업입니다.

 

 

5. /usr/share/ca-certificates/extra 디렉터리를 생성하고 ABC.crt 파일을 복사합니다.

$ sudo mkdir -p /usr/share/ca-certificates/extra
$ sudo cp ABC.crt /usr/share/ca-certificates/extra

 

 

6. sudo dpkg-reconfigure ca-certificates 명령을 통해서 인증서를 추가합니다.

$ sudo dpkg-reconfigure ca-certificates

위의 명령을 입력하면 아래와 같은 창이 뜹니다.

 

추가할 인증서를 선택합니다.

 

아래와 같은 메시지가 나오면서 신뢰할 수 있는 인증서에 추가가 완료됩니다.

Processing triggers for ca-certificates (20210119~16.04.1) ...
Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...

Adding debian:ABC.pem
done.
Updating Mono key store
Linux Cert Store Sync - version 4.2.1.0
Synchronize local certs with certs from local Linux trust store.
Copyright 2002, 2003 Motus Technologies. Copyright 2004-2008 Novell. BSD licensed.

I already trust 133, your new list has 130
Certificate added: O=ABC, OU=(URL), CN=(URL)
1 new root certificates were added to your trust store.
Import process completed.
Done
done.

 

 

 

[Ubuntu] Jenkins 업데이트 시 발생하는 에러(server certificate verification failed. CAfile: /etc/ssl/certs/ca-certific

Error 내용 다음 패키지를 업그레이드할 것입니다: jenkins 1개 업그레이드, 0개 새로 설치, 0개 제거 및 186개 업그레이드 안 함. 65.6 M바이트 아카이브를 받아야 합니다. 이 작업 후 11.8 M바이트의 디

secondmemory.kr

 

[문제 근본 해결 2. curl 패키지 업데이트]

위와 같이 인증서를 설치했음에도 불구하고, curl 명령에서 여전히 에러가 발생한다면 curl 패키지가 TLS 1.3을 지원하지 않는 문제일 수 있습니다. 저의 경우는 Ubuntu 20.04에서는 잘 동작하던 curl 명령이 Ubuntu 16.04에서는 동작하지 않는 문제점 때문에 다소 시간을 허비하게 되었습니다. 이 글은 여러분들의 시간과 노력을 절약해줄 것입니다. 

 

curl 7.47.0 버젼에서는 TLS 1.3을 지원하지 않는다.

 

Ubuntu 16.04 버전의 curl latest 버전은 V7.47.0입니다. 이 버전에서는 TLS 1.3을 지원하지 않기 때문에 인증 에러가 발생할 수 있습니다.

 

curl 7.68.0 버젼에서는 TLS 1.3를 지원하고 문제 없음

반면, Ubuntu 20.04 버전의 curl latest 버전은 2021년 2월 5일 기준으로 V7.68.0입니다. 이 버전에서는 TLS 1.3을 지원하므로 정상적으로 인증이 됩니다. 

 

Ubuntu 16.04에서 TLS 1.3으로 curl 통신을 하려면 2가지 방법이 있습니다. OS를 Ubuntu 20.04로 업그레이드하거나, curl 패키지를 수동으로 설치해야 합니다. OS를 업그레이드하는 것은 큰 일이고 다소 위험할 수 있습니다. 그렇기 때문에 curl 패키지를 수동으로 설치하는 방법을 권장드립니다. 그럼 지금부터 최신 curl 소스를 다운로드한 후 컴파일하고 설치하는 방법에 대해서 설명드리겠습니다. 

 

 

svn : Server SSL Certificate verification failed

svn checkout 이나 commit 하려고 할 때 SSL Certificate 관련된 오류가 발생할 때가 있다. svn: E170013: Commit failed (details follow): svn: E170013: Unable to connect to a repository at URL 'https://xx..

imitursa.tistory.com

 

 

1. curl 홈페이지에 접속하여 최종 버전을 확인합니다. 

2021년 2월 5일 기준으로 7.75.0 버전이 최종입니다. 최종 버전이 가장 좋은 것은 아니지만 저는 최종 버전으로 설치해보기로 했습니다. 

 

2. curl 패키지를 삭제합니다.

$ sudo apt-get remove curl
$ sudo apt-get purge curl

 

3. 컴파일 및 실행을 위한 패키지를 설치합니다.

$ sudo apt-get update
$ sudo apt-get install autoconf make libtool libssl-dev

 

4. wget 명령을 통해서 소스 코드를 받아옵니다.

위의 1번 과정에서 확인한 소스 코드의 링크를 입력하시면 됩니다.

$ cd /usr/local/src
$ sudo rm -rf curl*
$ sudo wget https://curl.se/download/curl-7.75.0.zip
$ sudo unzip curl-7.75.0.zip
$ cd curl-7.75.0

 

5. 컴파일을 수행합니다.

$ sudo ./buildconf
$ sudo ./configure --with-ssl
$ sudo make && sudo make install
$ sudo cp /ur/local/bin/curl /usr/bin/curl


위와 같이 최신 curl 패키지를 새로 설치한 후에 curl --version을 입력해보면 curl이 정상적으로 설치된 것을 확인하실 수 있습니다. 

 

[끝맺음 말]

이상으로 HTTPS 프로토콜을 이용하여 curl 명령을 수행 시에 "server certificate verification failed" 에러가 발생했을 때의 조치방법을 모두 마칩니다. 

제 경우에는 해당 사이트의 인증서가 신뢰할 수 있는 인증서에 추가되지 않아서 발생한 문제였고, 신뢰할 수 있는 인증서에 해당 인증서를 추가해준 이후에는 정상적으로 접속되는 것을 확인할 수 있었습니다. 

 

 

curl: (60) Peer's Certificate issuer is not recognized.

curl: (60) Peer's Certificate issuer is not recognized. More details here: http://curl.haxx.se/docs/sslcerts.html curl performs SSL certificate verification by default, using a "b..

algo79.tistory.com

 

 

일부 사용자에 대해서만 TLS 인증이 만료됨

수신 nginx를 역방향 프록시로 사용하는 k8s 클러스터가 있습니다. letsencrypt를 사용하여 TLS 인증서...

blog.naver.com

 

감사합니다. 

반응형