Post

Network

Network

목차

Part 1: 네트워크 기초

  1. 네트워크 기본 개념
  1. 물리 계층과 데이터 링크 계층
  1. 네트워크 계층 (IP)
  1. 전송 계층
  1. 응용 계층

Part 2: 리눅스 네트워킹

  1. 리눅스 네트워크 스택
  1. 리눅스 네트워크 도구
  1. iptables와 Netfilter
  1. 라우팅과 포워딩

Part 3: 가상 네트워크 (컨테이너 네트워킹의 기반)

  1. 가상 네트워크 디바이스
  1. 네트워크 네임스페이스
  1. 언더레이 vs 오버레이 네트워크
  1. SDN과 현대 네트워킹

Part 1: 네트워크 기초

1. 네트워크 기본 개념

1.1 OSI 7계층과 TCP/IP 모델

OSI 7계층 모델

OSI(Open Systems Interconnection) 모델은 네트워크 통신을 7개의 계층으로 추상화한 이론적 모델이다:

물리 계층 (Physical Layer)

  • 실제 하드웨어를 통한 비트 전송
  • 전압, 전파, 광신호 등
  • 예: 이더넷 케이블, 광섬유, 무선 신호

데이터 링크 계층 (Data Link Layer)

  • 인접한 노드 간 프레임 전송
  • MAC 주소 기반 통신
  • 에러 검출 및 복구
  • 예: Ethernet, Wi-Fi, ARP

네트워크 계층 (Network Layer)

  • 논리적 주소(IP) 기반 라우팅
  • 패킷 포워딩
  • 예: IP, ICMP, IGMP

전송 계층 (Transport Layer)

  • 종단 간 신뢰성 있는 데이터 전송
  • 포트 기반 프로세스 구분
  • 예: TCP, UDP

세션 계층 (Session Layer)

  • 세션 관리 (연결 설정, 유지, 종료)
  • 대화 제어

표현 계층 (Presentation Layer)

  • 데이터 형식 변환
  • 암호화/복호화
  • 압축/압축 해제

응용 계층 (Application Layer)

  • 사용자 애플리케이션 인터페이스
  • 예: HTTP, FTP, SMTP, DNS

TCP/IP 모델

실제 인터넷에서 사용되는 4계층 모델:

네트워크 접근 계층 (Network Access Layer)

  • OSI의 물리 + 데이터 링크 계층에 해당
  • Ethernet, Wi-Fi 등

인터넷 계층 (Internet Layer)

  • OSI의 네트워크 계층에 해당
  • IP, ICMP, ARP

전송 계층 (Transport Layer)

  • OSI의 전송 계층과 동일
  • TCP, UDP

응용 계층 (Application Layer)

  • OSI의 세션 + 표현 + 응용 계층을 통합
  • HTTP, DNS, SSH 등

1.2 IP 주소와 서브넷

IPv4 주소 체계

IPv4 주소는 32비트로 구성되며, 일반적으로 점-십진 표기법으로 표현된다:

  • 형식: 192.168.1.10
  • 4개의 옥텟(8비트)으로 구성
  • 각 옥텟은 0-255 범위

IP 주소 클래스

초기 IPv4는 클래스 기반으로 나뉘었다:

Class A

  • 범위: 1.0.0.0 ~ 126.255.255.255
  • 기본 서브넷 마스크: 255.0.0.0 (/8)
  • 대규모 네트워크용

Class B

  • 범위: 128.0.0.0 ~ 191.255.255.255
  • 기본 서브넷 마스크: 255.255.0.0 (/16)
  • 중규모 네트워크용

Class C

  • 범위: 192.0.0.0 ~ 223.255.255.255
  • 기본 서브넷 마스크: 255.255.255.0 (/24)
  • 소규모 네트워크용

Class D (멀티캐스트)

  • 범위: 224.0.0.0 ~ 239.255.255.255

Class E (예약)

  • 범위: 240.0.0.0 ~ 255.255.255.255

CIDR (Classless Inter-Domain Routing)

클래스 기반 주소의 비효율성을 해결하기 위해 도입:

  • 슬래시 표기법 사용: 192.168.1.0/24
  • /24는 네트워크 비트가 24개 (앞 3개 옥텟)
  • 호스트 비트는 8개 (마지막 옥텟)
  • 사용 가능한 호스트: 2^8 - 2 = 254개 (네트워크 주소와 브로드캐스트 주소 제외)

서브넷 마스크

네트워크 부분과 호스트 부분을 구분:

  • /24 = 255.255.255.0
  • /16 = 255.255.0.0
  • /8 = 255.0.0.0

예시 계산

192.168.1.0/24 네트워크:

  • 네트워크 주소: 192.168.1.0
  • 첫 번째 사용 가능 IP: 192.168.1.1
  • 마지막 사용 가능 IP: 192.168.1.254
  • 브로드캐스트 주소: 192.168.1.255
  • 총 호스트 수: 254개

사설 IP 주소 범위

인터넷에서 라우팅되지 않는 내부 네트워크용 주소:

  • Class A: 10.0.0.0/8 (10.0.0.0 ~ 10.255.255.255)
  • Class B: 172.16.0.0/12 (172.16.0.0 ~ 172.31.255.255)
  • Class C: 192.168.0.0/16 (192.168.0.0 ~ 192.168.255.255)

특수 IP 주소

  • 127.0.0.0/8: 루프백 주소 (localhost)
  • 0.0.0.0: 모든 인터페이스 또는 알 수 없는 주소
  • 169.254.0.0/16: APIPA (자동 사설 IP 주소)

1.3 캡슐화와 역캡슐화

캡슐화 (Encapsulation)란?

캡슐화는 데이터가 송신측에서 수신측으로 전달될 때, 각 계층을 거치면서 헤더(Header)트레일러(Trailer)를 추가하는 과정이다. 각 계층은 상위 계층으로부터 받은 데이터를 페이로드(Payload)로 취급하고, 자신의 제어 정보를 추가한다.

역캡슐화 (Decapsulation)란?

역캡슐화는 수신측에서 각 계층을 거치면서 해당 계층의 헤더를 제거하고 상위 계층으로 데이터를 전달하는 과정이다.

PDU (Protocol Data Unit) 개념

각 계층에서 처리하는 데이터 단위를 PDU라고 하며, 계층마다 다른 이름을 사용한다:

계층PDU 이름헤더 정보
응용 계층DataHTTP, DNS 등 프로토콜 데이터
전송 계층Segment (TCP) / Datagram (UDP)출발지/목적지 포트, 시퀀스 번호, 체크섬
네트워크 계층Packet출발지/목적지 IP 주소, TTL, 프로토콜
데이터 링크 계층Frame출발지/목적지 MAC 주소, FCS (에러 검출)
물리 계층Bit전기 신호, 광신호

캡슐화 과정 (송신 측)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
[응용 계층]
  HTTP Request: "GET /index.html"
  ↓

[전송 계층]
  TCP Header 추가
  ┌─────────────┬──────────────────────┐
  │ TCP Header  │ HTTP Data            │
  │ (Src Port,  │ "GET /index.html"    │
  │  Dst Port)  │                      │
  └─────────────┴──────────────────────┘
  = TCP Segment
  ↓

[네트워크 계층]
  IP Header 추가
  ┌─────────────┬─────────────┬──────────────────┐
  │ IP Header   │ TCP Header  │ HTTP Data        │
  │ (Src IP,    │             │                  │
  │  Dst IP)    │             │                  │
  └─────────────┴─────────────┴──────────────────┘
  = IP Packet
  ↓

[데이터 링크 계층]
  Ethernet Header + Trailer 추가
  ┌──────────┬─────────┬──────────┬──────────┬─────┐
  │ Ethernet │ IP Hdr  │ TCP Hdr  │ HTTP Data│ FCS │
  │ Header   │         │          │          │     │
  │(Src MAC, │         │          │          │     │
  │ Dst MAC) │         │          │          │     │
  └──────────┴─────────┴──────────┴──────────┴─────┘
  = Ethernet Frame
  ↓

[물리 계층]
  Bit 스트림으로 변환 → 전송

역캡슐화 과정 (수신 측)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[물리 계층]
  Bit 스트림 수신
  ↓

[데이터 링크 계층]
  Ethernet Frame 수신
  1. FCS로 에러 검사
  2. 목적지 MAC 주소 확인 (내 MAC과 일치?)
  3. Ethernet Header/Trailer 제거
  4. IP Packet을 네트워크 계층으로 전달
  ↓

[네트워크 계층]
  IP Packet 수신
  1. 목적지 IP 주소 확인 (내 IP와 일치?)
  2. TTL 확인 및 감소
  3. IP Header 제거
  4. TCP Segment를 전송 계층으로 전달
  ↓

[전송 계층]
  TCP Segment 수신
  1. 목적지 포트 확인 (어느 프로세스?)
  2. 체크섬으로 무결성 확인
  3. TCP Header 제거
  4. HTTP Data를 응용 계층으로 전달
  ↓

[응용 계층]
  HTTP Request 수신: "GET /index.html"
  웹 서버 프로세스가 처리

실제 예시: HTTP 요청의 캡슐화

Client (192.168.1.10) → Server (192.168.1.20:80) HTTP 요청을 보낼 때:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[응용 계층]
  "GET /index.html HTTP/1.1"

[전송 계층 - TCP Segment]
  Source Port: 54321
  Destination Port: 80
  Sequence Number: 1000
  Data: "GET /index.html HTTP/1.1"

[네트워크 계층 - IP Packet]
  Source IP: 192.168.1.10
  Destination IP: 192.168.1.20
  Protocol: TCP (6)
  TTL: 64
  Data: [TCP Segment]

[데이터 링크 계층 - Ethernet Frame]
  Source MAC: AA:BB:CC:DD:EE:FF
  Destination MAC: 11:22:33:44:55:66
  EtherType: 0x0800 (IPv4)
  Data: [IP Packet]
  FCS: 에러 검출 코드

주소 매핑 흐름

각 계층에서 사용하는 주소가 다르므로, 계층 간 주소 변환이 필요하다:

1
2
3
4
5
응용 계층:   www.example.com (Domain Name)
             ↓ DNS 조회
네트워크 계층: 192.168.1.20 (IP Address)
             ↓ ARP 프로토콜
데이터 링크:  11:22:33:44:55:66 (MAC Address)

캡슐화의 중요성

  1. 계층 간 독립성: 각 계층은 상위/하위 계층의 세부 구현을 알 필요 없음
  2. 유연성: 특정 계층의 프로토콜 변경이 다른 계층에 영향을 주지 않음
  3. 표준화: 각 계층의 PDU 형식이 표준화되어 상호 운용성 보장
  4. 에러 검출: 각 계층에서 독립적으로 에러 검출/복구 가능

면접 질문 예시

Q: “OSI 7계층에서 데이터가 송신될 때 각 계층에서 추가되는 정보는 무엇인가?”

A:

  • 전송 계층: 출발지/목적지 포트 번호 (어떤 프로세스와 통신할지)
  • 네트워크 계층: 출발지/목적지 IP 주소 (어떤 호스트로 보낼지)
  • 데이터 링크 계층: 출발지/목적지 MAC 주소 (같은 네트워크에서 어떤 장치로 보낼지)
  • 각 계층의 헤더는 해당 계층의 프로토콜이 필요로 하는 제어 정보를 담고 있음

Q: “왜 IP 주소만 있으면 되는데 MAC 주소도 필요한가?”

A: IP 주소는 논리적 주소로 네트워크 간 라우팅에 사용되고, MAC 주소는 물리적 주소로 같은 네트워크(L2 세그먼트) 내에서 실제 통신에 사용됨. 라우터를 거칠 때마다 MAC 주소는 변경되지만(다음 홉의 MAC으로), IP 주소는 최종 목적지까지 유지됨.

1.4 MAC 주소와 ARP

MAC 주소 (Media Access Control Address)

MAC 주소는 네트워크 인터페이스 카드(NIC)의 물리적 주소이다:

  • 48비트 (6바이트) 주소
  • 16진수 표기: 00:1A:2B:3C:4D:5E
  • 전 세계적으로 고유 (이론상)
  • 앞 3바이트: 제조사 식별 (OUI)
  • 뒤 3바이트: 제조사가 할당한 고유 번호

ARP (Address Resolution Protocol)

ARP는 IP 주소를 MAC 주소로 변환하는 프로토콜이다.

ARP 작동 과정

  1. 호스트 A가 호스트 B(192.168.1.10)와 통신하려 함
  2. 호스트 A의 ARP 캐시 확인
  3. 캐시에 없으면 ARP Request를 브로드캐스트
  • “192.168.1.10의 MAC 주소가 무엇인가요?”
  1. 해당 IP를 가진 호스트 B가 ARP Reply로 응답
  • “제 MAC 주소는 00:1A:2B:3C:4D:5E이다”
  1. 호스트 A가 ARP 캐시에 저장
  2. 이후 통신에서는 캐시 사용 (일정 시간 후 만료)

ARP 캐시 확인

1
2
3
4
5
6
7
8
9
# ARP 캐시 테이블 확인
arp -n
ip neigh show

# 특정 항목 추가 (정적 ARP)
arp -s 192.168.1.10 00:1A:2B:3C:4D:5E

# ARP 캐시 삭제
arp -d 192.168.1.10

RARP와 기타 변형

  • RARP (Reverse ARP): MAC → IP 변환 (현재는 거의 사용 안 함)
  • Gratuitous ARP: 자신의 IP를 브로드캐스트 (IP 충돌 검사, ARP 캐시 업데이트)
  • Proxy ARP: 라우터가 다른 네트워크의 ARP 요청에 대신 응답

2. 물리 계층과 데이터 링크 계층

2.1 Ethernet

Ethernet은 가장 널리 사용되는 데이터 링크 계층 프로토콜이다. IEEE 802.3 표준으로 정의되며 로컬 네트워크(LAN)에서 프레임 전송을 담당한다.

Ethernet 프레임 구조

  • Preamble: 동기화
  • Destination MAC: 수신자 MAC 주소
  • Source MAC: 송신자 MAC 주소
  • Type: 상위 계층 프로토콜 (IP=0x0800, ARP=0x0806)
  • Payload: 데이터
  • FCS: 오류 검사

Ethernet 속도

  • 10 Mbps (10BASE-T)
  • 100 Mbps (100BASE-TX)
  • 1 Gbps (1000BASE-T)
  • 10 Gbps (10GBASE-T)

2.2 Broadcast Domain vs Collision Domain

네트워크를 이해하는 데 주요 두 가지 개념으로, 네트워크 장비(Hub, Switch, Router)의 역할을 이해하는 데 필수적이다.

