728x90

VPN 과 관련한 여러가지 시험, 환경을 구축하다보니 로컬 라우팅 테이블이 꼬이는 현상이 발생하여 조사를 해보았습니다. 평소 사용하고 있던 IPv4 VPN 와 IPv6 VPN, 그리고 개별 과제로 만들고 있는 OpenVPN 기반의 IPv6 까지 아주 난장판이라 이런 문제가 생긴다고 생각해서 트러블슈팅 방법을 좀 정리해 보고자 합니다. (미래의 내가, 과거의 나를 찾을 것이 분명하니...)


지저분해지는 IPv6 라우팅 테이블

안그래도 복잡했던 로컬 IPv6 라우팅 테이블이 심하게 꼬인 것은 로컬 환경에서 OpenVPN Web UI 디버깅을 위해 OpenVPN 을 설치하고 구동하면서 부터였습니다. 오늘 아침 개발조직에 IPv6 접근 가이드를 해주기 위해 WIKI 를 정리하다보니 평소 사용하던 IPv6 VPN 에 연결하더라도 v6 웹 사이트 (가령 v6.google.com) 에 접근이 안되는 것을 확인했습니다. 

미처 캡쳐를 해두진 못했지만 netstat -nr 로 로컬의 라우팅 테이블을 살펴보니 스태틱으로 잡힌 테이블이 너무 많았습니다. VPN 연결시 생성되는 인터페이스인 utun 시리즈도 무려 6개나 존재하더군요. 인터페이스를 down 으로 하는 것과 라우팅 테이블은 별개라 한땀 한땀 삭제를 해주어야 했습니다. 사용한 명령들은 대략 아래의 패턴입니다. 

// 한 땀, 한 땀 삭제...
sudo route delete -inet6 ##v6주소##%utun0

// default 를 잠식한 utun 시리즈 삭제는 -ifscope 으로...
sudo route delete -inet6 default -ifscope utun1

이렇게 삭제를 하고나니 라우팅 테이블이 깔끔해졌습니다. 이제 라우팅 테이블을 지저분하게 만든 범인을 찾기 위해 간단한 스크립트로 리눅스 환경에서의 watch 를 구현하여 netstat -nr 명령을 반복하도록 해보았습니다. 우리가 기대하는 것은 VPN 연결시 필요한 라우팅 테이블이 추가 되었다가 VPN 연결을 종료하면 라우팅 테이블이 정리되는 것이겠죠!?

// Mac 환경에서 리눅스 watch 스타일로 명령 구동하기
while true; do clear; netstat -nr; sleep 2; done;

 

회사가 제공한 VPN 시험

먼저 회사가 제공한 IPv6 VPN 을 살펴보았습니다. 심증은 <범인은 OpenVPN 이다!> 였지만 확실하게 하기 위해서죠. 개발팀도 분명 비슷한 증상을 겪을 수 있으니 FAQ 를 준비하는 목적도 있었습니다. 자, 우선 IPv6 VPN 연결전에는 아래와 같이 깔끔한 라우팅 테이블 목록을 볼 수 있습니다. 물론... 앞서 이야기 한 것처럼 한 땀, 한 땀 라우팅 테이블을 정리한 상태입니다 ㅜㅜ

회사에서 셋업한 IPv6 VPN 을 연결해 보니 utun 인터페이스로 다수의 라우팅 테이블이 추가되는 것을 확인할 수 있었습니다. 

다시 VPN 연결을 끊었을때 v4, v6 쪽으로 추가된 라우팅 테이블이 깔끔하게 정리되는 것을 확인할 수 있었습니다. 범인은 OpenVPN 일까요? 확인해 보았습니다.

 

AWS 에 구축한 IPv6 OpenVPN 시험

이번에는 AWS 에 구축해 둔 IPv6 OpenVPN 을 시험해 보았습니다. VPN 에 연결되면 이전의 다른 VPN 과 마찬가지로 다량의 라우팅 테이블이 추가되는 것을 확인할 수 있었습니다. 이번에도 동일하게 utun4 를 사용했군요. 터널 인터페이스가 만들어지고 삭제되는 과정도 좀 궁금하지만 따로 알아보기로 하고...

