# OpenSSH의 구성 요소

#### SSH 클라이언트 (ssh)

SSH 클라이언트는 사용자가 원격 서버에 접속하기 위해 사용하는 프로그램이다. 이 프로그램은 사용자가 명령을 입력하면 원격 서버로 전송하고, 서버로부터의 응답을 다시 사용자가 볼 수 있도록 표시해 준다. SSH 클라이언트는 다양한 옵션을 제공하여 사용자 인증, 포트 포워딩, 프록시 사용 등 다양한 기능을 수행할 수 있다. 주요 기능 중 일부는 다음과 같다:

* **비밀번호 기반 인증**: 사용자가 원격 서버에 접속할 때 비밀번호를 사용하여 인증할 수 있다.
* **공개키 기반 인증**: 공개키를 사용하여 비밀번호 없이 원격 서버에 접속할 수 있다. 이는 보안성을 높이는 데 중요한 역할을 한다.
* **포트 포워딩**: 원격 서버의 포트를 로컬에서 사용할 수 있게 하거나, 반대로 로컬 포트를 원격 서버에서 사용할 수 있게 설정할 수 있다.
* **X11 포워딩**: 원격 서버의 X 윈도우 시스템을 로컬에서 실행 중인 것처럼 사용할 수 있다.

#### SSH 데몬 (sshd)

SSH 데몬은 SSH 서버 측에서 실행되는 프로그램으로, 클라이언트의 요청을 처리하고, 클라이언트와 서버 간의 안전한 통신을 보장한다. `sshd`는 서버에서 사용자의 접속 요청을 수신하고, 인증 과정을 거쳐 해당 사용자가 서버에 접속할 수 있도록 허용한다. 주요 역할은 다음과 같다:

* **포트 리스닝**: 기본적으로 포트 22번에서 클라이언트로부터의 접속을 기다리며, 설정에 따라 다른 포트로 변경할 수도 있다.
* **사용자 인증**: 클라이언트가 제공한 인증 정보 (비밀번호, 공개키 등)를 확인하여 사용자의 접속을 허용하거나 거부한다.
* **암호화 통신 설정**: 클라이언트와 서버 간에 안전한 암호화된 통신 채널을 설정하여 데이터가 안전하게 전송되도록 한다.

#### SSH 키 관리 도구 (ssh-keygen)

`ssh-keygen`은 공개키 기반 인증을 위한 키 쌍을 생성하는 도구이다. 이 도구를 사용하면 클라이언트 측에서 개인키와 공개키를 생성하고, 공개키를 서버에 배포함으로써 비밀번호 없이도 안전하게 서버에 접속할 수 있다. `ssh-keygen`의 주요 기능은 다음과 같다:

* **RSA, DSA, ECDSA, ED25519 키 생성**: 다양한 알고리즘을 선택하여 키를 생성할 수 있다. 기본적으로 RSA가 사용되며, ED25519는 최신 알고리즘 중 하나로 보안성과 성능에서 유리하다.
* **키 파일 형식**: 키는 일반적으로 `id_rsa`(개인키)와 `id_rsa.pub`(공개키) 형식으로 저장되며, 이 파일들은 매우 중요하다.
* **패스프레이즈 설정**: 생성된 키에 패스프레이즈를 설정하여, 개인키가 도난 당하더라도 패스프레이즈 없이는 사용할 수 없도록 보호할 수 있다.

#### SSH 에이전트 (ssh-agent)

`ssh-agent`는 공개키 기반 인증을 사용하는 경우, 사용자가 매번 개인키의 패스프레이즈를 입력하지 않도록 해주는 프로그램이다. 이 에이전트는 사용자의 개인키를 메모리에 저장해 두고, SSH 클라이언트가 서버에 접속할 때 자동으로 이 개인키를 사용하도록 돕는다.

* **에이전트 실행**: 사용자는 SSH 에이전트를 실행한 후 키를 추가하는데, 이 과정에서 패스프레이즈를 한 번만 입력하면 이후 접속할 때는 패스프레이즈를 입력할 필요가 없다.
* **에이전트 포워딩**: SSH 에이전트를 원격 서버에서도 사용할 수 있도록 포워딩 기능을 지원한다. 이를 통해 중간 서버를 거쳐 최종 서버에 접속할 때도 개인키를 로컬 에이전트를 통해 사용할 수 있다.

#### SSH 설정 파일 (ssh\_config, sshd\_config)