Collision Domain (충돌 도메인)

Collision Domain은 동시에 데이터를 전송할 때 충돌(Collision)이 발생할 수 있는 네트워크 영역이다.

특징:

  • 공유 매체 환경에서 발생 (예: 초기 Ethernet의 Hub 사용 시)
  • 같은 Collision Domain에 있는 장치들은 동시에 전송 불가능
  • CSMA/CD (Carrier Sense Multiple Access with Collision Detection) 프로토콜 사용
  • 충돌 발생 시 모든 장치가 전송 중단 후 랜덤 대기

Collision Domain 분할:

  • Hub: Collision Domain을 분할하지 못함 (모든 포트가 같은 Collision Domain)
  • Switch: 각 포트가 독립적인 Collision Domain (충돌 제거)
  • Router: 당연히 Collision Domain 분할

예시:

1
2
3
4
5
6
7
8
9
10
11
12
13
Hub 연결 (하나의 Collision Domain):
  [PC1] ─┐
  [PC2] ─┤─ Hub ─ [PC4]
  [PC3] ─┘
  → PC1, PC2, PC3, PC4 모두 같은 Collision Domain
  → PC1과 PC2가 동시 전송 시 충돌 발생

Switch 연결 (포트별 독립 Collision Domain):
  [PC1] ─┐
  [PC2] ─┤─ Switch ─ [PC4]
  [PC3] ─┘
  → 각 PC가 독립적인 Collision Domain
  → PC1과 PC2가 동시 전송 가능 (충돌 없음)

Broadcast Domain (브로드캐스트 도메인)

Broadcast Domain은 브로드캐스트 패킷이 전달되는 네트워크 영역이다.

특징:

  • 브로드캐스트 주소(예: 192.168.1.255)로 전송된 패킷이 도달하는 범위
  • ARP Request, DHCP Discover 등이 브로드캐스트 사용
  • Broadcast Domain이 클수록 불필요한 트래픽 증가 (성능 저하)

Broadcast Domain 분할:

  • Hub: Broadcast Domain을 분할하지 못함
  • Switch: Broadcast Domain을 분할하지 못함 (같은 VLAN 내에서는)
  • Router: Broadcast Domain 분할 (브로드캐스트를 전달하지 않음)
  • VLAN: Switch에서 논리적으로 Broadcast Domain 분할 가능

예시:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Switch 연결 (하나의 Broadcast Domain):
  [PC1] ─┐
  [PC2] ─┤─ Switch ─ [PC4]
  [PC3] ─┘
  → PC1, PC2, PC3, PC4 모두 같은 Broadcast Domain
  → PC1이 브로드캐스트 전송 시 PC2, PC3, PC4 모두 수신

Router 연결 (Broadcast Domain 분할):
  [PC1] ─ Switch1 ─┐
  [PC2] ─          │
                   Router ─ Switch2 ─ [PC3]
                   │                  [PC4]
  → 왼쪽(PC1, PC2)과 오른쪽(PC3, PC4)이 다른 Broadcast Domain
  → PC1의 브로드캐스트는 Router를 넘지 못함 (PC3, PC4 수신 못함)

네트워크 장비별 특성 비교

장비Collision DomainBroadcast Domain동작 계층
Hub분할 못함 (모든 포트 공유)분할 못함L1 (물리)
Switch분할함 (포트별 독립)분할 못함 (VLAN 없이)L2 (데이터 링크)
Router분할함분할함L3 (네트워크)

CSMA/CD (Carrier Sense Multiple Access with Collision Detection)

초기 Ethernet(Hub 사용 시)에서 충돌을 처리하는 메커니즘:

  1. CS (Carrier Sense): 전송 전에 매체가 사용 중인지 감지
  2. MA (Multiple Access): 여러 장치가 같은 매체 공유
  3. CD (Collision Detection): 충돌 감지 시 전송 중단

동작 과정:

1
2
3
4
5
6
7
8
1. PC1이 데이터 전송 전 매체 확인 (Idle?)
2. 매체가 비어있으면 전송 시작
3. 전송 중 충돌 감지 (다른 PC도 동시 전송)
4. 충돌 감지 시:
   - Jam Signal 전송 (다른 장치에게 충돌 알림)
   - 랜덤 백오프 시간 대기
   - 재전송 시도
5. 최대 16번 재시도 후 실패하면 포기

현대 네트워크의 변화:

  • Full-duplex Ethernet: Switch 사용으로 충돌 자체가 발생하지 않음
  • CSMA/CD 비활성화: Full-duplex에서는 불필요
  • Hub 퇴출: 거의 모든 네트워크가 Switch 기반

Unicast, Multicast, Broadcast, Anycast

패킷 전달 방식에 따른 분류:

Unicast (유니캐스트)

  • 1:1 통신: 특정 하나의 수신자에게만 전송
  • 목적지 MAC: 특정 장치의 MAC 주소
  • 목적지 IP: 특정 호스트의 IP 주소
  • 예: HTTP 요청, SSH 연결
1
2
[PC1] ─────> [PC2]
  (192.168.1.10 → 192.168.1.20)

Broadcast (브로드캐스트)

  • 1:All 통신: 같은 네트워크의 모든 장치에게 전송
  • 목적지 MAC: FF:FF:FF:FF:FF:FF
  • 목적지 IP: 네트워크 브로드캐스트 주소 (예: 192.168.1.255)
  • 예: ARP Request, DHCP Discover
1
2
[PC1] ─────> [모든 PC]
  (ARP: "192.168.1.20의 MAC 주소가 뭐야?")

Multicast (멀티캐스트)

  • 1:Many 통신: 특정 그룹의 장치들에게만 전송
  • 목적지 MAC: 01:00:5E:xx:xx:xx (IPv4 multicast)
  • 목적지 IP: 224.0.0.0 ~ 239.255.255.255 (Class D)
  • 예: 스트리밍, IPTV, 라우팅 프로토콜(OSPF, RIP)
  • 그룹에 가입한 장치만 수신 (IGMP 프로토콜 사용)
1
2
3
[PC1] ─────> [PC2] [PC4] (그룹 가입자만)
             [PC3]은 수신 안 함
  (멀티캐스트 그룹: 239.1.1.1)

Anycast (애니캐스트)

  • 1:Nearest 통신: 같은 IP를 가진 여러 서버 중 가장 가까운 하나에게 전송
  • 라우팅 프로토콜이 가장 가까운 서버로 자동 전달
  • 예: DNS Root Servers, CDN (Content Delivery Network)
  • IPv6에서 공식 지원
1
2
3
Client ─────> [Server A] (가장 가까운 서버)
              [Server B] (같은 IP를 가진 다른 서버)
              [Server C]

전달 방식 비교

방식목적지네트워크 부하사용 사례
Unicast1개낮음일반적인 통신 (HTTP, SSH)
Broadcast모든 장치높음ARP, DHCP
Multicast그룹 가입자중간스트리밍, IPTV
Anycast가장 가까운 1개낮음DNS, CDN (고가용성)

Broadcast Storm (브로드캐스트 폭풍)

Broadcast Domain이 너무 크면 발생하는 문제:

원인:

  • 네트워크 루프 (Switch 간 중복 연결)
  • 과도한 ARP Request
  • 잘못된 설정

증상:

  • 네트워크 전체 성능 급격히 저하
  • 모든 Switch의 CPU 사용률 100%
  • 정상적인 통신 불가능

해결책:

  1. STP (Spanning Tree Protocol): 루프 방지
  2. VLAN 분할: Broadcast Domain 축소
  3. Router 분할: 네트워크 세그먼트 분리
  4. Broadcast 제한: 일부 Switch는 broadcast rate limiting 지원

실전 면접 질문 예시

Q1: “Hub와 Switch의 차이를 Collision Domain 관점에서 설명하라”

A: Hub는 모든 포트가 하나의 Collision Domain을 공유하여 동시 전송 시 충돌이 발생하지만, Switch는 각 포트가 독립적인 Collision Domain이므로 충돌이 발생하지 않고 Full-duplex 통신이 가능하다. 이는 Switch가 MAC 주소 테이블을 사용해 프레임을 특정 포트로만 전달하기 때문이다.

Q2: “Broadcast Domain을 분할하는 방법은?”

A: 1) Router를 사용하여 물리적으로 분할 (가장 확실), 2) VLAN을 사용하여 논리적으로 분할 (같은 Switch 내에서도 가능), 3) L3 Switch를 사용하여 VLAN 간 라우팅. Router는 브로드캐스트를 전달하지 않으므로 자연스럽게 Broadcast Domain을 분할한다.

Q3: “왜 Broadcast Domain을 분할해야 하는가?”

A: Broadcast Domain이 클수록 모든 장치가 불필요한 브로드캐스트 패킷을 처리해야 하므로 1) CPU 리소스 낭비, 2) 네트워크 대역폭 낭비, 3) Broadcast Storm 위험 증가. VLAN과 Router로 적절히 분할하면 성능 향상과 보안 강화 효과를 얻을 수 있다.


3. 네트워크 계층 (IP)

3.1 IP (Internet Protocol)

IP의 역할

IP는 패킷을 목적지까지 전달하는 네트워크 계층 프로토콜이다.

IP의 특징

  • 비연결성 (Connectionless): 연결 설정 없이 바로 전송
  • 비신뢰성 (Unreliable): 패킷 손실, 순서 뒤바뀜 등을 보장하지 않음
  • 최선형 전달 (Best Effort): 가능한 한 최선을 다해 전달하지만 보장은 없음

IPv4 헤더 구조

주요 필드:

  • Version: IP 버전 (4)
  • Header Length: 헤더 길이
  • TOS (Type of Service): QoS 정보
  • Total Length: 전체 패킷 크기
  • Identification, Flags, Fragment Offset: 단편화 관련
  • TTL (Time To Live): 라우터 홉 제한 (패킷 루프 방지)
  • Protocol: 상위 계층 프로토콜 (TCP=6, UDP=17, ICMP=1)
  • Header Checksum: 헤더 오류 검사
  • Source IP Address: 출발지 IP
  • Destination IP Address: 목적지 IP

TTL (Time To Live)

TTL은 패킷이 무한 루프를 방지하는 메커니즘이다:

  • 초기값 설정 (보통 64 또는 128)
  • 라우터를 거칠 때마다 1씩 감소
  • 0이 되면 패킷 폐기 및 ICMP Time Exceeded 메시지 전송
  • traceroute 명령이 이 원리를 활용

IP 단편화 (Fragmentation)

네트워크 경로의 MTU(Maximum Transmission Unit)가 다를 때:

  • 패킷을 작은 조각으로 분할
  • 목적지에서 재조립
  • 성능 저하 원인이므로 가능하면 피해야 함
  • Path MTU Discovery로 최적 크기 탐색

3.2 ICMP (Internet Control Message Protocol)

ICMP의 역할

ICMP는 네트워크 진단과 에러 보고를 위한 프로토콜이다.

주요 ICMP 메시지 타입

Echo Request/Reply (Type 8/0)

  • ping 명령에서 사용
  • 네트워크 연결성 테스트

Destination Unreachable (Type 3)

  • 패킷이 목적지에 도달할 수 없을 때
  • 다양한 코드:
    • Code 0: Network Unreachable
    • Code 1: Host Unreachable
    • Code 3: Port Unreachable
    • Code 4: Fragmentation Needed (PMTU Discovery)

Time Exceeded (Type 11)

  • TTL이 0이 되었을 때
  • traceroute가 이용

Redirect (Type 5)

  • 더 나은 라우트 알림

ICMP와 보안

ICMP는 진단 도구이지만 보안 위험도 있다:

  • Ping flood (DDoS 공격)
  • Smurf attack (ICMP 증폭 공격)
  • 정보 수집에 악용 가능

많은 방화벽이 ICMP를 제한하거나 차단한다.

3.3 NAT (Network Address Translation)

NAT란?

NAT는 IP 패킷의 출발지 또는 목적지 IP 주소를 변환하는 기술로, 주로 사설 IP를 공인 IP로 변환하여 인터넷 접근을 가능하게 한다.

NAT의 필요성

  1. IPv4 주소 고갈 문제 해결: 공인 IP 1개로 수백 대의 사설 IP 장치가 인터넷 사용
  2. 보안: 내부 네트워크 구조 은닉
  3. 유연성: 내부 IP 체계 변경 시 외부에 영향 없음

NAT 종류

SNAT (Source NAT) - 출발지 주소 변환

사설 네트워크에서 인터넷으로 나갈 때 출발지 IP를 변환:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
내부 → 외부 통신:

[사설 PC]                  [NAT 라우터]              [인터넷 서버]
192.168.1.10:5000  →   203.0.113.5:61000   →   8.8.8.8:53
  (Private IP)         (Public IP:동적 포트)     (Google DNS)

1. PC가 패킷 전송: src=192.168.1.10:5000, dst=8.8.8.8:53
2. NAT 라우터가 출발지 변환:
   - src=192.168.1.10:5000 → src=203.0.113.5:61000
   - NAT 테이블에 매핑 저장:
     (192.168.1.10:5000 ↔ 203.0.113.5:61000)
3. 인터넷으로 전송: src=203.0.113.5:61000, dst=8.8.8.8:53

응답 패킷:
4. 서버 응답: src=8.8.8.8:53, dst=203.0.113.5:61000
5. NAT 라우터가 목적지 변환:
   - dst=203.0.113.5:61000 → dst=192.168.1.10:5000
6. PC로 전달: src=8.8.8.8:53, dst=192.168.1.10:5000

DNAT (Destination NAT) - 목적지 주소 변환

외부에서 내부 서버로 들어올 때 목적지 IP를 변환 (Port Forwarding):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
외부 → 내부 통신 (포트 포워딩):

[인터넷 클라이언트]      [NAT 라우터]              [내부 웹서버]
1.2.3.4:54321  →   203.0.113.5:80    →   192.168.1.100:80
   (Public)          (Public:80)          (Private)

1. 클라이언트 요청: src=1.2.3.4:54321, dst=203.0.113.5:80
2. NAT 라우터가 목적지 변환:
   - dst=203.0.113.5:80 → dst=192.168.1.100:80
   - NAT 규칙: 203.0.113.5:80 → 192.168.1.100:80
3. 내부 서버로 전달: src=1.2.3.4:54321, dst=192.168.1.100:80

응답 패킷:
4. 서버 응답: src=192.168.1.100:80, dst=1.2.3.4:54321
5. NAT 라우터가 출발지 변환:
   - src=192.168.1.100:80 → src=203.0.113.5:80
6. 클라이언트로 전달: src=203.0.113.5:80, dst=1.2.3.4:54321