자 이제... 대망의 연결 종료의 시간이 되었습니다. OpenVPN 연결을 종료했을때 깔끔하게 라우팅 테이블이 정리되었으면 하는 바램을 갖고... 도전!

이런... 예상과 다르게 너무 깔끔하게 라우팅 테이블이 정리가 되었습니다. 문제가 생기길 기대(?)했는데 깔끔해진 걸 보니... 뭔가 OpenVPN 에 등록해 둔 Profile 들을 시험하는 과정에, 연결이 깔끔하지 못했거나 강제 종료된 경우 등 예외 상황에서 문제의 현상이 나오는 것일 가능성이 생겼습니다. 

AWS EC2 를 이용한 OpenVPN 구축 연재는 아래 글타래로... (2편은 아직 못쓴...)

 

AWS EC2 를 이용한 IPv6 지원 OpenVPN 구축 #1

코로나 바이러스의 두번째 웨이브가 한창입니다. 다행히 오늘(9/3) 기준으로 확진자 수가 200명 밑으로 내려오긴 했지만, 긴장의 끈을 놓기에는 여전히 확진자 수가 많습니다. 많은 기업들이 원격

ondemand.tistory.com

 

Mac 로컬 환경의 OpenVPN 시험

내친김에 로컬 환경의 시험도 해보았습니다. 조금 까리한 것은 로컬에서는 초기에 proto udp 로 시험하다보니 AF_INET6 로 서버가 구동되는 문제가 있어서 proto udp4 로 설정해둔 상태였습니다. 만약, 이 상태에서도 문제가 없다면 proto udp 일때 AF_INET6 로 구동되는 과정, 종료되는 과정의 문제라고 생각해도 될 것 같았습니다. 

참고로 utun4 는 로컬의 OpenVPN 서버가 점유하고 있는 터널이고, utun7 은 로컬의 Tunnelblick 이 연결을 맺으면서 생성한 인터페이스입니다. 자, 이제 연결을 끊어보겠습니다. 

오오... 찾은 것 같습니다. Tunnelblick 종료시 utun7 이 빠졌고, OpenVPN 서버 종료시 utun4 가 빠졌지만, Internet6 쪽에 추가된 스태틱 라우팅 하나가 빠지지 않은 것을 확인할 수 있었습니다. 설정의 문제인지는 조금 더 조사해 봐야하고 로컬 환경에서만 생기는 문제인지 명확하진 않습니다만, 최소한 FAQ 에 기술해두고 개발자 분들께 가이드 하는데는 문제 없을것 같습니다. 


뭔가 완전히 잘 알지 못하는 분야는 늘 시행착오가 생기는 것 같습니다. 오늘도 몇 가지 시행착오를 겪으면서 한 걸음, 한 걸음, 뚜벅 뚜벅 걸어나가 봅니다!

 

728x90
728x90

VPN 서버를 로컬에서 운영해야 하는 이유는 (굳이 찾자면) 여러가지가 있겠습니다만, 개인적으로는 OpenVPN Web UI 의 커스터마이징을 위하여 개발 환경이 필요했던 관계로 설치를 하게 되었습니다. 리눅스 환경에서의 설치는 종종 해왔지만 막상 로컬 Mac 환경에 설치하려니 적당한 가이드가 없는 것 같아 시행착오를 하며 내용을 정리해 봅니다. 


Homebrew 를 이용한 패키지 설치

OpenVPN 커뮤니티 버전의 소스를 다운로드 받아 빌드를 할까? 하는 생각을 0.1 초간 한 뒤에 바로 Homebrew 로 돌아섰습니다. 안그래도 지저분한 로컬 환경이라 (도커에 익숙치가 않네요) 더 지저분하게 하지 말자는 생각이 있었고, 빌드 환경 설정에 시간을 쓰지 말자는 생각이 들어 Homebrew 를 사용해 봤습니다. 

% brew install openvpn
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 3 taps (homebrew/core, homebrew/cask and homebrew/services).
...
...
==> Installing dependencies for openvpn: lz4, openssl@1.1 and pkcs11-helper
==> Installing openvpn dependency: lz4
==> Pouring lz4-1.9.3.catalina.bottle.tar.gz
🍺  /usr/local/Cellar/lz4/1.9.3: 22 files, 657.6KB
==> Installing openvpn dependency: openssl@1.1
==> Pouring openssl@1.1-1.1.1h.catalina.bottle.tar.gz
==> Caveats
...
...

 

