- SSH(Secure Shell)는 암호화 및 인증 매커니즘을 사용하여 보안 액세스 및 파일 전송과 같은 서비스를 구현하는 네트워크 보안 프로토콜이다.
- Telnet 및 FTP와 같은 기존 원격 로그인 및 파일 전송 방법은 안전하지 않은 일반 텍스트로 데이터를 전송하며, 보안이 중요함에 따라 이러한 방법은 점점 덜 수용되고 있다.
- SSH는 네트워크 데이터를 암호화하고 인증하여 불안전한 네트워크 환경에서 안전한 네트워크 서비스를 제공한다.
- Telnet 및 기타 여러 안전하지 않은 원격 셸 프로토콜에 대한 안전한 대안 솔루션인 SSH 프로토콜은 전 세계적으로 널리 사용되며 대부분 장치들은 SSH를 지원한다.
20(FTP), 21(FTP, FTPS), 23(TELNET), 25(SMTP), 53(DNS), 80(HTTP), 123(NTP), 443(HTTPS), 3389(RDP), 5900(VNC)
SSH가 필요한 이유
- 기존 인터넷 통신에서는 데이터가 일반 텍스트로 전송된다.
- 이때, 데이터를 가로채면 완전히 노출되므로 보안 이슈가 발생하여 안전하지 않다.
- 하지만, SSH는 클라이언트-서버 모델을 사용하여 두 당사자를 인증하고 두 당사자 간의 데이터를 암호화하여 보안이 적용되지 않은 네트워크를 통해 네트워크 서비스를 안전하게 운영하기 위한 보안 전송 채널을 제공한다.
- SSH를 적용하는 가장 일반적인 시나리오는 원격 로그인 및 파일 전송인데, SSH가 등장하기 전에 Telnet은 원격 로그인 시나리오에서 널리 사용되어 네트워크 장치의 원격 관리를 용이하게 했다.
- FTP는 작동하기 쉽고 높은 전송 효율성을 제공하는 일반적인 파일 전송 프로토콜인데, Telnet과 FTP에는 모두 동일한 문제가 존재한다.
- 데이터가 일반 텍스트로 전송되므로 보안 위험이 발생하게 된다.
- Telnet 및 FTP 애플리케이션의 보안 문제를 해결하기 위해 SSH는 암호화된 데이터 전송 및 인증 강도 향상과 같은 방법을 사용하여 안전한 원격 로그인 및 파일 전송 서비스를 구현한다.
- SSH는 클라이언트-서버 모델을 사용하는데, 보안 SSH 채널을 설정하려면 두 당사자가 TCP 연결을 설정하고, 사용할 버전 번호와 알고리즘을 협상하고, 후속 대칭 암호화를 위해 동일한 세션 키를 생성해야한다.
- 사용자 인증이 완료되면 두 당사자는 데이터 교환을 위한 세션을 설정할 수 있다.
- SSH 작업 프로세스는 아래 단계로 구성된다.
1. 연결 설정(Connection establishment)
- SSH는 토신을 위해 포트를 사용하는데, SSH 연결이 설정되기 전에 SSH 서버는 지정된 포트에서 연결 요청을 수신한다.
- SSH 클라이언트가 SSH 서버의 지정된 포트로 연결 요청을 보내면 SSH 클라이언트와 SSH 서버 사이에 TCP 연결이 설정되고 이 포트를 통해 서로 통신한다.
- 기본적으로 SSH 서버는 포트 22번을 default로 사용하며, SSH를 NETCONF에 적용하는 경우 기본 포트 번호 22 혹은 830을 지정할 수 있다.
- SSH에서 사용하는 포트 번호는 장치에서 사용 가능한 다른 포트로 변경될수 있으며, 변경 후에는 현재 모든 연결이 끊어지고 SSH 서버가 새 포트를 수신하기 시작한다.
- default SSH 포트 번호로 22를 사용하며 키 보안 전송 중에 SSH 포트 번호를 변경하는 것이 좋다.
2. 버전 협상(Version Negotiation)
- SSH에는 SSH1.X(SSH2.0 이전 버전)와 SSH2.0 두 가지 버전이 있다.
- SSH1.X와 비교할때 SSH2.0은 확장된 구조를 가지며 더 많은 인증 방법과 키 교환 방법을 지원하고 서비스 기능을 향상시킨다.
- SSH 서버와 클라이언트는 아래 프로세스에 사용할 SSH 버전을 결정하기 위해 협상한다.
1. SSH 서버는 설정된 연결을 통해 지원되는 SSH 버전 정보를 SSH 클라이언트로 보낸다.
- SSH 클라이언트는 버전 정보를 받은 후 자신이 지원하는 SSH 버전을 기준으로 사용할 버전을 결정하고 해당 버전을 SSH 서버로 보낸다.
- SSH 서버는 클라이언트가 결정한 버전을 지원하는지 확인하고, 맞다면 버전 협상에 성공한 것이다.
3. 알고리즘 협상(Algorithm Negotiation)
- SSH는 세션 키 생성을 위한 키 교환 알고리즘, 데이터 암호화를 위한 대칭 암호화 알고리즘, 디지털 서명 및 인증을 위한 공개 키 알고리즘, 데이터 무결성 보호를 위한 HMAC 알고리즘 등 다양한 우형의 알고리즘을 사용한다.
- SSH 서버와 클라이언트는 각 유형의 여러 알고리즘을 지원하므로 각 유형에 사용할 알고리즘을 협상하고 결해야하는데, 프로세스는 아래와 같다.
1. SSH 서버와 클라이언트는 지원되는 알고리즘을 서로에게 보낸다.
- SSH 서버와 클라이언트는 각 유형에 사용할 알고리즘을 협상하게 되는데, 각 유형의 알고리즘을 협상하는 동안 SSH 서버와 클라이언트는 최종 알고리즘을 사용하기 위해 둘 다 지원하는 알고리즘으로 일치시키며, 각 유형에 대한 알고리즘이 성공적으로 일치하면 알고리즘 협상이 완료된다. 만약 유형에 대해 일치하는 알고리즘이 없다면 이 유형의 알고리즘 협상은 실패하게 되고 SSH 서버와 클라이언트 간의 SSH 연결은 끊어지게 된다.
4. 키 교환(Key Exchange)
- SSH 서버와 클라이언트는 키 교환 알고리즘을 사용하여 암호화된 채널을 설정하기 위한 공유 세션 키와 세션 ID를 동적으로 생성한다.
- 세션 키는 전송을 위해 후속 데이터를 암호화하는데 사용되며, 세션 ID는 인증 중에 관련 SSH 연결을 식별하는데 사용된다.
- SSH 서버와 클라이언트는 후속 대칭 암호화를 위해 동일 세션 키를 보유해야 하는데, 키 교환의 보안을 보장하기 위해 SSH는 보안 방법을 사용하여 세션 키를 생성한다.
- SSH 서버와 클라이언트는 공동으로 세션 키를 생성한다.(수학적 이론을 바탕으로 직접적인 키 전송 없이 키 교환을 구현하므로 안전하지 않은 채널을 통해 키를 전송할 필요가 없다.)
- 아래 그림 참고
5.1 사용자 인증(User Authentication)
- SSH 클라이언트는 SSH 서버에 인증 요청을 보낸 다음 SSH 클라이언트를 인증하는데, 아래 인증 모드를 지원한다.
- 비밀번호 인증(strong password authentication) : 클라이언트는 암호화된 사용자 이름과 비밀번호를 서버로 보낸다. 서버는 사용자 이름과 비밀번호를 해독하고 이를 로컬에 저장된 사용자 이름 및 비밀번호와 비교한 후 인증 성공 또는 실패 메세지를 클라이언트에 반환한다.
- 공개 키 인증(public key authentication) : 클라이언트는 사용자 이름, 공개 키, 공개 키 알고리즘을 사용하여 인증을 위해 서버와 데이터를 교환한다.
- 비밀번호 + 공개 키 인증 : 클라이언트는 비밀번호 인증과 공개키 인증을 모두 사용하여 서버의 인증을 받은 후에만 시스템에 로그인 할 수 있다.
- 비밀번호 인증과 공개 키 인증 방법 두가지는 기본 SSH 사용자 인증 방법이며, 비밀번호 인증 모드는 간단하므로 사용자는 로그인할 때마다 사용자 이름과 비밀번호만 입력하면 되고, 키 인증 방법은 널리 사용되고 있으며, 보안성이 높은 비밀번호 없이 로그인을 구현할 수 있으므로 권장된다.
5.2 비밀번호 인증(Password Authentication)
- 비밀번호 인증의 기본 원칙으로 SSH 클라이언트는 서버 공개 키를 사용하여 비밀번호를 암호화하고, SSH 서버는 개인 키를 사용하여 비밀번호를 해독하고 비밀번호 유효성을 확인한다.
- 과정은 아래와 같다.
- SSH 클라이언트가 SSH 서버에 로그인 요청을 보낸다.
- SSH 서버는 공개 키를 SSH 클라이언트로 보낸다.
- SSH 클라이언트에 비밀번호를 입력한 후, 서버 공개 키를 이용하여 비밀번호를 암호화하고, 암호화된 비밀번호를 SSH 서버로 전송한다.
- SSH 서버는 암호문을 수신하고 개인 키를 사용하여 이를 해독해 비밀번호를 얻는다. 그런 다음 SSH 서버는 비밀번호가 올바른지 확인하고 맞다면 인증에 성공한다.
- 이 인증 모드의 단점은 중간자(MITM) 공격의 위험이 있다는 것인데, 누군가 SSH 클라이언트의 로그인 요청을 가로채 SSH 서버인것처럼 가장하고 위조된 공개 키를 SSh 클라이언트에게 보내면 사용자의 로그인 비밀번호를 알아낼 수 있다.
- 따라서 SSH 서버에 처음 로그인하게 되면 SSH 클라이언트는 공개키 지문을 표시하고 로그인 확인 여부를 묻는데, 확인 후 공개 키는 저장되고 신뢰할 수 있게된다.
- 이후 다음 접속 시 SSH 클라이언트는 SSH 서버에서 보낸 공개 키가 로컬에 저장된 공개 키와 동일 한지 확인하는 작업을 거치게 된다. 이 방법은 공개키 지문을 공개한 SSH 서버와 올바른 SSH 서버에 로그인한 SSH 클라이언트에 적용 가능하다.
5.3 키 인증(Key Authentication)
- 중간자(MITM) 공격을 방지하려면 보다 안전한 키 인증을 사용할 수 있어야한다.
- 키 인증의 기본 원칙은 SSH 서버가 클라이언트 공개 키를 사용하여 임의의 콘텐츠를 암호화하고, SSH 클아이언트는 개인 키를 사용하여 콘텐츠를 해독하고 신원 확인을 위해 해독한 콘텐츠를 서버에 보낸다.
- 아래 그림은 해당 내용의 자세한 과정을 나타낸다.
- SSH 연결을 설정하기 전에 SSH 클라이언트는 자체 공개-개인 키 쌍을 생성하고 공개 키를 SSH 서버에 저장해야 한다.
- SSH 클라이언트는 SSH 서버에 로그인 요청을 보낸다.
- SSH 서버는 요청에 포함된 사용자 이름 등의 정보를 기반으로 하여 클라이언트 공개 키를 검색하고, 공개 키를 사용해 난수를 암호화한 후에 암호화된 난수를 클라이언트에게 보낸다.
- SSH 클라이언트는 수신 시 자체 개인 키를 사용하여 반환된 정보를 해독한 후 해독된 정보를 SSH 서버로 보낸다.
- SSH 서버는 SSH 클라이언트가 보낸 복호화된 정보가 올바른지 확인하게 되고, 정보가 정확하면 인증에 성공한 것이다.
6. 세션 요청(Session Request)
- 인증이 성공하면 SSH 클라이언트는 서버에 세션 요청을 보내 서버에 특정 유형의 서비스를 제공하도록 요청하는데 즉, SSH 클라이언트는 서버와의 세션 설정을 요청하고 서버는 클라이언트의 요청에 응답한다.
7. 세션 상호작용(Session Interaction)
- 세션이 설정된 후 SSH 서버와 클라이언트는 세션을 통해 데이터를 교환한다. SSH 서버와 클라이언트가 보낸 데이터는 세션 키를 사용하여 암호화되고 해독된다.
- /etc/hosts 설정
$ cat /etc/hosts 192.168.100.200 yangmaster1 192.168.100.201 yangworker1 192.168.100.202 yangworker2 or $ sudo bash -c 'cat >> /etc/hosts << EOF 192.168.100.200 yangmaster1 192.168.100.201 yangworker1 192.168.100.202 yangworker2 EOF'
- /etc/ssh/sshd_config 설정 및 확인
$ vi /etc/ssh/sshd_config
# Port 22 -> ssh 기본 접속 port는 22번 이며, 임의의 port를 지정하여 사용하고 싶다면, port 번호를 변경 후 주석을 해제시킨다. # ListenAddress 0.0.0.0 -> 기본 default 값은 주석으로 처리되어 정책이 동작하지 않지만 주석을 해제하고 특정 ip를 지정하게 되면 해당 ip에서만 접속이 허용된다. HostKey /etc/ssh/ssh_host_rsa_key #HostKey /etc/ssh/ssh_host_dsa_key HostKey /etc/ssh/ssh_host_ecdsa_key HostKey /etc/ssh/ssh_host_ed25519_key -> ssh 접속을 할 경우 필요한 암호화 키가 저장되는 default 경로로 ECDSA_KEY 암호화 방식을 사용한다. #PermitRootLogin no -> root 계정으로 원격 접속 시 허용 여부를 정의한다. 허용하고 싶다면 주석을 해제하고 no에서 yes로 변경하면 root로 접속이 허용되지만, 보안상 이슈가 발생할 수 있어 권장하지 않는다.
- sshd.service 재 시작하기
# /etc/ssh/sshd_config의 값을 변경 했다면 재시작하여 변경 내용을 적용해주자 $ systemctl restart sshd
방화벽 설정하기
- 방화벽(firewalld)와 iptables를 운영 중이라면 ssh default port인 22번 port를 허용해주자
# CentOS 7 버전 이상에서 사용 $ firewall-cmd --zone=public --add-port=22/tcp --permanent or $ firewall-cmd --permanent --zone=public --add-port=22/tcp # 방화벽 재시작 $ firewall-cmd --reload # iptables 설정 $ iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT # ssh port 확인하기(현재 네트워크가 어떻게 열려있고 통신하고 있는지 확인 가능) $ sudo netstat -antp
1. SSH key 생성(ssh-keygen)
- ssh key 생성하기
# 키 쌍 만들기 $ ssh-keygen or $ ssh-keygen -t rsa or $ ssh-keygen -t rsa -m pem Generating public/private rsa key pair. Enter file in which to save the key (/home/jsmith/.ssh/id_rsa):[Enter key] Enter passphrase (empty for no passphrase): [Press enter key] Enter same passphrase again: [Pess enter key] Your identification has been saved in /home/jsmith/.ssh/id_rsa. Your public key has been saved in /home/jsmith/.ssh/id_rsa.pub. The key fingerprint is: 33:b3:fe:af:95:95:18:11:31:d5:de:96:2f:f2:35:f9 yang@yangmaster
- 위 명령어를 실행하게 되면 ~/.ssh/ 경로에 public key(id_rsa.pub)와 Private key(id_rsa) 키가 생성된다.
- 키를 생성 했다면 public key(id_rsa.pub)를 remote server들에게 scp 명령어을 통해 전달하면 접속할 수 있다.
2.1 Password를 통한 접속
# ssh [user name]@[Server Name or Server IP] $ ssh yang@master yang@master`s password : 입력 $ ssh yang@192.168.100.200 yang@192.168.100.200`s password : 입력
2.2 SSH key를 통한 접속
- remote server의 authorized_keys 파일에, 생성한 자신의 공개키를 등록해야 하기 때문에 scp 명령을 통해 키를 전송해야 한다.
# 퍼블릭 키를 authorized_key로 copy $ cp id_rsa.pub authorized_keys # scp 명령어로 yangserver1과 yangserver2에 public key(authorized_keys) 전송하기 # 해당 방법 사용시 password를 입력해야 전송한다. $ scp ~/.ssh/* yang@yangserver1 $ scp ~/.ssh/* yang@yangserver1 # yangserver1과 yangserver2에 public key(authorized_keys)를 복사하기 $ cat ~/.ssh/id_rsa.pub ssh-rsa dasdsadadawdadawdsadwasdadw 생략 # 출력된 키 값을 복사하여 remote server에 접속하여 ~/.ssh/authorized_keys에 붙여넣기 $ cat <<EOF > ~/.ssh/authorized_keys ssh-rsa dasdsadadawdadawdsadwasdadw EOF # ssh key를 통해 접속하기 $ ssh yang@yangserver1 $ ssh yang@yangserver2 # ssh key 경로가 다른 경우 $ ssh -i KEY_PATH/id_rsa.pem yang@yangserver1 $ ssh -i KEY_PATH/id_rsa yang@yangserver2 # 정상 접속이 안된다면 -v | -vv | -vvv 옵션 중 하나를 맨뒤에 붙여 자세한 내용을 확인하자
2.3 ssh-keygen 및 ssh-copy-id를 사용하여 비밀번호 없이 SSH 로그인을 수행
- ssh-keygen은 공개 키와 개인 키를 생성한다.
- ssh-copy-id는 로컬 호스트의 공개 키를 원격 호스트의 Authorized_keys 파일에 복사하며, remote host의 ~/.ssh/authorized_keys에 적절한 권한을 할당한다.
- 먼저 1번 내용을 통해 ssh-keygen하여 키 쌍을 생성한다.
$ ssh-keygen
- ssh-copy-id를 사용하여 공개 키를 remote host에 복사한다.
# ssh-copy-id -i ~/.ssh/id_rsa.pub [hostname or IP of remote host] $ ssh-copy-id -i ~/.ssh/id_rsa.pub yangworker1 yang@yangworker1's password: [yangworker1의 password 입력] Now try logging into the machine, with "ssh 'yangworker1'", and check in: .ssh/authorized_keys to make sure we haven't added extra keys that you weren't expecting. $ ssh-copy-id -i ~/.ssh/id_rsa.pub yangworker2 yang@yangworker2's password: [yangworker2의 password 입력] Now try logging into the machine, with "ssh 'yangworker2'", and check in: .ssh/authorized_keys to make sure we haven't added extra keys that you weren't expecting. # 해당 작업을 완료하게 되면 비밀번호를 입력하지 않고 remote host(yangworker1 & yangworker2)에 로그인 할 수 있다.
- password 없이 remote host에 로그인
$ ssh yang@[yangworker1 or $ ssh yang@yangworker2
Authorized_keys의 중복
- 로컬 호스트에서 ssh-copy-id를 여러 번 실행하면 중복을 확인하지 않고 원격 호스트의 Authorized_keys 파일에 동일한 키를 계속 추가하기 때문에 해당 정보가 중복되어 저장된다.
- 항목이 중복되어도 문제가 되지 않지만 불피요한 정보가 계속 저장될 수 있다.
know_hosts
- 한번 원격 접속이 이루어지고 나면 사용자 홈 디레터리 ~/.ssh/know_hosts 파일에 원격지 접속에 필요한 키 값이 생성된다.
- hostname 혹은 ip로 같은 remote host에 원격 접속할 경우 출동이 발생할 수 있다.(이 경우 둘 중 하나는 주석(#) 처리)
- sftp & scp 프로토콜을 통해 SSH를 파일 전송에 사용할 수 있다.
- OS에서 SSH를 사용하도록 설정한 경우 sftp & scp로도 연결할 수 있다.
sftp(secure ftp)
usage: sftp [-46aCfpqrv] [-B buffer_size] [-b batchfile] [-c cipher] [-D sftp_server_path] [-F ssh_config] [-i identity_file] [-l limit] [-o ssh_option] [-P port] [-R num_requests] [-S program] [-s subsystem | sftp_server] destination
scp(secure copy)
usage: scp [-346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file] [-l limit] [-o ssh_option] [-P port] [-S program] source ... target
출처
What Is SSH?
3 Steps to Perform SSH Login Without Password Using ssh-keygen & ssh-copy-id
원격 호스트 인증을 위한 SSH 키 생성 및 사용
리눅스 ssh 명령어 사용법