[첫화면으로]SSH

마지막으로 [b]

Secure SHell

Telnet 대신에 SSH를, FTP 대신에 SFTP 를 사용하는 습관을!!!

Tip: 암호를 입력하지 않고 로그인하기

SSH 서버는 유닉스 환경일 때. (윈도우즈일 경우는 모름. 뭐 툴이 있겠지) 서버 계정의 암호를 매번 입력하는 게 귀찮으면 다음과 같이 할 수 있다. 서버와 클라이언트 사이에 호스트 공개키를 교환해서 인증하는 방법이다. 터미널 로그인이야 그렇다치고, CVS 등을 사용할 때 ssh 를 이용하여 update, commit 등을 하는 경우 매번 암호를 넣어야 하는데 아래의 방법을 쓰면 그럴 필요가 없으니 훨씬 편해진다.

Unix 클라이언트

상황

클라이언트와 서버의 기본 설정

먼저, 클라이언트의 호스트 키 쌍을 생성한다.
$ ssh-keygen -t rsa1
Generating public/private rsa1 key pair.
Enter file in which to save the key (/home/raymundo/.ssh/identity):   <-- 그냥 엔터
Created directory '/home/raymundo/.ssh'.
Enter passphrase (empty for no passphrase):                           <-- 그냥 엔터
Enter same passphrase again:                                          <-- 그냥 엔터
Your identification has been saved in /home/raymundo/.ssh/identity.
Your public key has been saved in /home/raymundo/.ssh/identity.pub.
The key fingerprint is:
9c:e1:c8:65:46:f3:17:08:8d:6c:cb:ba:3e:1d:ca:cd raymundo@raymundus
위와 같이 하면, ~raymundo/.ssh/ 아래에 비밀키 화일 identity 와 공개키 화일 identity.pub 가 생긴다. 공개키는 다음과 같은 식으로 되어 있다.
1024 35 128...527 raymundo@raymundus
위에서 마지막 필드 raymundo@raymundus 는 단지 키를 알아보기 쉬우라고 붙인 코멘트이다. 자기 좋을 대로 고쳐주면 된다.

이제 위에서 생성한 클라이언트의 공개키를 서버 쪽에 보관해야 한다. 서버의 ~gypark/.ssh/authrized_keys 화일(없으면 새로 만들어 준다)에 저 공개키의 내용을 append 하면 된다. 이때 키의 내용이 길어서 자동으로 줄바꿈이 되지 않도록 주의한다. 즉 한 키는 한 줄에 적어야 한다.

다시 클라이언트 쪽에서, "이 서버에 접속할 때는 SSH Protocol version 1 을 사용하라"고 알려줘야 한다. 클라이언트의 ~raymundo/.ssh/config 화일에 다음과 같이 적어준다.
Host gypark.pe.kr
    Protocol 1,2     <-- 1과 2중에 하나만 적으면 그 방식만 사용하라는 뜻이고, 1,2 로 적으면 버전1을 먼저 시도하고 안 되면 2를 하라는 뜻이다

이제는 평소처럼 ssh 로 접속하면 된다. 암호를 넣는 과정을 건너뛰고 로그인이 될 것이다.

서버 쪽에서의 SSH1 설정

만일 다음과 같은 에러가 난다면
$ ssh *******@******.pe.kr
Protocol major versions differ: 1 vs. 2
이것은 서버 쪽에서 SSH Protocol Version 1 을 지원하지 않는 경우이다. 이 경우는 서버의 설정을 바꿔주어야 한다.

서버의 /etc/ssh/sshd_config 화일을 수정한다.
...
Protocol 2,1           <-- "2" 를 "2,1"로 변경
...
HostKey /etc/ssh/ssh_host_key    <-- 이 줄이 없다면 추가
...

/etc/ssh/ssh_host_key 화일이 존재하는지 확인하고, 없다면 클라이언트에서와 마찬가지로 서버의 호스트 키를 생성한다.
# ssh-keygen -t rsa1 -f /etc/ssh/ssh_host_key

이제 sshd 를 재시작한다.
# /etc/init.d/ssh restart
Restarting OpenBSD Secure Shell server: sshd.

passphrase 를 사용