OpenSSH의 동작은 클라이언트와 서버 각각에서 설정 파일을 통해 제어할 수 있다. 클라이언트의 설정 파일은 `ssh_config`이며, 서버의 설정 파일은 `sshd_config`이다. 이 파일들은 각 환경에서 SSH의 동작 방식을 결정하며, 다양한 옵션을 통해 커스터마이징할 수 있다.

**클라이언트 설정 파일 (ssh\_config)**

`ssh_config`는 클라이언트 측에서 SSH의 동작을 제어하는 파일이다. 주로 사용되는 옵션은 다음과 같다:

* **Host**: 특정 호스트에 대해 별도의 설정을 정의할 수 있다. 예를 들어, 특정 서버에 접속할 때만 사용할 사용자 이름이나 포트를 지정할 수 있다.

  ```bash
  Host myserver
    HostName myserver.com
    User myuser
    Port 2222
  ```
* **IdentityFile**: 접속 시 사용할 개인키 파일을 지정할 수 있다.

  ```bash
  IdentityFile ~/.ssh/id_rsa
  ```
* **ForwardAgent**: 에이전트 포워딩을 허용할지 여부를 설정한다.

  ```bash
  ForwardAgent yes
  ```
* **ProxyJump**: 중간 서버(점프 호스트)를 거쳐 최종 서버에 접속하는 경우, 이를 설정할 수 있다.

  ```bash
  ProxyJump jumpserver
  ```

**서버 설정 파일 (sshd\_config)**

`sshd_config`는 서버 측에서 SSH 데몬의 동작을 제어하는 파일로, 보안, 인증 방법, 네트워크 설정 등을 포함한다. 주요 옵션은 다음과 같다:

* **Port**: SSH 데몬이 수신할 포트를 설정한다. 기본값은 22이지만 보안상의 이유로 다른 포트로 변경하는 것이 권장된다.

  ```bash
  Port 2222
  ```
* **PermitRootLogin**: 루트 계정으로의 직접 접속을 허용할지 여부를 설정한다. 보안상 일반적으로는 `no`로 설정하여 루트 계정으로 직접 접속하지 못하게 하는 것이 좋다.

  ```bash
  PermitRootLogin no
  ```
* **PasswordAuthentication**: 비밀번호 기반 인증을 사용할지 여부를 설정한다. 공개키 인증만을 사용하고 비밀번호 인증을 비활성화하는 것이 보안성을 높이는 데 도움을 준다.

  ```bash
  PasswordAuthentication no
  ```
* **AllowUsers, DenyUsers**: 특정 사용자만 SSH 접속을 허용하거나 거부할 수 있다.

  ```bash
  AllowUsers myuser
  ```

#### SCP (Secure Copy Protocol)

SCP는 SSH 프로토콜을 이용하여 안전하게 파일을 복사하는 프로그램이다. SCP는 데이터를 암호화하여 네트워크를 통해 전송하므로, 전송 중에 데이터가 유출되거나 변조되는 것을 방지할 수 있다. 주요 사용 방법은 다음과 같다:

* **로컬에서 원격 서버로 파일 전송**

  ```bash
  scp localfile user@remotehost:/path/to/destination
  ```
* **원격 서버에서 로컬로 파일 가져오기**

  ```bash
  scp user@remotehost:/path/to/file localfile
  ```
* **디렉토리 전송**: `-r` 옵션을 사용하여 디렉토리와 그 안의 모든 파일을 전송할 수 있다.

  ```bash
  scp -r localdir user@remotehost:/path/to/destination
  ```

#### SFTP (Secure File Transfer Protocol)

SFTP는 SSH 프로토콜을 기반으로 한 파일 전송 프로토콜로, SCP와 유사하게 데이터를 암호화하여 안전하게 파일을 전송할 수 있다. SCP와 달리 SFTP는 상호작용적인 파일 전송 인터페이스를 제공하며, 파일 업로드, 다운로드, 디렉토리 탐색, 파일 권한 변경 등 다양한 파일 관리 기능을 지원한다. 주요 기능과 사용 방법은 다음과 같다:

* **SFTP 접속**

  ```bash
  sftp user@remotehost
  ```
* **파일 다운로드**

  ```bash
  sftp> get remote_file local_file
  ```
* **파일 업로드**

  ```bash
  sftp> put local_file remote_file
  ```
* **디렉토리 전환**

  ```bash
  sftp> cd /path/to/directory
  ```
* **디렉토리 내 파일 목록 보기**

  ```bash
  sftp> ls
  ```
