발생일: 2013.07.11
키워드: nginx, https, ssl, 자가서명 인증서, localhost ssl, localhost https, nginx https, 로컬 ssl, ssl_certificate, ERR_CERT_COMMON_NAME_INVALID
문제:
노드로 https 서버를 띄우려는데, key.pem 과 cert.pem 이 필요하다고 한다.
지금은 프로토타이핑 용도라 테스트용 인증서만 있으면 된다.
위 두 파일이 의미하는 것과, HTTPS의 인증 과정, 테스트용 인증서를 만드는 방법이 궁금하다.
해결책:
SSL은 TCP/IP를 사용하는 두 개의 통신 애플리케이션 간 프라이버시와 무결성을 제공하는 프로토콜.
RSA 알고리즘을 암호 키 교환 및 디지털 서명에 사용한다.
디지털 인증서
디지털 인증서는 두 가지 목적을 갖는다.
- 소유자의 신원 확인
- 소유자가 퍼블릭 키를 사용할 수 있도록 함
디지털 인증서는 신용 기관(CA)에서 발행하며, 제한된 시간 동안에만 발행된다.
만료일이 지나면 인증서를 교체해야 하며, 이 인증서는 키 교환, 서버 인증, 클라이언트 인증에 사용한다.
인증서에는 인증서 소유자의 신분과 인증서 기구에 대한 정보가 포함되어 있어야 한다.
- 소유자 이름
- 소유자 퍼블릭 키
- 디지털 인증서가 발행된 날짜
- 인증서의 종료 날짜
- 발행 기구 이름 (CA의 기구명)
- 발행 기구의 디지털 서명
인증서 유형
SSL은 인증서를 사용해 연결을 확인한다.
인증서는 보안 서버에 놓이고, 데이터를 암호화하고 웹 사이트를 확인하는데 사용된다.
또한, 그 사람이 속해있는 사이트를 확인하고, 인증서 보유에 대한 정보, 발행된 도메인,
발행한 인증 기관(CA, Certificate Authority)의 이름을 포함하고 있다.
SSL은 아래 방법으로 생성할 수 있다.
1. CA 인증서를 사용한다. (CA로부터 구입해야 한다)
2. 자가 서명 인증서를 사용한다.
3. 더미 인증서를 사용한다.
CA 인증서 사용하기
CA는 업계의 신임을 받는 기구이며, 인터넷 인증서를 발행한다.
대표적인 예로 VeriSign을 들 수 있다.
CA 서명 인증서를 획득하려면, 충분한 정보를 CA에 제공하여 CA가 우리 신원을 확인할 수 있도록 해야 한다.
CA는 새로운 인증서를 만들고, 이것을 디지털 서명한 다음 제공한다.
대중적인 웹 브라우저는 특정 CA에 의해 서명된 인증서를 신임하도록 미리 설정되어 있다.
클라이언트가 SSL을 통해 인증서가 발행된 서버로 연결하기 위해 추가적인 클라이언트 설정을 할 필요가 없다.
자가 서명 인증서 사용하기
자가 서명 인증서는 사용자가 생성한 인증서다.
자가 서명 인증서에서는 인증서 발행자 사용자가 동일하다.
이 인증서는 CA 서명 인증서를 획득하는 것보다 시간이 덜 걸리는 장점이 있지만,
SSL 연결을 통해 인증서를 설치하는 서버로 연결된 클라이언트가 인증서의 서명자를 신임하도록 설정해야 한다.
인증서는 자가 서명되었기 때문에, 서명이 클라이언트의 트러스트 파일 목록에 있지 않기 때문이다.
모든 클라이언트의 트러스트 파일에 액세스하는 것이 비현실적이라면, 자가 서명 대신 CA 서명을 사용하는 것이 좋다.
더미 인증서 사용하기
지정된 환경에서 테스트 또는 임시로 사용하기 위한 인증서이다.
임시적으로 사용할 수 있는 가상의 정보를 포함하고 있다.
클라이언트/서버 인증
인증서를 획득한 후에는 인증을 받아야 하며, 두 가지 유형의 SSL 인증이 있다.
- 서버 측 인증
- 클라이언트 측 인증
SSL 서버 인증은 서버의 신원을 확인할 수 있도록 한다.
클라이언트 소프트웨어는 퍼블릭 키를 사용해 서버의 인증서와 퍼블릭 ID가 유효하고,
신임을 받은 CA 클라이언트 리스트에 있는 인증서 기구에서 발행된 것인지를 검사한다.
만약 사용자가 네트워크를 통해 신용 카드 번호를 보내고, 서버가 이를 받았는지 검사하고 싶을 때 이와 같은 확인이 중요하다.
SSL 클라이언트 인증은 사용자의 신원을 서버가 확인할 수 있도록 한다.
서버 인증에 사용되었던 것과 같은 기술로, 클라이언트의 인증서와 퍼블릭 ID가 유효하고,
신임을 받는 CA의 클라이언트 리스트에 있는 인증서 기구에서 발행된 것인지 확인한다.
만약 서버가 기밀 금융 정보를 고객에게 보내고 있는 은행이고, 수신자 신원을 확인해야 할 때 중요하다.
자가서명 인증서 생성 방법
1. 먼저 인증 기관(CA)의 개인키를 생성한다. (자가 서명이므로, 내가 인증 기관이다)
$ openssl genrsa -out dev_ssl.key 2048
2. 서버 인증서 발급을 위한 요청 파일인 CSR(Certificate Sinning Request)를 생성한다
$ openssl req -new -key dev_ssl.key -out dev_ssl.csr
3. 인증서에 포함할 추가 정보를 별도의 파일로 생성해둔다.
아래 내용에서 [alt_names] 항목의 도메인을 본인에 맞게 변경한 후, v3.ext 파일로 만들어두면 된다.
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = *.example.com
DNS.2 = *.foo.com
4. 자가 서명 인증서를 생성한다.
$ openssl x509 -req -in dev_ssl.csr -signkey dev_ssl.key -out dev_ssl.crt -days 3650 -sha256 -extfile v3.ext
이 작업 결과로 dev_ssl.crt 라는 서버용 인증서가 생성된다.
자가 서명한 인증서를 신뢰하도록 추가하기
MacOS 라면 생성한 crt 인증서 파일을 Keychain Access 에 추가하면 된다.
생성한 .crt 파일을 더블클릭하면, 키체인 액세스 창이 뜨니 여기서 추가하고, Trust 항목에서 항상 허용(Always Trust)하도록 설정하면 된다.
논의:
# 생성한 csr 파일과 cst 파일의 내용은 아래 방법으로 조회할 수 있다.
crt 파일: $ openssl x509 -in *.crt -noout -text
csr 파일: $ openssl req -in *.csr -noout -text
# nginx 에 자가 서명한 인증서를 추가하려면 아래와 같이 server 블럭에 추가하면 된다.
server {
listen 443 ssl;
ssl_certificate server.crt;
ssl_certificate_key server.key;
ssl_prefer_server_ciphers on;
... 중략
}
# 인증서를 추가했는데도 갱신이 되지 않는다면, nginx 를 재시작했는데 확인해보자. -_-;;
참고:
http://an5asis.blog.me/60112380592
http://www.akadia.com/services/ssh_test_certificate.html
http://golmong.tistory.com/112
http://www.robpeck.com/2010/10/google-chrome-mac-os-x-and-self-signed-ssl-certificates/
----
2019.05.07 추가
예전 방식으로 자가 서명한 인증서를 만들었더니, 크롬에서 아래와 같은 보안 오류가 나오면서 접속되지 않는다.
its security certificate does not specify Subject Alternative Names.
구 버전 인증서의 보안 이슈 때문으로 보인다. 현재 버전의 크롬에서도 동작할 수 있게, 위 가이드를 수정해뒀다.
참고:
https://stackoverflow.com/questions/43665243/invalid-self-signed-ssl-cert-subject-alternative-name-missing
https://stackoverflow.com/a/43666288