개념 사전 · 프로토콜

SSH와 OpenSSH

Secure Shell · 시큐어 셸

SSH는 서버 신원 확인과 암호화된 전송 위에서 ·원격 명령·파일 전송·포트 전달을 제공하는 프로토콜이다. OpenSSH는 이를 구현한 도구 모음이며 서버 호스트 키와 키의 역할을 구분해야 한다.

밑줄 용어에 마우스를 올리거나, 키보드로 선택하거나, 터치하면 설명을 볼 수 있습니다.

01무엇이고, 어떤 일을 하나

  • 접속 상대 서버를 호스트 키로 확인한다.
  • 보호된 전송 위에서 과 제한된 채널을 제공한다.
  • 원격 명령의 출력·오류·종료 상태를 전달하여 운영 자동화를 지원한다.

02어떤 순서로 동작하나

  1. 연결·협상

    서버 포트에 연결하고 버전·암호 알고리즘을 협상한다.

  2. 키 교환·서버 확인

    세션 암호화 자료를 만들고 host key의 서명과 신뢰된 지문으로 서버를 확인한다.

  3. 공개키 서명·비밀번호 등 허용된 인증 경로를 완료한다. 공개키 방식은 개인키를 서버에 보내지 않는다.

  4. 채널 실행

    권한에 맞는 셸·명령·SFTP·포워딩 채널을 열고 결과를 반환한다. 인증 성공 뒤에도 채널별 제한으로 작업이 거부될 수 있다.

03먼저 알아둘 용어와 구성요소

host key는 서버를 식별하는 장기 키이고 세션 암호화 키와 사용자 개인키는 역할이 다르다.
클라이언트의 는 이전에 신뢰한 서버 키를 기억하는 장소다.
사용자 개인키는 클라이언트에 두고 대응하는 공개키만 서버 계정의 에 등록한다.
는 잠금 해제된 키로 서명 작업을 대신할 수 있지만 agent forwarding은 원격 호스트에서 그 서명 기능을 사용할 경로를 열 수 있으므로 별도 신뢰 판단이 필요하다.
.ssh 디렉터리와 가 다른 사용자에게 쉽게 수정될 수 있으면 공격자가 자기 키를 추가할 수 있어 같은 검사가 소유권·쓰기 권한을 살핀다.
OpenSSH 에서 쉼표로 연결한 방식은 순서대로 모두 성공해야 하는 한 경로다. 공백으로 나눈 여러 목록은 허용되는 대안 경로를 표현한다.
LEARN THROUGH PRACTICE

SSH 서비스의 active와 enabled를 서로 다른 상태로 읽기

서비스를 지금 시작하는 작업과 부팅 시 시작 경로를 등록하는 작업을 실제 status 출력으로 구별한다.

