Skip to content

Split View: IPsec 완전 정복 — VPN 터널의 동작 원리부터 구축까지

|

IPsec 완전 정복 — VPN 터널의 동작 원리부터 구축까지

IPsec Deep Dive

들어가며

VPN을 켜면 인터넷이 느려지는 건 알지만, 느려지는지 아시나요? 그 안에서 IPsec이라는 프로토콜이 모든 패킷을 암호화하고, 인증하고, 터널링하고 있기 때문입니다.

IPsec은 네트워크 엔지니어뿐 아니라, 클라우드 아키텍트(VPC 피어링, Site-to-Site VPN), DevOps 엔지니어(WireGuard vs IPsec), 보안 엔지니어 모두에게 필수 지식입니다.

IPsec이란?

IPsec (IP Security) = IP 계층(L3)에서 동작하는 보안 프로토콜 스위트

구성요소:
├── AH (Authentication Header): 인증만 (무결성 + 출처 확인)
├── ESP (Encapsulating Security Payload): 암호화 + 인증 (실무에서 99%)
├── IKE (Internet Key Exchange): 키 교환 + SA 협상
└── SA (Security Association): 보안 연결 정보 저장소

핵심 개념

SA (Security Association) — 보안 연결의 계약서

SA = 두 장비 간의 "보안 합의서"

포함 정보:
├── SPI (Security Parameter Index): SA 식별자 (32bit)
├── 암호화 알고리즘: AES-256-GCM
├── 인증 알고리즘: SHA-256 HMAC
├── 키 값: 공유 비밀 키
├── 수명: 3600초 또는 100GB
└── 모드: 터널 / 전송

SA는 단방향 → 양방향 통신에는 SA 2개 필요!

터널 모드 vs 전송 모드

[전송 모드 (Transport Mode)]
  호스트 ↔ 호스트 직접 통신
  원본 IP 헤더 유지, 페이로드만 암호화

  ┌──────────┬──────────┬────────────────┐
IP Header│ESP Header│ 암호화된 Payload│
   (원본)   │          │                │
  └──────────┴──────────┴────────────────┘

[터널 모드 (Tunnel Mode)]Site-to-Site VPN
  게이트웨이 ↔ 게이트웨이 (원본 패킷 전체를 감싸기)
IP 헤더 추가, 원본 IP도 암호화!

  ┌──────────┬──────────┬─────────────────────────┐
  │ 새 IPESP Header│ 암호화된 [원본IP + Data]Header   │          │                         │
  └──────────┴──────────┴─────────────────────────┘

실무에서 터널 모드가 중요한 이유: 내부 네트워크 IP 주소가 외부에 노출되지 않음!

ESP (Encapsulating Security Payload) — 핵심

ESP 패킷 구조:

┌─────────────────────────────────────────────┐
IP Header (새로운, 터널모드)├─────────────────────────────────────────────┤
ESP Header│  ├── SPI (32bit): 어떤 SA를 쓸지           │
│  └── Sequence Number (32bit): 재전송 방지   │
├─────────────────────────────────────────────┤
│ ★ 암호화 영역 (Encrypted)│  ├── 원본 IP Header (터널모드)│  ├── 원본 Payload (TCP/UDP + Data)│  └── ESP Trailer (Padding + Next Header)├─────────────────────────────────────────────┤
ESP Auth (ICV): HMAC-SHA256 (무결성 검증)└─────────────────────────────────────────────┘
# ESP 암호화 과정 (의사코드)
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os

def esp_encrypt(original_packet, sa):
    """ESP 암호화 (AES-256-GCM)"""
    # 1. SA에서 키와 알고리즘 가져오기
    key = sa.encryption_key  # 256-bit
    spi = sa.spi
    seq = sa.next_sequence_number()

    # 2. ESP Header 생성
    esp_header = spi.to_bytes(4, 'big') + seq.to_bytes(4, 'big')

    # 3. Padding 추가 (블록 크기 맞추기)
    pad_len = (16 - (len(original_packet) + 2) % 16) % 16
    padding = bytes(range(1, pad_len + 1))
    esp_trailer = padding + bytes([pad_len, 4])  # 4 = IP-in-IP

    # 4. 암호화 (AES-256-GCM)
    nonce = os.urandom(12)
    aesgcm = AESGCM(key)
    plaintext = original_packet + esp_trailer
    ciphertext = aesgcm.encrypt(nonce, plaintext, esp_header)  # AAD = ESP Header

    # 5. 새 IP 헤더 + ESP Header + 암호화된 데이터
    new_ip = create_ip_header(sa.tunnel_src, sa.tunnel_dst)
    return new_ip + esp_header + nonce + ciphertext