매번 느끼는 거지만 Homebrew 는 업데이트가 너무 많습니다. 따로 패키지만 올리고 싶어도 일단 필요한 것들을 다 업데이트 하고 시작하니 시간이 꽤 걸립니다. 한참을 지나 OpenVPN 설치를 위해 Dependency 가 있는 패키지들을 쭈욱~ 설치해 나갑니다. 중간에 몇 가지 심볼릭링크 작업이 에러가 나는게 보였지만... 잘 되리라 믿고 진행을 계속 했습니다. 한 15분정도 걸렸던 것 같네요.

 

OpenVPN 바이너리는 어디에!?

리눅스 환경에서는 패키지로 공급되는 프로그램들은 대부분 데몬 설정 파일도 같이 올려주고 systemctl 이나 services 명령으로 활성화, 비활성화를 쉽게 할 수 있습니다. 막상 Mac 환경에서는 그렇게 쓰는 경우가 잘 없다보니... 설치후에 무얼 해야하나 5분정도 멍을 때렸습니다. 이단 설치경로를 찾아보기로 했고 아래의 경로에서 OpenVPN 을 찾을 수 있었습니다. 

% pwd
/usr/local/opt/openvpn

% cd sbin
% ls -al
total 1440
drwxr-xr-x   3 xxx  yyy      96 10 28 16:25 .
drwxr-xr-x  17 xxx  yyy     544 12  1 12:36 ..
-r-xr-xr-x   1 xxx  yyy  735160 12  1 12:36 openvpn

그런데 설정 파일은 어디에 있는걸까요?

 

OpenVPN 설정파일은 여기에!!

OpenVPN 이 설치되고나면 설정파일은 아래의 경로에서 찾아볼 수 있습니다. client.conf 는 VPN 의 클라이언트가 될 머신에서 사용하는 파일이고 server.conf 는 VPN 서버에서 사용하는 파일입니다. 리눅스에서도 그랬었나 기억이 좀 가물거립니다만 친절한 안내 멘트가 같이 들어 있으니 익숙하지 않은 경우에는 내용을 하나씩 살펴보는 것을 추천드립니다. (라고 적으면서 저도 잘 모르는 내용이 많긴 합니다만... ㅎ)

% cd /usr/local/etc/openvpn
% ls -al
total 32
drwxr-xr-x   4 xxx  admin    128 12  1 12:36 .
drwxrwxr-x  20 xxx  admin    640 12  1 12:46 ..
-rw-r--r--   1 xxx  admin   3589 12  1 12:36 client.conf
-rw-r--r--   1 xxx  admin  10784 12  1 12:36 server.conf

 

우리는 성미가 급하니 OpenVPN 이 동작하는지 한번 보겠습니다. 느낌적 느낌으로 인지하셨겠지만 당연히 동작하지 않습니다 ㅎㅎ. 필요한 키생성 등을 해야 하지만 그래도 한번 실행해 보는 맛이 있어야겠죠?

% /usr/local/opt/openvpn/sbin/openvpn --config ./server.conf
2020-12-01 13:06:17 WARNING: --topology net30 support for server configs with IPv4 pools will be removed in a future release. Please migrate to --topology subnet as soon as possible.
2020-12-01 13:06:17 DEPRECATED OPTION: --cipher set to 'AES-256-CBC' but missing in --data-ciphers (AES-256-GCM:AES-128-GCM). Future OpenVPN version will ignore --cipher for cipher negotiations. Add 'AES-256-CBC' to --data-ciphers or change --cipher 'AES-256-CBC' to --data-ciphers-fallback 'AES-256-CBC' to silence this warning.
2020-12-01 13:06:17 Cannot pre-load tls-auth keyfile (ta.key)
2020-12-01 13:06:17 Exiting due to fatal error

네, 그렇습니다. 치명적인 에러가 있어서 실행이 안되었네요 ㅎㅎ DEPRECATED 로 표시된 부분은 server.conf 를 열어서 AES-256-CBC 로 된 부분을 AES-256-GCM 으로 변경해주시면 됩니다. 자, 그러면 tls-auth 를 위한 ta.key 파일을 생성해 보겠습니다

 