위의 설정으로는 로그인 과정이 매우 간편하기는 한데, 서버가 해킹당하던가 하여 비밀키를 타인이 획득하게 되면 서버까지 줄줄이 뚤리게 될 것이다. 따라서 공개키에 passphrase 를 지정할 수 있다. 처음에 ssh-keygen 을 실행할 때 passphrase 를 입력하거나, 이미 생성한 비밀키에 대해서는 ssh-keygen 에 -p 옵션을 써서 passphrase 를 수정해 줄 수 있다.

그런데, 이렇게 하면 이번에는 매번 로그인할 때마다 저 passphrase 를 넣어야 한다. 이것은 암호를 넣는 것만큼 불편하다. 따라서 별도의 agent 프로그램을 사용한다.

key agent 를 사용

개념은, agent 프로그램을 띄우고, 내 비밀키를 등록해 두면 (이 때 passphrase 를 한 번 입력) 그 다음부터는 내 비밀키에 관련된 연산은 이 agent 가 도맡아 하고, SSH 클라이언트는 이 agent 를 사용해 인증 절차를 거친다는 것이다. 따라서 passphrase 를 처음 한 번만 입력하면 그 다음부터는 입력할 필요가 없다.

다음과 같이 agent 를 띄운다
$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-XX7LNH7N/agent.20929; export SSH_AUTH_SOCK;     <-- 이 줄과
SSH_AGENT_PID=20930; export SSH_AGENT_PID;                             <-- 이 줄을 복사해서
echo Agent pid 20930;
$ SSH_AUTH_SOCK=/tmp/ssh-XX7LNH7N/agent.20929; export SSH_AUTH_SOCK;   <-- 쉘에서 실행한다
$ SSH_AGENT_PID=20930; export SSH_AGENT_PID;

복사해서 실행하는 게 귀찮으니 다음과 같이 하면 편하다
$ eval `ssh-agent`     <-- 자동으로 환경변수 세팅까지 된다
Agent pid 20930
$

이제 ssh-agent 는 계속 물밑에서 수행된다. 종료시키고 싶다면 다음과 같이 한다.
$ ssh-agent -k
unset SSH_AUTH_SOCK;          <-- 마찬가지로 두 줄을 복사해서
unset SSH_AGENT_PID;
echo Agent pid 20930 killed;
$ unset SSH_AUTH_SOCK;        <-- 쉘에서 실행한다.
$ unset SSH_AGENT_PID;

마찬가지로 다음과 같이 간편하게 할 수 있다.
$ eval `ssh-agent -k`

일단 agent 가 실행이 되면 다음과 같이 자신의 비밀키를 등록한다.
$ ssh-add
Enter passphrase for raymundo@raymundus:    <-- passphrase 를 입력
Identity added: /home/raymundo/.ssh/identity (raymundo@raymundus)

이제는 저 agent 를 종료하기 전까지는 별도의 암호 입력이 필요없이 ssh 를 사용할 수 있다.

ssh-agent 를 띄우고 비밀키를 추가하는 것은 각 클라이언트 세션마다 한번씩 해 줘야 한다. 여전히 조금은 불편하다. 그래서 다음과 같은 스크립트를 만든다. (KLDP BBS 의 dk 님께 감사)

do_ssh_agent="t"

if [ -f "$ssh_agent_info" ]; then
    . "$ssh_agent_info"
    if agent_list=`pgrep -u "$USER" ssh-agent`; then
        for agent in $agent_list; do
            if [ "$agent" -eq "$SSH_AGENT_PID" ]; then
                do_ssh_agent="nil"
                break
            fi
        done
    fi
fi

if [ "$do_ssh_agent" == "t" ]; then
    eval `ssh-agent | grep -v echo | tee "$ssh_agent_info"`
fi

위 스크립트를 ~/.bash_profile 안에 직접 적던가, 별도의 화일에 저장한후 ~/.bash_profile 에는
. 스크립트이름
으로 적어준다. 이러면 한 번 ssh-agent 를 실행할 때 환경변수 정보를 화일에 보관해 두었다가, 다른 쉘이 뜰 때 그 화일을 읽어서 환경변수를 세팅한다. 즉 처음 한 번만 ssh-add 를 해 주면 이후에 다른 세션에서도 사용할 수 있다.

Windows 클라이언트

PuTTY 의 경우

만일 passphrase 를 지정할 경우는

