-2,10 +2,304 |
|
Telnet 대신에 [[SSH]]를, FTP 대신에 [[SFTP]] 를 사용하는 습관을!!! |
|
== Tip: 암호를 입력하지 않고 로그인하기 == |
SSH 서버는 유닉스 환경일 때. (윈도우즈일 경우는 모름. 뭐 툴이 있겠지) 서버 계정의 암호를 매번 입력하는 게 귀찮으면 다음과 같이 할 수 있다. 서버와 클라이언트 사이에 호스트 공개키를 교환해서 인증하는 방법이다. 터미널 로그인이야 그렇다치고, [[CVS]] 등을 사용할 때 ssh 를 이용하여 update, commit 등을 하는 경우 매번 암호를 넣어야 하는데 아래의 방법을 쓰면 그럴 필요가 없으니 훨씬 편해진다. |
|
=== Unix 클라이언트 === |
'''상황''' |
|
* 서버 - 리눅스, 도메인:gypark.pe.kr, 계정:gypark, OpenSSH |
* 클라이언트 - 리눅스, 호스트네임:raymundus, 계정:raymundo, OpenSSH |
|
'''클라이언트와 서버의 기본 설정''' |
|
먼저, 클라이언트의 호스트 키 쌍을 생성한다. |
{{{ |
$ 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 님께 감사) |
|
{{{bash |
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 의 경우''' |
* PuTTY 패키지 안에 (또는 PuTTY 홈페이지에서 따로 받을 수도 있다) 있는 puttygen.exe 로 호스트 키 쌍을 생성할 수 있다. |
* 호스트 키가 생성되면 서버 쪽에서는 위에서와 동일하게 해 주면 된다. |
* PuTTY 의 세션설정에서 자신의 비밀키를 등록을 해 준다. |
|
만일 passphrase 를 지정할 경우는 |
* pageant.exe 가 위의 ssh-agent 와 동일한 기능을 한다. |
* 이 때는 각 세션 설정에서 비밀키를 일일이 등록할 필요가 없다. 따라서 passphrase 를 지정하지 않더라도 agent 를 띄우는 게 편하다. |
|
'''TortoiseCVS 의 경우''' |
|
TortoiseCVS 는, ssh 프로토콜을 사용할 경우 내부적으로는 putty 를 사용한다. 따라서 위의 PuTTY 의 설정을 했다면 별도로 해 줄 것이 없다. :-) |
|
|
=== 클라이언트를 백그라운드로 실행하기 === |
|
* [https://unix.stackexchange.com/a/156813 ssh tunneling - SSH: tunnel without shell on ssh server - Unix & Linux Stack Exchange] |
|
터널링 등의 이유로 ssh 접속을 하는 거라서 굳이 셸이 뜰 필요는 없을 때: |
|
그냥 <code>ssh -N... &</code>로 백그라운드로 보내고 <code>fg</code>로 올려서 중단할 수도 있지만... |
|
{{{#!vim |
$ 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 |
}}} |
|
이 연결을 종료할 때는: |
|
{{{#!vim |
$ ssh -S /tmp/file-sock -O exit HOST |
}}} |
|
-M, -S는 .ssh/config 파일에 적어줄 수도 있음. 접속은 <code>ssh -f -N c1.host1</code> 등으로. |
|
{{{#!vim |
$ 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에 추가하겠냐고 묻는 과정이 있어서 자동화가 안 된다. |
|
* https://askubuntu.com/questions/87449/how-to-disable-strict-host-key-checking-in-ssh |
|
{{{#!vim |
# ~/.ssh/config |
Host * |
StrictHostKeyChecking no |
|
# 커맨드 라인 옵션 |
ssh -o StrictHostKeyChecking=no HOST |
}}} |
|
=== 윈도우 SSH 서버 === |
|
윈도우2016 서버에 ssh 서버 구성 |
|
1. 설치 |
|
* https://hostadvice.com/how-to/how-to-install-an-openssh-server-client-on-a-windows-2016-server/ |
** https://github.com/PowerShell/Win32-OpenSSH/releases 여기에서 zip 파일 다운로드 |
** <code>C:\Program Files\</code> 아래에 압축 해제 |
** 시스템 환경 변수 Path 에 <code>C:\Program Files\OpenSSH-Win64</code> 추가 |
** Powershell 을 관리자 모드로 실행, 위 경로에서 <code>.\install-sshd.ps1</code> 실행하여 서비스 등록 |
** <code>.\ssh-keygen.exe -A</code> 실행하여 호스트 키 생성 |
** '서비스' 관리 화면에서 OpenSSH SSH Server 와 OpenSSH Authentication Agent 실행 여부 및 자동 시작 여부 확인 |
** 방화벽에서 22번 포트 오픈 |
|
2. 퍼블릭 키 로그인 사용 |
|
이게 은근히 까다롭다. |
|
* https://github.com/PowerShell/Win32-OpenSSH/issues/1306#issuecomment-589995528 |
** <code>C:\ProgramData\ssh\sshd_config</code> 수정 |
{{{ |
# 아래 단락은 주석처리 |
#Match Group administrators |
# AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys |
|
# 주석해제...하라고 되어 있긴 한데, |
# PubkeyAuthentication 는 기본값이 yes라서 굳이 해제하지 않아도 되고 |
PubkeyAuthentication yes |
# PasswordAuthentication 를 no로 하면 키 방식 로그인만 되고 비밀번호 입력을 아예 못 하게 되니 주의 |
PasswordAuthentication no |
}}} |
** <code>C:\Users\<자기계정>\.ssh\authorized_keys</code> 파일에 공개키 내용 저장 |
*** 개행 문자가 반드시 \r\n 형태여야 되느니 하는 말도 있던데 큰 상관 없는 듯 |
|
원래는 여기까지만 해도 잘 되었었는데, 어느날 갑자기 키 로그인이 안 되고 비밀번호 입력을 요구하게 됨. |
|
** 위 링크 내용대로, .ssh 폴더와 authorized_keys 파일에 대해 다음과 같이 보안 속성 설정 |
*** 우클릭 - 등록 정보 - 보안 - 고급 - 상속 사용 안 함 클릭 - "상속된 사용 권한을 이 개체에 대한 명시적 사용 권한으로 변환합니다" 선택 - SYSTEM, ADMINISTRATOR, 자기계정 세 가지만 놔두고 제거 |
|
내 경우는 관리자 권한이 있는 다른 계정 이름이 목록에 있어서 제거하니 그때부터 되긴 했는데, 그 전에는 왜 동작했었는지는 의문 |
|
|
== 다른 서버를 경유하여 접속 == |
|
방화벽 등의 문제로 B 서버에 직접 ssh 접속을 할 수가 없고, A서버를 경유하여 접속하려고 할 때 |
|
* https://wiki.gentoo.org/wiki/SSH_jump_host |
|
{{{#!vim |
ssh -J a@A b@B |
}}} |
|
그런데 ssh 버전이 낮으면 <code>-J</code> 파라메터(그리고 여기에 해당하는 <code>ProxyJump</code>옵션)가 지원되지 않는다. |
|
이런 경우는 <code>ProxyCommand</code> 옵션을 이용: |
|
{{{#!vim |
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 |
}}} |
|
* 비밀번호는 두 번 물어본다, A에 접속하기 위해서, B에 접속하기 위해서 |
* A의 <code>authorized_keys</code>에 출발지의 공개키가 등록되어 있으면 A에 접속할 때는 공개키 로그인으로 진행 |
* B에서도 공개키 로그인을 하려면 B의 <code>authorized_keys</code>에도 **출발지의 공개키**가 등록되어 있어야 한다. A의 공개키는 소용 없음 |
|
|
|
|
|
---- |
관련 링크: |
* http://www.ssh.com 상용 SSH 홈페이지 |
* PuTTY - [[SSH]] 클라이언트, 공개프로그램 |
* [[ZTerm]] - [[SSH]] 클라이언트, 공개프로그램 |
|
---- |
[[컴퓨터분류]] |