IKE (Internet Key Exchange) — 키 협상

IPsec에서 가장 복잡한 부분! 두 단계로 나뉩니다.

Phase 1 (IKE SA) — "서로 신뢰할 수 있나?"

목적: 안전한 채널 확립 (이후 Phase 2를 보호)

[Initiator]                    [Responder]
    │                              │
    │──── SA Proposal ────────────▶│  암호화/해시/DH 그룹 제안
    │◀─── SA Accepted ────────────│  합의
    │                              │
    │──── DH Public Value ────────▶│  Diffie-Hellman 키 교환
    │◀─── DH Public Value ────────│  양쪽이 같은 비밀 키 도출!
    │                              │
    │──── Auth (PSK/Cert) ────────▶│  사전 공유 키 또는 인증서
    │◀─── Auth ────────────────────│  상호 인증
    │                              │
    ╔══════════════════════════════╗
IKE SA 수립 (암호화 채널)    ╚══════════════════════════════╝

Phase 2 (IPsec SA) — "어떤 트래픽을 어떻게 보호할지"

IKE SA로 보호된 채널 안에서:

[Initiator]                    [Responder]
    │                              │
    │──── IPsec SA Proposal ──────▶│  ESP/AH, 암호화 알고리즘
    │◀─── IPsec SA Accepted ──────│  합의
    │                              │
    │──── Traffic Selector ────────▶│  어떤 IP/Port 범위를 보호?
    │◀─── Traffic Selector ────────│  합의
    │                              │
    ╔══════════════════════════════╗
IPsec SA 수립 (x2, 양방향)    ║  → 실제 데이터 암호화 시작!    ╚══════════════════════════════╝

Diffie-Hellman 키 교환 (마법의 핵심)

# DH 키 교환 — 도청자가 봐도 비밀 키를 알 수 없음!
p = 23  # 큰 소수 (실제: 2048/4096 bit)
g = 5   # 생성자

# Alice
a = 6   # Alice의 비밀 값
A = pow(g, a, p)  # 5^6 mod 23 = 8  → 공개 전송

# Bob
b = 15  # Bob의 비밀 값
B = pow(g, b, p)  # 5^15 mod 23 = 19 → 공개 전송

# 공유 비밀 키 도출 (같은 값!)
alice_secret = pow(B, a, p)  # 19^6 mod 23 = 2
bob_secret = pow(A, b, p)    # 8^15 mod 23 = 2

assert alice_secret == bob_secret  # ✅ 같은 비밀 키!
# 도청자: p=23, g=5, A=8, B=19를 알아도
# a나 b를 모르면 비밀 키 2를 구할 수 없음 (이산 로그 문제)

실무: AWS Site-to-Site VPN

온프레미스 (192.168.1.0/24)
    ├── Customer Gateway (IPsec)
    │       │
    │       │ ══ IPsec 터널 1 (Active) ══
    │       │ ══ IPsec 터널 2 (Standby) ══
    │       │
    ├── Virtual Private Gateway
AWS VPC (10.0.0.0/16)
# Linux에서 IPsec VPN 설정 (strongSwan)
sudo apt install strongswan

# /etc/ipsec.conf
cat << 'EOF'
conn aws-vpn
    type=tunnel
    auto=start
    left=203.0.113.1          # 로컬 공인 IP
    leftsubnet=192.168.1.0/24 # 로컬 네트워크
    right=52.10.20.30         # AWS VGW IP
    rightsubnet=10.0.0.0/16   # AWS VPC CIDR
    ike=aes256-sha256-modp2048
    esp=aes256-sha256
    keyexchange=ikev2
    authby=secret
EOF

# /etc/ipsec.secrets
echo '203.0.113.1 52.10.20.30 : PSK "MyPreSharedKey123"' | sudo tee /etc/ipsec.secrets

