OpenSSH 배포판에 포함 된 ssh-agent는
RSA와 DSA키를 좀 더 편리하고 안전하게 다루기 위해 만들어진 특별한 프로그램이다.(OpenSSH
키 관리, Part 1 참조). ssh 와는 다르게 ssh-agent는
해독된 비밀 키를 캐싱(caching)할 유일한 목적으로 만들어진 장기 실행(long-running) 데몬(daemon)이다.
ssh는 ssh-agent와 커뮤니케이션을 할 수 있도록 지원되기 때문에,
매번 새롭게 연결 할 때마다 패스워드를 입력하지 않아도 ssh는 해독된 비밀 키를 입수할 수 있다. ssh-agent를
이용하면 간단히 ssh-add로 비밀 키를 ssh-agent 캐시에 추가할 수
있다. 이것은 'one-time' 프로세스이다; ssh-add를 사용한 후에는 ssh는
비밀 키를 ssh-agent에서 파악한다. passphrase를 입력 할 필요가 없다.
전체 ssh-agent 키 캐싱 시스템이 어떻게 작동하는지 살펴보자. ssh-agent가
시작되면, 몇가지 중요한 환경 변수들을 만들어 낸다.다음은 ssh-agent가 시작될 때 생성된 아웃풋이다:
% ssh-agent SSH_AUTH_SOCK=/tmp/ssh-XX4LkMJS/agent.26916; export SSH_AUTH_SOCK; SSH_AGENT_PID=26917; export SSH_AGENT_PID; echo Agent pid 26917; |
ssh-agent의 아웃풋은 실제로는 일련의 bash 커맨드이다; 이 커맨드가 실행되면 한 쌍의 환경
변수들(SSH_AUTH_SOCK와 SSH_AGENT_PID)을 설정한다: export 커맨드로 인해서, 이러한 환경 변수들은
후에 추가적인 커맨드를 실행할 수 있다. 실제로 쉘에서 이러한 라인들의 값이 구해졌다면 무슨 일이든 일어날 것이다. 하지만 지금은
stdout으로 프린트 될 것이다. 이러한 문제를 해결하기 위해서 다음과 같은 방법으로 ssh-agent를
실행할 수 있다:
eval `ssh-agent` |
이 명령어는 bash가 ssh-agent을 실행하고 그런 다음 ssh-agent의
아웃풋 값을 구하도록 한다. 이러한 방식으로 실행되어(single quote가 아닌 back-quote(`)라는
것에 주목할 것), SSH_AGENT_PID 와 SSH_AUTH_SOCK 변수들은 쉘에 의해 설정되고 익스포트 된다. 로그인
세션 동안 시작하는 모든 새로운 프로세스에 이러한 변수들을 사용할 수 있다.
ssh-agent를 시작하는 최상의 방법은 위 라인을 ~/.bash_profile에 추가하는 것이다.
이러한 방식을 통해, 로그인 쉘에서 시작하는 모든 프로그램이 환경 변수들을 인식하고 ssh-agent의
위치를 지정하여 필요한 키에 맞춰 쿼리 할 것이다. 특별한 중요성을 지닌 환경 변수는 SSH_AUTH_SOCK 이다; SSH_AUTH_SOCK에는
ssh-agent와 대화하기 위해서 ssh와 scp이 사용할
수 있는 UNIX 도메인 소켓으로의 경로가 포함되어 있다.
물론, ssh-agent는 해독된 비밀 키의 빈 캐시로 시작한다. 실제로 ssh-agent를
사용하기 전에 비밀 키(들)을 ssh-agent의 캐시에 ssh-add 명령어를
사용하여 추가해야 한다. 다음 예제에서, 나는 ssh-add를 사용하여 ~/.ssh/identity 비밀
RSA 키를 ssh-agent의 캐시에 추가했다:
# ssh-add ~/.ssh/identity Need passphrase for /home/drobbins/.ssh/identity Enter passphrase for /home/drobbins/.ssh/identity (enter passphrase) |
예제를 보면, ssh-add는 ssh-agent의 캐시에 저장될 수 있도록
passphrase를 묻는다. 일단 ssh-add를 사용하여 비밀 키(들)을 ssh-agent의
캐시에 추가하면, SSH_AUTH_SOCK은 현재 쉘에서 정의되고, ssh를 사용하여 원격 시스템에 연결할
수 있게 되는 것이다. passphrase가 필요없다.
ssh-agent는 정말 훌륭하다. 하지만 초기 설정은 여전히 까다롭다.
그 첫번째 이유는, ~/.bash_profile의 eval `ssh-agent`을 이용하면 ssh-agent의
새로운 카피가 모든 로그인 세션 때마다 시작된다; 이것은 소모적일 뿐 아니라, 비밀 키를 각각의 ssh-agent의
새로운 카피에 추가하기 위해서 ssh-add 를 사용해야 한다는 것을 의미한다. 시스템 상의 단일 터미널이나
콘솔을 열 경우 이것은 큰 문제가 아니지만 대부분은 많은 터미널을 열어야 하고 새로운 콘솔을 열 때마다 passphrase를
입력해야 한다. 기술적으로 이렇게 해야 할 이유가 없다. 왜냐하면 단일 ssh-agent 프로세스로 충분하기
때문이다.
초기 ssh-agent 셋업과 관련한 또 다른 문제는 cron job과 호환이 되지 않는다는 점이다.
cron job은 cron 프로세스에 의해 시작하기 때문에, SSH_AUTH_SOCK 변수를 그들의 환경에서 변수들을 상속 받지
않는다. 그래서 ssh-agent 프로세스가 실행하고 있는 지 알 수 없고 연결 할 방법도 모른다. 이러한
문제 또한 해결이 가능하다.
이러한 문제들을 풀기위해서 나는 keychain 이라는 bash 기반의 ssh-agent
front-end를 작성했다. keychain이 특별한 이유는 시스템 당 단일 ssh-agent
프로세스를 사용할 수 있다는 점이다. 로그인 세션 기준이 아니다. 이것은 비밀 키 당 하나의 ssh-add를
실행한다는 것을 의미한다. keychain은 ssh-agent의 캐시에서 이미
존재하지 않는 비밀 키를 추가하는 것을 시도하는 것만으로도 ssh-add 프로세스를 최적화 할 수 있다.
keychain이 어떻게 작동하는지 자세하게 살펴보자. ~/.bash_profile에서 시작할 때,
이것은 우선 ssh-agent가 이미 실행중인지의 여부를 살핀다. 실행하고 있지 않다면 이것은 ssh-agent를
실행시키고 중요한 SSH_AUTH_SOCK와 SSH_AGENT_PID 변수들을 ~/.ssh-agent 파일에 기록한다. 보안과
향후 사용 목적이다. 다음은 keychain을 시작하는 최상의 방법이다; ssh-agent를
사용할 때 처럼 ~/.bash_profile에서 필요한 셋업을 수행한다:
#!/bin/bash #example ~/.bash_profile file /usr/bin/keychain ~/.ssh/id_rsa #redirect ~/.ssh-agent output to /dev/null to zap the annoying #"Agent PID" message source ~/.ssh-agent > /dev/null |
ssh-agent를 직접 사용할 때 처럼 아웃풋을 계산하지 않고 keychain으로
~/.ssh-agent file을 '소스(source)'하지만 결과는 같다. 너무나도 중요한 SSH_AUTH_SOCK 이 정의되면,
ssh-agent는 실행되고 사용할 준비가 된다. SSH_AUTH_SOCK이 ~/.ssh-agent에
기록되었기 때문에, 쉘 스크립트와 cron job은 ~/.ssh-agent file을 소싱함으로서 쉽게 ssh-agent
와 연결된다. keychain 자체적으로 이 파일을 이용한다; keychain
이 시작되면, 기존 ssh-agent가 실행하고 있는 지를 검사한다는 것을 기억하라. 실행중이라면 이것은
~/.ssh-agent file을 사용하여 적절한 SSH_AUTH_SOCK 세팅을 입수한다. 그래서 이것이 새로운 agent를
시작하지 않고 기존 agent를 사용할 수 있도록 한다. keychain이 새로운 ssh-agent
프로세스를 시작하는 경우는 ~/.ssh-agent file이 무효거나 (존재하지 않는 ssh-agent),
~/.ssh-agent 자체가 존재하지 않을 경우이다.
keychain 설치는 간단하다. 우선 keychain
project page에서 가장 최신 버전의 keychain 소스 아카이브를 다운로드 한다. 그런다음
다음과 같이 설치한다:
# tar xzvf keychain-1.0.tar.gz # cd keychain-1.0 # install -m0755 keychain /usr/bin |
keychain이 /usr/bin/에 있기 때문에 이것을 ~/.bash_profile에 추가한다.
인자로서 비밀 키로 가는 경로를 제시한다. 다음은 keychain-enabled ~/.bash_profile이다:
An example keychain-enabled ~/.bash_profile
#!/bin/bash #on this next line, we start keychain and point it to the private keys that #we'd like it to cache /usr/bin/keychain ~/.ssh/id_rsa ~/.ssh/id_dsa source ~/.ssh-agent > /dev/null #sourcing ~/.bashrc is a good thing source ~/.bashrc |
로그인을 할 때 마다 keychain을 호출하기 위해서 ~/.bash_profile을 설정했다면 로그아웃
하고 다시 로그인 한다. 그러면, keychain은 ssh-agent를 시작하고
agent의 환경 변수 세팅을 ~/.ssh-agent에 기록하고, ~/.bash_profile의 keychain
커맨드 라인에 지정된 비밀 키를 묻는 프롬프트가 나타난다:
Keychain 시작
passphrase를 입력하면 비밀 키는 캐시 될 것이고 keychain은 종료된다. 그런 다음, ssh-agent를
사용 할 로그인 세션을 초기화하면서 ~/.ssh-agent는 실행 될 것이다. 지금 로그아웃 한 후 다시 로그인을 시도해 보라.
keychain이 기존 ssh-agent 프로세스를 찾고 있다는 것을 알 수 있을
것이다; 로그아웃 할 때 종료되지 않았다. 게다가 keychain은 여러분이 지정한 비밀 키(들)가 이미
ssh-agent의 캐시에 존재하고 있다는 것을 확인한다. 그렇지 않다면, 적절한 passphrase를
입력해야 한다. 이것이 잘 수행되었다면 기존 ssh-agent는 이전에 추가한 비밀 키를 포함하고 있을
것이다; 이것은 패스워드를 입력할 필요가 없다는 것을 의미한다:
Keychain이 기존 ssh-agent를 찾는다
축하한다! 이제는 로그인하여 원격 시스템으로 ssh 와 scp 가 가능하다;
로그인 후에 ssh-add를 사용할 필요가 없다. 그리고 ssh와 scp
역시 passphrase를 입력하라는 프롬프트를 내보내지 않는다. 사실, 초기의 ssh-agent 프로세스가
계속 실행되는 한 로그인은 가능하고 패스워드 없이 ssh 연결을 할 수 있다. 머신이 재부팅 될 때까지
ssh-agent 프로세스는 계속 실행할 것이다; 왜냐하면 Linux 시스템 상에서 세팅했기 때문에 길게는
여러 달 동안 passphrase를 입력할 필요가 없을지도 모른다! 이것이 바로 RSA와 DSA 인증을 이용한 보안과 패스워드
없는 연결이다.
계속하여 여러개의 새로운 로그인 세션을 만들면 keychain이 매번 정확히 같은 ssh-agent
프로세스로 "hook in" 하는 것을 보게 될 것이다. 실행하고 있는 ssh-agent에
"hook in" 하기 위해서 cron job과 스크립트를 얻을 수 있다는 것을 명심해라. 쉘 스크립트와 cron
job에 ssh 또는 scp 명령어를 사용하기 위해서는 ~/.ssh-agent
file을 우선 'source' 해야 한다:
source ~/.ssh-agent |
그런다음 모든 ssh 또는 scp 명령어들은 현재 실행되고 있는 ssh-agent를
찾고 쉘에서 여러분이 했던 것처럼 보안 암호없이 연결한다.
keychain을 실행시킨 후에, keychain --help 을 타이핑하여 모든
keychain의 커맨드 라인 옵션에 익숙해지도록 하라. 이제는 --clear
옵션에 대해서 살펴보겠다: .
Part
1 에서는 암호화 되지 않은 비밀 키를 사용하는 것은 위험한 관행이라는 것을 설명했다. 이것은 누군가가 여러분의 비밀
키를 훔쳐서 패스워드 없이 다른 시스템에서 여러분의 원격 계정에 로그인 하는데 사용하도록 하는 결과를 일으키기 때문이라는 것을
설명했다. 그렇다면, keychain이 (암호화된 키를 사용하는 한)이런 종류의 남용에는 강한 반면,
keychain이 오래 실행되는 ssh-agent 프로세스에 너무나도 쉽게 "hook-in"한다는
사실 때문에 잠재적인 약점이 도사리고 있다. 만일 어떤 침입자가 나의 패스워드와 패스프레이즈를 알아내고 로컬 시스템에 로그인
한다면 어떤일이 발생할까? 만일 그들이 나의 유저네임으로 로그인한다면 keychain 때문에 그들은 곧바로
암호가 해독된 비밀 키로 액세스 할 수 있다.
계속하기에 앞서 보안 위협에 대해서 미리 경고하고자 한다. 만일 악의를 가진 사용자가 본인으로 가장하여 로그인을 할 수 있다면,
keychain은 실제로 그들이 나의 원격 계정에 액세스 하는 것을 허용한다. 하지만 침입자가 나의 해독된
비밀 키를 훔치는 것은 매우 힘들다. 왜냐하면 키들은 디스크상에서는 여전히 암호화 되어 있기 때문이다. 또한 나의 비밀 키로
액세스 하기 위해서는 사용자가 실제로 나 처럼 로그인 해야 한다. 그래서 ssh-agent를
도용하는 것은 단순히 암호화 되지 않은 비밀 키를 훔치는 것보다 훨씬 어려운 일이 된다. 그것은 침입자가 ~/.ssh의 내 파일에
액세스 해야 한다는 것을 의미한다. 하지만 침입자가 성공적으로 나처럼 로그인을 할 수 있다면 그들은 나의 암호가 해독된 비밀
키를 사용함으로서 추가적인 피해를 입힐 수 있다. 따라서 자주 로그인 하지 않거나 보안 위험에 대해서 적극적으로 감시하지 않는
서버상에서 keychain을 사용하게 된다면 --clear 옵션을 사용하여 추가적인
보안 레이어를 만드는 것을 고려해 보는 것도 좋은 방법이다.
--clear 옵션을 이용하면 keychain으로 하여금 여러분의 계정의 모든
새로운 로그인에 대해서, 입증되지 않는 한 모두 잠재적인 보안 침입이라고 간주하도록 한다. --clear
옵션을 이용하여 keychain을 시작할 때, 로그인 할때, 정상 작동을 수행하기 전에, ssh-agent의
캐시로부터 모든 비밀 키들을 즉시 플러시(flush)한다. 따라서 만일 칩입자라면, keychain은
여러분에게 기존에 존재하는 캐시된 키에 액세스 권한을 주기 않고 passphrase 를 묻게 될 것이다. 하지만 이것이 보안을
향상시킬 수는 있지만 약간 불편하다. 그리고 keychain 없이 ssh-agent
자체가 실행되는 것과 비슷하다. 좀 더 나은 보안을 선택할 것인지 편리함을 추구할 것인지를 선택해야 한다. 둘 다 동시에 만족시킬
수는 없다.
그럼에도 불구하고, --clear와 함께 keychain을 사용하는 것은 ssh-agent를
단독으로 사용하는 것보다 훨씬 더 낫다; keychain --clear 을 사용할 때, cron job과
스크립트에는 여전히 패스워드 없이 연결 할 수 있다는 것을 기억하라; 왜냐하면 비밀 키들이 로그아웃이 아니라 로그인
될 때 플러시 되기 때문이다. 시스템으로부터의 로그아웃은 잠재적 보안 위험을 야기하지 않기 때문에 ssh-agent의
키들을 플러싱 함으로서 keychain이 대응할 필요가 없는 것이다. 따라서, --clear
옵션은 백업 서버, 방화벽, 라우터와 같은 보안 카핑(copying) 태스크를 수행할 필요가 있는 서버에 간헐적으로 액세스 할
경우 이상적이다.
OpenSSH 키 관리 시리즈는 이것으로 마감한다. RSA와 DSA 키들을 숙지하고 편리하고 안전한 방법으로 사용하는 방법을 익히길 바란다. 아래 참고자료도 반드시 확인하라.
- developerWorks worldwide 사이트에서 이 기사에 관한 영어원문.
-
Part
1 : OpenSSH 키 관리, Part 1.
-
home of OpenSSH development:
OpenSSH 개발 홈페이지.
-
most recent
version of
keychain: keychain 최신 버전. -
latest
OpenSSH source tarballs and RPMs.
-
OpenSSH : OpenSSH FAQ.
-
PuTTY
: Windows용
ssh클라이언트. -
Authors' site : O'Reilly의
"SSH, The Secure Shell: The Definitive Guide" 관련 정보.
-
more
Linux resources : developerWorks.
-
more
Open source resources : developerWorks.
Daniel Robbins는 Gentoo Technologies, inc.의 사장/CEO이다. 또 PC용 고급 Linux인 Gentoo Linux의 창설자이자, 차세대 Linux 포트 시스템인 Portage 시스템의 창시자이다. 또한 Macmillan사에서 출판하는 Caldera OpenLinux Unleashed, SuSE Linux Unleashed, Samba Unleashed에 집필활동을 하고 있다.