최근 openssl 관련 이슈로 인해 리눅스 기반 시스템의 openssl 업데이트를 하는 일이 발생되고 있다. 그런데 RPM 패키징 관리시스템을 사용하는 RHEL(또는 CentOS)에서 openssl을 소스 설치를 하게되면 주의할 것들이 있다. 자칫 잘 못하면 openssl과 연관된 패키지들이 동작을 제대로 안하는 문제가 발생을 할 수 있기 때문이다. 이 문서에서는 일부러 문제를 발생시키고, 문제를 해결하는 방법을 설명하고 있다.
목차
1. 설치
1.1. 설치 참고 문서
아래 웹사이트에서 opensssl-1.0.1h 설치 방법에 대해 가이드 하고 있다. 이 방법을 참고하여 RHEL 6.4에 opensssl-1.0.1h를 소스 설치 해보겠다.
http://www.linuxfromscratch.org/blfs/view/svn/postlfs/openssl.html
1.2. 기존 rpm 버전 정보확인
기존 openssl 의 버전 정보는 아래와 같다.
[root@Sample-local ~]# rpm -qa | grep openssl openssl-1.0.0-27.el6.x86_64 openssl-devel-1.0.0-27.el6.x86_64 |
1.3. 소스 설치
위의 웹사이트의 방식으로 설치 진행한다.
[root@Samplelocal ~]# tar zxvf openssl1.0.1h.tar.gz [root@Samplelocal ~]# cd openssl1.0.1h [root@Samplelocal openssl1.0.1h]# ./config prefix=/usr openssldir=/etc/ssl libdir=lib64 shared zlib-dynamic [root@Samplelocal openssl1.0.1h]# make [root@Samplelocal openssl1.0.1h]# make install |
-> config에서 libdir 지정은 해당 서버가 64bit 아키텍쳐라 그에 맞게 설정함.
2. 문제발생
2.1. 설치 후 이상 증상
설치를 끝내고 몇가지 데몬(sshd, ntpd)을 restart 해보면 아래와 같이 에러가 발생을 한다.
[root@Sample-local openssl-1.0.1h]# /etc/init.d/sshd restart [root@Sample-local openssl-1.0.1h]# /etc/init.d/ntpd restart |
2.2. 원인
에러의 원인은 해당 데몬을 구동하기 위한 바이너리가 참조하는 openssl 동적라이브러리 파일이 맞질 않아서 그렇다. ntpd는 메시지가 뜨지도 않고, sshd는 openssl 버전 문제라고만 명시를 해주고 있다.
2.3. 원인 분석
그렇다면 sshd는 어떤 openssl 동적라이브러리 파일을 참조하길래 동작을 안하는걸까? 먼저 sshd 바이너리 파일이 참조하는 동적라이브러리 파일리스트를 살펴보자.
[root@Sample-local openssl-1.0.1h]# ldd /usr/sbin/sshd linux-vdso.so.1 => (0x00007fffc01ff000) libfipscheck.so.1 => /lib64/libfipscheck.so.1 (0x00002b1ee8ae1000) libwrap.so.0 => /lib64/libwrap.so.0 (0x00002b1ee8ce4000) libaudit.so.1 => /lib64/libaudit.so.1 (0x00002b1ee8ef0000) libpam.so.0 => /lib64/libpam.so.0 (0x00002b1ee910c000) libdl.so.2 => /lib64/libdl.so.2 (0x00002b1ee931a000) libselinux.so.1 => /lib64/libselinux.so.1 (0x00002b1ee951f000) libcrypto.so.10 => /usr/lib64/libcrypto.so.10 (0x00002b1ee973e000) libutil.so.1 => /lib64/libutil.so.1 (0x00002b1ee9b1a000) libz.so.1 => /lib64/libz.so.1 (0x00002b1ee9d1e000) . . |
그런데 너무나 많다. 그럼 이 중에서 openssl 이 제공하는 동적라이브러리 파일이 무엇인지는 아래와 같이 살펴보면 알 수 있다.
[root@Sample-local openssl-1.0.1h]# rpm -ql openssl-1.0.0-27.el6.x86_64 | grep lib /usr/lib64/.libcrypto.so.1.0.0.hmac /usr/lib64/.libcrypto.so.10.hmac /usr/lib64/.libssl.so.1.0.0.hmac /usr/lib64/.libssl.so.10.hmac /usr/lib64/libcrypto.so.1.0.0 /usr/lib64/libcrypto.so.10 /usr/lib64/libssl.so.1.0.0 /usr/lib64/libssl.so.10 . . |
/usr/lib64/libcrypto.so.10 동적라이브러리가 sshd를 구동할 때 요구되는 openssl 동적라이브러리이다. 아래는 rpm으로 설치됐을 때 파일리스트이다.
[root@Samplelocal openssl1.0.1h]# ls -la /usr/lib64/libcrypto* lrwxrwxrwx. 1 root root 18 Jul 4 2014 /usr/lib64/libcrypto.so -> libcrypto.so.1.0.0 lrwxrwxrwx. 1 root root 18 Jul 4 2014 /usr/lib64/libcrypto.so.10 -> libcrypto.so.1.0.0 -rwxr-xr-x. 1 root root 1662832Oct 12 2012 /usr/lib64/libcrypto.so.1.0.0 |
-> /usr/lib64/libcrypto.so.10 은 링크파일이고 실제 파일은 /usr/lib64/libcrypto.so.1.0.0 이다.
그리고 아래와 같은 방법으로 의존되는 라이브러리를 확인해 볼 수 있다.
(실제로 remove 시키지 않고 의존성만 보고 yum을 끝낼 것)
[root@Samplelocal openssl1.0.1h]# yum remove openssl | grep ssh-server --> Processing Dependency: libcrypto.so.10()(64bit) for package: openssh-server-5.3p1-84.1.el6.x86_64 --> Package openssh-server.x86_64 0:5.3p1-84.1.el6 will be erased |
문제의 원인은 openssl 소스 설치 시 지정한 prefix 에 있었다.
--prefix=/usr
/usr 을 기준으로 하게 되면 openssl 이 설치 될 때 기존의 /usr/lib64, /usr/include, /usr/bin 디렉토리에 컴파일 후의 파일들을 배치하게 되고, 기존 openssl rpm package 파일들과 경로가 같을 경우 덮어 씌워지게 된다. 아래는 소스 설치 후 라이브러리 파일 리스트 이다.
[root@Sample-local openssl-1.0.1h]# ls -la /usr/lib64/libcrypto* -rw-r--r-- 1 root root 3931032 Jul 4 01:48 /usr/lib64/libcrypto.a lrwxrwxrwx 1 root root 18 Jul 4 01:48 /usr/lib64/libcrypto.so -> libcrypto.so.1.0.0 lrwxrwxrwx. 1 root root 18 Jul 4 2014 /usr/lib64/libcrypto.so.10 -> libcrypto.so.1.0.0 -r-xr-xr-x 1 root root 2204359Jul 4 01:48 /usr/lib64/libcrypto.so.1.0.0 |
-> rpm 으로 설치된 /usr/lib64/libcrypto.so.1.0.0 의 파일사이즈와 날짜가 다른 걸 알 수 있다.
3. 문제해결
소스 설치된 openssl을 지우고 다시 원래의 rpm 패키지로 복원하는 방법을 살펴보겠다.
3.1. uninstall 시도
소스 설치를 위해 ./config 명령을 쳤던 디렉토리에서 make uninstall을 해본다.
[root@Sample-local openssl-1.0.1h]# make uninstall make: *** No rule to make target `uninstall'. Stop. |
안타깝게도 Makefile에 uninstall에 대해서 명시를 안하고 있어서 uninstall이 동작하지 않으니 직접 일일이 지워야 한다.
하지만 파일 개수가 400 개가 넘다보니 일일히 지우는것도 일이다.
그래서 고유 디렉토리에 소스 설치를 다시 한번 해서 그 디렉토리안의 파일리스트를 가지고서 /usr 디렉토리 밑에 흩어져있는 파일들을 제거 하는 방법을 사용하겠다.
3.2. openssl 소스 재설치
기존 시스템 디렉토리와 겹치지 않게 /usr/local/openssl 이라는 고유 디렉토리 밑에 설치가 된 걸 확인 할 수 있다.
[root@Sample-local openssl-1.0.1h]# make clean [root@Sample-local openssl-1.0.1h]# ./config --prefix=/usr/local/openssl --openssldir=/usr/local/openssl/etc/ssl --libdir=lib64 shared zlib-dynamic [root@Sample-local openssl-1.0.1h]# make [root@Sample-local openssl-1.0.1h]# make install [root@Sample-local openssl-1.0.1h]# ls -l /usr/local/openssl total 16 drwxr-xr-x 2 root root 4096 Jul 4 04:02 bin drwxr-xr-x 3 root root 4096 Jul 4 04:02 etc drwxr-xr-x 3 root root 4096 Jul 4 02:35 include drwxr-xr-x 4 root root 4096 Jul 4 04:02 lib64 |
3.3. 잘 못 설치된 openssl 지우기
잘 못 설치된 파일들을 /usr/local/openssl 디렉토리 내의 파일들과 비교하여 지우도록 하겠다.
먼저, find로 /usr/local/openssl 내의(/usr/local/openssl/etc를 제외한) 파일들을 찾아서 디렉토리 경로를 /usr 로 변경하고 그 값을 받아서 rm으로 지운다.
[root@Sample-local ~]# find /usr/local/openssl ! \( -path "/usr/local/openssl/etc" -prune \) -type f | sed 's/\/usr\/local\/openssl/\/usr/g' | xargs rm -fv {} \; |
그리고 위에서 etc를 제외한 것에 대한 처리를 한다. /etc/ssl 밑의 파일들을 지우기 위함이다.
[root@Sample-local ~]# find /usr/local/openssl/etc/ssl -type f | sed 's/\/usr\/local\/openssl//g' | xargs rm -fv {} \; |
-> make uninstall를 통해 삭제하는 경우에도 디렉토리는 지우지 않고 파일들만 지운다. 위의 방식도 파일들만 지운다. 왜 그런지는 조금만 생각해 보면 알 수 있다. 따라서 디렉토리는 수동으로 지워야 되며, 나둬도 상관은 없다.
3.4. openssl rpm 재설치
소스 설치 파일들이 지워졌으므로 이제 기존의 openssl rpm 버전에 맞게 rpm을 재설치를 해줘야 한다.
1) yum을 통해서 설치
[root@Sample-local ~]# yum reinstall openssl-1.0.0-27.el6.x86_64 |
그런데 yum의 경우 repository 에 따라 원하는 버전을 설치 하지 못할 수 있으므로 rpm 파일을 구해서 아래처럼 설치하는 것을 권장한다.
2) rpm 설치
[root@Sample-local ~]# rpm -ivh openssl-1.0.0-27.el6.x86_64.rpm -force |
4. 확인하기
원래대로 라이브러리가 복구 됐으며, openssl-1.0.0-27 버전의 다른 파일들도 복원이 되었다.
4.1. 동적 라이브러리 확인
[root@Sample-local ~]# ls -la /usr/lib64/libcrypto* lrwxrwxrwx. 1 root root 18 Jul 4 2014 /usr/lib64/libcrypto.so -> libcrypto.so.1.0.0 lrwxrwxrwx. 1 root root 18 Jul 4 2014 /usr/lib64/libcrypto.so.10 -> libcrypto.so.1.0.0 -rwxr-xr-x. 1 root root 1662832 Oct 12 2012 /usr/lib64/libcrypto.so.1.0.0 |
4.2. 데몬 구동 확인
[root@Sample-local ~]# /etc/init.d/sshd start Startting sshd: [ OK ] [root@Sample-local ~]# /etc/init.d/ntpd start Starting ntpd: [ OK ] |
4.3. 라이브러리 생성 유무
참고로 소스 설치 config 옵션의 shared 를 빼면 동적라이브러리 파일이 생성되지 않고,
소스 디렉토리에서 아래처럼 Makefile의 정적라이브러리 명시 부분을 주석처리하게 되면 정적라이브러리 파일 libcrypto.a libssl.a 두개가 생성되지 않는다.
[root@Sample-local openssl-1.0.1h]# sed -i 's# libcrypto.a##;s# libssl.a##' Makefile |
비단 openssl 뿐만 아니라 소스 설치시엔 prefix 경로를 될 수 있는한 기존 시스템 디렉토리와 겹치지 않게 설정하는 것이 좋고, 어쩔 수 없는 경우 여러 상황을 고려하고 설치를 해야된다. 특히 openssl 과 같이 많은 패키지들이 의존적인 관계를 맺고 있는 경우 더욱 신중해야 된다. 이상으로 문서를 마친다.
정말 감사합니다. 비슷한 문제로 서버가 문제가 생겨서 헤매고 있었는데 구세주가 되어 주셨네요 ㅠㅠ
감사합니다..
openssl 지웠다가 ssh도 안되고 고생했는데. 덕분에 해결했습니다.
마지막부분이 참조됫네요
libcrypto.so.6 -> libcrypto.so.0.9.8e
libssl.so.6 -> libssl.so.0.9.8e
>>실제 실행경로가 libssl.so.0.9.8e로 되는것을 확인한후
ln -Tfs /usr/local/ssl/lib/libssl.so.1.0.0 /lib/libssl.so.6
ln -Tfs /usr/local/ssl/lib/libcrypto.so.1.0.0 /lib/libcrypto.so.6
하니 해결됬습니다.
감사합니당
잘 해결되어 다행입니다. 🙂