# 시작
sudo ipsec restart
sudo ipsec status

IPsec vs WireGuard vs OpenVPN

항목IPsec (IKEv2)WireGuardOpenVPN
레이어L3L3L3/L4
코드량~400K lines~4K lines~100K lines
속도빠름가장 빠름보통
설정복잡간단보통
모바일우수 (IKEv2)우수보통
엔터프라이즈표준신흥널리 사용

📝 퀴즈 — IPsec (클릭해서 확인!)

Q1. ESP와 AH의 차이는? ||ESP: 암호화 + 인증(무결성). AH: 인증만 (암호화 없음). 실무에서는 ESP가 99% 사용됨||

Q2. 터널 모드와 전송 모드의 차이는? ||터널 모드: 원본 IP 패킷 전체를 새 IP로 감싸서 암호화 (게이트웨이 간 VPN). 전송 모드: 원본 IP 헤더 유지, 페이로드만 암호화 (호스트 간 직접)||

Q3. IKE Phase 1과 Phase 2의 역할은? ||Phase 1: IKE SA 수립 — DH 키 교환 + 상호 인증으로 안전한 채널 확보. Phase 2: IPsec SA 수립 — Phase 1 채널 안에서 실제 트래픽 보호 정책 합의||

Q4. SPI(Security Parameter Index)란? ||32비트 식별자로, 수신 측이 어떤 SA(보안 합의)를 적용할지 결정하는 데 사용. ESP 헤더에 포함됨||

Q5. DH 키 교환이 안전한 이유는? ||이산 로그 문제 — 공개 값(g, p, A, B)을 알아도 비밀 지수(a, b)를 구하는 것이 계산적으로 불가능. 도청자가 모든 공개 통신을 봐도 공유 비밀 키를 도출할 수 없음||

Q6. IPsec에서 SA가 단방향인 이유와 그 결과는? ||각 SA는 한 방향의 트래픽만 보호 (보안 파라미터가 방향별로 다를 수 있음). 따라서 양방향 통신에는 SA 2개(인바운드 + 아웃바운드)가 필요||

IPsec Mastery — From VPN Tunnel Internals to Deployment

IPsec Deep Dive

Introduction

You know that turning on a VPN slows down the internet, but do you know why? It is because IPsec, the protocol underneath, is encrypting, authenticating, and tunneling every single packet.

IPsec is essential knowledge not only for network engineers but also for cloud architects (VPC peering, Site-to-Site VPN), DevOps engineers (WireGuard vs IPsec), and security engineers alike.

What Is IPsec?

IPsec (IP Security) = A security protocol suite operating at the IP layer (L3)

Components:
├── AH (Authentication Header): Authentication only (integrity + origin verification)
├── ESP (Encapsulating Security Payload): Encryption + Authentication (99% in practice)
├── IKE (Internet Key Exchange): Key exchange + SA negotiation
└── SA (Security Association): Security connection information store

Core Concepts

SA (Security Association) — The Contract of a Secure Connection

SA = A "security agreement" between two devices

Included information:
├── SPI (Security Parameter Index): SA identifier (32-bit)
├── Encryption algorithm: AES-256-GCM
├── Authentication algorithm: SHA-256 HMAC
├── Key value: Shared secret key
├── Lifetime: 3600 seconds or 100GB
└── Mode: Tunnel / Transport

SAs are unidirectional → Bidirectional communication requires 2 SAs!

Tunnel Mode vs Transport Mode

[Transport Mode]
  Host-to-host direct communication
  Original IP header preserved, only payload encrypted

  ┌──────────┬──────────┬────────────────┐
IP Header│ESP Header│ Encrypted   (original)│         │ Payload  └──────────┴──────────┴────────────────┘

[Tunnel Mode]Site-to-Site VPN
  Gateway-to-gateway (wraps the entire original packet)
  New IP header added, original IP is also encrypted!

  ┌──────────┬──────────┬─────────────────────────┐
New IPESP Header│ EncryptedHeader   │          │ [Original IP + Data]  └──────────┴──────────┴─────────────────────────┘

Why Tunnel Mode matters in practice: Internal network IP addresses are never exposed to the outside!

ESP (Encapsulating Security Payload) — The Core

ESP Packet Structure:

┌─────────────────────────────────────────────┐
IP Header (new, tunnel mode)├─────────────────────────────────────────────┤
ESP Header│  ├── SPI (32bit): Which SA to use           │
│  └── Sequence Number (32bit): Anti-replay   │
├─────────────────────────────────────────────┤
Encrypted Region│  ├── Original IP Header (tunnel mode)│  ├── Original Payload (TCP/UDP + Data)│  └── ESP Trailer (Padding + Next Header)├─────────────────────────────────────────────┤
ESP Auth (ICV): HMAC-SHA256 (integrity)└─────────────────────────────────────────────┘
# ESP encryption process (pseudocode)
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os

def esp_encrypt(original_packet, sa):
    """ESP Encryption (AES-256-GCM)"""
    # 1. Get key and algorithm from SA
    key = sa.encryption_key  # 256-bit
    spi = sa.spi
    seq = sa.next_sequence_number()

    # 2. Create ESP Header
    esp_header = spi.to_bytes(4, 'big') + seq.to_bytes(4, 'big')

    # 3. Add Padding (align to block size)
    pad_len = (16 - (len(original_packet) + 2) % 16) % 16
    padding = bytes(range(1, pad_len + 1))
    esp_trailer = padding + bytes([pad_len, 4])  # 4 = IP-in-IP

    # 4. Encrypt (AES-256-GCM)
    nonce = os.urandom(12)
    aesgcm = AESGCM(key)
    plaintext = original_packet + esp_trailer
    ciphertext = aesgcm.encrypt(nonce, plaintext, esp_header)  # AAD = ESP Header

    # 5. New IP Header + ESP Header + Encrypted data
    new_ip = create_ip_header(sa.tunnel_src, sa.tunnel_dst)
    return new_ip + esp_header + nonce + ciphertext

IKE (Internet Key Exchange) — Key Negotiation

The most complex part of IPsec! It consists of two phases.

Phase 1 (IKE SA) — "Can we trust each other?"

Purpose: Establish a secure channel (to protect Phase 2)

[Initiator]                    [Responder]
    │                              │
    │──── SA Proposal ────────────▶│  Propose encryption/hash/DH group
    │◀─── SA Accepted ────────────│  Agreement
    │                              │
    │──── DH Public Value ────────▶│  Diffie-Hellman key exchange
    │◀─── DH Public Value ────────│  Both derive the same secret key!
    │                              │
    │──── Auth (PSK/Cert) ────────▶│  Pre-shared key or certificate
    │◀─── Auth ────────────────────│  Mutual authentication
    │                              │
    ╔══════════════════════════════╗
IKE SA established          ║
      (encrypted channel)    ╚══════════════════════════════╝

Phase 2 (IPsec SA) — "What traffic to protect and how"

Inside the channel protected by IKE SA:

[Initiator]                    [Responder]
    │                              │
    │──── IPsec SA Proposal ──────▶│  ESP/AH, encryption algorithm
    │◀─── IPsec SA Accepted ──────│  Agreement
    │                              │
    │──── Traffic Selector ────────▶│  Which IP/port ranges to protect?
    │◀─── Traffic Selector ────────│  Agreement
    │                              │
    ╔══════════════════════════════╗
IPsec SA established (x2,    ║  bidirectional)    ║  → Actual data encryption    ║
    ║    begins!    ╚══════════════════════════════╝

Diffie-Hellman Key Exchange (The Magic at the Core)

# DH Key Exchange — Even an eavesdropper cannot learn the secret key!
p = 23  # Large prime (actual: 2048/4096 bit)
g = 5   # Generator

# Alice
a = 6   # Alice's secret value
A = pow(g, a, p)  # 5^6 mod 23 = 8  → Transmitted publicly

# Bob
b = 15  # Bob's secret value
B = pow(g, b, p)  # 5^15 mod 23 = 19 → Transmitted publicly

# Derive the shared secret key (same value!)
alice_secret = pow(B, a, p)  # 19^6 mod 23 = 2
bob_secret = pow(A, b, p)    # 8^15 mod 23 = 2

assert alice_secret == bob_secret  # ✅ Same secret key!
# Eavesdropper: Even knowing p=23, g=5, A=8, B=19,
# without knowing a or b, the secret key 2 cannot be computed
# (Discrete Logarithm Problem)