TortoiseCVS 의 경우

TortoiseCVS 는, ssh 프로토콜을 사용할 경우 내부적으로는 putty 를 사용한다. 따라서 위의 PuTTY 의 설정을 했다면 별도로 해 줄 것이 없다. :-)

클라이언트를 백그라운드로 실행하기

터널링 등의 이유로 ssh 접속을 하는 거라서 굳이 셸이 뜰 필요는 없을 때:

그냥 ssh -N... &로 백그라운드로 보내고 fg로 올려서 중단할 수도 있지만...

$ ssh -f -N -M -S /tmp/file-sock -L 10000:127.0.0.1:10000 HOST
$ ssh \
 -f \    # 백그라운드로 보냄
 -N \    # 원격 명령을 실행하지 않음(-f 없이 이것만 하면 로그인 후 그 상태에서 진행없이 busy상태로 있게 됨)
 -M \    # 연결 공유용 마스터로 동작
 -S /tmp/file-sock \ # 연결 공유용 소켓
 -L 10000:127.0.0.1:10000 \ # 포워드할 포트
 HOST

이 연결을 종료할 때는:

 $ ssh -S /tmp/file-sock -O exit HOST

-M, -S는 .ssh/config 파일에 적어줄 수도 있음. 접속은 ssh -f -N c1.host1 등으로.

$ cat ~/.ssh/config
Host c1.host1
    hostname IP주소
    port 포트
    # 만약에 이 IP에도 직접 접근할 수 없어서 중간에 다른 서버를 경유해야 한다면
    # (ProxyJump 옵션을 쓰거나, ProxyJump가 없는 구버전이라면 아래와 같이)
    ProxyCommand ssh 경유서버 -W %h:%p
    user 유저네임
    # 포워딩할 포트
    LocalForward 127.0.0.1:19100 10.0.0.1:9100
    # -M
    ControlMaster yes
    # -S 소켓파일명
    ControlPath 소켓파일명

호스트 키 확인 절차 스킵

도커 컨테이너 안에서 다른 컨테이너나 호스트로 ssh 접속을 시키려고 하는데, 암호를 입력하는 거야 키 파일을 쓰도록 하면 되지만 첫 접속 때 호스트 키를 known host에 추가하겠냐고 묻는 과정이 있어서 자동화가 안 된다.

# ~/.ssh/config
Host *
    StrictHostKeyChecking no

# 커맨드 라인 옵션
ssh -o StrictHostKeyChecking=no HOST

윈도우 SSH 서버

윈도우2016 서버에 ssh 서버 구성

1. 설치

2. 퍼블릭 키 로그인 사용

이게 은근히 까다롭다.

# 아래 단락은 주석처리
#Match Group administrators
#      AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys

# 주석해제...하라고 되어 있긴 한데,
# PubkeyAuthentication 는 기본값이 yes라서 굳이 해제하지 않아도 되고
PubkeyAuthentication yes
# PasswordAuthentication 를 no로 하면 키 방식 로그인만 되고 비밀번호 입력을 아예 못 하게 되니 주의
PasswordAuthentication no

원래는 여기까지만 해도 잘 되었었는데, 어느날 갑자기 키 로그인이 안 되고 비밀번호 입력을 요구하게 됨.

내 경우는 관리자 권한이 있는 다른 계정 이름이 목록에 있어서 제거하니 그때부터 되긴 했는데, 그 전에는 왜 동작했었는지는 의문

다른 서버를 경유하여 접속

방화벽 등의 문제로 B 서버에 직접 ssh 접속을 할 수가 없고, A서버를 경유하여 접속하려고 할 때

ssh -J a@A b@B

그런데 ssh 버전이 낮으면 -J 파라메터(그리고 여기에 해당하는 ProxyJump옵션)가 지원되지 않는다.

이런 경우는 ProxyCommand 옵션을 이용:

ssh -o 'ProxyCommand=ssh a@A -W %h:%p' b@B

# 또는 .ssh/config 파일에 적을 경우
Host B
   Hostname B
   User b
   ProxyCommand ssh a@A -W %h:%p


관련 링크:


컴퓨터분류

마지막 편집일: 2023-5-12 10:45 am (변경사항 [d])
7158 hits | Permalink | 변경내역 보기 [h] | 페이지 소스 보기