PAT (Port Address Translation) / NAPT / IP Masquerading

하나의 공인 IP로 여러 사설 IP를 변환 (포트 번호 활용):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
여러 PC가 동시에 인터넷 사용:

PC1: 192.168.1.10:5000 → NAT → 203.0.113.5:61000 → Internet
PC2: 192.168.1.20:6000 → NAT → 203.0.113.5:61001 → Internet
PC3: 192.168.1.30:7000 → NAT → 203.0.113.5:61002 → Internet

NAT 테이블:
┌──────────────────┬───────────────────┬─────────┐
│ 사설 IP:Port      │ 공인 IP:Port      │ 타이머  │
├──────────────────┼───────────────────┼─────────┤
│ 192.168.1.10:5000│ 203.0.113.5:61000│ 120s    │
│ 192.168.1.20:6000│ 203.0.113.5:61001│ 300s    │
│ 192.168.1.30:7000│ 203.0.113.5:61002│ 60s     │
└──────────────────┴───────────────────┴─────────┘

포트 번호로 어느 PC의 패킷인지 구분!

Full Cone NAT (완전 원뿔형)

  • 외부의 모든 호스트가 매핑된 포트로 접근 가능
  • 가장 개방적, 보안 취약
  • 게임/P2P에 유리
1
2
3
4
내부: 192.168.1.10:5000 → 공인: 203.0.113.5:61000

이후 모든 외부 IP:Port에서 203.0.113.5:61000으로 패킷 전송 가능
→ 자동으로 192.168.1.10:5000으로 전달

Restricted Cone NAT (제한된 원뿔형)

  • 내부에서 먼저 통신한 외부 IP에서만 접근 가능
  • 포트는 상관없음
1
2
3
4
내부 → 외부: 192.168.1.10:5000 → 8.8.8.8:53

허용: 8.8.8.8:any_port → 203.0.113.5:61000 (IP 일치)
차단: 1.1.1.1:53 → 203.0.113.5:61000 (IP 불일치)

Port Restricted Cone NAT (포트 제한 원뿔형)

  • 내부에서 통신한 외부 IP:Port 조합만 허용
  • 가장 제한적
1
2
3
4
내부 → 외부: 192.168.1.10:5000 → 8.8.8.8:53

허용: 8.8.8.8:53 → 203.0.113.5:61000
차단: 8.8.8.8:80 → 203.0.113.5:61000 (포트 불일치)

Symmetric NAT (대칭형)

  • 목적지마다 다른 공인 포트 할당
  • 가장 보안적, P2P 어려움
1
2
3
같은 내부 소스라도 목적지에 따라 다른 매핑:
192.168.1.10:5000 → 8.8.8.8:53     → 203.0.113.5:61000
192.168.1.10:5000 → 1.1.1.1:53     → 203.0.113.5:61001 (다름!)

NAT 타입 비교

NAT 타입외부 접근 가능보안 수준P2P 적합성
Full Cone모두 가능낮음매우 좋음
Restricted Cone통신한 IP만중간좋음
Port Restricted통신한 IP:Port만높음보통
Symmetric거의 불가능매우 높음매우 어려움

NAT Traversal (NAT 통과)

NAT 뒤의 장치끼리 직접 통신하는 문제 해결:

STUN (Session Traversal Utilities for NAT)

1
2
3
4
5
6
7
목적: 자신의 공인 IP:Port 확인

Client ──┬───> STUN Server (공인 IP)
         │
         └───< "당신의 공인 IP:Port는 203.0.113.5:61000"

→ P2P 연결 시 상대에게 이 정보 전달

TURN (Traversal Using Relays around NAT)

1
2
3
4
5
6
7
목적: Symmetric NAT 등 직접 연결 불가 시 릴레이

Client A ──────> TURN Server ◄────── Client B
                 (중계 서버)

→ 직접 연결 실패 시 TURN 서버가 패킷 중계
→ 대역폭 소모, 지연 증가

ICE (Interactive Connectivity Establishment)

1
2
3
4
STUN + TURN 조합:
1. STUN으로 직접 연결 시도
2. 실패 시 TURN 릴레이 사용
→ WebRTC가 ICE 사용

NAT의 문제점

  1. End-to-End 원칙 위배: 패킷 헤더 수정
  2. 일부 프로토콜 문제: FTP(능동 모드), SIP 등
  3. NAT 테이블 고갈: 동시 연결 수 제한
  4. NAT 타임아웃: 유휴 연결 자동 종료 (보통 60초)
  5. P2P 어려움: NAT Traversal 필요

Linux에서 NAT 설정

iptables를 이용한 SNAT (IP Masquerading):

1
2
3
4
5
6
7
8
# IP 포워딩 활성화
sysctl -w net.ipv4.ip_forward=1

# SNAT (Masquerade): 사설 네트워크 → 인터넷
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE

# 또는 고정 공인 IP 사용 시:
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT --to-source 203.0.113.5

iptables를 이용한 DNAT (Port Forwarding):

1
2
3
4
5
6
7
8
# 외부 80 포트 → 내부 웹서버 192.168.1.100:80
iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 80 -j DNAT --to-destination 192.168.1.100:80

# 외부 2222 포트 → 내부 SSH 서버 192.168.1.50:22
iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 2222 -j DNAT --to-destination 192.168.1.50:22

# DNAT와 함께 FORWARD 체인 허용 필요:
iptables -A FORWARD -p tcp -d 192.168.1.100 --dport 80 -j ACCEPT

NAT 테이블 확인:

1
2
3
4
5
6
7
8
9
# NAT 규칙 확인
iptables -t nat -L -n -v

# Conntrack (연결 추적) 테이블 확인
conntrack -L
cat /proc/net/nf_conntrack

# 현재 NAT 세션 수
conntrack -L | wc -l

NAT와 Docker

Docker도 NAT를 사용하여 컨테이너 네트워킹 구현:

1
2
3
4
5
6
# 컨테이너 → 외부 (SNAT):
iptables -t nat -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE

# 외부 → 컨테이너 (DNAT, 포트 매핑):
docker run -p 8080:80 nginx
→ iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 172.17.0.2:80

NAT 타임아웃 조정

1
2
3
4
5
6
7
8
9
10
# TCP 연결 NAT 타임아웃 확인
sysctl net.netfilter.nf_conntrack_tcp_timeout_established
# 기본값: 432000초 (5일)

# UDP NAT 타임아웃 확인
sysctl net.netfilter.nf_conntrack_udp_timeout
# 기본값: 30초

# 타임아웃 변경 (예: UDP 120초로)
sysctl -w net.netfilter.nf_conntrack_udp_timeout=120

면접 질문 예시

Q1: “SNAT와 DNAT의 차이는?”

A:

  • SNAT: 출발지 IP 변환, 사설 네트워크 → 인터넷 통신 시 사용. 내부 PC들이 하나의 공인 IP로 인터넷 접근
  • DNAT: 목적지 IP 변환, 인터넷 → 내부 서버 접근 시 사용 (포트 포워딩). 공인 IP:Port를 내부 서버 IP:Port로 변환
  • 예: 홈 공유기는 SNAT로 내부 기기들의 인터넷 접근 제공, DNAT로 외부에서 특정 포트를 내부 서버로 포워딩

Q2: “PAT와 NAT의 차이는?”

A: NAT는 IP 주소만 변환하지만, PAT(Port Address Translation)는 IP와 포트를 함께 변환하여 하나의 공인 IP로 수천 개의 사설 IP 장치를 동시에 인터넷 연결 가능. 일반적으로 말하는 “NAT”는 사실 PAT를 의미함. PAT는 포트 번호로 각 내부 장치를 구분.

Q3: “NAT 환경에서 P2P 연결이 어려운 이유는?”

A: NAT는 내부→외부 통신 시 매핑을 생성하지만, 외부에서 먼저 접근 시 어느 내부 장치로 보낼지 알 수 없음. 특히 Symmetric NAT는 목적지마다 다른 포트를 할당하여 더 어려움. 해결: STUN으로 공인 IP:Port 확인 후 직접 연결 시도, 실패 시 TURN 서버로 릴레이.

Q4: “Docker 컨테이너가 외부와 통신하는 과정을 NAT 관점에서 설명하라”

A: 컨테이너(172.17.0.2) → 외부(8.8.8.8) 통신 시:

  1. 패킷: src=172.17.0.2, dst=8.8.8.8
  2. docker0 브리지 → 호스트 네트워크 스택
  3. iptables SNAT (MASQUERADE): src=172.17.0.2 → src=호스트_IP
  4. 외부로 전송, 응답은 역순으로 DNAT하여 컨테이너로 전달
  5. 포트 매핑(-p 8080:80) 시 PREROUTING에서 DNAT: dst=호스트:8080 → dst=172.17.0.2:80

4. 전송 계층

4.1 TCP (Transmission Control Protocol)

TCP의 특징

TCP는 신뢰성 있는 연결 지향 프로토콜이다:

  • 연결 지향: 3-way handshake로 연결 설정
  • 신뢰성 보장: 패킷 손실 시 재전송
  • 순서 보장: 순서가 뒤바뀐 패킷 재정렬
  • 흐름 제어: 수신자 버퍼 오버플로 방지
  • 혼잡 제어: 네트워크 혼잡 완화

TCP 헤더 구조

주요 필드:

  • Source/Destination Port: 송신/수신 포트
  • Sequence Number: 바이트 스트림 상의 위치
  • Acknowledgment Number: 다음 수신할 바이트 번호
  • Flags: SYN, ACK, FIN, RST, PSH, URG
  • Window Size: 수신 윈도우 크기 (흐름 제어)
  • Checksum: 세그먼트 오류 검사

3-Way Handshake (연결 설정)

  1. SYN: 클라이언트 → 서버
  • “연결 요청, 내 초기 시퀀스 번호는 X이다”
  1. SYN-ACK: 서버 → 클라이언트
  • “연결 요청 확인, 내 초기 시퀀스 번호는 Y이다. X+1 수신 완료”
  1. ACK: 클라이언트 → 서버
  • “Y+1 수신 완료, 연결 완료”

4-Way Handshake (연결 종료)

  1. FIN: 클라이언트 → 서버
  • “데이터 전송을 완료”
  1. ACK: 서버 → 클라이언트
  • “확인 완료”
  1. FIN: 서버 → 클라이언트
  • “데이터 전송을 완료”
  1. ACK: 클라이언트 → 서버
  • “확인 완료”

TIME_WAIT 상태

연결 종료 후 일정 시간(2 * MSL) 동안 유지:

  • 지연된 패킷이 새 연결에 영향을 주지 않도록 방지
  • 일반적으로 60초 (Linux는 기본 60초)

TCP State Transition Diagram (상태 전환도)

TCP 연결의 생명주기 동안 거치는 모든 상태와 전환 과정:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
                          [CLOSED]
                              │
                              │ (passive open)
                              ↓
        (active open)    [LISTEN]
        SYN sent             │
Client ──────────────────────┤
    │                        │ (SYN received)
    │                        ↓
    │                   [SYN_RCVD]
    │                        │
    │                        │ (SYN+ACK sent)
    ↓                        │
[SYN_SENT] ──────────────────┤ (ACK received)
    │                        │
    │ (SYN+ACK received)     │
    │ ACK sent               │
    ↓                        ↓
[ESTABLISHED] ◄───────── [ESTABLISHED]
    │                        │
    │ (close)                │ (close)
    │ FIN sent               │ FIN sent
    ↓                        ↓
[FIN_WAIT_1]            [FIN_WAIT_1]
    │                        │
    │ (ACK received)         │ (FIN received)
    ↓                        ↓
[FIN_WAIT_2]            [CLOSING]
    │                        │
    │ (FIN received)         │ (ACK received)
    │ ACK sent               │
    ↓                        ↓
[TIME_WAIT] ────────────► [TIME_WAIT]
    │
    │ (2*MSL timeout)
    ↓
[CLOSED]


동시 종료 경로:
[ESTABLISHED] ─(close)─> [FIN_WAIT_1] ─(FIN received)─> [CLOSING] ─(ACK received)─> [TIME_WAIT] ─> [CLOSED]

TCP 상태 설명

연결 설정 관련 상태:

상태설명관점
CLOSED연결 없음 (초기 상태)양쪽
LISTEN연결 요청 대기 중서버
SYN_SENTSYN 전송 후 SYN+ACK 대기클라이언트
SYN_RCVDSYN 수신 후 SYN+ACK 전송, ACK 대기서버
ESTABLISHED연결 완료, 데이터 전송 가능양쪽

연결 종료 관련 상태:

상태설명관점
FIN_WAIT_1FIN 전송 후 ACK 대기능동 종료 측
FIN_WAIT_2ACK 수신 후 상대방 FIN 대기능동 종료 측
CLOSE_WAITFIN 수신 후 종료 준비 중수동 종료 측
LAST_ACKFIN 전송 후 최종 ACK 대기수동 종료 측
TIME_WAIT연결 종료 후 2*MSL 대기능동 종료 측
CLOSING동시 종료 시 최종 ACK 대기양쪽 (드물게)

정상적인 연결 설정 과정 (3-Way Handshake)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Client                           Server
[CLOSED]                         [LISTEN]
   │                                │
   │──────── SYN (seq=X) ──────────►│
   │                                │
[SYN_SENT]                    [SYN_RCVD]
   │                                │
   │◄──── SYN+ACK (seq=Y, ack=X+1)──│
   │                                │
[ESTABLISHED]                      │
   │                                │
   │─────── ACK (ack=Y+1) ─────────►│
   │                                │
[ESTABLISHED]                [ESTABLISHED]

정상적인 연결 종료 과정 (4-Way Handshake)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Client (능동 종료)               Server (수동 종료)
[ESTABLISHED]                [ESTABLISHED]
   │                                │
   │────────── FIN ────────────────►│
   │                                │
[FIN_WAIT_1]                  [CLOSE_WAIT]
   │                                │
   │◄────────── ACK ────────────────│
   │                                │
[FIN_WAIT_2]                  [CLOSE_WAIT]
   │                                │
   │                                │ (애플리케이션이 close() 호출)
   │                                │
   │◄────────── FIN ────────────────│
   │                                │
[TIME_WAIT]                   [LAST_ACK]
   │                                │
   │────────── ACK ────────────────►│
   │                                │
[TIME_WAIT]                      [CLOSED]
   │
   │ (2*MSL 대기, 보통 60초)
   ↓
[CLOSED]

특수 상황

동시 연결 (Simultaneous Open):

1
2
3
양쪽 모두 active open 수행:
Client: [CLOSED] → [SYN_SENT] → [SYN_RCVD] → [ESTABLISHED]
Server: [CLOSED] → [SYN_SENT] → [SYN_RCVD] → [ESTABLISHED]