실습 구성과 전제

  • 의 ssh.service 화면을 사용한다. 배포판에 따라 같은 서버 프로그램의 unit 이름이 sshd.service일 수 있다.
  • 첫 화면과 enable 이후 화면은 Main PID와 시작 시각을 대조해 읽는다. socket activation 표시도 함께 살핀다.
  1. 현재 실행 상태를 읽는다

    • start는 현재 서비스의 시작을 요청한다. status의 Active가 active (running)이면 해당 unit의 실행 상태를 뜻하며, 부팅 때 자동 시작하도록 등록되었다는 뜻은 아니다.
    • ExecStartPre의 sshd 검사 성공과 Main PID를 보면 사전 검사와 실제 서버 를 분리할 수 있다. TriggeredBy의 ssh.socket은 별도 소켓 unit과의 관계다.
    bash
    systemctl status ssh.service --no-pager
    systemctl is-active ssh.service
    systemctl is-enabled ssh.service

    예시다. 각 조회 명령의 출력과 종료 상태는 서로 다른 질문에 답한다.

    4/22 · 명령·상태 출력 2원본 크기로 보기 ↗
    • Loaded 줄에는 disabled가 보이지만 Active 줄은 active (running)이다.
    • ExecStartPre의 종료 상태는 성공이고 Main PID가 표시되며, ssh.socket의 트리거 관계도 나타난다.
    확인 기준

    active와 disabled는 모순이 아니다. 실행 여부와 unit 파일의 활성화 상태를 별도 열로 기록한다.

  2. enable이 만든 시작 경로를 확인한다

    • enable은 unit의 설치 지시를 바탕으로 target의 wants 같은 연결을 만든다. 기본 enable만으로 현재 를 새로 실행하거나 재시작하지 않는다.
    • 화면에서는 enable 후 생성 메시지가 나오고 Loaded가 enabled로 바뀐다. 이미 실행 중인 서버의 Main PID가 이어지는 것이 이 차이를 보여 준다.
    4/22 · 명령·상태 출력 3원본 크기로 보기 ↗
    • enable 출력에 multi-user.target.wants/ssh.service 등의 연결 생성 메시지가 보인다.
    • Loaded는 enabled로 바뀌었고 Active는 여전히 running이며 기존 Main PID가 유지된다.
    확인 기준

    enable --now는 활성화 등록과 현재 시작을 함께 요청하는 옵션이다. enable만 실행한 사례와 구분한다.

  3. 서비스·소켓·부팅 경로를 함께 대조한다

    • is-enabled만으로 서버가 현재 수신 가능한지 판단하지 않는다. 서비스 실패, 소켓 unit의 활성화, 실제 리슨 포트를 각각 확인한다.
    • 소켓 활성화를 사용하는 배포판에서는 ssh.socket이 연결을 받아 서비스를 시작할 수 있다. unit 파일과 현재 소켓 상태를 확인한 뒤 해당 환경의 시작 경로를 설명한다.
    bash
    systemctl status ssh.socket --no-pager
    systemctl cat ssh.service ssh.socket
    ss -lnt

    설치된 unit 구성과 리슨 소켓을 읽기 전용으로 대조한다.

    확인 기준

    서비스가 active인데 접속되지 않으면 포트·주소·방화벽을 확인한다. 서비스가 inactive여도 소켓 활성화가 설정되었는지 먼저 살핀다.

실습에서 확인한 동작 원리

  • active는 현재 실행 상태이고 enabled는 시작 의존 관계를 등록한 상태다.
  • 설정 파일, unit 활성화, , 리슨 소켓은 서로 연결되지만 같은 증거는 아니다.
관련 개념·전체 실습 화면 이어서 읽기 →
동작·명령 참고 문서
LEARN THROUGH PRACTICE

sshd 실행·22번 포트 수신·SSH 인증을 순서대로 확인하기

서비스 상태와 소켓 출력에서 서버 준비를 읽고, 실제 SSH 접속의 실패 단계를 구별한다.

