📚 네트워크 · 패킷 분석 › 02. 포트 · 프로토콜 분석 — 90편
이전 글: 89. 비표준 포트에서 동작하는 서비스 식별 · 다음 글: 91. IP + Port 분석
참고(리눅스 시스템 기초): 38. 비정상 네트워크 연결 탐지 — 호스트에서 수상한 ESTABLISHED 연결을 찾는 방법
20편이 "낯선 포트에서 무엇이 동작하는가"였다면, 이번 글은 반대 상황입니다. 포트는 아주 익숙한데(443) 그 안의 통신이 정상이 아닌 경우입니다.
감염된 호스트가 공격자 서버(C2, Command and Control)와 통신할 때 443을 선호하는 이유는 단순합니다.
그래서 관제에서 "443이니까 웹 브라우징"이라고 넘기면 가장 중요한 신호를 놓칠 수 있습니다. 이 글의 질문은 "443에서 정말로 웹 브라우징(HTTPS)이 통신하고 있는가"이며, 내용을 복호화하지 않고도 볼 수 있는 단서들을 정리합니다. 공격 도구의 구성·실행 방법은 다루지 않습니다.
| 유형 | 설명 | 관찰 가능한 단서 |
|---|---|---|
| TLS 기반 C2 | 정상 HTTPS처럼 TLS로 통신 | 연결 주기, 목적지 평판, 인증서, 클라이언트 지문 |
| 비TLS 프로토콜 on 443 | 443을 쓰지만 TLS가 아닌 자체 프로토콜 | 첫 바이트가 TLS(0x16)가 아님, IDS app_proto 판정 실패 |
| 정상 서비스 악용 | 클라우드 스토리지·협업 도구·CDN을 중계로 사용 | 도메인은 정상, 대신 사용 주체·양·시간대가 이상 |
| 암호화된 DNS(DoH) | DNS 질의를 HTTPS로 전송 | 내부 DNS 서버를 거치지 않는 이름 해석 |
감염된 호스트가 C2 서버에 주기적으로 "명령 있나요?"라고 확인하는 통신을 비커닝이라고 합니다.
| 특징 | 정상 웹 브라우징 | 비커닝 |
|---|---|---|
| 연결 간격 | 사용자 행동에 따라 불규칙 | 일정(예: 60초마다), 또는 일정 간격에 무작위 편차(jitter) 추가 |
| 시간대 | 업무 시간 중심 | 야간·주말에도 계속 |
| 요청·응답 크기 | 페이지마다 다양 | 작고 비슷한 크기의 반복 |
| 목적지 | 다수 사용자가 공통으로 방문 | 조직 내 소수 호스트만 접속하는 드문 목적지 |
단, 정상 소프트웨어도 비커닝처럼 보입니다. 업데이트 확인, 백신 클라우드 조회, 메신저·메일 동기화, 텔레메트리가 대표적입니다. 그래서 주기성은 단독 판정 근거가 아니라 우선순위를 높이는 신호로 사용합니다.
06편에서 정리한 것처럼 TLS Handshake 일부는 평문입니다.
| 항목 | TLS 1.2 | TLS 1.3 |
|---|---|---|
| SNI(접속하려는 도메인) | 보임 | 보임 (ECH를 쓰면 숨겨짐, 아직 제한적으로 사용) |
| 서버 인증서 | 보임 | 암호화됨 (패킷만으로 확인 어려움) |
| ClientHello의 암호 스위트·확장 목록 | 보임 | 보임 |
| 연결 시각·크기·지속 시간 | 보임 | 보임 |
같은 프로그램은 ClientHello를 항상 비슷한 모양으로 보냅니다. 이 모양을 요약한 값이 클라이언트 지문입니다.
| 구분 | 내용 | 주의점 |
|---|---|---|
| JA3 | ClientHello의 TLS 버전·암호 스위트·확장·타원곡선·포인트 형식을 이어 붙여 MD5 해시 | 같은 TLS 라이브러리를 쓰는 정상 프로그램과 값이 겹칠 수 있음. 확장 순서를 무작위로 바꾸는 브라우저가 늘면서 값이 불안정해짐 |
| JA4 | 프로토콜·버전·SNI 유무·개수·ALPN 등을 사람이 읽을 수 있는 앞부분과, 정렬된 목록의 해시로 구성(예: t13d1516h2_... 형태) | 순서 변화에 강하도록 설계됐지만 역시 단독 판정 근거는 아님 |
지문은 "이 연결을 만든 프로그램이 평소와 같은 종류인가"를 보는 보조 지표입니다. 공격자가 정상 브라우저의 지문을 흉내낼 수도 있으므로 지문 일치 = 정상, 불일치 = 악성으로 판단하지 않습니다.
443 연결 하나를 복호화 없이 판단하는 흐름입니다.