동시 종료 (Simultaneous Close):

1
2
3
양쪽 모두 동시에 FIN 전송:
Client: [ESTABLISHED] → [FIN_WAIT_1] → [CLOSING] → [TIME_WAIT] → [CLOSED]
Server: [ESTABLISHED] → [FIN_WAIT_1] → [CLOSING] → [TIME_WAIT] → [CLOSED]

RST를 통한 강제 종료:

1
2
3
4
모든 상태에서 RST 수신 시 즉시 [CLOSED]로 전환
- 비정상 종료
- 연결이 존재하지 않는 포트로 패킷 도착 시
- 방화벽이 차단 시

상태 확인 명령어

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 모든 TCP 연결 상태 확인
netstat -tan
ss -tan

# ESTABLISHED 상태만 확인
netstat -tan | grep ESTABLISHED
ss -tan state established

# TIME_WAIT 상태 개수 확인 (많으면 문제)
netstat -tan | grep TIME_WAIT | wc -l
ss -tan state time-wait | wc -l

# 특정 포트의 상태 확인
ss -tan '( dport = :80 or sport = :80 )'

실전 문제: TIME_WAIT 소켓 과다

증상:

1
2
$ ss -tan state time-wait | wc -l
15000  # 매우 많음!

원인:

  • 높은 요청 빈도 (로드밸런서, 프록시)
  • 능동 종료를 서버가 수행 (클라이언트가 해야 정상)
  • 짧은 연결 수명 (Keep-Alive 미사용)

해결책:

1
2
3
4
5
6
7
8
9
10
11
# 1. tcp_tw_reuse 활성화 (나가는 연결에 TIME_WAIT 소켓 재사용)
sysctl -w net.ipv4.tcp_tw_reuse=1

# 2. Keep-Alive 사용 (연결 재사용)
# HTTP/1.1 기본 지원

# 3. 연결 풀링 (Connection Pooling)
# 애플리케이션 레벨에서 연결 재사용

# 4. SO_LINGER 옵션 (비권장)
# 강제 종료는 데이터 손실 위험

주의: net.ipv4.tcp_tw_recycle사용하지 말 것 (NAT 환경에서 문제, Linux 4.12부터 제거됨)

CLOSE_WAIT 소켓 과다

증상:

1
2
$ ss -tan state close-wait | wc -l
1000  # 많음!

원인:

  • 애플리케이션 버그: close() 호출 안 함
  • 클라이언트가 FIN 보냈지만 서버가 소켓을 닫지 않음

해결책:

1
2
3
4
5
애플리케이션 코드 수정:
- try-finally 블록에서 소켓 close() 호출
- with 문 사용 (Python)
- defer 사용 (Go)
- RAII (C++)

면접 질문 예시

Q1: “3-Way Handshake 과정에서 각 단계의 상태는?”

A:

  • 클라이언트: CLOSED → SYN_SENT → ESTABLISHED
  • 서버: LISTEN → SYN_RCVD → ESTABLISHED
  • SYN을 보낸 클라이언트는 SYN_SENT, SYN을 받은 서버는 SYN_RCVD 상태가 되며, 최종 ACK 수신 후 양쪽 모두 ESTABLISHED가 됨

Q2: “TIME_WAIT 상태는 왜 필요한가?”

A:

  1. 지연된 패킷 처리: 네트워크에 남아있는 이전 연결의 패킷이 새 연결에 영향을 주지 않도록 2*MSL (보통 60초) 대기
  2. 마지막 ACK 재전송: 수동 종료 측이 마지막 ACK를 못 받으면 FIN을 재전송하는데, 이때 능동 종료 측이 이미 CLOSED면 RST를 보내 문제 발생. TIME_WAIT 상태면 ACK 재전송 가능

Q3: “CLOSE_WAIT 상태가 많으면 어떤 문제인가?”

A: CLOSE_WAIT는 상대방이 FIN을 보냈지만 애플리케이션이 아직 소켓을 닫지 않은 상태. 많다면 애플리케이션 버그로 소켓을 제대로 close()하지 않는 것. 메모리 누수, 파일 디스크립터 고갈로 이어져 새 연결을 받지 못하게 됨.

Q4: “SYN_RCVD 상태가 많으면 어떤 공격인가?”

A: SYN Flooding 공격. 공격자가 대량의 SYN 패킷을 보내고 ACK는 보내지 않아 서버가 SYN_RCVD 상태 소켓을 많이 유지하게 됨. 서버의 half-open 연결 큐가 가득 차서 정상 연결을 받지 못함. 방어: SYN Cookie, 연결 큐 크기 증가.

TCP 재전송

패킷 손실 감지 및 재전송 메커니즘:

타임아웃 기반

  • ACK를 받지 못하면 RTO(Retransmission Timeout) 후 재전송
  • RTO는 RTT를 기반으로 동적 계산

빠른 재전송 (Fast Retransmit)

  • 중복 ACK 3개 수신 시 즉시 재전송
  • 타임아웃을 기다리지 않아 더 빠름

TCP 흐름 제어 (Flow Control)

수신자의 처리 속도에 맞춰 전송 속도 조절:

  • 슬라이딩 윈도우: 수신 버퍼 크기만큼만 전송
  • Window Size 필드: 수신 가능한 바이트 수 알림
  • Zero Window: 수신자가 버퍼가 가득 차면 0을 전송하여 일시 중단

TCP 혼잡 제어 (Congestion Control)

네트워크 혼잡을 감지하고 완화:

Slow Start

  • 연결 초기에는 작은 윈도우로 시작
  • ACK 수신마다 윈도우 크기 지수적 증가
  • 임계값(ssthresh)까지 빠르게 증가

Congestion Avoidance

  • 임계값 도달 후 선형적으로 증가
  • 패킷 손실 감지 시 윈도우 축소

Fast Recovery

  • 빠른 재전송 후 윈도우를 절반으로 줄임
  • Slow Start로 돌아가지 않음

주요 혼잡 제어 알고리즘

  • Reno: 전통적 알고리즘
  • CUBIC: Linux 기본값, 고속 네트워크 최적화
  • BBR: Google 개발, RTT 기반

4.2 UDP (User Datagram Protocol)

UDP의 특징

UDP는 단순하고 빠른 비연결 프로토콜이다:

  • 비연결성: 연결 설정 없이 바로 전송
  • 비신뢰성: 패킷 손실, 중복, 순서 뒤바뀜 가능
  • 오버헤드 최소: 헤더가 8바이트로 매우 작음
  • 실시간 전송: 지연이 적어 실시간 애플리케이션에 적합

UDP 헤더 구조

매우 간단한 구조:

  • Source Port: 송신 포트 (2바이트)
  • Destination Port: 수신 포트 (2바이트)
  • Length: 전체 데이터그램 길이 (2바이트)
  • Checksum: 오류 검사 (2바이트, 선택적)

UDP 사용 사례

DNS (Domain Name System)

  • 빠른 조회가 중요
  • 손실 시 재요청하면 됨

DHCP (Dynamic Host Configuration Protocol)

  • 클라이언트가 IP 주소 받을 때
  • 연결이 없는 상태에서도 통신 필요

스트리밍 (Video/Audio)

  • 약간의 패킷 손실은 허용 가능
  • 재전송보다 실시간성이 중요
  • RTP (Real-time Transport Protocol)

온라인 게임

  • 낮은 지연이 중요
  • 일부 패킷 손실 허용

VoIP (Voice over IP)

  • 실시간 음성 통신
  • 지연보다 품질 저하가 나음

TCP vs UDP 비교

특성TCPUDP
연결연결 지향비연결
신뢰성보장보장 안 함
순서보장보장 안 함
속도상대적으로 느림빠름
헤더 크기20바이트 이상8바이트
용도파일 전송, 웹, 이메일스트리밍, 게임, DNS

4.3 포트 번호

포트의 개념

포트는 하나의 호스트에서 여러 서비스를 구분하기 위한 논리적 주소이다:

  • 16비트 번호 (0-65535)
  • IP 주소 + 포트 = 소켓 (통신의 종단점)

포트 번호 분류

Well-Known Ports (0-1023)

  • 표준 서비스용으로 예약
  • root 권한 필요 (CAP_NET_BIND_SERVICE)
  • 주요 포트:
    • 20/21: FTP
    • 22: SSH
    • 23: Telnet
    • 25: SMTP
    • 53: DNS
    • 80: HTTP
    • 110: POP3
    • 143: IMAP
    • 443: HTTPS
    • 3306: MySQL
    • 5432: PostgreSQL

Registered Ports (1024-49151)

  • IANA에 등록된 애플리케이션용
  • 일반 사용자도 바인딩 가능
  • 주요 포트:
    • 3000: 많은 개발 서버
    • 5000: Flask 기본 포트
    • 6379: Redis
    • 8080: 대체 HTTP
    • 9090: Prometheus

Dynamic/Private Ports (49152-65535)

  • 클라이언트의 임시 포트 (ephemeral ports)
  • 운영체제가 자동 할당
  • 연결 종료 후 재사용

소켓 주소

통신 종단점은 IP + 포트로 표현:

  • 로컬 소켓: 192.168.1.10:8080
  • 원격 소켓: 203.0.113.5:443
  • 연결은 (로컬 IP, 로컬 포트, 원격 IP, 원격 포트) 4-tuple로 고유 식별

5. 응용 계층

응용 계층은 사용자 애플리케이션이 네트워크 서비스에 접근하는 계층이다. HTTP, DNS, SSH, FTP 등 많은 프로토콜이 이 계층에서 작동한다.

주요 프로토콜은 하위 계층(TCP/IP, 라우팅, 네임스페이스 등)의 기초 위에서 작동하며, 각 계층의 이해가 응용 계층의 구현과 최적화에 필수적이다.

5.1 DNS (Domain Name System)

DNS란?

DNS는 사람이 읽을 수 있는 도메인 이름(예: www.example.com)을 IP 주소(예: 192.0.2.1)로 변환하는 분산 계층적 시스템이다.

DNS의 필요성

  1. 사용자 편의성: 사람은 숫자(IP)보다 이름(도메인)을 기억하기 쉬움
  2. 유연성: 서버 IP가 변경되어도 도메인은 그대로 유지 가능
  3. 로드 밸런싱: 하나의 도메인에 여러 IP 매핑 가능
  4. 서비스 위치 추상화: 물리적 위치와 무관하게 서비스 접근

DNS 계층 구조

DNS는 트리 구조의 분산 데이터베이스:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
                          [.] (Root)
                           │
        ┌──────────────────┼──────────────────┐
        │                  │                  │
      [com]              [org]              [kr]  (TLD: Top-Level Domain)
        │                  │                  │
    ┌───┴───┐          [wikipedia]       ┌───┴───┐
[google] [amazon]          │          [co]    [ac]
    │                      │            │       │
[www] [mail]            [www]       [naver] [seoul]
                                       │
                                    [www]

예시:
www.google.com  → Root → com → google → www
www.naver.co.kr → Root → kr → co → naver → www

DNS 서버 계층

Root Name Servers (루트 네임서버)

  • 전 세계 13개 루트 서버 (A~M)
  • TLD 서버의 위치 제공
  • Anycast로 수백 개의 물리 서버에 분산
  • 예: a.root-servers.net (198.41.0.4)

TLD Name Servers (최상위 도메인 서버)

  • 각 TLD(.com, .org, .kr 등)를 담당
  • Authoritative 서버의 위치 제공
  • 예: .com TLD 서버는 google.com의 네임서버 정보 제공

Authoritative Name Servers (권한 네임서버)

  • 특정 도메인의 실제 IP 주소 보유
  • 도메인 소유자가 직접 관리 또는 호스팅 업체 이용
  • 예: ns1.google.comwww.google.com의 IP 제공

Recursive Resolver (재귀 리졸버)

  • ISP 또는 퍼블릭 DNS 제공 (예: 8.8.8.8)
  • 사용자 대신 계층적 조회 수행
  • 캐싱으로 성능 향상

DNS 조회 과정 (Recursive Query)

사용자가 www.example.com을 조회할 때:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
┌─────────┐
│ Client  │ (브라우저)
└────┬────┘
     │ 1. www.example.com?
     ↓
┌──────────────┐
│ Recursive    │ (8.8.8.8 - Google Public DNS)
│ Resolver     │
└──────┬───────┘
       │ 2. .com의 네임서버는 어디?
       ↓
┌─────────────┐
│ Root Server │ (a.root-servers.net)
└──────┬──────┘
       │ 3. .com TLD 서버는 a.gtld-servers.net
       ↓
┌─────────────┐
│ TLD Server  │ (a.gtld-servers.net)
│ (.com)      │
└──────┬──────┘
       │ 4. example.com의 네임서버는 ns1.example.com
       ↓
┌──────────────────┐
│ Authoritative    │ (ns1.example.com)
│ Server           │
│ (example.com)    │
└──────┬───────────┘
       │ 5. www.example.com = 93.184.216.34
       ↓
┌──────────────┐
│ Recursive    │ (캐시에 저장)
│ Resolver     │
└──────┬───────┘
       │ 6. 93.184.216.34
       ↓
┌─────────┐
│ Client  │ (이제 IP로 HTTP 요청)
└─────────┘

DNS 조회 단계별 상세:

  1. Client → Recursive Resolver: “www.example.com의 IP는?”
  2. Resolver → Root Server: “.com TLD 서버의 주소는?”
  3. Root → Resolver: “a.gtld-servers.net (192.5.6.30)”
  4. Resolver → TLD Server: “example.com의 네임서버는?”
  5. TLD → Resolver: “ns1.example.com (192.0.2.1)”
  6. Resolver → Authoritative: “www.example.com의 IP는?”
  7. Authoritative → Resolver: “93.184.216.34”
  8. Resolver → Client: “93.184.216.34” (캐시에 저장)

DNS 레코드 타입

레코드 타입용도예시
AIPv4 주소 매핑www.example.com → 93.184.216.34
AAAAIPv6 주소 매핑www.example.com → 2606:2800:220:1:248:1893:25c8:1946
CNAME도메인 별칭 (Canonical Name)blog.example.com → www.example.com
MX메일 서버 지정example.com → mail.example.com (우선순위 10)
NS네임서버 지정example.com → ns1.example.com
TXT임의 텍스트 (SPF, DKIM 등)“v=spf1 include:_spf.google.com ~all”
PTR역방향 조회 (IP → 도메인)93.184.216.34 → www.example.com
SOA도메인 권한 정보Primary NS, Admin email, Serial, Refresh 등
SRV서비스 위치 (포트 포함)_sip._tcp.example.com → sipserver.example.com:5060