각종 Key 생성하기

우선 OpenVPN 용 Static Key 를 만들겠습니다. tls-auth 용 키이며 ta.key 파일을 만들어야 하는데요,  생성하는 것은 간단합니다. OpenVPN 바이너리에서 옵션을 지정하여 키를 생성할 수 있습니다. Configuration 파일이 위치한 경로에 ta.key 파일도 만들어 보도록 하겠습니다. 

% /usr/local/opt/openvpn/sbin/openvpn --genkey tls-auth ta.key
% cat ta.key
#
# 2048 bit OpenVPN static key
#
-----BEGIN OpenVPN Static key V1-----
9b61ceee61da49815108d6703e722d22
3c0f98a075c5476a3189c394274bedb3
...
...
535613076cde018b76a098bd48fbde83
ba2a1259d8df458b15c6f521b7ae0c57
-----END OpenVPN Static key V1----

사용자와 PKI 연결 설정에 사용할 인증서 파일도 생성해 보도록 하겠습니다. 인증서 파일 생성을 하는 방법은 여러가지이지만 easyrsa 를 사용해 보도록 하겠습니다. Dependency 설치시에 같이 설치가 되지 않았던 것 같아 Homebrew 로 설치해 주었습니다. 

% brew install easy-rsa
...
% brew --prefix easy-rsa
/usr/local/opt/easy-rsa

이제 easyrsa 를 이용하여 PKI 를 구성하기 위한 루트 인증서, 비밀키, 공개키 등을 만들도록 하겠습니다. 참고로, easyrsa 는 기본 값으로 /usr/local/etc/pki 경로에 파일들을 생성하도록 되어 있으니 참고하시기 바랍니다. 

//===============================
// 초기화
//===============================
% /usr/local/opt/easy-rsa/bin/easyrsa init-pki

init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /usr/local/etc/pki

//===============================
// CA Certificate 생성
//===============================
% /usr/local/opt/easy-rsa/bin/easyrsa build-ca nopass
Using SSL: /usr/local/opt/openssl@1.1/bin/openssl OpenSSL 1.1.1h  22 Sep 2020
Generating RSA private key, 2048 bit long modulus (2 primes)
..........................................................................................................................................+++++
..............................................................................................+++++
e is 65537 (0x010001)
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.
-----
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:MyLocalPKI

CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/usr/local/etc/pki/ca.crt

//===============================
// 서버인증서 생성
//===============================
% /usr/local/opt/easy-rsa/bin/easyrsa build-server-full server nopass
Using SSL: /usr/local/opt/openssl@1.1/bin/openssl OpenSSL 1.1.1h  22 Sep 2020
Generating a RSA private key
..............................................................+++++
...................................................................................................................................+++++
writing new private key to '/usr/local/etc/pki/easy-rsa-38744.0yXv0x/tmp.Xb7eac'
-----
Using configuration from /usr/local/etc/pki/easy-rsa-38744.0yXv0x/tmp.VwN7Lb
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'server'
Certificate is to be certified until Mar  6 04:45:50 2023 GMT (825 days)

Write out database with 1 new entries
Data Base Updated

//===============================
// 키 교환 알고리즘용 DH 파라메터 생성
//===============================
% /usr/local/opt/easy-rsa/bin/easyrsa gen-dh
Using SSL: /usr/local/opt/openssl@1.1/bin/openssl OpenSSL 1.1.1h  22 Sep 2020
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
...............................................................................+....................................+......................................
DH parameters of size 2048 created at /usr/local/etc/pki/dh.pem


//===============================
// Client 용 Credential 생성
//===============================
% /usr/local/opt/easy-rsa/bin/easyrsa build-client-full mylocalclient nopass
Using SSL: /usr/local/opt/openssl@1.1/bin/openssl OpenSSL 1.1.1h  22 Sep 2020
Generating a RSA private key
...................................................................................................................................................................+++++
..+++++
writing new private key to '/usr/local/etc/pki/easy-rsa-65143.eROtDW/tmp.haeAUt'
-----
Using configuration from /usr/local/etc/pki/easy-rsa-65143.eROtDW/tmp.EOABaH
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'mylocalclient'
Certificate is to be certified until Mar  6 05:03:20 2023 GMT (825 days)

