로컬 개발 환경을 production 환경과 맞춰서 secure 통신으로 세팅을 해놓으면, https 를 비롯해서, 기본적으로는 여러 경고 문구들과 마주할 수밖에 없다. 웹브라우저라면 몇번의 클릭으로 넘어갈 수도 있겠지만 여러 서버 모듈이 있다면 서로간의 통신에서 검증 단계를 스킵하는 코드를 심어야하는 번거로운 작업이 많이 발생할 수도 있다.
이런 귀찮은 일들을 줄이고 시각적인 만족감을 위해서는 로컬 환경을 "신뢰받는" 환경으로 만들어버리면 되는데 스스로 root CA 를 발급해서 인증해버리면 된다.
root CA
root CA; root Certificate Authorization
인증서는 기본적으로 웹사이트와 같은 웹서비스에서 제공하는 공개키가 위변조되지 않았다는 것을 인증 기관(CA)이 증명해주는 문서이다. 이 인증 단계의 가장 꼭대기에 있는 곳이 root CA인데 인증 단계 최상위에 위치하고 있기 때문에 이 기관들은 다른 기관에서 인증해주지는 않지만 신뢰할 수 있는 기관이라 "믿고" 쓴다고 볼 수 있다.
Verisign
, Comodo
, Thawte
같은 회사들이 인터넷에서 바로 이런 root CA 역할을 하고 있는데 이런 유명한 회사의 인증서들은 추가적으로 다른 기관에서 인증해주지는 않지만 웹브라우저나 OS에 기본적으로 설치되어 있기때문에 올바른 인증서로 취급되어진다. 사실 이런 root CA 인증서들은 내 로컬 컴퓨터가 인증하고 있는 셈이다.
결국 이런 root CA 인증서들은 root CA 기관에서 셀프 서명한 인증서이면서 강제로 웹브라우저나 OS 벤더들이 강제로 설치해놨기때문에 신뢰할 수 있는 것인데 이 느낌 그대로, 내 로컬 서버를 root CA로 만들고 내 로컬 클라이언트에 추가로 설치만 해주면 로컬 서버를 root CA 에서 인증받은 "trusted"
site 로 둔갑시킬 수 있다.
self-signed root CA 인증서 발급
먼저 다음과 같이 private key 를 만들어야하는데
openssl genrsa -des3 -out localCA.key 2048
pass phrase
를 입력하지 않으면 에러가 발생하니 꼭 입력하고 잘 기억해두어야 한다.
Generating RSA private key, 2048 bit long modulus
.........................+++
..+++
e is 65537 (0x10001)
Enter pass phrase for localCA.key: # 아무것도 입력하지 않으면 아래와 같이 에러 발생
139743430993808:error:28069065:lib(40):UI_set_result:result too small:ui_lib.c:831:You must type in 4 to 1023 characters
Enter pass phrase for localCA.key:
Verifying - Enter pass phrase for localCA.key:
localCA.key
파일이 생성되었으면 이 private key 를 이용해서 root CA 인증서를 다음과 같이 만들어준다.
openssl req -x509 -new -nodes -key localCA.key -sha256 -days 365 -out localCA.pem
Enter pass phrase for localCA.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) []:Seoul
Locality Name (eg, city) [Default City]:DDM
Organization Name (eg, company) [Default Company Ltd]:Virtual Machines. OBOKI. net.
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:centos.vm.oboki.net
Email Address []:papa@oboki.net
localCA.pem
파일이 생성되었으면 root CA 인증서 발급 끝
OS 별 root CA 등록 방법
Windows 클라이언트
먼저 아래와 같이 *.crt 파일로 변경해서 windows 클라이언트에 파일을 옮겨준 뒤
openssl x509 -outform der -in localCA.pem -out localCA.crt
해당 파일을 더블클릭해서 인증서 설치
버튼을 눌러 간단히 설치하거나
관리자 권한으로 cmd
를 열어 certmgr
를 입력하면 인증서 관리자가 실행되는데 아래와 같이 신뢰할 수 있는 루트 인증 기관
에 CA 인증서를 추가해주면 된다.
Linux
CentOS7 기준 /etc/pki/ca-trust/source/anchors/
위치에 앞서 생성한 root CA 인증서를 복사해두고 update-ca-trust
명령만으로 간단하게 등록할 수 있다.
cp localCA.pem /etc/pki/ca-trust/source/anchors/.
update-ca-trust
Mac OS X
맥에서도 root CA 인증서를 가져와서 다음과 같이 CLI 로 등록할 수도 있고
sudo security add-trusted-cert -d -r trustRoot -k "/Library/Keychains/System.keychain" localCA.pem
Keychain
앱을 통해 화면으로 등록할 수도 있다. Mac이 회사에만 있어서 캡처를 등록하지는 못함 ㅜㅜ
CA-signed 인증서 생성
이제부터는 생성된 root CA 인증서를 이용해서 필요한 호스트들을 내맘대로 무차별적으로 인증해줄 수가 있는데 인증하고자 하는 호스트에 대해 다음과 같이 private key 를 생성하고
openssl genrsa -out airflow.centos.vm.oboki.net.key 2048
Generating RSA private key, 2048 bit long modulus
.........................+++
..............+++
e is 65537 (0x10001)
CSR을 생성하고
openssl req -new -key airflow.centos.vm.oboki.net.key -out airflow.centos.vm.oboki.net.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) []:Seoul
Locality Name (eg, city) [Default City]:DDM
Organization Name (eg, company) [Default Company Ltd]:Airflow
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:airflow.centos.vm.oboki.net
Email Address []:papa@oboki.net
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
다음과 같은 설정 파일을 작성한 뒤
vim airflow.centos.vm.oboki.net.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = airflow.centos.vm.oboki.net
다음 명령을 수행해서 pass phrase 를 입력해주면 airflow.centos.vm.oboki.net
호스트를 centos.vm.oboki.net
CA 가 인증하는 인증서를 발급할 수 있다.
openssl x509 -req -in airflow.centos.vm.oboki.net.csr -CA localCA.pem -CAkey localCA.key -CAcreateserial \
-out airflow.centos.vm.oboki.net.crt -days 365 -sha256 -extfile airflow.centos.vm.oboki.net.ext
Signature ok
subject=/C=KR/ST=Seoul/L=DDM/O=Airflow/CN=airflow.centos.vm.oboki.net/emailAddress=papa@oboki.net
Getting CA Private Key
Enter pass phrase for localCA.key:
발급된 인증서를 웹서버에 등록해서 클라이언트에서 접근해보면 다음과 같이 보안 경고 없이 정상적으로 응답해주는 것을 확인할 수 있다.
개인적으로 웹브라우저에서 주의 요함
이 아닌 초록색 자물쇠가 뜨는 것에서 오는 만족감이 정말 큰 것 같다.
서버들 간의 통신에서도 원래는 보안 경고가 발생하는데
# curl -I https://airflow.centos.vm.oboki.net
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 "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 -I https://airflow.centos.vm.oboki.net
HTTP/1.1 302 FOUND
Server: nginx/1.19.1
Date: Sun, 26 Jul 2020 14:23:18 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 217
Connection: keep-alive
Location: http://airflow.centos.vm.oboki.net/home
Vary: Cookie
Set-Cookie: session=eyJfcGVybWFuZW50Ijp0cnVlfQ.Xx2R1g.Se8JyvqlgR9nIltqP8Xnc7Sp3Sc; Expires=Tue, 25-Aug-2020 14:23:18 GMT; HttpOnly; Path=/