DNS 레코드 예시:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# A 레코드: 도메인 → IPv4
www.example.com.  IN  A  93.184.216.34

# AAAA 레코드: 도메인 → IPv6
www.example.com.  IN  AAAA  2606:2800:220:1:248:1893:25c8:1946

# CNAME 레코드: 별칭
blog.example.com.  IN  CNAME  www.example.com.

# MX 레코드: 메일 서버 (우선순위 포함)
example.com.  IN  MX  10  mail1.example.com.
example.com.  IN  MX  20  mail2.example.com.

# TXT 레코드: SPF (이메일 인증)
example.com.  IN  TXT  "v=spf1 ip4:93.184.216.0/24 -all"

# NS 레코드: 네임서버
example.com.  IN  NS  ns1.example.com.
example.com.  IN  NS  ns2.example.com.

DNS 캐싱 (Caching)

성능 향상을 위해 여러 레벨에서 캐싱:

  1. 브라우저 캐시: 브라우저 자체가 DNS 응답 캐시 (짧은 TTL, 보통 1분)
  2. OS 캐시: 운영체제 수준 DNS 캐시 (systemd-resolved, nscd)
  3. Recursive Resolver 캐시: ISP/Public DNS가 조회 결과 캐시 (TTL 기반)

TTL (Time To Live):

1
2
3
4
5
6
7
www.example.com.  300  IN  A  93.184.216.34
                  ↑
                  TTL = 300초 (5분)

→ 5분 후 캐시 만료, 재조회 필요
→ TTL이 작으면: 빠른 변경 반영, 높은 조회 부하
→ TTL이 크면: 낮은 조회 부하, 느린 변경 반영

DNS 조회 도구

nslookup:

1
2
3
4
5
6
7
8
9
# 기본 조회 (시스템 기본 DNS 사용)
nslookup www.google.com

# 특정 DNS 서버 사용
nslookup www.google.com 8.8.8.8

# 특정 레코드 타입 조회
nslookup -type=MX google.com
nslookup -type=NS google.com

dig (권장):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 기본 조회
dig www.google.com

# 특정 DNS 서버 사용
dig @8.8.8.8 www.google.com

# 특정 레코드 타입
dig www.google.com AAAA
dig google.com MX

# 간결한 출력
dig +short www.google.com

# 전체 조회 경로 추적
dig +trace www.google.com

# 역방향 조회 (IP → 도메인)
dig -x 8.8.8.8

host:

1
2
3
4
5
# 기본 조회
host www.google.com

# 모든 레코드 조회
host -a www.google.com

DNS 보안

DNS 캐시 포이즈닝 (Cache Poisoning):

1
2
3
4
5
6
7
8
9
10
11
12
공격자가 DNS 응답을 위조하여 Resolver의 캐시를 오염:

1. 사용자가 bank.com 조회
2. 공격자가 위조된 DNS 응답 전송:
   bank.com → 공격자_IP
3. Resolver가 캐시에 저장
4. 이후 모든 사용자가 공격자 서버로 연결

방어:
- DNSSEC (서명 검증)
- 랜덤 포트, 랜덤 트랜잭션 ID
- 0x20 인코딩 (대소문자 랜덤화)

DNSSEC (DNS Security Extensions):

  • DNS 응답에 디지털 서명 추가
  • 응답의 무결성과 출처 검증
  • 캐시 포이즈닝 방지

DoH (DNS over HTTPS) / DoT (DNS over TLS):

  • DNS 쿼리를 암호화하여 전송
  • ISP의 DNS 감청 방지
  • 예: Cloudflare 1.1.1.1, Google 8.8.8.8 DoH 지원

DNS 로드 밸런싱

하나의 도메인에 여러 IP 매핑:

1
2
3
4
5
6
7
8
9
$ dig www.google.com +short
142.250.185.68
142.250.185.36
142.250.185.100
142.250.185.132

→ DNS가 여러 IP를 Round-Robin으로 반환
→ 클라이언트가 랜덤하게 하나 선택
→ 부하 분산 효과

GeoDNS (지리적 DNS):

1
2
3
4
5
6
사용자 위치에 따라 다른 IP 반환:

한국 사용자 → www.example.com → 서울 서버 IP
미국 사용자 → www.example.com → 버지니아 서버 IP

→ CDN에서 활용 (Cloudflare, AWS Route 53)

DNS 문제 해결

DNS 캐시 플러시:

1
2
3
4
5
6
7
8
9
# Linux (systemd-resolved)
systemd-resolve --flush-caches

# macOS
dscacheutil -flushcache
killall -HUP mDNSResponder

# Windows
ipconfig /flushdns

DNS 서버 변경:

1
2
3
4
5
6
# /etc/resolv.conf 수정 (영구적 변경은 NetworkManager 등 사용)
nameserver 8.8.8.8
nameserver 1.1.1.1

# systemd-resolved 사용 시
resolvectl dns eth0 8.8.8.8 1.1.1.1

Public DNS 서버:

  • Google: 8.8.8.8, 8.8.4.4
  • Cloudflare: 1.1.1.1, 1.0.0.1
  • Quad9: 9.9.9.9
  • OpenDNS: 208.67.222.222, 208.67.220.220

면접 질문 예시

Q1: “DNS 조회 과정을 Root부터 단계별로 설명하라”

A: www.example.com 조회 시:

  1. Recursive Resolver → Root Server: “.com TLD 서버 주소 요청”
  2. Root → Resolver: “a.gtld-servers.net 사용”
  3. Resolver → TLD Server (.com): “example.com 네임서버 요청”
  4. TLD → Resolver: “ns1.example.com 사용”
  5. Resolver → Authoritative (ns1.example.com): “www의 IP 요청”
  6. Authoritative → Resolver: “93.184.216.34”
  7. Resolver → Client: “93.184.216.34” (캐시 저장)

Q2: “A 레코드와 CNAME 레코드의 차이는?”

A:

  • A 레코드: 도메인 → IPv4 주소 직접 매핑 (www.example.com → 93.184.216.34)
  • CNAME 레코드: 도메인 → 다른 도메인 별칭 (blog.example.com → www.example.com)
  • CNAME은 최종적으로 A 레코드를 참조. Root 도메인(example.com)은 CNAME 사용 불가, A 레코드만 가능

Q3: “DNS 캐시 포이즈닝을 어떻게 방어하는가?”

A:

  1. DNSSEC: 디지털 서명으로 응답 검증
  2. 랜덤화: 트랜잭션 ID, 소스 포트 랜덤화
  3. DoH/DoT: DNS 쿼리 암호화
  4. 0x20 인코딩: 도메인 대소문자 랜덤화로 위조 어렵게 함

5.2 HTTP/HTTPS (HyperText Transfer Protocol)

HTTP란?

HTTP는 웹 브라우저와 웹 서버 간 데이터를 주고받기 위한 응용 계층 프로토콜이다. Stateless(무상태) 방식으로, 각 요청은 독립적으로 처리된다.

HTTP 버전 역사

버전연도특징
HTTP/0.91991GET만 지원, 헤더 없음
HTTP/1.01996헤더, POST/HEAD 추가, 연결마다 TCP 재설정
HTTP/1.11997Keep-Alive 기본, Pipelining, Chunked Transfer
HTTP/22015Binary Protocol, Multiplexing, Server Push, Header Compression
HTTP/32022QUIC (UDP 기반), 더 빠른 연결, 패킷 손실 복구 개선

HTTP 요청 구조

1
2
3
4
5
6
7
GET /index.html HTTP/1.1          ← Request Line
Host: www.example.com              ← Headers
User-Agent: Mozilla/5.0
Accept: text/html
Connection: keep-alive
                                   ← Blank Line
[Request Body - POST/PUT 시에만]   ← Body (optional)

Request Line 구성:

  • Method: GET, POST, PUT, DELETE 등
  • URI: 요청 대상 리소스 경로
  • HTTP Version: HTTP/1.1, HTTP/2 등

HTTP 응답 구조

1
2
3
4
5
6
7
8
9
10
HTTP/1.1 200 OK                    ← Status Line
Content-Type: text/html            ← Headers
Content-Length: 1024
Server: nginx/1.18.0
Cache-Control: max-age=3600
                                   ← Blank Line
<!DOCTYPE html>                    ← Body
<html>
...
</html>

Status Line 구성:

  • HTTP Version: HTTP/1.1
  • Status Code: 200, 404, 500 등
  • Reason Phrase: OK, Not Found, Internal Server Error

HTTP 메서드 (Methods)

메서드용도IdempotentSafe
GET리소스 조회
POST리소스 생성, 데이터 제출
PUT리소스 전체 교체
PATCH리소스 부분 수정
DELETE리소스 삭제
HEADGET과 동일하나 Body 없음
OPTIONS지원 메서드 확인 (CORS)
  • Idempotent (멱등성): 동일 요청을 여러 번 해도 결과가 같음
  • Safe (안전성): 서버 상태를 변경하지 않음

HTTP 상태 코드 (Status Codes)

1xx - Informational (정보):

  • 100 Continue: 클라이언트가 요청 계속 진행 가능
  • 101 Switching Protocols: WebSocket 업그레이드 시

2xx - Success (성공):

  • 200 OK: 요청 성공
  • 201 Created: 리소스 생성 성공 (POST)
  • 204 No Content: 성공했으나 반환할 Body 없음 (DELETE)

3xx - Redirection (리다이렉션):

  • 301 Moved Permanently: 영구 이동 (SEO에 영향)
  • 302 Found: 임시 이동
  • 304 Not Modified: 캐시된 리소스 사용 가능

4xx - Client Error (클라이언트 오류):

  • 400 Bad Request: 잘못된 요청 (문법 오류)
  • 401 Unauthorized: 인증 필요
  • 403 Forbidden: 권한 없음 (인증되었으나 접근 거부)
  • 404 Not Found: 리소스 없음
  • 429 Too Many Requests: Rate Limit 초과

5xx - Server Error (서버 오류):

  • 500 Internal Server Error: 서버 내부 오류
  • 502 Bad Gateway: 게이트웨이/프록시 오류
  • 503 Service Unavailable: 서버 과부하 또는 유지보수
  • 504 Gateway Timeout: 게이트웨이/프록시 타임아웃

HTTP 헤더

Request Headers:

1
2
3
4
5
6
7
8
Host: www.example.com               # 필수 (HTTP/1.1)
User-Agent: Mozilla/5.0             # 클라이언트 정보
Accept: text/html,application/json  # 수용 가능한 미디어 타입
Accept-Language: ko-KR,en-US        # 선호 언어
Accept-Encoding: gzip, deflate      # 압축 방식
Cookie: session_id=abc123           # 쿠키
Referer: https://www.google.com     # 이전 페이지
Authorization: Bearer eyJhbGc...    # 인증 토큰

Response Headers:

1
2
3
4
5
6
7
8
Content-Type: text/html; charset=utf-8  # 응답 미디어 타입
Content-Length: 1024                    # Body 크기 (바이트)
Content-Encoding: gzip                  # 압축 방식
Server: nginx/1.18.0                    # 서버 소프트웨어
Set-Cookie: session_id=xyz; HttpOnly    # 쿠키 설정
Cache-Control: max-age=3600             # 캐싱 정책
Location: https://www.example.com/new   # 리다이렉션 URL (3xx)
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"  # 리소스 버전

HTTP Keep-Alive (지속 연결)

HTTP/1.0:

1
2
3
4
매 요청마다 TCP 연결 생성 → 느림
Request 1: TCP 연결 → GET /a.html → 응답 → TCP 종료
Request 2: TCP 연결 → GET /b.css  → 응답 → TCP 종료
Request 3: TCP 연결 → GET /c.js   → 응답 → TCP 종료

HTTP/1.1 (Keep-Alive 기본):

1
2
3
4
5
하나의 TCP 연결로 여러 요청 처리 → 빠름
TCP 연결 → GET /a.html → 응답
        → GET /b.css  → 응답
        → GET /c.js   → 응답
        → (일정 시간 후 또는 연결 종료 요청 시) TCP 종료

HTTPS (HTTP Secure)

HTTP에 TLS/SSL 암호화 추가:

HTTPS 필요성:

  1. 기밀성: 데이터 암호화 (도청 방지)
  2. 무결성: 데이터 변조 방지
  3. 인증: 서버 신원 확인 (중간자 공격 방지)

TLS Handshake (간소화된 과정):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Client                              Server
  │                                    │
  │──── ClientHello ──────────────────►│
  │     (지원 암호화 방식, 랜덤 값)      │
  │                                    │
  │◄──── ServerHello ─────────────────│
  │     (선택한 암호화, 인증서, 랜덤)    │
  │                                    │
  │ (인증서 검증: CA 서명 확인)          │
  │                                    │
  │──── ClientKeyExchange ────────────►│
  │     (공개키로 암호화된 PreMaster)    │
  │                                    │
  │ (양쪽이 PreMaster로 세션 키 생성)    │
  │                                    │
  │──── Finished ─────────────────────►│
  │◄──── Finished ────────────────────│
  │                                    │
  │ (이후 세션 키로 대칭키 암호화 통신)  │

TLS 1.3 개선점:

  • Handshake 1-RTT로 단축 (기존 2-RTT)
  • 0-RTT 재연결 (이전 세션 재사용)
  • 더 안전한 암호화 방식만 지원

HTTPS 포트: 443 (HTTP는 80)

curl로 HTTP 요청 테스트:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 기본 GET 요청
curl https://www.example.com

# 헤더 포함 출력
curl -i https://www.example.com

# POST 요청 (JSON)
curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -d '{"name": "John", "email": "john@example.com"}'

# 인증 헤더 포함
curl -H "Authorization: Bearer token123" \
  https://api.example.com/protected

# 쿠키 포함
curl -b "session_id=abc123" https://www.example.com

# 리다이렉션 따라가기
curl -L https://www.example.com

# 응답 시간 측정
curl -w "@curl-format.txt" -o /dev/null -s https://www.example.com
# curl-format.txt:
# time_namelookup:  %{time_namelookup}\n
# time_connect:     %{time_connect}\n
# time_starttransfer: %{time_starttransfer}\n
# time_total:       %{time_total}\n

HTTP/2 vs HTTP/1.1

특징HTTP/1.1HTTP/2
프로토콜텍스트 기반바이너리 기반
멀티플렉싱❌ (HOL Blocking)✅ (동시 여러 스트림)
헤더 압축✅ (HPACK)
Server Push
우선순위

HTTP/2 Multiplexing:

1
2
3
4
5
6
7
8
9
10
HTTP/1.1 (Pipelining):
GET /a.html → 대기 → 응답
GET /b.css  → 대기 → 응답 (앞 요청 완료까지 대기)