Practical Example: AWS Site-to-Site VPN

On-premises (192.168.1.0/24)
    ├── Customer Gateway (IPsec)
    │       │
    │       │ ══ IPsec Tunnel 1 (Active) ══
    │       │ ══ IPsec Tunnel 2 (Standby) ══
    │       │
    ├── Virtual Private Gateway
AWS VPC (10.0.0.0/16)
# IPsec VPN setup on Linux (strongSwan)
sudo apt install strongswan

# /etc/ipsec.conf
cat << 'EOF'
conn aws-vpn
    type=tunnel
    auto=start
    left=203.0.113.1          # Local public IP
    leftsubnet=192.168.1.0/24 # Local network
    right=52.10.20.30         # AWS VGW IP
    rightsubnet=10.0.0.0/16   # AWS VPC CIDR
    ike=aes256-sha256-modp2048
    esp=aes256-sha256
    keyexchange=ikev2
    authby=secret
EOF

# /etc/ipsec.secrets
echo '203.0.113.1 52.10.20.30 : PSK "MyPreSharedKey123"' | sudo tee /etc/ipsec.secrets

# Start
sudo ipsec restart
sudo ipsec status

IPsec vs WireGuard vs OpenVPN

ItemIPsec (IKEv2)WireGuardOpenVPN
LayerL3L3L3/L4
Codebase~400K lines~4K lines~100K lines
SpeedFastFastestModerate
ConfigurationComplexSimpleModerate
MobileExcellent (IKEv2)ExcellentModerate
EnterpriseStandardEmergingWidely used

Quiz — IPsec (Click to reveal!)

Q1. What is the difference between ESP and AH? ||ESP: Encryption + Authentication (integrity). AH: Authentication only (no encryption). ESP is used 99% of the time in practice.||

Q2. What is the difference between Tunnel Mode and Transport Mode? ||Tunnel Mode: Wraps the entire original IP packet in a new IP and encrypts it (gateway-to-gateway VPN). Transport Mode: Keeps the original IP header, encrypts only the payload (direct host-to-host).||

Q3. What are the roles of IKE Phase 1 and Phase 2? ||Phase 1: Establish IKE SA — DH key exchange + mutual authentication to secure a channel. Phase 2: Establish IPsec SA — Negotiate actual traffic protection policies inside the Phase 1 channel.||

Q4. What is an SPI (Security Parameter Index)? ||A 32-bit identifier used by the receiver to determine which SA (security agreement) to apply. It is included in the ESP header.||

Q5. Why is the DH key exchange secure? ||The Discrete Logarithm Problem — even knowing the public values (g, p, A, B), it is computationally infeasible to determine the secret exponents (a, b). An eavesdropper who sees all public communication cannot derive the shared secret key.||

Q6. Why are SAs unidirectional in IPsec, and what is the consequence? ||Each SA protects traffic in only one direction (security parameters can differ per direction). Therefore, bidirectional communication requires 2 SAs (inbound + outbound).||

Quiz

Q1: What is the main topic covered in "IPsec Mastery — From VPN Tunnel Internals to Deployment"?

IPsec core protocols (AH, ESP, IKE), Tunnel Mode vs Transport Mode, SA/SPI concepts, and the Phase 1/Phase 2 negotiation process. We dissect the entire journey of a packet being encrypted and delivered, with diagrams and code.

Q2: What is Core Concepts? SA (Security Association) — The Contract of a Secure Connection Tunnel Mode vs Transport Mode Why Tunnel Mode matters in practice: Internal network IP addresses are never exposed to the outside!

Q3: Explain the core concept of IKE (Internet Key Exchange) — Key Negotiation. The most complex part of IPsec! It consists of two phases. Phase 1 (IKE SA) — "Can we trust each other?" Phase 2 (IPsec SA) — "What traffic to protect and how" Diffie-Hellman Key Exchange (The Magic at the Core)

Q4: What are the key differences in IPsec vs WireGuard vs OpenVPN? Q1. What is the difference between ESP and AH? Q2. What is the difference between Tunnel Mode and Transport Mode? Q3. What are the roles of IKE Phase 1 and Phase 2? Q4. What is an SPI (Security Parameter Index)? Q5. Why is the DH key exchange secure? Q6.