Write out database with 1 new entries
Data Base Updated

뭔가 번잡하니 많네요. 하지만 늘 하던 일이었다고 생각하시고 하나씩 따라오셨으면 특별히 문제 없었을 겁니다. 이제 생성된 파일들이 어디에 있는지 체크해 볼까요?

// 서버 인증서와 클라이언트 인증서
% pwd
/usr/local/etc/pki/issued
% ls
mylocalclient.crt	server.crt

// 서버 비밀키와 클라이언트 비밀키, CA 비밀키
% pwd
/usr/local/etc/pki/private
% ls
ca.key			mylocalclient.key	server.key

// CA 인증서와 DH 파라메터 파일
% pwd
/usr/local/etc/pki
% ls ca.crt dh.pem
ca.crt	dh.pem

3가지 경로에 각 파일이 나뉘어져 있습니다. easyrsa 는 마치 내가 CA (Certificate Authority) 가 된 것처럼 인증서를 발급해주고 만들어주는 역할을 한 것이고, 각각 필요한 키들이 생성되어 적절한 위치에 나뉘어져 있다고 생각하시면 됩니다. 

 

OpenVPN 서버를 다시 시작해보자

간결한 관리를 위하여 앞서 작업했던 /usr/local/etc/openvpn 경로로 서버에서 필요한 파일들을 복사해 오도록 하겠습니다. 파일명은 server.conf 에 기술된 파일명을 기준으로 하고 있으니, 다른 이름으로 생성했다면 이름을 변경해 주셔도 무방합니다. 파일이 복사되었다면 sudo 권한으로 OpenVPN 서버를 실행하도록 하겠습니다. 

% pwd
/usr/local/etc/openvpn
% cp /usr/local/etc/pki/ca.crt .
% cp /usr/local/etc/pki/dh.pem ./dh2048.pem
% cp /usr/local/etc/pki/private/server.key .
% cp /usr/local/etc/pki/issued/server.crt .

% sudo /usr/local/opt/openvpn/sbin/openvpn --config ./server.conf
% sudo /usr/local/opt/openvpn/sbin/openvpn --config ./server.conf
2020-12-01 14:17:01 WARNING: --topology net30 support for server configs with IPv4 pools will be removed in a future release. Please migrate to --topology subnet as soon as possible.
2020-12-01 14:17:01 OpenVPN 2.5.0 x86_64-apple-darwin19.6.0 [SSL (OpenSSL)] [LZO] [LZ4] [PKCS11] [MH/RECVDA] [AEAD] built on Nov 13 2020
2020-12-01 14:17:01 library versions: OpenSSL 1.1.1h  22 Sep 2020, LZO 2.10
2020-12-01 14:17:01 NOTE: your local LAN uses the extremely common subnet address 192.168.0.x or 192.168.1.x.  Be aware that this might create routing conflicts if you connect to the VPN server from public locations such as internet cafes that use the same subnet.
2020-12-01 14:17:01 Diffie-Hellman initialized with 2048 bit key
2020-12-01 14:17:01 Outgoing Control Channel Authentication: Using 160 bit message hash 'SHA1' for HMAC authentication
2020-12-01 14:17:01 Incoming Control Channel Authentication: Using 160 bit message hash 'SHA1' for HMAC authentication
2020-12-01 14:17:01 Opened utun device utun7
2020-12-01 14:17:01 /sbin/ifconfig utun7 delete
ifconfig: ioctl (SIOCDIFADDR): Can't assign requested address
2020-12-01 14:17:01 NOTE: Tried to delete pre-existing tun/tap instance -- No Problem if failure
2020-12-01 14:17:01 /sbin/ifconfig utun7 10.8.0.1 10.8.0.2 mtu 1500 netmask 255.255.255.255 up
2020-12-01 14:17:01 /sbin/route add -net 10.8.0.0 10.8.0.2 255.255.255.0
add net 10.8.0.0: gateway 10.8.0.2
2020-12-01 14:17:01 Could not determine IPv4/IPv6 protocol. Using AF_INET6
2020-12-01 14:17:01 Socket Buffers: R=[786896->786896] S=[9216->9216]
2020-12-01 14:17:01 setsockopt(IPV6_V6ONLY=0)
2020-12-01 14:17:01 UDPv6 link local (bound): [AF_INET6][undef]:1194
2020-12-01 14:17:01 UDPv6 link remote: [AF_UNSPEC]
2020-12-01 14:17:01 MULTI: multi_init called, r=256 v=256
2020-12-01 14:17:01 IFCONFIG POOL IPv4: base=10.8.0.4 size=62
2020-12-01 14:17:01 IFCONFIG POOL LIST
2020-12-01 14:17:01 Initialization Sequence Completed

