📚 네트워크 · 패킷 분석 › 02. 포트 · 프로토콜 분석 — 69편
이전 글: 68. POP3 · 다음 글: 70. DNS 레코드와 질의 유형
IMAP(Internet Message Access Protocol)은 메일을 서버에 둔 채로 여러 기기에서 조회·정리하는 프로토콜입니다. 현재 널리 쓰이는 IMAP4rev1은 RFC 3501, 개정판 IMAP4rev2는 RFC 9051입니다. 메일 포트 전체 구성은 82. 메일 프로토콜 SMTP·POP3·IMAP에서 다뤘습니다.
68. POP3가 "가져가서 지운다"라면 IMAP은 "서버가 원본, 기기는 창"입니다. 그래서 폴더, 읽음 표시, 검색이 모두 서버에서 처리됩니다.
| 항목 | 값 |
|---|---|
| 전송 계층 | TCP |
| 기본 포트 | 143 (평문, STARTTLS로 전환 가능), 993 (접속 즉시 TLS) |
| 명령 형식 | 태그 명령 인자 (예: a1 LOGIN ...) |
| 응답 형식 | 태그 + OK / NO / BAD, 중간 데이터는 *로 시작 |
| 세션 특성 | 길게 유지, 서버가 새 메일을 알려 줄 수 있음(IDLE) |
IMAP 세션은 네 가지 상태를 오갑니다. 클라이언트는 명령마다 태그를 붙여 여러 명령을 보내고, 서버는 같은 태그로 완료를 알립니다.
클라이언트 192.168.10.50:50310 서버 192.168.10.30:993
│ ── TCP 연결 + TLS Handshake ──────────────→ │
│ ←─ * OK [CAPABILITY ...] ready ──────────── │
↓ │
[Not Authenticated] │
│ ── a1 LOGIN / AUTHENTICATE ───────────────→ │
↓ a1 OK │
[Authenticated] ── 폴더 목록(LIST), 상태(STATUS)│
│ ── a2 SELECT INBOX ───────────────────────→ │
↓ * 25 EXISTS ... a2 OK │
[Selected] ── FETCH / SEARCH / STORE / COPY │
│ ── a3 IDLE ───────────────────────────────→ │ (대기)
│ ←─ * 26 EXISTS (새 메일 도착 알림) ─────────── │
│ ── DONE / a4 LOGOUT ──────────────────────→ │
↓ ↓
[Logout] → 연결 종료
*로 시작하는 줄은 태그 없는 응답(서버가 보내는 데이터·알림)입니다.\Deleted 플래그를 붙인 뒤 EXPUNGE(또는 CLOSE)로 확정됩니다.| 명령 | 상태 | 의미 |
|---|---|---|
CAPABILITY | 모든 상태 | 지원 기능 조회 |
STARTTLS | Not Authenticated | 143에서 TLS 전환 |
LOGIN, AUTHENTICATE | Not Authenticated | 인증 |
LIST, STATUS | Authenticated | 폴더 목록, 폴더별 메일 수 |
SELECT, EXAMINE | Authenticated | 폴더 열기(EXAMINE은 읽기 전용) |
FETCH, SEARCH | Selected | 메일 일부·전체 조회, 서버 측 검색 |
STORE, COPY, EXPUNGE | Selected | 플래그 변경, 복사, 삭제 확정 |
IDLE, LOGOUT | 인증 이후 / 모든 상태 | 알림 대기, 종료 |
시스템 플래그는 메일 상태를 서버에 기록하는 값입니다.
| 플래그 | 의미 | 관제 관점 |
|---|---|---|
\Seen | 읽음 | 사용자가 모르는 사이 읽음 처리된 메일 → 제3자 접근 단서 |
\Deleted | 삭제 예정 | EXPUNGE 전까지 복구 가능 |
\Flagged | 중요 표시 | — |
\Answered | 답장함 | — |
\Draft | 임시 보관 | — |
FETCH는 헤더만(BODY.PEEK[HEADER]), 본문 일부, 전체를 골라 받을 수 있습니다. .PEEK가 붙으면 \Seen 플래그를 바꾸지 않고 읽습니다.
실습 예시 — 본인 소유 실습 메일 서버(Dovecot, 192.168.10.30)에서 로그인 없이 기능 목록만 확인합니다.
# 993: TLS 접속 후 입력 → a1 CAPABILITY / a2 LOGOUT
openssl s_client -connect 192.168.10.30:993 -quiet
# 143: 평문 접속 후 같은 명령 (STARTTLS·LOGINDISABLED 표시 확인)
nc -C 192.168.10.30 143
# 서버: 리슨 포트와 IMAP 세션 수 (Rocky/Ubuntu 공통)
sudo ss -tnp state established '( sport = :993 or sport = :143 )'
143 응답 형식 예시(값은 환경마다 다름):
* OK [CAPABILITY IMAP4rev1 SASL-IR LOGIN-REFERRALS ID ENABLE IDLE LITERAL+ STARTTLS LOGINDISABLED] Dovecot ready.
a1 CAPABILITY
* CAPABILITY IMAP4rev1 SASL-IR LOGIN-REFERRALS ID ENABLE IDLE LITERAL+ STARTTLS LOGINDISABLED
a1 OK Pre-login capabilities listed, post-login capabilities have more.
a2 LOGOUT
* BYE Logging out
a2 OK Logout completed.
LOGINDISABLED는 평문 구간에서 LOGIN을 거부한다는 뜻입니다. 143에서 이 값이 없으면 비밀번호가 평문으로 오갈 수 있습니다.
Dovecot 종료 로그 형식 예시(값은 환경마다 다름):
dovecot: imap(alice): Disconnected: Logged out in=412 out=5120433 deleted=0 expunged=0 trashed=0 hdr_count=0 hdr_bytes=0 body_count=0 body_bytes=0
in/out은 세션의 수신·송신 바이트로, out이 크면 많은 메일 데이터가 클라이언트로 나갔다는 뜻입니다.
📷 [실습 화면 삽입 위치] 143과 993의 CAPABILITY 응답 비교(LOGINDISABLED 유무)
LOGIN이 허용되면 자격 증명이 노출됩니다. 993 전용 운영 또는 LOGINDISABLED 상태를 확인합니다.FETCH BODY.PEEK[]를 쓰면 읽음 표시를 바꾸지 않고 메일을 가져갈 수 있어 사용자가 알아채기 어렵습니다.| 흔적 위치 | 확인할 수 있는 것 |
|---|---|
| 메일 서버 로그 | 로그인 성공·실패, 클라이언트 IP, TLS 여부, 세션 송신 바이트, 삭제 수 |
| 방화벽 | 143/993 세션 시간, 바이트, 출발지 |
| IDS/NSM | 143 평문 구간의 LOGIN, NO 응답 반복 |
관제자가 확인할 질문
EXPUNGE·삭제 수가 많은가? (흔적 삭제 가능성)ID 명령 값)가 보이는가?오탐 주의: 스마트폰 메일 앱은 IDLE로 긴 세션을 유지하고 네트워크가 바뀔 때마다 재접속하므로, 모바일 통신사 IP에서 로그인이 잦은 것은 정상일 수 있습니다. 새 기기 설정 시 첫 동기화도 대량 전송을 만듭니다.
OK/NO/BAD, 서버 데이터는 * 줄로 옵니다..PEEK 조회는 읽음 표시를 남기지 않습니다.