* **파일 권한 변경**

  ```bash
  sftp> chmod 644 remote_file
  ```

#### SSH 포트 포워딩

SSH 포트 포워딩은 로컬 시스템과 원격 시스템 간의 네트워크 트래픽을 SSH 프로토콜을 통해 안전하게 전송하는 기능이다. 이를 통해 중간 네트워크를 거치지 않고, 안전한 통신을 설정할 수 있다. SSH 포트 포워딩은 크게 **로컬 포트 포워딩**, **원격 포트 포워딩**, 그리고 **동적 포트 포워딩**으로 구분된다.

**로컬 포트 포워딩**

로컬 포트 포워딩은 로컬 시스템의 특정 포트로 들어오는 트래픽을 SSH 터널을 통해 원격 서버로 전송하는 방식이다. 이를 통해 로컬 시스템에서 외부 서버로 안전하게 접속할 수 있다.

* 예시: 로컬 시스템의 8080 포트로 들어오는 트래픽을 원격 서버의 80 포트로 전달.

  ```bash
  ssh -L 8080:remotehost:80 user@remotehost
  ```

**원격 포트 포워딩**

원격 포트 포워딩은 원격 서버의 포트로 들어오는 트래픽을 SSH 터널을 통해 로컬 시스템으로 전달하는 방식이다. 이를 통해 외부에서 로컬 네트워크에 안전하게 접근할 수 있다.

* 예시: 원격 서버의 8080 포트로 들어오는 트래픽을 로컬 시스템의 80 포트로 전달.

  ```bash
  ssh -R 8080:localhost:80 user@remotehost
  ```

**동적 포트 포워딩**

동적 포트 포워딩은 SSH 터널을 통해 다양한 목적지로의 트래픽을 전달하는 방식이다. SOCKS 프록시처럼 작동하여, 여러 서버로의 트래픽을 프록시 서버를 통해 전달할 수 있다.

* 예시: 로컬 시스템의 1080 포트에서 SOCKS 프록시를 설정하여 다양한 서버에 접속.

  ```bash
  ssh -D 1080 user@remotehost
  ```

#### 프록시 점프 (ProxyJump)

프록시 점프는 SSH 클라이언트가 중간 서버(점프 호스트)를 거쳐 최종 목적지 서버에 접속하는 방식이다. 중간 서버를 경유하여 직접 접근이 불가능한 네트워크 환경에서도 안전하게 접속할 수 있다.

* **단일 점프 호스트**

  ```bash
  ssh -J jumpuser@jumphost targetuser@targethost
  ```
* **여러 점프 호스트** 중간에 여러 점프 호스트가 있을 경우, `-J` 옵션을 여러 번 사용하여 설정할 수 있다.

  ```bash
  ssh -J jumpuser@jumphost1 -J jumpuser@jumphost2 targetuser@targethost
  ```

#### X11 포워딩

X11 포워딩은 원격 서버에서 실행 중인 GUI 응용 프로그램을 로컬 시스템에서 마치 로컬에서 실행하는 것처럼 사용할 수 있도록 해주는 기능이다. 이 기능은 SSH 터널을 통해 X11 디스플레이 프로토콜을 안전하게 전달한다. 이를 사용하면 원격 서버에서 실행되는 그래픽 응용 프로그램을 로컬에서 볼 수 있으며, 네트워크 상에서 데이터가 암호화되어 전달된다.

* **X11 포워딩 활성화** SSH 클라이언트를 통해 X11 포워딩을 사용하려면 `-X` 또는 `-Y` 옵션을 사용하여 SSH 연결 시 X11 포워딩을 활성화할 수 있다. `-Y` 옵션은 신뢰할 수 있는 X11 포워딩을 사용하며, `-X`는 기본 X11 포워딩을 사용한다.

  ```bash
  ssh -X user@remotehost
  ```
* **원격 서버 설정** 원격 서버에서 X11 포워딩을 허용하려면 서버의 `sshd_config` 파일에서 다음 설정을 확인하고, 필요 시 수정해야 한다.

  ```bash
  X11Forwarding yes
  ```
* **DISPLAY 환경 변수** 원격 서버에서 X11 응용 프로그램을 실행하기 위해서는 `DISPLAY` 환경 변수가 적절히 설정되어 있어야 한다. 일반적으로 SSH 클라이언트가 자동으로 이 변수를 설정하지만, 필요 시 수동으로 확인할 수 있다.

  ```bash
  echo $DISPLAY
  ```

