-
openssl 로 self-signed certificate 만들기linux 2021. 9. 10. 11:56반응형
서버에서 사용할 self-signed 인증서를 만드려고 한다.
- X.509 extensions
보통 브라우저에서는 상관없지만, Docker api 등에서는 인증서의 v3 extension 필드를 요구하는 경우가 있다. 이 경우를 위해 extension 의 일부 필드를 사용한다.
- basicConstraints: root 인증서에서 사용할 필드이다. 다른 인증서(서버용 인증서) 에 서명을 하는 경우 필요하다.
- subjectAltName: 서버 인증서에서 사용할 필드이다. 도메인과 일치하는 DNS 값이 있어야 한다. 이전에는 CN(Common Name) 만 도메인과 동일하면 문제가 되지 않았는데, 도커 20.10.8 에서는 api 사용 시 이 값이 도메인과 일치하는 것을 요구해서 추가하였다.
openssl 에서 extension 파라미터를 넘기는 방법이 여러개 있는데, 여기서는 파일을 전달하는 방식을 사용한다.
또한, 파일 전달 형식에서도,
-extfile {{config 파일명}} -extensions {{section이름}}
으로 진행하는 방법이 있고, section 이름 없이 필요한 정보만 적은 파일을-extfile
로 전달하는 방식이 있는데 후자를 선택한다. (-extensions
가 없으면 default section (파일 내에서 별도로 section 으로 정의하지 않은 영역) 을 사용하게 된다.)extensions 의 종류와 파라미터 전달 방식은 아래를 참고:
- x509 명령어 옵션들: https://www.openssl.org/docs/manmaster/man1/openssl-x509.html
- v3 conig 에 들어갈 수 있는 값, 포맷 정리: https://www.openssl.org/docs/manmaster/man5/x509v3_config.html
- 진행 환경:
동일한 환경을 유지 하기 위해서 docker 컨테이너를 이용하였지만, 굳이 docker 컨테이너 내부에서 진행할 필요는 없다. 혹시 docker 컨테이너를 사용하려고 한다면 결과물을 호스트 서버로 꺼내야 하니까 마운트 하는 것을 잊지 말자.
- Rocky Linux 8.5 (docker image)
- root 로 진행
- openssl 버전: 1.1.1k (yum install 로 설치한 경우)- 인증서 내용:
1. openssl 설치
yum 으로 설치한다.
# yum -y install openssl
버전 확인
# openssl version OpenSSL 1.1.1k FIPS 25 Mar 2021
2. root 인증서
2-1. root 를 위한 키를 우선 만든다.
# openssl genrsa -aes256 -out root.key 2048 Generating RSA private key, 2048 bit long modulus (2 primes) ........+++++ ..................................+++++ e is 65537 (0x010001) Enter pass phrase for root.key: Verifying - Enter pass phrase for root.key:
이 때, pass phrase 를 요구한다. 나중에 서버 인증서 서명시 필요하니 기억해야 한다.
참고로 비밀번호가 4개 보다 작으면 아래처럼 에러가 발생한다.
UI routines:UI_set_result_ex:result too small:crypto/ui/ui_lib.c:905:You must type in 4 to 1023 characters
또한, 일반적으로는 문제가 없지만, 혹시 권한 문제가 있다면 아래처럼 권한을 변경한다.
# chmod 600 root.key
그 다음은 CSR(Certificate Signing Request) 을 만들자. 미리 정한 값을 넣는다.
# openssl req -new -key root.key -out root.csr Enter pass phrase for root.key: You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:KR State or Province Name (full name) []: Locality Name (eg, city) [Default City]:Seoul Organization Name (eg, company) [Default Company Ltd]:bitgadak Organizational Unit Name (eg, section) []: Common Name (eg, your name or your server's hostname) []:bitgadak root Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:
잘 들어갔는지 확인해 보자
# openssl req -in root.csr -noout -text Certificate Request: Data: Version: 1 (0x0) Subject: C = KR, L = Seoul, O = bitgadak, CN = bitgadak root Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public-Key: (2048 bit) Modulus: (...생략...) Exponent: 65537 (0x10001) Attributes: a0:00 Signature Algorithm: sha256WithRSAEncryption (...생략...)
이제 인증서를 만들어야 하는데, 거기에 전달할 extensions 을 위한 파일을 만들자. 파일명은 root.ext 로 하였다.
root 에서 필요한 확장 필드는 basicConstraints 이다.
# cat root.ext basicConstraints = CA:TRUE
이제 위에서 만든 CSR 과 extension 파일을 가지고 인증서를 만든다. (10년)
# openssl x509 -req -days 3650 -in root.csr -signkey root.key -extfile root.ext -out root.crt Signature ok subject=C = KR, L = Seoul, O = bitgadak, CN = bitgadak root Getting Private key Enter pass phrase for root.key:
내용을 확인해 보자
# openssl x509 -text -in root.crt Certificate: Data: Version: 3 (0x2) Serial Number: (...생략...) Signature Algorithm: sha256WithRSAEncryption Issuer: C = KR, L = Seoul, O = bitgadak, CN = bitgadak root Validity Not Before: Sep 10 01:48:21 2021 GMT Not After : Sep 8 01:48:21 2031 GMT Subject: C = KR, L = Seoul, O = bitgadak, CN = bitgadak root Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public-Key: (2048 bit) Modulus: (...생략...) Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:TRUE Signature Algorithm: sha256WithRSAEncryption (...생략...) -----BEGIN CERTIFICATE----- (...생략...) -----END CERTIFICATE-----
extensiosn 도 잘 들어가 있다.
3. 서버용 인증서
key 를 만들자. 일단은 비밀번호를 추가해서 만들어야 한다.
# openssl genrsa -aes256 -out server-with-password.key 2048 Generating RSA private key, 2048 bit long modulus (2 primes) ..............+++++ ....................................+++++ e is 65537 (0x010001) Enter pass phrase for server-with-password.key: Verifying - Enter pass phrase for server-with-password.key:
비밀번호를 제거한 버전을 만든다.
# openssl rsa -in server-with-password.key -out server.key Enter pass phrase for server-with-password.key: writing RSA key
서버용 CSR 생성
# openssl req -new -key server.key -out server.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:KR State or Province Name (full name) []: Locality Name (eg, city) [Default City]:Seoul Organization Name (eg, company) [Default Company Ltd]:bitgadak Organizational Unit Name (eg, section) []: Common Name (eg, your name or your server's hostname) []:bitgadak.tistory.com Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:
인증서 생성시 필요한 extensions 를 적은 파일을 만든다. 이름은 server.ext 로 하였다.
여기서 필요한 확장 필드는 subjectAltName 이다. 여러 개가 필요한 경우 DNS.1, DNS.2 처럼 넣을 수 있는데, 일단 하나만 적었다. @alt_names 는 alt_names 섹션 ([alt_names] 이하 영역) 을 불러온다는 의미이다.
# cat server.ext subjectAltName = @alt_names [alt_names] DNS = bitgadak.tistory.com
이제 인증서를 만들자 (1년)
# openssl x509 -req -days 365 -in server.csr -extfile server.ext \ -CA root.crt -CAkey root.key -CAcreateserial -out server.crt Signature ok subject=C = KR, L = Seoul, O = bitgadak, CN = bitgadak.tistory.com Getting CA Private Key Enter pass phrase for root.key:
확인해 보자
# openssl x509 -text -in server.crt Certificate: Data: Version: 3 (0x2) Serial Number: (...생략...) Signature Algorithm: sha256WithRSAEncryption Issuer: C = KR, L = Seoul, O = bitgadak, CN = bitgadak root Validity Not Before: Sep 10 01:58:59 2021 GMT Not After : Sep 10 01:58:59 2022 GMT Subject: C = KR, L = Seoul, O = bitgadak, CN = bitgadak.tistory.com Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public-Key: (2048 bit) Modulus: (...생략...) Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Alternative Name: DNS:bitgadak.tistory.com Signature Algorithm: sha256WithRSAEncryption (...생략...) -----BEGIN CERTIFICATE----- (...생략...) -----END CERTIFICATE-----
완료되었다. 이제 서버에 적용하면 된다.
4. 기타
4-1. nginx 에서 사용시
nginx 에서 사용하려면 root 인증서 정보가 포함된 crt 를 입력해야 한다고 한다. 순서가 중요하다.
nginx 에서 사용할 crt 만들기. nginx 입장에서는 이름이 중요하진 않은데, server-chained.crt 라고 정했다.
# cat server.crt root.crt > server-chained.crt
이렇게 만든 파일을 nginx 의 설정 파일에서 server 영역 안에 넣어준다.
예시:
server { listen 443 ssl; (...생략...) ssl_certificate /etc/nginx/server-chained.crt; ssl_certificate_key /etc/nginx/server.key; (...생략...) }
4-2. CentOS 에서 신뢰할 수 있는 인정서 추가
Self-Signed 의 경우 Docker api 사용시 에러가 나온다. CentOS 라면 root 인증서를 신뢰할 수 있는 인증서로 추가하면 해결된다.
사용자가 인증서를 추가하는 경우엔
/etc/pki/ca-trust/source/anchors/
에 추가하고
$ sudo update-ca-trust
이렇게 갱신하면 된다.
Docker 가 인식하려면 Docker 의 재시작이 필요하다. 재시작 없이 리로딩 했으면 좋겠는데, 아직 방법을 모르겠다.
수정사항
- 2022-02-13: 인증서를 만든 컨테이너 이미지를 CentOS 8 에서 Rocky Linux 로 변경 (CentOS 8 저장소 만료로 인해 yum install 이 동작하지 않음)
반응형'linux' 카테고리의 다른 글
certbot 으로 let's encrypt 인증서 발급받기 (1) 2022.01.30 [CentOS 7] firewalld 설정을 통해 서버를 게이트웨이로 사용하기 (0) 2021.09.03