HTTP/2:
GET /a.html ──┐
GET /b.css   ─┼─ 동시 전송
GET /c.js    ─┘
       ↓
모든 응답 병렬 수신 (스트림별 독립적)

면접 질문 예시

Q1: “HTTP GET과 POST의 차이는?”

A:

  • GET: 리소스 조회, 파라미터가 URL에 노출 (?key=value), 브라우저 캐시 가능, Idempotent, Safe
  • POST: 리소스 생성/데이터 제출, 파라미터가 Body에 포함, 캐시 불가, Non-idempotent, Non-safe
  • 예: 게시글 조회는 GET, 게시글 작성은 POST

Q2: “HTTP 상태 코드 401과 403의 차이는?”

A:

  • 401 Unauthorized: 인증 필요 (로그인 안 함). “누구인지 모르니 인증하세요”
  • 403 Forbidden: 인증되었으나 권한 없음. “누군지는 알지만 접근 권한 없음”
  • 예: 로그인 안 한 사용자 → 401, 일반 사용자가 관리자 페이지 접근 → 403

Q3: “HTTPS의 TLS Handshake 과정을 설명하라”

A:

  1. ClientHello: 클라이언트가 지원하는 암호화 방식과 랜덤 값 전송
  2. ServerHello: 서버가 선택한 암호화 방식, 인증서(공개키 포함), 랜덤 값 전송
  3. 클라이언트가 CA로 인증서 검증
  4. ClientKeyExchange: 공개키로 PreMaster Secret 암호화하여 전송
  5. 양쪽이 PreMaster + 랜덤 값으로 세션 키 생성
  6. Finished: 핸드셰이크 완료, 이후 세션 키로 대칭키 암호화 통신

Q4: “HTTP/1.1의 Keep-Alive가 왜 필요한가?”

A: HTTP/1.0은 매 요청마다 TCP 3-way handshake를 수행하여 오버헤드가 큼. Keep-Alive는 하나의 TCP 연결로 여러 HTTP 요청을 처리하여:

  1. TCP 연결 생성 시간 절감
  2. 네트워크 대역폭 절약
  3. 전체 페이지 로딩 속도 향상 HTTP/1.1부터 기본 활성화됨 (Connection: keep-alive)

Part 2: 리눅스 네트워킹

6. 리눅스 네트워크 스택

6.1 Linux 네트워크 스택 구조

Linux 네트워크 스택의 계층

Linux 커널의 네트워크 구현은 다음과 같이 계층화되어 있다:

하드웨어 레벨

  • 물리적 네트워크 인터페이스 카드 (NIC)
  • DMA를 통한 패킷 송수신

디바이스 드라이버

  • 하드웨어 추상화
  • 링크 계층 프로토콜 처리 (Ethernet, Wi-Fi 등)
  • sk_buff 구조체로 패킷 표현

네트워크 프로토콜 스택

  • IP 계층: 라우팅, 포워딩, 단편화
  • TCP/UDP 계층: 연결 관리, 포트 다중화
  • 소켓 계층: 애플리케이션 인터페이스

소켓 API

  • 시스템 콜 인터페이스
  • socket(), bind(), listen(), connect(), send(), recv() 등

패킷 수신 과정

  1. 하드웨어 인터럽트
  • NIC가 패킷 수신 시 인터럽트 발생
  • 드라이버의 인터럽트 핸들러 호출
  1. NAPI (New API)
  • 고속 네트워크를 위한 폴링 메커니즘
  • 인터럽트 빈도 감소
  1. sk_buff 생성
  • 패킷 데이터를 sk_buff 구조체에 저장
  • 메타데이터 포함 (프로토콜, 길이 등)
  1. 프로토콜 처리
  • IP 계층: 라우팅 결정, 헤더 검사
  • TCP/UDP: 포트 확인, 체크섬 검증
  • 소켓 버퍼로 전달
  1. 애플리케이션으로 전달
  • recv() 시스템 콜로 데이터 복사

패킷 송신 과정

  1. 애플리케이션 전송
  • send() 시스템 콜 호출
  • 데이터를 커널 버퍼로 복사
  1. 프로토콜 처리
  • TCP/UDP 헤더 추가
  • IP 헤더 추가
  • 라우팅 테이블 조회
  1. 큐잉
  • QDisc (Queueing Discipline)로 전달
  • 트래픽 셰이핑, 우선순위 적용
  1. 드라이버 전송
  • 네트워크 드라이버로 전달
  • DMA로 NIC 메모리로 복사
  1. 물리적 전송
  • NIC가 패킷을 네트워크로 전송

6.2 네트워크 인터페이스

네트워크 인터페이스의 개념

네트워크 인터페이스는 시스템과 네트워크를 연결하는 소프트웨어 객체이다:

  • 물리적 인터페이스: eth0, eth1, wlan0 등
  • 가상 인터페이스: lo, tun0, veth0 등

인터페이스 명명 규칙

전통적 명명 (Predictable Network Interface Names)

  • ethX: 이더넷 인터페이스
  • wlanX: 무선 인터페이스
  • lo: 루프백 인터페이스

systemd 명명 규칙 (현대적)

  • eno1: 온보드 이더넷
  • ens1: PCI Express 슬롯
  • enp0s3: PCI 버스 위치 기반
  • wlp3s0: 무선 PCI

인터페이스 관리

ifconfig (전통적 도구)

1
2
3
4
5
6
7
8
9
10
11
# 모든 인터페이스 확인
ifconfig -a

# 인터페이스 활성화
ifconfig eth0 up

# IP 주소 설정
ifconfig eth0 192.168.1.10 netmask 255.255.255.0

# 비활성화
ifconfig eth0 down

ip 명령 (현대적 도구)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 모든 인터페이스 확인
ip link show
ip addr show

# 인터페이스 활성화/비활성화
ip link set eth0 up
ip link set eth0 down

# IP 주소 추가
ip addr add 192.168.1.10/24 dev eth0

# IP 주소 삭제
ip addr del 192.168.1.10/24 dev eth0

# 라우트 확인
ip route show

# 기본 게이트웨이 추가
ip route add default via 192.168.1.1

네트워크 인터페이스 상태

  • UP: 인터페이스 활성화
  • DOWN: 인터페이스 비활성화
  • LOWER_UP: 물리적 연결 감지 (케이블 연결됨)
  • BROADCAST: 브로드캐스트 지원
  • MULTICAST: 멀티캐스트 지원
  • PROMISC: 프로미스큐어스 모드 (모든 패킷 수신)

6.3 라우팅 테이블

라우팅 테이블의 역할

라우팅 테이블은 패킷을 어디로 보낼지 결정하는 규칙 집합이다.

라우팅 테이블 확인

1
2
3
4
5
6
7
8
9
10
# route 명령 (전통적)
route -n

# ip route 명령 (현대적)
ip route show

# 출력 예시:
# default via 192.168.1.1 dev eth0
# 192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.10
# 172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1

라우팅 테이블 항목 구성

각 라우팅 항목은 다음 정보를 포함:

  • Destination: 목적지 네트워크
  • Gateway: 다음 홉 라우터 (없으면 직접 전달)
  • Genmask: 서브넷 마스크
  • Flags: 라우트 속성
  • Metric: 우선순위 (낮을수록 우선)
  • Iface: 나가는 인터페이스

라우팅 결정 과정

  1. 목적지 IP와 가장 긴 매칭 (Longest Prefix Match)
  2. 여러 경로가 매칭되면 Metric이 낮은 것 선택
  3. 해당 인터페이스로 패킷 전송
  4. Gateway가 있으면 Gateway로, 없으면 직접 전달

라우트 추가/삭제

1
2
3
4
5
6
7
8
9
10
11
# 특정 네트워크로 가는 라우트 추가
ip route add 10.0.0.0/24 via 192.168.1.254 dev eth0

# 기본 게이트웨이 설정
ip route add default via 192.168.1.1

# 라우트 삭제
ip route del 10.0.0.0/24

# 특정 인터페이스로 직접 전달
ip route add 192.168.2.0/24 dev eth1

정책 기반 라우팅 (Policy-based Routing)

단순 목적지 주소 외에 다른 조건으로도 라우팅 가능:

  • 출발지 IP 주소
  • TOS (Type of Service)
  • 방화벽 마크
1
2
3
4
5
6
7
8
# 출발지 기반 라우팅 테이블 생성
ip route add default via 192.168.2.1 table 100

# 출발지 IP에 따라 라우팅 테이블 선택
ip rule add from 10.0.1.0/24 table 100

# 규칙 확인
ip rule show

6.4 소켓과 포트

소켓의 개념

소켓은 네트워크 통신의 종단점이다. 애플리케이션은 소켓을 통해 네트워크 I/O를 수행한다.

소켓 타입

Stream Socket (SOCK_STREAM)

  • TCP 기반
  • 연결 지향, 신뢰성 보장
  • 바이트 스트림

Datagram Socket (SOCK_DGRAM)

  • UDP 기반
  • 비연결, 메시지 경계 보존

Raw Socket (SOCK_RAW)

  • IP 계층 직접 접근
  • 커스텀 프로토콜 구현 가능
  • root 권한 필요

소켓 프로그래밍 흐름

서버 측

  1. socket() - 소켓 생성
  2. bind() - 로컬 주소/포트 바인딩
  3. listen() - 연결 대기 상태로 전환
  4. accept() - 클라이언트 연결 수락
  5. recv()/send() - 데이터 송수신
  6. close() - 소켓 종료

클라이언트 측

  1. socket() - 소켓 생성
  2. connect() - 서버에 연결
  3. send()/recv() - 데이터 송수신
  4. close() - 소켓 종료

소켓 상태 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 모든 소켓 확인
ss -tuln

# TCP 소켓만
ss -tln

# UDP 소켓만
ss -uln

# 프로세스 정보 포함
ss -tlnp

# netstat (구형 도구)
netstat -tuln

소켓 상태

TCP 소켓은 다양한 상태를 가진다:

  • LISTEN: 연결 대기 중
  • ESTABLISHED: 연결 확립됨
  • SYN_SENT: SYN 전송 후 ACK 대기
  • SYN_RECEIVED: SYN 수신 후 ACK 대기
  • FIN_WAIT1/2: 연결 종료 진행 중
  • TIME_WAIT: 연결 종료 후 대기
  • CLOSE_WAIT: 원격 종료 대기
  • CLOSED: 소켓 닫힘

포트 바인딩 이슈

Address already in use 에러

이미 사용 중인 포트에 바인딩 시도 시 발생:

1
2
3
4
5
6
# 해당 포트를 사용 중인 프로세스 확인
lsof -i :8080
ss -tlnp | grep :8080

# TIME_WAIT 상태의 소켓 때문일 수 있음
# SO_REUSEADDR 소켓 옵션으로 해결

권한 문제

1024 이하 포트는 root 권한 필요:

  • CAP_NET_BIND_SERVICE capability 필요
  • 또는 setcap으로 capability 부여
1
2
# 특정 바이너리에 capability 부여
sudo setcap 'cap_net_bind_service=+ep' /path/to/binary

7. 리눅스 네트워크 도구

리눅스는 네트워크 진단, 모니터링, 성능 분석을 위한 풍부한 도구들을 제공한다. 이들 도구는 네트워크 문제 해결과 성능 최적화에 필수적이다.

주요 도구 범주:

  • 정보 확인: ifconfig, ip, ss, netstat
  • 연결 테스트: ping, traceroute, mtr
  • 패킷 캡처: tcpdump, wireshark
  • 성능 분석: iperf, netperf

8. iptables와 Netfilter

8.1 Netfilter 프레임워크

Netfilter란?

Netfilter는 Linux 커널 내부의 패킷 필터링 프레임워크이다. 네트워크 패킷을 가로채서 검사, 수정, 차단할 수 있다.

Netfilter Hooks

Netfilter는 패킷 처리 경로에 5개의 훅 포인트를 제공한다:

PREROUTING

  • 라우팅 결정 전
  • 패킷이 시스템에 도착한 직후
  • DNAT (Destination NAT)에 사용

INPUT

  • 로컬 프로세스로 전달되는 패킷
  • 방화벽 규칙 적용

FORWARD

  • 라우팅되어 다른 인터페이스로 전달되는 패킷
  • 라우터나 브리지 역할 시 사용

OUTPUT

  • 로컬 프로세스에서 생성된 패킷
  • 라우팅 결정 전

POSTROUTING

  • 라우팅 결정 후
  • 패킷이 시스템을 떠나기 직전
  • SNAT (Source NAT), Masquerade에 사용

8.2 iptables 기본

iptables의 개념

iptables는 Netfilter를 설정하는 사용자 공간 도구이다. 방화벽 규칙, NAT, 패킷 필터링 등을 설정한다.

iptables 구조

테이블 (Tables)

iptables는 여러 테이블을 가지며, 각 테이블은 특정 목적을 가진다:

filter 테이블 (기본)

  • 패킷 필터링 (허용/차단)
  • 체인: INPUT, OUTPUT, FORWARD

nat 테이블

  • 주소 변환 (NAT)
  • 체인: PREROUTING, OUTPUT, POSTROUTING

mangle 테이블

  • 패킷 헤더 수정
  • QoS, TTL 변경 등

raw 테이블

  • 연결 추적 제외
  • 성능 최적화

체인 (Chains)

각 테이블은 여러 체인을 가지며, 체인은 규칙들의 리스트이다:

  • 내장 체인: INPUT, OUTPUT, FORWARD, PREROUTING, POSTROUTING
  • 사용자 정의 체인: 복잡한 규칙을 모듈화

규칙 (Rules)

각 규칙은 다음을 포함:

  • 매칭 조건: 출발지 IP, 목적지 IP, 프로토콜, 포트 등
  • 타겟 (Target): 패킷을 어떻게 처리할지
    • ACCEPT: 패킷 허용
    • DROP: 패킷 버림 (응답 없음)
    • REJECT: 패킷 거부 (ICMP 에러 응답)
    • LOG: 패킷 로깅
    • MASQUERADE: 동적 SNAT
    • DNAT: 목적지 주소 변환
    • SNAT: 출발지 주소 변환

8.3 iptables 사용법

기본 명령

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 규칙 목록 확인
iptables -L -n -v

# 특정 테이블의 규칙 확인
iptables -t nat -L -n -v

# 규칙 추가 (체인 끝에)
iptables -A INPUT -s 192.168.1.100 -j DROP

# 규칙 삽입 (특정 위치에)
iptables -I INPUT 1 -s 192.168.1.100 -j DROP

# 규칙 삭제
iptables -D INPUT -s 192.168.1.100 -j DROP