#### SSH 다중 세션 및 다중 명령 실행

SSH는 한 번의 연결로 여러 세션을 생성하거나, 여러 명령을 연속적으로 실행할 수 있는 기능을 제공한다. 이를 통해 효율적인 원격 시스템 관리가 가능하다.

* **다중 세션 사용**: 하나의 SSH 연결에서 여러 세션을 사용하여 작업할 수 있다. 이는 `ControlMaster`와 `ControlPath` 옵션을 사용하여 설정할 수 있다. 첫 번째 SSH 세션을 열 때는 마스터 세션을 만들고, 이후의 SSH 접속은 해당 마스터 세션을 통해 빠르게 연결된다.

  ```bash
  ssh -M -S /tmp/ssh_control user@remotehost
  ```
* **다중 명령 실행**: SSH를 통해 한 번에 여러 명령을 실행할 수도 있다. 명령어들을 세미콜론 `;` 또는 논리 연산자 `&&`, `||`를 사용하여 연결할 수 있다.

  ```bash
  ssh user@remotehost 'command1; command2'
  ```

#### SSH 복제 및 백업 (rsync)

`rsync`는 SSH를 기반으로 한 데이터 복제 및 백업 도구로, 원격 서버와 로컬 서버 간에 파일을 효율적으로 동기화할 수 있다. `rsync`는 차이점만을 전송하는 방식으로 동작하여, 네트워크 대역폭을 절약하고 전송 시간을 줄인다.

* **기본 사용법**: 로컬 디렉토리의 파일을 원격 서버로 복사할 수 있다.

  ```bash
  rsync -avz /local/dir/ user@remotehost:/remote/dir/
  ```
* **반대로 복사**: 원격 서버의 파일을 로컬로 가져올 수 있다.

  ```bash
  rsync -avz user@remotehost:/remote/dir/ /local/dir/
  ```
* **--delete 옵션**: 원격 서버와 로컬 서버의 디렉토리를 완전히 동기화할 때, 로컬에서 삭제된 파일을 원격에서도 삭제하려면 `--delete` 옵션을 사용할 수 있다.

  ```bash
  rsync -avz --delete /local/dir/ user@remotehost:/remote/dir/
  ```

#### SSH 연결 유지 및 재시도 설정

네트워크 환경이 불안정할 경우, SSH 연결이 자주 끊기는 문제가 발생할 수 있다. 이를 방지하고 SSH 연결을 안정적으로 유지하기 위한 설정이 있다.

* **KeepAlive 옵션**: SSH 연결이 유휴 상태일 때도 주기적으로 패킷을 전송하여 연결을 유지할 수 있다. 클라이언트 측에서는 `ssh_config` 파일에 다음 옵션을 추가할 수 있다.

  ```bash
  ServerAliveInterval 60
  ```

  서버 측에서도 `sshd_config` 파일에 다음 옵션을 설정할 수 있다.

  ```bash
  ClientAliveInterval 60
  ```
* **재시도 설정**: 네트워크 연결이 끊어졌을 때 자동으로 재시도할 수 있도록 설정할 수 있다. `ConnectTimeout`과 `ConnectionAttempts` 옵션을 통해 재시도 횟수와 시간을 지정할 수 있다.

  ```bash
  ConnectTimeout 10
  ConnectionAttempts 5
  ```

#### SSH 멀티팩터 인증 (MFA)

SSH 멀티팩터 인증(MFA)은 SSH 접속 시 추가적인 보안 계층을 제공하여, 단순한 비밀번호나 공개키 인증에 비해 훨씬 안전한 인증 절차를 구현할 수 있다. OpenSSH는 다양한 멀티팩터 인증 방식을 지원하며, 이를 통해 여러 가지 인증 방식을 조합하여 사용자의 신원을 확인할 수 있다.

* **TOTP 기반 인증**: Time-based One-Time Password(TOTP)는 시간에 따라 변하는 일회용 비밀번호를 사용하는 방식으로, Google Authenticator나 Authy 같은 애플리케이션을 이용하여 설정할 수 있다. 이를 설정하려면 `pam_google_authenticator` 모듈을 설치하고, SSH 서버의 `sshd_config` 파일에서 다음과 같이 설정해야 한다.

  ```bash
  ChallengeResponseAuthentication yes
  ```

  PAM 설정 파일에도 다음을 추가해야 한다.

  ```bash
  auth required pam_google_authenticator.so
  ```