이렇게 대략 로컬 설치가 끝났습니다. 사실 이후에 udp4 만 사용하도록 변경, tls-auth 가 생각처럼 동작하지 않아 제외하는 작업등을 진행한 후에 정상적인 기동, 클라이언트의 연결이 가능했습니다. 이 부분은 다음 포스팅에서 정리해 보도록 하겠습니다. 

 

[ NordVPN 크리스마스 할인행사 > bit.ly/39unoRx ]

 

NordVPN: Best VPN Service Provider | #1 Editors' Choice

온라인에서 개인정보를 보호하고 지리적 위치 제약 없이 콘텐츠에 액세스하세요. 60개국 이상에서 1000개 이상의 서버를 사용할 수 있으며, 강력한 암호화와 로그 삭제 정책을 갖추고 있습니다.

nordvpn.com

 

본 포스팅은 제휴마케팅을 통해 소정의 수수료를 받을 수 있습니다.

728x90
728x90

웹 기반의 서비스를 제공한다면 SSL 인증서의 사용은 이제 필수 아니 기본이 되었습니다. Let's Encrypt 와 같은 선택지가 생기면서 비용때문에 SSL 기반의 HTTPS 통신을 제공하지 않는 다는 것은 더이상 변명이 되기도 힘든 시기입니다. 물론 서버의 성능 이야기를 한다면 <정말 아주 약간>의 배려를 해줄 수 있긴 합니다만 근래의 컴퓨팅 파워와 비용을 생각하면 그리 와닿지는 않는 변명입니다. 

이렇게 SSL 인증서 사용이 기본이 되고 있지만 SSL 인증서를 서버에 설치하고 적용하는 것은 여전히 까다롭습니다. 까다로운 것은 다름아닌 익숙하지 않음에서 비롯된다고 생각합니다. 개발은 늘 하는 일이지만 SSL 인증서는 아주 짧으면 3개월부터, 보통은 1년, 길면 2년정도 되어야 한 번 할까 말까한 작업이기 때문입니다. 눈치 채셨겠지만, 이 기간은 인증서를 교체해야 하는 주기와 일치합니다. 

이렇게 인증서가 잘 설치되었는지, 인증서에는 문제가 없는지 확인하는 것이 DevOps 시대에는 필수가 되었습니다. 그렇지만 언급했던 것처럼 <어쩌다 한 번 하는 작업> 이다보니 무언가 공부를 하기도 애매하고, 공부를 해두었다 하더라도 정작 필요한 시점에는 써먹지 못하는게 현실입니다. 여기에 더하여 운영중인 서버에 인증서를 적용하는 전후에 무엇을 어떻게 확인하는게 좋은지도 사실 적당한 레퍼런스가 없습니다. 


퍼블릭으로 공개된 서버의 인증서 점검

가이드 드리고 싶은 내용은 1) 운영중인 서버의 인증서 상황 점검과 2) 교체하려는 인증서 구성이 문제 없는지 어떻게 확인하는가 하는 점입니다. 1) 번과 같이 운영중인 서버의 인증서 상황 점검은 무척 쉽습니다. Mac 이나 Linux 환경을 사용하고 있다면 openssl 명령 혹은 어플리케이션을 이용하여 도메인 혹은 IP 를 가지고 있는 서버에 설치된 인증서를 쉽게 확인할 수 있습니다. 

// 인증서 정보 확인
% openssl s_client -connect www.naver.com:443