# 규칙 번호로 삭제
iptables -D INPUT 1

# 체인의 모든 규칙 삭제
iptables -F INPUT

# 모든 규칙 삭제
iptables -F

방화벽 규칙 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 특정 IP 차단
iptables -A INPUT -s 192.168.1.100 -j DROP

# 특정 포트 허용 (SSH)
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# 특정 포트 범위 허용
iptables -A INPUT -p tcp --dport 8000:9000 -j ACCEPT

# 확립된 연결 허용
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# 로컬 루프백 허용
iptables -A INPUT -i lo -j ACCEPT

# 기본 정책 설정
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

NAT 규칙 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 출발지 NAT (SNAT) - 고정 IP
iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 203.0.113.5

# Masquerade - 동적 IP
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

# 목적지 NAT (DNAT) - 포트 포워딩
iptables -t nat -A PREROUTING -p tcp --dport 8080 \
  -j DNAT --to-destination 192.168.1.10:80

# 로드 밸런싱 (round-robin)
iptables -t nat -A PREROUTING -p tcp --dport 80 \
  -m statistic --mode nth --every 2 --packet 0 \
  -j DNAT --to-destination 192.168.1.10
iptables -t nat -A PREROUTING -p tcp --dport 80 \
  -m statistic --mode nth --every 2 --packet 1 \
  -j DNAT --to-destination 192.168.1.11

연결 추적 (Connection Tracking)

1
2
3
4
5
6
7
8
9
10
# NEW: 새로운 연결
# ESTABLISHED: 기존 연결의 일부
# RELATED: 관련 연결 (예: FTP 데이터 연결)
# INVALID: 추적할 수 없는 패킷

# 확립된 연결 허용
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# 새 연결은 특정 포트만 허용
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT

8.4 Docker와 iptables

Docker의 iptables 사용

Docker는 컨테이너 네트워킹을 위해 iptables를 광범위하게 사용한다:

컨테이너 격리

1
2
3
4
# Docker가 자동으로 추가하는 규칙 예시
iptables -t filter -N DOCKER
iptables -t filter -A FORWARD -j DOCKER
iptables -t filter -A DOCKER -i docker0 -o docker0 -j DROP

포트 매핑 (포트 포워딩)

1
2
3
4
5
# docker run -p 8080:80
# 호스트의 8080 포트를 컨테이너의 80 포트로 포워딩

iptables -t nat -A DOCKER -p tcp --dport 8080 \
  -j DNAT --to-destination 172.17.0.2:80

NAT (Masquerade)

1
2
3
# 컨테이너가 외부와 통신할 수 있도록 NAT 설정
iptables -t nat -A POSTROUTING -s 172.17.0.0/16 \
  -o eth0 -j MASQUERADE

Docker 체인 확인

1
2
3
4
5
6
7
# Docker가 생성한 체인들
iptables -t nat -L -n | grep DOCKER
iptables -t filter -L -n | grep DOCKER

# DOCKER 체인
# DOCKER-ISOLATION 체인
# DOCKER-USER 체인 (사용자 정의 규칙용)

Docker와 iptables 충돌 방지

Docker가 iptables 규칙을 자동 관리하므로 주의 필요:

  • DOCKER-USER 체인에 사용자 규칙 추가 권장
  • Docker 재시작 시 규칙 초기화 가능
  • iptables-persistent 등으로 규칙 영구 저장

8.5 nftables (iptables의 후속)

nftables란?

nftables는 iptables를 대체하는 차세대 패킷 필터링 프레임워크이다:

  • 더 간결한 문법
  • 더 나은 성능
  • 통합된 인터페이스 (iptables, ip6tables, arptables, ebtables 통합)
  • 커널 5.0 이상에서 권장

기본 사용법

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 규칙 확인
nft list ruleset

# 테이블 생성
nft add table inet filter

# 체인 생성
nft add chain inet filter input { type filter hook input priority 0 \; }

# 규칙 추가
nft add rule inet filter input tcp dport 22 accept

# 규칙 삭제
nft delete table inet filter

9. 라우팅과 포워딩

9.1 IP 포워딩

IP 포워딩이란?

IP 포워딩은 한 인터페이스로 수신한 패킷을 다른 인터페이스로 전달하는 기능이다. 리눅스 호스트를 라우터로 사용하려면 반드시 활성화해야 한다.

IP 포워딩 활성화

1
2
3
4
5
6
7
8
9
10
# 현재 설정 확인
cat /proc/sys/net/ipv4/ip_forward

# 임시로 활성화 (재부팅 시 초기화)
echo 1 > /proc/sys/net/ipv4/ip_forward
sysctl -w net.ipv4.ip_forward=1

# 영구 활성화
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl -p

IPv6 포워딩

1
2
3
# IPv6 포워딩 활성화
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
sysctl -w net.ipv6.conf.all.forwarding=1

포워딩이 필요한 경우

  • 라우터 구성
  • NAT 게이트웨이
  • VPN 서버
  • Docker 호스트 (컨테이너 간 통신)
  • 브리지 네트워크

9.2 라우팅 결정 과정

라우팅 알고리즘

패킷의 목적지를 결정하는 과정:

  1. Longest Prefix Match
  • 목적지 IP와 가장 길게 매칭되는 라우트 선택
  • 예: 192.168.1.10은 192.168.1.0/24가 192.168.0.0/16보다 우선
  1. Metric 비교
  • 같은 prefix length면 metric이 낮은 것 선택
  • Metric: 경로의 비용 또는 우선순위
  1. 로컬 전달 vs 포워딩
  • 목적지가 로컬 인터페이스: INPUT 체인으로
  • 목적지가 다른 네트워크: FORWARD 체인으로

라우팅 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
# 라우팅 테이블
# default via 192.168.1.1 dev eth0
# 192.168.1.0/24 dev eth0 proto kernel scope link
# 10.0.0.0/8 via 192.168.1.254 dev eth0

# 목적지 192.168.1.50
# → 192.168.1.0/24 매칭, eth0로 직접 전달

# 목적지 10.20.30.40
# → 10.0.0.0/8 매칭, 192.168.1.254로 전달

# 목적지 8.8.8.8
# → default 매칭, 192.168.1.1로 전달

9.3 다중 라우팅 테이블

정책 기반 라우팅

Linux는 여러 라우팅 테이블을 지원하며, 규칙에 따라 테이블을 선택할 수 있다.

라우팅 테이블 확인

1
2
3
4
5
6
7
8
# 메인 라우팅 테이블
ip route show table main

# 특정 테이블 확인
ip route show table 100

# 모든 테이블 목록
cat /etc/iproute2/rt_tables

규칙 기반 라우팅 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 테이블 100 생성 및 라우트 추가
ip route add default via 192.168.2.1 table 100

# 출발지 IP 기반 규칙
ip rule add from 10.0.1.0/24 table 100

# 특정 인터페이스 기반
ip rule add iif eth1 table 100

# 방화벽 마크 기반
iptables -t mangle -A PREROUTING -s 10.0.1.0/24 -j MARK --set-mark 1
ip rule add fwmark 1 table 100

# 규칙 확인
ip rule show

사용 사례

  • 멀티-ISP 환경 (로드 밸런싱)
  • VPN 트래픽 분리
  • 특정 애플리케이션 트래픽 라우팅
  • 출발지 기반 정책 라우팅

9.4 컨테이너 라우팅

Docker 네트워크 라우팅

Docker 컨테이너의 라우팅 구조:

컨테이너 내부 라우팅

1
2
3
4
5
6
# 컨테이너 내부에서 확인
docker exec <container_id> ip route show

# 일반적인 구조:
# default via 172.17.0.1 dev eth0
# 172.17.0.0/16 dev eth0 scope link

호스트 라우팅

1
2
3
4
# 호스트에서 Docker 네트워크 라우팅
ip route show

# 172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1

외부 통신 흐름

  1. 컨테이너(172.17.0.2) → 외부(8.8.8.8) 패킷 전송
  2. 컨테이너의 기본 게이트웨이(172.17.0.1 = docker0)로 전달
  3. 호스트의 라우팅 테이블 조회
  4. POSTROUTING에서 SNAT/Masquerade 적용
  5. 호스트의 eth0로 나가면서 출발지 IP가 호스트 IP로 변경

Kubernetes 네트워크 라우팅

Kubernetes는 더 복잡한 라우팅을 사용:

  • 각 노드는 Pod CIDR 블록 할당
  • CNI 플러그인이 라우팅 구성
  • 노드 간 라우팅 (Overlay 또는 라우팅 프로토콜)

Part 3: 가상 네트워크 (컨테이너 네트워킹의 기반)

10. 가상 네트워크 디바이스

10.1 루프백 인터페이스 (lo)

루프백의 개념

루프백 인터페이스는 자기 자신과 통신하기 위한 가상 인터페이스이다:

  • 항상 127.0.0.1 (IPv4) 또는 ::1 (IPv6)
  • 물리적 네트워크 카드 없이 동작
  • 로컬 프로세스 간 네트워크 통신에 사용

루프백의 용도

  • 로컬 서비스 테스트
  • 프로세스 간 TCP/IP 통신
  • localhost로 바인딩된 서비스 접근
  • 네트워크 프로그래밍 학습

특징

  • MTU가 매우 큼 (보통 65536 바이트)
  • 실제 네트워크를 거치지 않아 매우 빠름
  • 패킷이 NIC를 거치지 않고 커널 내부에서만 처리

10.2 TUN/TAP 디바이스

TUN/TAP의 개념

TUN과 TAP는 사용자 공간 프로그램이 네트워크 패킷을 직접 처리할 수 있게 하는 가상 인터페이스이다.

TUN vs TAP

TUN (Network TUNnel)

  • OSI 3계층 (Network Layer) 디바이스
  • IP 패킷 처리
  • VPN에서 주로 사용

TAP (Network TAP)

  • OSI 2계층 (Data Link Layer) 디바이스
  • Ethernet 프레임 처리
  • 브리지, 가상 머신 네트워킹에 사용

작동 원리

  1. 커널이 TUN/TAP 디바이스로 패킷 전송
  2. 사용자 공간 프로그램이 패킷 읽기
  3. 프로그램이 패킷 처리 (암호화, 터널링 등)
  4. 처리된 패킷을 다시 디바이스에 쓰기

사용 사례

VPN (Virtual Private Network)

  • OpenVPN, WireGuard 등
  • 암호화된 터널 생성

네트워크 에뮬레이션

  • 패킷 지연, 손실 시뮬레이션
  • 네트워크 조건 테스트

가상화

  • QEMU, VirtualBox 등
  • VM의 네트워크 인터페이스

10.3 veth pair (Virtual Ethernet)

veth pair의 개념

veth pair는 두 개의 가상 이더넷 인터페이스가 쌍으로 연결된 것이다. 마치 양쪽 끝에 네트워크 카드가 달린 가상 케이블과 같다.

특징

  • 한쪽 끝에서 전송한 패킷이 다른 쪽 끝에서 수신됨
  • 양방향 통신 가능
  • 서로 다른 네트워크 네임스페이스를 연결하는 데 사용
  • 컨테이너 네트워킹의 주요 컴포넌트

작동 원리

  • veth0과 veth1이 쌍으로 생성
  • veth0으로 전송된 패킷은 veth1에서 수신
  • veth1으로 전송된 패킷은 veth0에서 수신

생성 및 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# veth pair 생성
ip link add veth0 type veth peer name veth1

# 상태 확인
ip link show

# veth0을 기본 네임스페이스에, veth1을 다른 네임스페이스에 배치
ip netns add netns1
ip link set veth1 netns netns1

# IP 주소 할당
ip addr add 10.0.0.1/24 dev veth0
ip netns exec netns1 ip addr add 10.0.0.2/24 dev veth1

# 인터페이스 활성화
ip link set veth0 up
ip netns exec netns1 ip link set veth1 up

# 연결 테스트
ping 10.0.0.2

컨테이너에서의 사용

Docker 컨테이너가 생성될 때:

  1. veth pair 생성
  2. 한쪽 끝은 컨테이너의 네트워크 네임스페이스에 배치 (eth0으로 이름 변경)
  3. 다른 쪽 끝은 호스트의 브리지(docker0)에 연결
  4. 컨테이너는 veth를 통해 외부와 통신

10.4 Linux Bridge

Linux Bridge의 개념

Linux Bridge는 소프트웨어로 구현된 L2 스위치이다. 여러 네트워크 인터페이스를 연결하여 하나의 네트워크 세그먼트를 만든다.

작동 원리

  • 물리적 스위치처럼 MAC 주소 학습
  • MAC 주소 테이블 유지
  • 프레임을 적절한 포트로 포워딩
  • 브로드캐스트는 모든 포트로 전달

브리지 생성 및 관리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 브리지 생성
ip link add br0 type bridge

# 브리지 활성화
ip link set br0 up

# 인터페이스를 브리지에 추가
ip link set eth0 master br0
ip link set veth0 master br0

# 브리지에서 인터페이스 제거
ip link set eth0 nomaster

# 브리지 삭제
ip link delete br0

# 브리지 상태 확인
bridge link show
ip link show master br0

브리지 네트워크 설정

1
2
3
4
5
# 브리지에 IP 주소 할당
ip addr add 192.168.100.1/24 dev br0

# 브리지가 게이트웨이 역할
# 연결된 디바이스들은 192.168.100.0/24 네트워크에 속함

Docker와 브리지

Docker는 기본적으로 docker0 브리지를 생성:

1
2
3
4
5
6
7
8
# docker0 브리지 확인
ip link show docker0
brctl show docker0  # bridge-utils 패키지 필요

# 컨테이너가 시작되면:
# 1. veth pair 생성
# 2. 한쪽은 컨테이너 네임스페이스의 eth0
# 3. 다른 쪽은 docker0 브리지에 연결

브리지 vs NAT

브리지는 L2(링크 계층)에서 작동:

  • MAC 주소 기반 포워딩
  • 같은 서브넷에 있는 것처럼 동작
  • 브리지에 연결된 모든 디바이스가 같은 브로드캐스트 도메인

NAT는 L3(네트워크 계층)에서 작동:

  • IP 주소 변환
  • 다른 서브넷 간 통신

10.5 VLAN

VLAN의 개념

VLAN(Virtual LAN)은 물리적 네트워크를 논리적으로 분할하는 기술이다.

VLAN의 장점

  • 하나의 물리적 스위치로 여러 독립된 네트워크 구성
  • 브로드캐스트 도메인 분리
  • 보안 향상 (VLAN 간 격리)
  • 유연한 네트워크 관리

VLAN 태깅 (802.1Q)