실습 구성과 전제

  • sshd status와 ss 출력은 서로 다른 시점의 화면이다. PID 906과 843이 다르므로 같은 의 동시 조회라고 꾸미지 않는다.
  • 준비한 실습 서버와 사전에 확인한 호스트 키를 사용한다. 주소와 계정은 문서용 값으로 바꾸었다.
  1. 실행 상태와 unit 이름을 확인한다

    • 사례는 sshd.service를 사용한다. status의 running과 Main PID로 현재 데몬 실행을 확인하고 enabled로 시작 설정을 읽는다.
    • 이름이 ssh.service인 배포판도 있으므로 unit 이름을 그대로 복사해 설치 실패로 단정하지 않는다. 가 살아 있다는 사실은 포트나 인증 설정이 맞다는 뜻까지 포함하지 않는다.
    bash
    systemctl status sshd.service --no-pager
    journalctl -u sshd.service -n 30 --no-pager

    sshd.service를 사용하는 배포판의 조회 예시다.

    Rocky Linux SSH 준비 · b. ssh 작동 확인 (2)원본 크기로 보기 ↗
    • sshd 서비스가 active (running)이며 enabled로 표시된다.
    • Main PID는 906으로 나타나 서버 프로세스 식별을 제공한다.
    확인 기준

    서비스 실패라면 네트워크 시험 전에 해당 unit의 설정 검사·시작 로그부터 확인한다.

  2. 소켓이 어느 주소·포트에서 수신하는지 읽는다

    • 별도 ss 화면은 22번 포트가 ·에서 LISTEN인 상태를 보여 준다. 같은 출력에 있는 chronyd의 323 소켓은 SSH의 포트가 아니다.
    • 주소가 loopback에만 묶인 경우와 모든 로컬 주소에 수신하는 경우는 외부 도달 조건이 다르다. LISTEN 이후에도 경로와 방화벽을 통과해야 한다.
    bash
    ss -lntp "sport = :22"

    SSH 기본 포트의 리슨을 좁혀 조회한다. 정보에는 추가 권한이 필요할 수 있다.

    Rocky Linux SSH 준비 · d. 22/tcp 포트 확인 (3)원본 크기로 보기 ↗
    • ss 출력에 22번 TCP LISTEN 행과 sshd 프로세스가 표시된다.
    • chronyd의 323 포트 행은 별도 UDP 소켓으로 함께 나열되어 있어 프로토콜을 구분해야 한다.
    확인 기준

    프로토콜·주소·포트·를 한 행 단위로 읽는다. 다른 시점의 PID 차이를 즉시 비정상으로 해석하지 않는다.

  3. 호스트 확인 뒤 사용자 인증과 명령 실행을 구별한다

    • SSH 클라이언트는 연결 뒤 키 교환과 서버 호스트 키 확인을 수행하고 그다음 을 한다. 인증 후 원격 명령 채널을 열어 실행 결과를 받는다.
    • 재구성 명령에서 host key verification failed, permission denied, 원격 명령의 비영 종료는 서로 다른 실패 단계다. 처음 보는 호스트 키를 검증 없이 신뢰하도록 설정하지 않는다.
    bash
    ssh -v -o StrictHostKeyChecking=yes labuser@192.0.2.30 "id"

    신뢰 호스트 키가 미리 등록된 실습 서버에 현재 자격 정보를 조회하는 예시다.

    확인 기준

    서비스·리스너 조회만으로 로그인 성공을 주장하지 않는다. 사전에 등록한 신뢰 호스트에 한해 실제 클라이언트 로그와 명령 종료 상태를 확인한다.

실습에서 확인한 동작 원리

  • 실행과 소켓 수신은 서버 준비를 보여 주며, 실제 암호화·신원 확인·은 클라이언트 연결에서 확인한다.
  • 실패 메시지를 처리 단계에 맞추면 방화벽·호스트 키·사용자 권한 문제를 분리할 수 있다.
관련 개념·전체 실습 화면 이어서 읽기 →
동작·명령 참고 문서
LEARN THROUGH PRACTICE

SSH 인증 실패와 반복 mkdir 실패를 멱등 모듈로 구별하기

의 UNREACHABLE·FAILED·CHANGED가 발생한 처리 단계를 비교하고 원하는 디렉터리 상태로 작업을 표현한다.