* **U2F 및 FIDO 인증**: U2F(Universal 2nd Factor) 및 FIDO 인증은 YubiKey와 같은 하드웨어 토큰을 사용한 인증 방법이다. OpenSSH는 FIDO 기반의 인증을 지원하며, 이를 위해 `sshd_config` 파일에 다음 설정을 추가할 수 있다.

  ```bash
  PubkeyAuthentication yes
  AuthenticationMethods publickey,keyboard-interactive:pam
  ```

  U2F 키 설정은 `ssh-keygen` 명령어로 생성할 수 있다.

  ```bash
  ssh-keygen -t ecdsa-sk -f ~/.ssh/id_ecdsa_sk
  ```
* **SMS 또는 이메일 인증**: SMS나 이메일을 통한 추가 인증 단계도 설정할 수 있다. 이를 위해 별도의 스크립트나 외부 인증 서비스와 연동하여, SSH 접속 시 추가적인 인증을 요구할 수 있다. PAM(PAM 인증 모듈)과 연동하여 이런 방식을 구현할 수 있다.

#### SSH 터널링을 통한 VPN 구축

SSH를 사용하여 안전한 VPN(Virtual Private Network)을 구축할 수 있다. SSH 터널링을 활용하면 인터넷 상에서 안전하게 데이터를 전송하고, 원격 네트워크에 접속할 수 있다. VPN 기능은 특히 비공개 네트워크에 안전하게 접근할 때 유용하다.

**SSH 기반 VPN 설정**

SSH를 통해 VPN을 설정하려면 **TUN/TAP** 디바이스를 사용하여 네트워크 인터페이스를 가상화해야 한다. 이 방식은 SSH 터널을 통해 네트워크 트래픽을 안전하게 전송하는 방법을 제공한다.

* **SSH 서버에서 TUN/TAP 장치 활성화**: SSH 서버의 `sshd_config` 파일에 다음과 같이 TUN/TAP 장치 사용을 허용해야 한다.

  ```bash
  PermitTunnel yes
  ```
* **클라이언트에서 SSH 터널 생성**: 클라이언트 측에서는 `-w` 옵션을 사용하여 TUN 인터페이스를 설정하고, SSH 터널을 생성할 수 있다.

  ```bash
  ssh -w any:any user@remotehost
  ```

**VPN 터널링을 통한 보안 네트워크 구성**

SSH 기반 VPN은 다음과 같은 방법으로 보안 네트워크 구성을 할 수 있다:

* 원격 네트워크의 내부 자원에 안전하게 접속할 수 있다.
* 공용 네트워크에서 데이터 전송을 암호화하여 보안성을 강화한다.

**성능 최적화**

SSH 기반 VPN은 다른 VPN 솔루션에 비해 성능이 낮을 수 있기 때문에 최적화를 위해 여러 설정을 조정할 수 있다:

* **Compression 옵션 활성화**: SSH 트래픽을 압축하여 데이터 전송 속도를 향상시킬 수 있다.

  ```bash
  ssh -C user@remotehost
  ```
* **AES-NI 하드웨어 가속 사용**: 서버와 클라이언트에서 AES-NI 명령어 세트를 지원하는 하드웨어 가속 기능을 사용하여 암호화 속도를 향상시킬 수 있다.

#### SSH 연결 제한 설정

SSH 서버에 대한 연결 요청을 제한하여, 불필요한 접속 시도를 막고 서버의 리소스를 보호할 수 있다. 이는 특히 무차별 대입 공격을 방지하고, 서버의 성능을 보호하는 데 도움이 된다.

* **MaxSessions**: 하나의 SSH 연결에서 허용되는 최대 세션 수를 설정할 수 있다. 이를 통해 동일한 연결에서 너무 많은 세션을 열어 서버 자원을 낭비하는 것을 방지할 수 있다.

  ```bash
  MaxSessions 10
  ```
* **MaxStartups**: 동시에 허용되는 SSH 연결 시도의 수를 제한하여 무차별 대입 공격을 방어할 수 있다.

  ```bash
  MaxStartups 10:30:60
  ```

  위 설정은 10개의 SSH 연결 시도를 허용하며, 그 이후로는 연결이 30%의 확률로 거부되고, 60개 이상이 되면 완전히 차단된다.
* **LoginGraceTime**: 사용자가 로그인하지 못하고 대기할 수 있는 시간을 설정하여, 로그인 대기 상태로 인해 자원이 낭비되는 것을 방지할 수 있다.

  ```bash
  LoginGraceTime 60
  ```
