[네트워크 보안 + Node.js] 실제로 패킷을 캡쳐해 HTTP의 위험성을 확인해보자 (feat. Wireshark로 HTTP vs HTTPS 패킷 캡처하기)

Maria Kim·2025년 9월 8일
0
post-thumbnail

Mac M1 + Express 서버 테스트 기반

웹을 하다 보면 브라우저에서 “이 사이트는 안전하지 않습니다” 같은 경고를 볼 때가 있죠.
또한 웹 개발을 배우다 보면 “HTTP는 위험하니 반드시 HTTPS를 써야 한다”는 말을 수도 없이 듣습니다.

그런데, 혹시 이렇게 생각해 본 적 없나요?

“정말 HTTP 요청은 암호화가 전혀 안 돼서,
중간에서 보면 그대로 다 보일까?

이번 글에서는 Wireshark를 활용해
• HTTP 요청을 중간에서 가로채 평문을 확인하고
• HTTPS 요청이 암호화되는 과정을 직접 테스트해보겠습니다.

테스트

1. 테스트 목표

•	HTTP 요청 → Wireshark에서 ID/PW가 평문으로 노출되는 것 확인
•	HTTPS 요청 → Wireshark에서 암호화돼서 내용을 알 수 없는 것 확인

2. 테스트 환경

3. Express 서버 설정

폴더 구조

express-tls-test/       ← 프로젝트 루트
├── cert/               ← 인증서 폴더
│   ├── key.pem         ← 개인 키 (비밀)
│   └── cert.pem        ← 공개 인증서
├── index.js           ← Express 서버 코드
├── package.json
└── node_modules/

3.1 프로젝트 생성

mkdir express-tls-test
cd express-tls-test
npm init -y
npm install express

3.2 SSL 인증서 생성

mkdir cert
cd cert

개인 키 생성

  • 서버에서 비밀로 보관, TLS 핸드셰이크 시 대칭키 암호화

openssl genrsa -out key.pem 2048

✅ 명령어 구조
• openssl
→ OpenSSL 툴을 실행하는 명령어
• genrsa
→ RSA 개인 키(private key) 생성 명령
• -out key.pem
→ 생성된 개인 키를 key.pem 파일로 저장
• 2048
→ 키 길이를 2048비트로 설정 (기본 보안 권장값)

🔹 동작 원리
• HTTPS 서버는 대칭키 + 비대칭키 혼합 암호화를 사용해요.
• 여기서 생성하는 개인 키(private key) 는 TLS 핸드셰이크에서 사용되는 비대칭키 중 하나예요.
• 개인 키는 서버에서만 보관하며, 절대로 외부에 노출되면 안 돼요.

공개 인증서 생성 (Common Name → localhost)

  • 브라우저에 제공, 서버 신원 확인 및 공개키 전달

openssl req -new -x509 -key key.pem -out cert.pem -days 365

✅ 명령어 구조
• openssl
→ OpenSSL 툴 실행
• req
→ X.509 인증서 요청 및 생성 관련 명령
• -new
→ 새 인증서 생성
• -x509
→ 인증기관(CA)에 요청하지 않고 자체 서명(self-signed) 인증서 생성
• -key key.pem
→ 아까 만든 개인 키를 사용
• -out cert.pem
→ 생성된 공개 인증서를 cert.pem 파일로 저장
• -days 365
→ 인증서 유효기간을 365일로 설정

• Common Name (CN) → localhost 또는 도메인 입력 필수
• 로컬 개발용이므로 localhost로 설정하는 게 안전해요.

3.3 package.json

{
  "name": "https",
  "version": "1.0.0",
  "type": "module",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "express": "^5.1.0"
  }
}

3.4 Express 서버 코드

// index.js

import fs from "fs";
import http from "http";
import https from "https";
import express from "express";

const app = express();
app.use(express.json()); 

// 테스트용 라우트
app.post("/login", (req, res) => {
  const { username, password } = req.body;
  console.log("📩 요청 도착:", username, password);
  res.json({ message: "로그인 요청 수신 완료", username });
});

// HTTP 서버 실행
const httpPort = 8080;
http.createServer(app).listen(httpPort, () => {
  console.log(`🔓 HTTP 서버 실행 중: http://localhost:${httpPort}`);
});

// HTTPS 서버 실행
const httpsPort = 8443;
const options = {
  key: fs.readFileSync("./cert/key.pem"),
  cert: fs.readFileSync("./cert/cert.pem"),
};
https.createServer(options, app).listen(httpsPort, () => {
  console.log(`🔐 HTTPS 서버 실행 중: https://localhost:${httpsPort}`);
});

4. Wireshark 설치 및 설정 (Mac M1)

4.1 다운로드

•	[Wireshark](https://www.wireshark.org/#download) 공식 사이트
•	Mac M1 (Apple Silicon) → macOS Arm Disk 

Wireshark 실행 후 Capture > Options:
• localhost 트래픽 캡처 → lo0 선택 ✅

5. HTTP 패킷 캡처 테스트

5.1 HTTP 요청 보내기

curl -X POST http://localhost:8080/login \
  -H "Content-Type: application/json" \
  -d '{"username":"kimsh","password":"mypassword123"}'

5.2 Wireshark 필터 적용

tcp.port == 8080

• Hypertext Transfer Protocol → Request Body에서 평문 그대로 노출:

6. HTTPS 패킷 캡처 테스트

curl -k -X POST https://localhost:8443/login \
  -H "Content-Type: application/json" \
  -d '{"username":"kimsh","password":"mypassword123"}'
tcp.port == 8443

마무리

Wireshark로 실습해보니 HTTPS의 중요성을 다시금 실감했습니다.
• HTTP 요청 → 패킷 평문 그대로 노출 ❌
• HTTPS 요청 → 암호화로 안전하게 보호 ✅

결론:
HTTP 사이트에서는 로그인, 결제 등 민감한 정보 입력을 절대 하지 마세요.
HTTPS는 선택이 아니라 필수입니다.

profile
Developer, who has business in mind.

0개의 댓글