실습 구성과 전제

  • 사진은 inventory 대상에 command 모듈을 실행한 사례다. 아래에서는 대상 그룹·경로를 lab과 /tmp/-lab으로 재구성한다.
  • 관리 대상에 검증한 SSH 접속과 파일 모듈 실행 환경이 준비되어 있어야 한다. 화면의 삭제 명령은 재실행하지 않는다.
  1. 원격 작업 전에 연결이 성립했는지 읽는다

    • 첫 화면의 UNREACHABLE과 Permission denied는 SSH 인증 단계의 실패다. 원하는 mkdir 작업이 실행되어 실패한 것이 아니다.
    • changed=false도 디렉터리 상태를 검사해 이미 정상이었다는 뜻이 아니라, 이 사례에서는 원격 작업까지 도달하지 못했다는 결과와 함께 읽어야 한다.
    bash
    ansible-inventory -i inventory --graph
    ansible lab -i inventory -m ansible.builtin.ping

    연결과 모듈 실행 준비를 확인하는 예시다. ping은 ping이 아니다.

    9/7 - Ansible · 실습·개념 참고 화면 8원본 크기로 보기 ↗
    • inventory와 -u 사용자를 지정한 command 실행이 UNREACHABLE로 끝난다.
    • 메시지는 Permission denied이며 changed=false가 함께 표시된다.
    확인 기준

    inventory의 주소·사용자·인증 키와 수동 SSH 접속 조건을 대조한다. module 인자를 바꿔도 앞단 인증 실패는 해결되지 않는다.

  2. 명령 실행 성공과 원하는 상태의 달성을 구별한다

    • 다음 화면의 mkdir는 이미 존재하는 디렉터리 때문에 rc=1로 실패한다. 필요한 상태가 이미 있어도 명령은 매번 생성 연산을 시도한다.
    • 화면의 별도 삭제 명령은 rc=0과 CHANGED로 나타난다. 이를 반복 생성 문제의 필수 해결책으로 삼지 않고, 처음부터 원하는 디렉터리 상태를 표현하는 것이 적절하다.
    9/7 - Ansible · 실습·개념 참고 화면 10원본 크기로 보기 ↗
    • mkdir 결과에 File exists, rc=1, FAILED가 표시된다.
    • 다른 삭제 작업은 rc=0과 CHANGED로 나와 상태 변경과 명령 종료 결과를 각각 보여 준다.
    확인 기준

    command 모듈의 CHANGED는 작업이 업무적으로 올바른 상태를 만들었다는 자동 검증이 아니다. 결과의 의미를 해당 명령과 연결한다.

  3. file 모듈로 상태를 선언하고 재실행 결과를 비교한다

    • file 모듈의 state: directory는 경로가 디렉터리인지와 요청한 속성을 비교한다. 없으면 만들고, 이미 조건을 만족하면 불필요한 변경을 하지 않는 구조다.
    • 재구성 playbook을 같은 대상에 두 번 적용한다면 첫 변경 이후 두 번째는 해당 task의 changed가 줄어드는지 확인한다. 이는 실제 사진의 결과가 아니라 준비한 환경에서 검증할 기대 동작이다.
    yaml
    - name: Ensure the lab directory exists
      hosts: lab
      gather_facts: false
      tasks:
        - name: Keep the directory at the desired mode
          ansible.builtin.file:
            path: /tmp/ansible-lab
            state: directory
            mode: "0750"

    대상과 경로를 재구성한 playbook이다. inventory와 접속 신뢰 설정을 먼저 준비한다.

    확인 기준

    두 번째에도 changed가 반복되면 권한·소유자·다른 작업의 변경·경로 종류를 확인한다. check 모드와 실제 실행을 구분한다.

실습에서 확인한 동작 원리

  • UNREACHABLE은 연결 경계, FAILED는 작업 실패, CHANGED는 변경 판정이므로 처리 위치를 구분한다.
  • 멱등성은 같은 명령을 반복하는 것이 아니라 현재 상태와 원하는 상태를 비교하는 방식에서 얻는다.
관련 개념·전체 실습 화면 이어서 읽기 →
동작·명령 참고 문서

04예제로 따라가기

  • 불일치는 사용자 암호 실패가 아니라 서버 신원 확인 단계의 문제이므로 무조건 기록을 지워 넘기지 않는다.
  • publickey,password는 공개키 성공 뒤 비밀번호까지 요구하는 하나의 인증 경로이므로 첫 성공 로그가 최종 로그인 완료를 뜻하지 않는다.
  • 원격 명령이 rc=1로 끝나도 SSH 전송 자체는 정상일 수 있다. 채널 출력·stderr·종료 상태를 통신 오류와 분리한다.

05혼동하기 쉬운 점과 확인 기준

  • agent에 여러 키가 있으면 허용된 키에 도달하기 전에 MaxAuthTries 제한을 만날 수 있다. 시도 순서와 IdentitiesOnly 적용 여부를 확인한다.
  • 올바른 키인데 거부되면 계정 홈·AuthorizedKeysFile·소유권·쓰기 가능 상태·키별 옵션을 확인한다. 공개키가 어딘가에 저장되었다는 사실만으로 해당 계정이 허용한 것이 아니다.
  • 불일치는 사용자 키 실패보다 앞선 서버 신뢰 문제다. 별도 경로로 교체 사실과 지문을 대조하기 전 기록을 지워 경고만 없애지 않는다.

06상세 노트 · 실습 자료

헤더 구조, 설정 예시, 수치 계산과 수업 캡처는 아래 노트에서 이어집니다.

공식 문서 · 표준

기초 개념과 동작 설명을 대조한 자료입니다. 제품 버전과 실제 설정에 따른 차이는 본문 및 원문에서 확인하세요.