CONNECTED(00000003)
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
verify return:1
depth=1 C = US, O = DigiCert Inc, CN = DigiCert SHA2 Secure Server CA
verify return:1
depth=0 C = KR, ST = Gyeonggi-do, L = Seongnam-si, O = NAVER Corp., CN = *.www.naver.com
verify return:1
---
Certificate chain
...

openssl 을 이용하여 `s_client` 옵션을 주고 `-connect` 에 확인하고자 하는 도메인 정보와 포트정보 (보통은 443이죠) 를 넣으면 구성되어있는 인증서 체인정보 (서버 인증서 > 중간 인증서 > 루트 인증서) 와 인증서의 상세한 정보를 확인할 수 있습니다. 웹 브라우저로 접근 가능한 HTTPS 를 사용하는 모든 도메인 / 서버에 대해서는 이 명령을 통해 인증서 정보를 확인할 수 있습니다. 

 

교체하려는 인증서 점검

인증서를 교체하기 위해서는 인증서 발급기관, 속칭 CA 로 부터 인증서를 발급받아 전달받게 됩니다. 보통 서버에 인증서를 설치하기 위해서는 1) 서버 개인키와 2) 서버 공개키 + 공개키를 인증할때 사용한 중간 인증서의 공개키를 합친 파일 을 서버에 설치하게 됩니다. 설치된 파일은 Apache Server 나 nginx 와 같은 웹 서버의 설정(configuration) 파일에 설치된 경로, 파일 정보, 사용할 Cipher Suite 정보등을 기술하게 됩니다. 

서버에 인증서 파일을 업로드 하고 설정 변경을 해서 아무런 문제가 없다면 얼마나 좋을까요? 결국 사람이 하는 일이다보니 실수가 생기거나 오류가 생기는 경우가 발생하곤 합니다. 그러면 드는 생각이 <교체하려는 인증서 파일을 미리 확인해 볼 수 없나?> 하는 것일겁니다. 앞서 본 것처럼 openssl 을 이용해서 파일 단위로 구성된 인증서를 미리 확인해보는 방법은 없을까요?

아래의 코드는 서버에 배포하기 위해서 중간 체인 인증서와 서버 인증서를 합친 파일을 점검해주는 간단한 스크립트 입니다. 서버에서 사용하고 있는 인증서를 `openssl s_client` 명령으로 확인한 것처럼 서버 인증서, 중간 인증서가 문제 없는지, 혹은 체인이 어떻게 구성되어 있는지를 확인할 수 있는 스크립트입니다. 참고로 스크립트의 출처는 kdecherf.com/blog/2015/04/10/show-the-certificate-chain-of-a-local-x509-file/ 입니다. 

#!/bin/bash

chain_pem="${1}"

if [[ ! -f "${chain_pem}" ]]; then
    echo "Usage: $0 BASE64_CERTIFICATE_CHAIN_FILE" >&2
    exit 1
fi

if ! openssl x509 -in "${chain_pem}" -noout 2>/dev/null ; then
    echo "${chain_pem} is not a certificate" >&2
    exit 1
fi

awk -F'\n' '
        BEGIN {
            showcert = "openssl x509 -noout -subject -issuer"
        }

        /-----BEGIN CERTIFICATE-----/ {
            printf "%2d: ", ind
        }

        {
            printf $0"\n" | showcert
        }

        /-----END CERTIFICATE-----/ {
            close(showcert)
            ind ++
        }
    ' "${chain_pem}"

echo
openssl verify -untrusted "${chain_pem}" "${chain_pem}"

스크립트를 만들고 chmod u+x #파일명# 으로 실행 가능하게 만드시기 바랍니다. 실행 가능한 스크립트가 되었다면 `./#스크립트파일명# #인증서파일명#` 형식의 명령을 통해 로컬에 존재하는 파일 형태의 인증서 + 중간 인증서를 s_client 옵션을 이용한 것처럼 검증할 수 있게 됩니다. 문제가 없다면 서버에 배포하고 웹 서버를 reload 하면 되겠지요!

728x90
728x90