Ethernet 프레임에 4바이트 VLAN 태그 추가:

  • 12비트 VLAN ID (1-4094)
  • VLAN 0: 우선순위만 표시
  • VLAN 1: 기본 VLAN

Linux에서 VLAN 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# VLAN 인터페이스 생성 (eth0.10 = eth0의 VLAN 10)
ip link add link eth0 name eth0.10 type vlan id 10

# IP 주소 할당
ip addr add 192.168.10.1/24 dev eth0.10

# 활성화
ip link set eth0.10 up

# 삭제
ip link delete eth0.10

# 확인
cat /proc/net/vlan/config

VLAN과 컨테이너

컨테이너를 서로 다른 VLAN에 배치하여 네트워크 격리:

  • 각 VLAN마다 별도의 브리지 생성
  • 컨테이너를 특정 브리지에 연결
  • VLAN 간 통신은 라우터를 통해서만 가능

10.6 VXLAN (Virtual Extensible LAN)

VXLAN의 개념

VXLAN은 물리적 네트워크 인프라를 추상화하여 논리적 네트워크를 구성하는 오버레이 네트워킹 기술이다.

VXLAN의 특징

  • Layer 2 오버레이 네트워크
  • UDP 기반 터널링 (port 4789)
  • VNI (VXLAN Network Identifier): 24비트 (1-16777215)
  • 대규모 데이터센터에 적합
  • Kubernetes 오버레이 네트워킹에서 사용

VXLAN 터널링 메커니즘

  1. 원본 패킷 (L2 Ethernet 프레임)
  2. VXLAN 헤더 추가
  3. UDP 헤더 추가
  4. IP 헤더 추가
  5. 물리 네트워크로 전송
  6. 수신 측에서 역순으로 역캡슐화

11. 네트워크 네임스페이스

11.1 네트워크 네임스페이스의 개념

Network Namespace란?

네트워크 네임스페이스는 네트워크 스택 전체를 격리하는 Linux 커널 기능이다. 각 네트워크 네임스페이스는 독립된 네트워크 환경을 가진다:

  • 독립적인 네트워크 인터페이스
  • 독립적인 라우팅 테이블
  • 독립적인 iptables 규칙
  • 독립적인 네트워크 통계
  • 독립적인 소켓

왜 필요한가?

  • 컨테이너마다 독립된 네트워크 환경 제공
  • 네트워크 격리 및 보안
  • 테스트 환경 구축
  • VPN이나 특수 네트워크 설정 격리

11.2 네트워크 네임스페이스 관리

네임스페이스 생성 및 관리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 네트워크 네임스페이스 생성
ip netns add netns1

# 네임스페이스 목록 확인
ip netns list

# 네임스페이스 내에서 명령 실행
ip netns exec netns1 <command>

# 예: 네임스페이스의 인터페이스 확인
ip netns exec netns1 ip link show

# 네임스페이스 삭제
ip netns delete netns1

네임스페이스 간 통신 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# veth pair 생성
ip link add veth0 type veth peer name veth1

# veth1을 netns1로 이동
ip link set veth1 netns netns1

# 호스트 측 설정
ip addr add 10.0.0.1/24 dev veth0
ip link set veth0 up

# 네임스페이스 내부 설정
ip netns exec netns1 ip addr add 10.0.0.2/24 dev veth1
ip netns exec netns1 ip link set veth1 up
ip netns exec netns1 ip link set lo up

# 통신 테스트
ping 10.0.0.2
ip netns exec netns1 ping 10.0.0.1

11.3 네임스페이스 격리의 범위

격리되는 것

  • 네트워크 인터페이스 (lo, eth0 등)
  • IP 주소
  • 라우팅 테이블
  • iptables 규칙
  • ARP 테이블
  • /proc/net/* 내용
  • 소켓 및 네트워크 통계

격리되지 않는 것

  • 파일 시스템 (별도의 Mount Namespace 필요)
  • 프로세스 (별도의 PID Namespace 필요)
  • 사용자/그룹 (별도의 User Namespace 필요)
  • 호스트명 (별도의 UTS Namespace 필요)

11.4 컨테이너와 네트워크 네임스페이스

Docker의 네트워크 네임스페이스 사용

Docker 컨테이너가 시작될 때:

  1. 새로운 네트워크 네임스페이스 생성
  2. veth pair 생성
  3. 한쪽 끝을 컨테이너의 네임스페이스에 배치 (eth0으로 이름 변경)
  4. 다른 쪽 끝을 호스트의 docker0 브리지에 연결
  5. 컨테이너에 IP 주소 할당
  6. 기본 게이트웨이 설정

네임스페이스 확인

1
2
3
4
5
6
7
8
9
10
11
# 실행 중인 컨테이너의 네트워크 네임스페이스 찾기
docker inspect <container_id> | grep SandboxKey

# 또는
docker inspect -f '{{.NetworkSettings.SandboxKey}}' <container_id>

# 네임스페이스로 진입
nsenter --net=/var/run/docker/netns/<namespace_id> <command>

# 예: 네임스페이스 내부의 인터페이스 확인
nsenter --net=/var/run/docker/netns/<namespace_id> ip addr show

호스트 네트워크 모드

컨테이너가 호스트의 네트워크 네임스페이스를 공유:

1
docker run --network host <image>

이 경우:

  • 네트워크 격리 없음
  • 컨테이너가 호스트의 모든 네트워크 인터페이스 접근
  • 포트 매핑 불필요
  • 성능은 좋지만 보안은 약함

12. 언더레이 vs 오버레이 네트워크

12.1 언더레이 네트워크 (Underlay)

언더레이의 개념

언더레이 네트워크는 물리적 네트워크 인프라를 기반으로 하는 네트워크이다.

특징

  • 실제 하드웨어와 케이블 기반
  • IP 라우팅 또는 L2 스위칭으로 동작
  • 물리적 토폴로지가 네트워크 구성을 결정
  • 낮은 지연과 높은 성능

예시

  • 전통적인 데이터센터 네트워크
  • BGP 기반 라우팅
  • 물리 스위치와 라우터로 구성

12.2 오버레이 네트워크 (Overlay)

오버레이의 개념

오버레이 네트워크는 언더레이 네트워크 위에 구축되는 논리적 네트워크이다. 물리 네트워크를 추상화하여 가상 네트워크를 만든다.

특징

  • 언더레이와 독립적인 논리적 토폴로지
  • 터널링을 통한 패킷 전송
  • 물리 네트워크 제약 완화
  • 더 유연한 네트워크 구성

오버레이 프로토콜

VXLAN (Virtual Extensible LAN)

  • UDP 기반 터널링
  • VNI로 논리적 네트워크 분리
  • Kubernetes Flannel, Calico VXLAN 모드에서 사용

GRE (Generic Routing Encapsulation)

  • IP 기반 터널링
  • 레거시 기술이지만 여전히 사용됨

Geneve (Generic Network Virtualization Encapsulation)

  • VXLAN의 후속 기술
  • 더 유연한 옵션 지원

12.3 오버레이 vs 언더레이 비교

특성언더레이오버레이
기초물리 인프라언더레이 네트워크
성능높음상대적으로 낮음
지연낮음높음 (캡슐화)
확장성물리 구조에 제한높은 확장성
구현 복잡도낮음높음
사용 사례데이터센터멀티 호스트 컨테이너

12.4 오버레이 네트워크의 오버헤드

캡슐화 오버헤드

  • 원본 패킷: 약 1500 바이트 (MTU)
  • 터널 헤더 추가: 약 50-70 바이트
  • 결과: 유효 데이터 크기 감소

성능 영향

  • 처리량 감소
  • CPU 사용률 증가
  • 지연 시간 증가

최적화 방법

Jumbo Frame

  • MTU를 9000 바이트로 증가
  • 오버헤드 비율 감소
1
2
# Jumbo Frame 설정
ip link set dev eth0 mtu 9000

하드웨어 오프로드

  • VXLAN 터널링을 NIC에서 처리
  • CPU 부하 감소
  • ethtool로 확인 가능

경로 최적화

  • 노드 간 물리 경로 최적화
  • 호퍼 수 최소화

13. SDN과 현대 네트워킹

13.1 SDN (Software-Defined Networking)

SDN의 개념

SDN은 네트워크 제어를 소프트웨어로 구현하는 아키텍처이다. 컨트롤 플레인과 데이터 플레인을 분리하여 네트워크를 더 유연하고 프로그래머블하게 만든다.

SDN의 주요 원칙

  • 컨트롤 플레인과 데이터 플레인 분리: 제어 로직을 중앙에서 관리
  • 프로그래머블 네트워크: 소프트웨어로 네트워크 동작 정의
  • 오픈 인터페이스: OpenFlow, NETCONF 등 표준 프로토콜 사용

SDN 아키텍처

1
2
3
4
5
6
7
8
9
┌─────────────────────────────────┐
│   Applications & Services       │
├─────────────────────────────────┤
│    SDN Controller (Control)     │
├─────────────────────────────────┤
│  OpenFlow / NETCONF / etc       │
├─────────────────────────────────┤
│  Switches, Routers (Data Plane) │
└─────────────────────────────────┘

Kubernetes와 SDN

  • Calico: BGP 기반 또는 VXLAN 오버레이
  • Flannel: VXLAN 또는 Host-GW 모드
  • Cilium: eBPF 기반

13.2 eBPF 기반 네트워킹

eBPF (Extended Berkeley Packet Filter)란?

eBPF는 Linux 커널에서 안전하게 실행되는 가상 머신이다. 커널을 수정하지 않고도 커널 기능을 확장할 수 있다.

eBPF의 특징

  • 보안: 검증 메커니즘으로 악의적 코드 실행 방지
  • 성능: 커널 공간에서 네이티브 속도로 실행
  • 유연성: 동적으로 프로그램 로드/언로드 가능
  • 확장성: 새로운 커널 수정 없이 기능 추가

eBPF 프로그램 종류

  • tc (Traffic Control): 네트워크 트래픽 제어
  • XDP (eXpress Data Path): 패킷 처리
  • kprobes/uprobes: 커널/사용자 공간 추적
  • tracepoints: 성능 분석

XDP (eXpress Data Path)

XDP는 NIC 수준에서 패킷을 처리하는 eBPF 프로그램이다.

XDP의 이점

  • 극도의 성능: 최소 오버헤드로 높은 처리량
  • 조기 필터링: 불필요한 패킷 조기 차단
  • DDoS 방어: 고속 패킷 필터링

XDP 동작 위치

1
NIC (RX) → XDP → Kernel Network Stack → Application

XDP 반환 값

  • XDP_DROP: 패킷 버림
  • XDP_PASS: 커널 네트워크 스택으로 전달
  • XDP_TX: 패킷 송신
  • XDP_REDIRECT: 다른 인터페이스로 리다이렉트
  • XDP_ABORTED: 에러 (DROP과 유사)

XDP 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 간단한 UDP 패킷 필터링
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/udp.h>

SEC("xdp")
int xdp_filter(struct xdp_md *ctx) {
    void *data_end = (void *)(long)ctx->data_end;
    void *data = (void *)(long)ctx->data;

    struct ethhdr *eth = data;
    if ((void *)(eth + 1) > data_end)
        return XDP_DROP;

    if (eth->h_proto != htons(ETH_P_IP))
        return XDP_PASS;

    struct iphdr *ip = (void *)(eth + 1);
    if ((void *)(ip + 1) > data_end)
        return XDP_DROP;

    if (ip->protocol == IPPROTO_UDP)
        return XDP_DROP;  // UDP 패킷 모두 버림

    return XDP_PASS;
}

Cilium (eBPF 기반 CNI)

Cilium은 eBPF와 XDP를 기반으로 하는 고성능 컨테이너 네트워킹 솔루션이다.

Cilium의 특징

  • 고성능: eBPF 기반으로 커널 레벨에서 동작
  • 마이크로세그멘테이션: 세밀한 정책 기반 네트워크 제어
  • 서비스 메시: 네트워크 레벨에서 로드 밸런싱
  • 관찰성: 네트워크 트래픽 가시성 제공

Cilium 아키텍처

  • Agent: 각 노드에서 실행, eBPF 프로그램 관리
  • Operator: 클러스터 레벨 관리
  • Policy Engine: 네트워크 정책 처리

Cilium 네트워크 정책

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: l3-l4-policy
spec:
  podSelector:
    matchLabels:
      role: backend
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - fromEndpoints:
    - matchLabels:
        role: frontend
    toPorts:
    - ports:
      - port: "8080"
        protocol: TCP
  egress:
  - toEndpoints:
    - matchLabels:
        role: database
    toPorts:
    - ports:
      - port: "5432"
        protocol: TCP

eBPF 기반 로드 밸런싱

Cilium은 eBPF로 L3/L4 로드 밸런싱을 구현:

  • 성능: 커널에서 처리하므로 매우 빠름
  • 효율: 사용자 공간 프록시 불필요
  • 유연성: 복잡한 로드 밸런싱 정책 지원

eBPF 기반 서비스 메시 기능

1
2
3
4
5
6
7
8
# Cilium 설치 (Kubernetes)
helm install cilium cilium/cilium --namespace kube-system

# 정책 확인
kubectl get ciliumnetworkpolicies

# 트래픽 모니터링
hubble observe -f

다른 eBPF 기반 도구

Falco: 보안 모니터링

  • 시스템 콜 추적
  • 이상 행동 감지

BCC (BPF Compiler Collection): eBPF 프로그래밍 도구

  • Python/Lua로 eBPF 프로그램 작성
  • 성능 분석 도구

bpftrace: 동적 추적 도구

  • 한 줄 짜리 eBPF 프로그램
  • 빠른 성능 분석

13.3 서비스 메시 네트워킹

서비스 메시의 개념

서비스 메시는 마이크로서비스 간 통신을 관리하는 계층이다. 네트워크 인프라를 추상화하여 서비스 간 통신을 더 안전하고 관찰 가능하게 만든다.

주요 서비스 메시 솔루션

Istio

  • 가장 널리 사용
  • 복잡한 설정이지만 강력한 기능
  • Envoy 사이드카 프록시 사용

Linkerd

  • 가볍고 빠름
  • Rust 기반 프록시
  • 설치와 운영이 간단

Cilium Service Mesh (eBPF 기반)

  • 커널 레벨에서 동작
  • 사이드카 프록시 불필요
  • 낮은 오버헤드

서비스 메시의 역할

  • 트래픽 관리: 요청 라우팅, 재시도, 타임아웃
  • 보안: mTLS, 네트워크 정책
  • 관찰성: 분산 추적, 메트릭 수집
  • 복구력: 서킷 브레이킹, 자동 복구

This post is licensed under CC BY 4.0 by the author.