그림 1. 443 포트라도 접속 간격이 지나치게 규칙적이면 추가 확인 대상입니다
호스트 A → 203.0.113.50:443 연결 발견
↓
① 프로토콜: 첫 바이트가 TLS Handshake(0x16)인가? ── 아니오 → 포트-프로토콜 불일치 (우선 조사)
↓ 예
② SNI: 도메인이 있는가? 평판·등록 시점·조직 내 방문 빈도는?
↓
③ 인증서(볼 수 있는 경우): 자체 서명? SNI와 이름 불일치? 발급 직후? 비정상적 발급자·유효기간?
↓
④ 클라이언트 지문(JA3/JA4): 이 호스트의 평소 브라우저·앱 지문과 다른가?
↓
⑤ 행위: 연결 간격이 규칙적인가? 야간에도 지속되는가? 크기가 일정한가? 연결이 매우 길게 유지되는가?
↓
⑥ 호스트: 이 연결을 만든 프로세스는 무엇인가? (브라우저인가, 알 수 없는 실행 파일인가)
↓
여러 신호가 겹치면 → 우선순위 상향 → 호스트 조사·차단 검토
①~⑤는 네트워크 데이터로, ⑥은 호스트 데이터로 확인합니다. 네트워크 신호만으로 단정하지 않고 ⑥으로 확정하는 것이 핵심입니다.
실습 환경: 본인 소유 Linux VM (Rocky Linux 또는 Ubuntu). 인터페이스 ens33은 예시입니다. 이 실습은 정상 HTTPS 통신을 관찰하고, curl 반복 실행으로 "규칙적인 연결"이 어떻게 보이는지 확인하는 것으로, 악성 코드나 C2 도구는 사용하지 않습니다.
# Rocky Linux
sudo dnf install -y tcpdump curl openssl
# Ubuntu
sudo apt update && sudo apt install -y tcpdump curl openssl
sudo ss -tnp state established '( dport = :443 )'
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName
-servername으로 SNI를 지정하지 않으면 다른 인증서(기본 인증서)가 돌아올 수 있습니다. SNI와 인증서의 관계를 이해하는 데 좋은 비교입니다.
# 터미널 1: 443으로 나가는 새 연결(SYN)의 시각과 직전 연결과의 간격 출력
sudo tcpdump -ni ens33 -tt -l 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0 and dst port 443' \
| awk '{ if (p) printf "%s 간격=%.1f초 %s\n", $1, $1-p, $5; fflush(); p=$1 }'
# 터미널 2: 30초마다 한 번씩 HTTPS 요청 (10회, 정상 사이트 대상)
for i in $(seq 1 10); do curl -s -o /dev/null https://example.com; sleep 30; done
다른 443 통신이 섞이면 간격이 흐트러지므로, 실습 중에는 브라우저 등 다른 프로그램을 꺼 둡니다.
📷 [실습 화면 삽입]
openssl s_client로 확인한 인증서 subject·issuer·SAN·유효기간
📷 [실습 화면 삽입] tcpdump + awk로 출력한 443 연결 간격(약 30초 간격이 반복되는 모습)
연결 간격 출력 형식 예시(값은 환경마다 다름)
1790000031.402113 간격=30.4초 203.0.113.50.443:
1790000061.815920 간격=30.4초 203.0.113.50.443:
1790000092.230551 간격=30.4초 203.0.113.50.443:
curl 실행 시간이 더해져 정확히 30초가 아니라 30초 남짓의 거의 일정한 간격이 나타납니다. 실제 비커닝 분석에서는 이런 간격의 분포(평균·표준편차)를 목적지별로 계산해 규칙성을 봅니다.
인증서 확인 결과 형식 예시(값은 환경마다 다름)
subject=CN = example.com
issuer=C = US, O = Example CA, CN = Example CA R1
notBefore=Aug 10 00:00:00 2026 GMT
notAfter=Nov 8 23:59:59 2026 GMT
X509v3 Subject Alternative Name:
DNS:example.com, DNS:www.example.com
점검 체크리스트
ss -tnp)| 관찰 내용 | 정상일 수 있는 경우 | 의심해야 하는 경우 |
|---|---|---|
| 규칙적인 443 연결 | 업데이트 확인, 백신·EDR 클라우드 조회, 메일·메신저 동기화 | 조직 내 다른 호스트는 접속하지 않는 드문 목적지로의 규칙적 연결 |
| 자체 서명 인증서 | 내부 관리 콘솔, 개발 서버 | 외부 IP·신규 도메인에서 자체 서명 또는 기본값 형태의 인증서 |
| SNI 없음 | IP로 직접 접속하는 일부 장비·API | 일반 PC가 IP로 직접 443 연결을 반복 |
| SNI와 인증서 불일치 | CDN·공유 호스팅의 설정 오류 | 정상 서비스 도메인을 SNI로 쓰면서 전혀 다른 인증서를 받음 |
| 443인데 TLS 아님 | 일부 VPN·터널 제품, 포트 다중화 설정 | 알 수 없는 프로세스가 비TLS 프로토콜로 443 통신 |
| 드문 JA3/JA4 지문 | 새 앱 설치, 브라우저 업데이트 | 서버·PC에 설치되지 않은 클라이언트 유형의 지문이 등장 |
| 장시간 유지되는 연결 | 웹소켓·스트리밍·원격 회의 | 알 수 없는 프로세스의 수 시간 이상 유지되는 저용량 연결 |
Suricata eve.json tls 이벤트 일부 형식 예시(값은 환경마다 다름)
{"event_type":"tls","src_ip":"192.168.10.50","dest_ip":"203.0.113.50","dest_port":443,
"tls":{"sni":"update-check.example.net","subject":"CN=localhost","issuerdn":"CN=localhost",
"version":"TLS 1.2","ja3":{"hash":"<32자리 해시>"}}}
이 예시에서는 SNI(update-check.example.net)와 인증서 subject(CN=localhost)가 맞지 않고 발급자도 자기 자신입니다. 단독으로 악성이라 할 수는 없지만 호스트 조사로 넘길 근거가 됩니다. (JA3 필드 기록은 Suricata 설정에 따라 활성화가 필요할 수 있습니다.)
# 의심 목적지와 연결된 프로세스 확인
sudo ss -tnp dst 203.0.113.50
# 해당 PID의 실행 파일 확인 (20편 절차)
sudo readlink -f /proc/<PID>/exe