HTTPS 통신을 위해서는 SSL/TLS 인증서가 필요합니다. 서버측에 Private Key 와 Public key 를 설치하고, 웹 브라우저로 대표되는 User-Agent 는 Public Key 를 전달받아 통신 구간의 암호화에 사용하게 됩니다. 이러한 인증서에는 여러가지 정보들이 담겨 있는데요 가장 대표적인 것으로 도메인 정보를 담고 있는 CN (Common Name) 입니다. 

네이버의 인증서 정보 - 일반 이름이 Common Name 입니다

 CN 이외에도 인증서에는 인증서와 관련한 여러가지 정보를 담기 위한 필드들이 존재합니다. 위의 네이버 인증서 정보에 나오는 주/도, 소재지, 조직 등의 모든 정보들이 인증서의 Public Key 에 포함되어 사용자에게 전달되는 값 들입니다. 네, 당연히 전송되는 용량에 포함되는 값들입니다. openssl 명령으로 이 인증서를 조금 더 자세히 살펴보면...

...인증서의 발급 체계에 따라 서버 인증서, 중간 인증서, 루트 인증서의 정보를 확인할 수 있습니다. 서버 인증서에 있는 C, ST, L, O 등의 값이 브라우저에 표시되었던 정보임을 알 수 있습니다. 가장 위에 있는 루트 인증서를 보면 OU Organization Unit 라는 값이 있는데요 여기에 www.digicert.com  이라는 인증서 발급사의 도메인 정보가 들어가 있는 것을 볼 수 있습니다.

OU 를 직역하면 조직 단위 내지는 부서명 정도가 될 것 같은데 좀 엉뚱한 정보가 들어가 있는 느낌이죠? 회사에서 사용하는 LDAP 정보를 살펴봐도 보통 OU 에는 부서 혹은 조직 단위에 따른 편제 정보가 들어가 있곤 합니다. SSL/TLS 인증서 세계(?)에서는 이 필드를 원래의 목적과 다르게 사용하는 경우가 많았고, 이로 인해 불필요한 바이트의 전송이 관례적으로 있어 왔다는 것을 짐작할 수 있겠습니다 (=우리의 소중한 데이터를 소모해 왔다는 것도...)

Digicert 에서는 더 이상 OU 를 쓰지 않겠다고 발표했군요

이 필드에 대한 논란이 있어온 이래 저렴한 인증서의 대명사였던 Sectigo (과거 COMODO 였죠) 는 진작에 필드를 제거했습니다. Sectigo 쪽에서는 SSL/TLS 인증서의 제품 정보를 표현하는 것과 같은 용도로 쓰이고 있었던 것 같습니다. 역시나 제정되었던 표준, 약속과는 다른 방향이었습니다.

Digicert 는 대한민국발 인증서 사태이후 시만텍의 인증서 사업을 인수해서 운영하고 있는 가장 큰 CA 중 하나입니다. 이제 Digicert 가 OU 필드를 인증서 발급에 사용하지 않고 인증서 정보에도 포함시키지 않을 것이라고 하니, OU 필드는 퇴출이 확정된 거라 봐도 무방할 것 같습니다. 아울러 사용자들은 자신의 인터넷 회선, 모바일 플랜에서 불필요한 전송 비용을 줄일 수 있게 된 것이기도 합니다. 

[ 참고 링크들 ]

 

Public certificates – Data entries that violate industry standards

If you only put a hyphen in the organization unit field, a CA will be unable to validate the value. However, if you enter an organization name that includes a hyphen in it (for example, Dev-Ops), this hyphen does not prevent a CA from validating your organ

docs.digicert.com

https://knowledge.digicert.com/alerts/ou-removal.html

 

DigiCert will deprecate the Organizational Unit field

Description DigiCert will deprecate the Organizational Unit (OU) field to simplify certificate ordering. Why is the OU field being removed? The OU field allows optional metadata to be stored in a certificate, however, it’s intended purpose is extremely l

knowledge.digicert.com

https://www.xolphin.com/news/Change_in_use_of_OU-fields_in_Sectigo_certificates

 

Change in use of OU-fields in Sectigo certificates

Change in use of OU-fields in Sectigo certificates 19 December 2019 As of December 15, 2019, Sectigo will change the use of OU fields for all new Sectigo certificates. From this date, it is no longer permitted to include non-organization-related informatio

www.xolphin.com

 

728x90

+ Recent posts