본문 바로가기

NAT와 DHCP

사설 주소를 쓰는 장치들이 공인 주소 하나를 나누어 쓰게 하는 NAT와 PAT의 변환 표를 모델로 만들어, 나가는 연결과 돌아오는 응답이 어떻게 이어지는지 따라갑니다. 포트 포워딩과 NAT의 한계, CGNAT를 정리하고, DHCP가 DORA 교환으로 주소를 빌려주고 갱신하는 과정을 다룹니다.

앞의 글들에서 사설 주소는 인터넷으로 내보내지 않는다고 했습니다. 그렇다면 192.168.0.x 주소를 받은 노트북은 어떻게 인터넷의 서버와 통신할까요? 답은 공유기가 하는 NAT(network address translation)입니다. 또 노트북이 그 주소를 어떻게 받았는지도 궁금한데, 그것은 DHCP의 일입니다. 이 글에서는 이 두 가지를 차례로 살펴봅니다.

NAT와 PAT

NAT는 패킷이 지나갈 때 IP 주소를 바꾸어 주는 기능입니다. 집이나 회사에서 흔히 NAT라고 부르는 것은 대개 PAT(port address translation) 또는 NAPT라고도 하는 방식으로, IP 주소뿐 아니라 TCP와 UDP의 포트 번호까지 함께 바꾸어 내부의 여러 장치가 공인 주소 하나를 나누어 쓰게 합니다.

PAT 매핑의 요청 변환과 응답 복원

내부 출발지를 유효한 공인 끝점 매핑으로 바꿉니다. 응답 목적지를 원래 내부 끝점으로 복원합니다. 각 단계의 값과 전환 이유를 비교합니다.

PAT STATE · OUTBOUND SOURCE / RETURN DESTINATION

요청 출발지 변환의 매핑을 응답 목적지 복원에 사용한다

내부 192.168.1.10:51514를 예시 공인 203.0.113.7:40001에 매핑합니다. TCP/UDP 프로토콜과 외부 목적지 등 나머지 연결 튜플은 생략했습니다. 실제 측정·서비스 주소가 아닙니다.

PAT의 요청 출발지·응답 목적지 변환요청은 내부호스트에서 NAT를거쳐외부로전달되며출발지주소와포트가바뀐다. 응답은역방향으로돌아오며동일한유효매핑으로목적지주소와포트를복원한다. 나머지연결튜플과허용정책은별도조건이다.내부 호스트192.168.1.10:51514NAT 매핑203.0.113.7:40001외부 서비스튜플·정책 조건 유지요청 → 출발지 변환내부 호스트192.168.1.10:51514NAT 매핑203.0.113.7:40001외부 서비스튜플·정책 조건 유지응답 ← 목적지 복원
PAT 변환과 같은 매핑의 응답 복원요청은 내부호스트에서 NAT를거쳐외부로전달되며출발지주소와포트가바뀐다. 응답은역방향으로돌아오며동일한유효매핑으로목적지주소와포트를복원한다. 나머지연결튜플과허용정책은별도조건이다.내부 호스트192.168.1.10포트 51514NAT의 유효 매핑203.0.113.7:40001요청: 출발지 변환응답: 목적지 복원외부 서비스요청 ↓ · ↑ 응답요청 ↓ · ↑ 응답
PAT 매핑의 요청 변환과 응답 복원
패킷 방향변환 전 필드변환 후 필드
외부로 나가는 요청출발지 192.168.1.10:51514출발지 203.0.113.7:40001
내부로 돌아오는 응답목적지 203.0.113.7:40001목적지 192.168.1.10:51514

같은 매핑, 서로 다른 방향의 필드

요청: 출발지 IP·포트 변경 → 외부 서비스. 모바일 오른쪽 실선은 아래로 전달합니다.

응답: 공인 목적지 IP·포트 조회 → 원래 내부 목적지 복원. 모바일 왼쪽 점선은 위로 돌아옵니다.

실제 장비는 충돌이 없으면 원래 포트를 유지할 수도 있습니다. 상태 손실은 기존 흐름에 영향을 주며 NAT 매핑과 방화벽 허용 정책은 별도입니다.

이 예의 조건

  • 본문과 전체 도표의 예를 따라 요청 변환부터 목적지 복원까지 진행합니다.
관계도의 보충 설명
전체 도표의 표기·관계·조건
구분전체 도표의 내용
관계 설명요청은 내부 호스트에서 NAT를 거쳐 외부로 전달되며 출발지 주소와 포트가 바뀝니다. 응답은 역방향으로 돌아오며 동일한 유효 매핑으로 목적지 주소와 포트를 복원합니다. 나머지 연결 튜플과 허용 정책은 별도 조건입니다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
요청 변환

내부 출발지를 유효한 공인 끝점 매핑으로 바꿉니다.

  • 주소·PAT 매핑 1: 192.168.1.10:51514→203.0.113.7:40001
  • 요청의 출발지 주소·포트를 변환
응답 도착

외부 서비스가 공인 끝점으로 응답합니다.

  • 주소·PAT 매핑 1: destination203.0.113.7:40001
  • 유지된 같은 PAT 매핑을 조회
목적지 복원

응답 목적지를 원래 내부 끝점으로 복원합니다.

  • 주소·PAT 매핑 1: destination192.168.1.10:51514
  • 내부로 전달; 매핑 소실과 방화벽 조건은 별도

PAT 매핑의 요청 변환과 응답 복원

내부 출발지를 유효한 공인 끝점 매핑으로 바꿉니다. 응답 목적지를 원래 내부 끝점으로 복원합니다. 각 단계의 값과 전환 이유를 비교합니다.

PAT STATE · OUTBOUND SOURCE / RETURN DESTINATION

요청 출발지 변환의 매핑을 응답 목적지 복원에 사용한다

내부 192.168.1.10:51514를 예시 공인 203.0.113.7:40001에 매핑합니다. TCP/UDP 프로토콜과 외부 목적지 등 나머지 연결 튜플은 생략했습니다. 실제 측정·서비스 주소가 아닙니다.

PAT의 요청 출발지·응답 목적지 변환요청은 내부호스트에서 NAT를거쳐외부로전달되며출발지주소와포트가바뀐다. 응답은역방향으로돌아오며동일한유효매핑으로목적지주소와포트를복원한다. 나머지연결튜플과허용정책은별도조건이다.내부 호스트192.168.1.10:51514NAT 매핑203.0.113.7:40001외부 서비스튜플·정책 조건 유지요청 → 출발지 변환내부 호스트192.168.1.10:51514NAT 매핑203.0.113.7:40001외부 서비스튜플·정책 조건 유지응답 ← 목적지 복원
PAT 변환과 같은 매핑의 응답 복원요청은 내부호스트에서 NAT를거쳐외부로전달되며출발지주소와포트가바뀐다. 응답은역방향으로돌아오며동일한유효매핑으로목적지주소와포트를복원한다. 나머지연결튜플과허용정책은별도조건이다.내부 호스트192.168.1.10포트 51514NAT의 유효 매핑203.0.113.7:40001요청: 출발지 변환응답: 목적지 복원외부 서비스요청 ↓ · ↑ 응답요청 ↓ · ↑ 응답
PAT 매핑의 요청 변환과 응답 복원
패킷 방향변환 전 필드변환 후 필드
외부로 나가는 요청출발지 192.168.1.10:51514출발지 203.0.113.7:40001
내부로 돌아오는 응답목적지 203.0.113.7:40001목적지 192.168.1.10:51514

같은 매핑, 서로 다른 방향의 필드

요청: 출발지 IP·포트 변경 → 외부 서비스. 모바일 오른쪽 실선은 아래로 전달합니다.

응답: 공인 목적지 IP·포트 조회 → 원래 내부 목적지 복원. 모바일 왼쪽 점선은 위로 돌아옵니다.

실제 장비는 충돌이 없으면 원래 포트를 유지할 수도 있습니다. 상태 손실은 기존 흐름에 영향을 주며 NAT 매핑과 방화벽 허용 정책은 별도입니다.

이 예의 조건

  • 본문과 전체 도표의 예를 따라 요청 변환부터 목적지 복원까지 진행합니다.

관계도의 보충 설명

전체 도표의 표기·관계·조건
구분전체 도표의 내용
관계 설명요청은 내부 호스트에서 NAT를 거쳐 외부로 전달되며 출발지 주소와 포트가 바뀝니다. 응답은 역방향으로 돌아오며 동일한 유효 매핑으로 목적지 주소와 포트를 복원합니다. 나머지 연결 튜플과 허용 정책은 별도 조건입니다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
요청 변환

내부 출발지를 유효한 공인 끝점 매핑으로 바꿉니다.

  • 주소·PAT 매핑 1: 192.168.1.10:51514→203.0.113.7:40001
  • 요청의 출발지 주소·포트를 변환
응답 도착

외부 서비스가 공인 끝점으로 응답합니다.

  • 주소·PAT 매핑 1: destination203.0.113.7:40001
  • 유지된 같은 PAT 매핑을 조회
목적지 복원

응답 목적지를 원래 내부 끝점으로 복원합니다.

  • 주소·PAT 매핑 1: destination192.168.1.10:51514
  • 내부로 전달; 매핑 소실과 방화벽 조건은 별도

그림처럼 내부 장치가 바깥으로 연결을 시작하면, 공유기는 패킷의 출발지 주소와 포트를 자기의 공인 주소와 비어 있는 포트로 바꾸어 내보내고, 그 짝을 변환 표에 적어 둡니다. 바깥 서버의 응답은 공인 주소의 그 포트로 돌아오므로, 공유기는 표를 찾아 목적지를 원래 내부 장치의 주소와 포트로 되돌려 보냅니다. 나가는 패킷에서는 출발지가, 돌아오는 패킷에서는 목적지가 바뀐다는 점이 중요합니다. 다음 코드는 이 변환 표를 흉내 냅니다.

class PAT:
    def __init__(self, public_ip, first_port=40001):
        self.public_ip, self.next_port = public_ip, first_port
        self.out, self.back = {}, {}                    # 나가는 방향과 돌아오는 방향의 표

    def outbound(self, src, dst):
        key = (src, dst)
        if key not in self.out:                         # 처음 보는 연결이면 공인 포트를 하나 배정한다
            mapped = (self.public_ip, self.next_port)
            self.next_port += 1
            self.out[key], self.back[(mapped, dst)] = mapped, src
        return self.out[key]

    def inbound(self, dst_mapped, src):
        return self.back.get((dst_mapped, src), "표에 없음: 버림")

nat = PAT("203.0.113.7")
server = ("198.51.100.10", 443)
a = nat.outbound(("192.168.1.10", 51514), server)
b = nat.outbound(("192.168.1.11", 51514), server)
print("A의 연결:", a)
print("B의 연결:", b)
print("40002로 온 응답:", nat.inbound(("203.0.113.7", 40002), server))
print("모르는 곳에서 40002로:", nat.inbound(("203.0.113.7", 40002), ("192.0.2.99", 443)))
A의 연결: ('203.0.113.7', 40001)
B의 연결: ('203.0.113.7', 40002)
40002로 온 응답: ('192.168.1.11', 51514)
모르는 곳에서 40002로: 표에 없음: 버림

두 장치가 우연히 같은 출발지 포트 51514를 썼지만, 공유기가 서로 다른 공인 포트 40001과 40002를 배정했으므로 두 연결은 섞이지 않습니다. 40002로 돌아온 서버의 응답은 표를 찾아 B로 갔고, 표에 없는 상대가 같은 포트로 보낸 패킷은 버려졌습니다. 실제 장비는 포트를 고르는 방법과, 처음 연결한 상대가 아닌 곳에서 온 패킷을 받아 줄지가 저마다 다르며, RFC 4787은 이런 동작을 몇 가지로 나누어 정리합니다. 변환 표는 연결이 끝나거나 한동안 쓰이지 않으면 지워집니다.

NAT의 종류와 포트 포워딩

종류바꾸는 것쓰임
SNAT출발지 주소내부의 클라이언트가 인터넷에 나갈 때
DNAT목적지 주소바깥에서 들어오는 연결을 내부 서버로 넘길 때
PAT(NAPT)주소와 포트를 함께여러 내부 장치가 공인 주소 하나를 나누어 쓸 때
1:1 NAT내부 주소 하나와 공인 주소 하나를 고정해 짝짓기서버를 통째로 공개할 때

PAT는 내부에서 먼저 시작한 연결에 대해서만 표가 만들어지므로, 바깥에서 먼저 들어오는 연결은 갈 곳을 모릅니다. 그래서 내부 서버를 바깥에 공개하려면 "공인 주소의 443번 포트로 들어온 연결은 내부의 192.168.1.50:8443으로 보낸다"는 정적인 DNAT 규칙을 미리 만들어 두는데, 이를 포트 포워딩(port forwarding)이라고 합니다. Linux를 라우터로 쓴다면 다음과 같이 설정합니다.

sudo sysctl -w net.ipv4.ip_forward=1                        # 패킷 전달을 켠다
sudo iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE    # 내부에서 나가는 연결의 출발지를 바꾼다
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 \
  -j DNAT --to-destination 192.168.1.50:8443                # 바깥의 443을 내부 서버로 넘긴다
sudo iptables -t nat -L -n -v                                # NAT 규칙 확인
sudo conntrack -L                                            # 지금의 변환 표(연결 추적 항목)

NAT 규칙은 주소를 바꿀 뿐 통과를 허락하지는 않으므로, 방화벽의 FORWARD 규칙도 그 연결을 허락해야 합니다. 요즘 배포판은 같은 일을 nftables로 하기도 합니다.

NAT의 한계

NAT는 주소의 부족을 크게 덜어 주었지만, 인터넷의 장치들이 서로 직접 연결할 수 있다는 원래의 설계를 깨뜨렸습니다. 바깥에서 먼저 연결할 수 없으니 P2P나 화상 통화는 STUN 서버로 자기의 공인 주소와 포트를 알아내 상대와 맞추어 보고, 그래도 안 되면 TURN 서버를 거쳐 중계해야 합니다. 변환 표의 포트와 메모리가 바닥나면 새 연결을 만들 수 없고, 공유기가 다시 시작해 표를 잃으면 진행 중인 연결이 모두 끊깁니다. FTP의 액티브 모드나 SIP처럼 데이터 안에 IP 주소와 포트를 적어 보내는 프로토콜은 NAT가 그 내용까지 고쳐 주어야 동작합니다.

통신사가 가입자 여럿에게 공인 주소 하나를 나누어 쓰게 하는 CGNAT(carrier-grade NAT) 아래에서는 문제가 더 커집니다. 가입자의 공유기가 받은 주소가 4장 1편에서 본 100.64.0.0/10의 공유 주소라면, 공유기 위에 통신사의 NAT가 하나 더 있는 것입니다. 이때는 공유기에 포트 포워딩을 설정해도 통신사의 NAT가 바깥의 연결을 넘겨주지 않으므로 소용이 없고, 통신사에 공인 주소를 요청하거나 IPv6를 쓰거나, 내부에서 바깥으로 먼저 연결을 맺어 두는 Cloudflare Tunnel이나 ngrok 같은 터널을 써야 합니다.

더 깊이: NAT가 지켜야 할 동작을 정한 RFC

RFC 4787(BCP 127)과 RFC 5382(BCP 142)는 각각 UDP와 TCP에 대해, NAT가 어떻게 동작해야 응용 프로그램이 덜 깨지는지를 정한 운영 지침입니다. 두 문서는 매핑(mapping)과 필터링(filtering)을 나누어 봅니다. 매핑은 내부의 주소와 포트에 어떤 공인 포트를 배정하느냐이고, 필터링은 그 공인 포트로 들어온 패킷 가운데 무엇을 받아 주느냐입니다. 매핑은 목적지가 어디든 같은 공인 포트를 다시 쓰는 끝점 독립 매핑(endpoint-independent mapping), 목적지 주소가 같을 때만 다시 쓰는 주소 의존 매핑, 목적지 주소와 포트가 모두 같을 때만 다시 쓰는 주소·포트 의존 매핑으로 나뉩니다.

두 RFC는 NAT가 끝점 독립 매핑을 따라야 한다고 요구합니다. 그래야 STUN 서버에게 물어 알아낸 공인 주소와 포트를 다른 상대에게 알려 주었을 때 그 상대와도 같은 포트로 통신이 이어지기 때문이며, RFC 4787은 이를 지키지 않으면 UDP 중계를 쓸 수밖에 없다고 적습니다. 매핑을 이렇게 정해도 보안이 약해지지는 않습니다. 어떤 패킷을 들여보낼지는 매핑과 따로 필터링이 정하기 때문입니다.

변환 표를 언제 지울지도 정해 두었습니다. UDP의 매핑은 2분보다 빨리 지우면 안 되고 기본값은 5분 이상을 권하며, 맺어진 TCP 연결은 조용하더라도 2시간 4분보다 빨리 지우면 안 됩니다. 이 값은 TCP keep-alive가 켜져 있으면 기본으로 2시간마다 나간다는 점에 맞춘 것입니다. 다만 모든 NAT가 이 권고를 따르는 것은 아니어서, 예를 들어 AWS의 NAT 게이트웨이는 350초 동안 조용한 연결을 끊고, 그 뒤에 연결을 이어 가려는 내부 쪽에 RST를 돌려준다고 문서에 밝혀 두었습니다.

DHCP: 주소를 자동으로 빌려주기

컴퓨터를 네트워크에 연결하면 주소가 저절로 정해지는 것은 DHCP(dynamic host configuration protocol)가 있기 때문입니다. DHCP 서버는 정해 둔 주소 범위에서 주소를 골라 일정한 기간 동안 빌려주는데, 이를 임대(lease)라고 합니다. 처음 주소를 받는 교환은 네 메시지의 첫 글자를 따서 DORA라고 부릅니다.

DHCP 최초 주소 임대의 DORA 교환

유효 임대가 없는 클라이언트가 서버를 찾습니다. ACK 뒤 조건을 확인하고 임대를 설정합니다. 각 단계의 값과 전환 이유를 비교합니다.

DHCPv4 FIRST LEASE · DISCOVER / OFFER / REQUEST / ACK

최초 임대는 제안을 선택한 뒤 ACK로 확정한다

같은 LAN에서 서버 하나가 응답하는 최초 임대 성공 예시입니다. Discover·선택 알림 Request는 브로드캐스트이고 Offer·ACK의 전달 방식은 클라이언트 상태와 플래그에 따라 달라집니다. Relay·갱신 경로는 생략했습니다.

DHCP 최초 주소 임대의 DORA 교환같은 LAN에서 서버 하나가 응답하는 최초 임대의 성공 경로입니다. Discover와 선택 알림 Request는 브로드캐스트이며 Offer와 ACK의 전달 방식은 클라이언트 상태와 플래그에 따라 달라집니다. Relay와 갱신 경로는 제외합니다.1 · Discover서버 찾기2 · Offer주소 제안3 · Request선택한 제안 알림4 · ACK임대 확정클라이언트UDP 68DHCP 서버UDP 67
DHCP 최초 주소 임대의 DORA 교환같은 LAN에서 서버 하나가 응답하는 최초 임대의 성공 경로입니다. Discover와 선택 알림 Request는 브로드캐스트이며 Offer와 ACK의 전달 방식은 클라이언트 상태와 플래그에 따라 달라집니다. Relay와 갱신 경로는 제외합니다.1 · Discover서버 찾기2 · Offer주소 제안3 · Request선택한 제안 알림4 · ACK임대 확정클라이언트UDP 68DHCP 서버UDP 67

위에서 아래로 시간 순서, 가로 화살표는 메시지 방향입니다. 점선 Offer는 응답 방향을 구별하기 위한 표현이며 유니캐스트라는 뜻이 아닙니다. 세로 점선은 시간축, 청록 ACK는 이 예시의 임대 확정입니다.

이 예의 조건

  • 본문과 전체 도표의 예를 따라 Discover부터 ACK까지 진행합니다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
Discover

유효 임대가 없는 클라이언트가 서버를 찾습니다.

  • 임대·메시지 1: clientUDP68→server67
  • 임대·메시지 2: broadcast
  • 최초 임대의 Discover를 브로드캐스트
Offer

서버가 192.168.1.100을 제안합니다.

  • 임대·메시지 1: offer192.168.1.100
  • 임대·메시지 2: 아직 사용 확정 아님
  • 주소 사용은 아직 확정 전; 응답 방식은 조건에 따라 달라짐
Request

선택한 서버와 주소를 알립니다.

  • 임대·메시지 1: 선택 제안
  • 임대·메시지 2: broadcast
  • Request 브로드캐스트; 아직 ACK·설정 성공은 미확인
ACK

ACK 뒤 조건을 확인하고 임대를 설정합니다.

  • 임대·메시지 1: lease 확정
  • 임대·메시지 2: 충돌 확인 추가
  • 추가 충돌 확인 필요; 임대만으로 DNS·경로·인터넷 업무 성공을 보장하지 않음

DHCP 최초 주소 임대의 DORA 교환

유효 임대가 없는 클라이언트가 서버를 찾습니다. ACK 뒤 조건을 확인하고 임대를 설정합니다. 각 단계의 값과 전환 이유를 비교합니다.

DHCPv4 FIRST LEASE · DISCOVER / OFFER / REQUEST / ACK

최초 임대는 제안을 선택한 뒤 ACK로 확정한다

같은 LAN에서 서버 하나가 응답하는 최초 임대 성공 예시입니다. Discover·선택 알림 Request는 브로드캐스트이고 Offer·ACK의 전달 방식은 클라이언트 상태와 플래그에 따라 달라집니다. Relay·갱신 경로는 생략했습니다.

DHCP 최초 주소 임대의 DORA 교환같은 LAN에서 서버 하나가 응답하는 최초 임대의 성공 경로입니다. Discover와 선택 알림 Request는 브로드캐스트이며 Offer와 ACK의 전달 방식은 클라이언트 상태와 플래그에 따라 달라집니다. Relay와 갱신 경로는 제외합니다.1 · Discover서버 찾기2 · Offer주소 제안3 · Request선택한 제안 알림4 · ACK임대 확정클라이언트UDP 68DHCP 서버UDP 67
DHCP 최초 주소 임대의 DORA 교환같은 LAN에서 서버 하나가 응답하는 최초 임대의 성공 경로입니다. Discover와 선택 알림 Request는 브로드캐스트이며 Offer와 ACK의 전달 방식은 클라이언트 상태와 플래그에 따라 달라집니다. Relay와 갱신 경로는 제외합니다.1 · Discover서버 찾기2 · Offer주소 제안3 · Request선택한 제안 알림4 · ACK임대 확정클라이언트UDP 68DHCP 서버UDP 67

위에서 아래로 시간 순서, 가로 화살표는 메시지 방향입니다. 점선 Offer는 응답 방향을 구별하기 위한 표현이며 유니캐스트라는 뜻이 아닙니다. 세로 점선은 시간축, 청록 ACK는 이 예시의 임대 확정입니다.

이 예의 조건

  • 본문과 전체 도표의 예를 따라 Discover부터 ACK까지 진행합니다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
Discover

유효 임대가 없는 클라이언트가 서버를 찾습니다.

  • 임대·메시지 1: clientUDP68→server67
  • 임대·메시지 2: broadcast
  • 최초 임대의 Discover를 브로드캐스트
Offer

서버가 192.168.1.100을 제안합니다.

  • 임대·메시지 1: offer192.168.1.100
  • 임대·메시지 2: 아직 사용 확정 아님
  • 주소 사용은 아직 확정 전; 응답 방식은 조건에 따라 달라짐
Request

선택한 서버와 주소를 알립니다.

  • 임대·메시지 1: 선택 제안
  • 임대·메시지 2: broadcast
  • Request 브로드캐스트; 아직 ACK·설정 성공은 미확인
ACK

ACK 뒤 조건을 확인하고 임대를 설정합니다.

  • 임대·메시지 1: lease 확정
  • 임대·메시지 2: 충돌 확인 추가
  • 추가 충돌 확인 필요; 임대만으로 DNS·경로·인터넷 업무 성공을 보장하지 않음

아직 주소가 없는 클라이언트는 출발지 0.0.0.0의 UDP 68번 포트에서, 목적지 255.255.255.255의 67번 포트로 "주소를 줄 서버가 있느냐"는 Discover를 브로드캐스트로 보냅니다. 서버들은 빌려줄 주소를 담은 Offer로 답하고, 클라이언트는 그 가운데 하나를 골라 "이 서버의 이 주소를 쓰겠다"는 Request를 다시 브로드캐스트로 보냅니다. 브로드캐스트로 보내는 것은 고르지 않은 다른 서버들도 자기 제안이 거절되었음을 알게 하기 위해서입니다. 마지막으로 고른 서버가 ACK로 확정하면, 클라이언트는 그 주소를 인터페이스에 설정합니다. 이 절차는 RFC 2131에 정해져 있습니다.

DHCP 서버가 주는 것은 주소만이 아닙니다.

받는 정보예쓰임
IP 주소와 서브넷 마스크192.168.1.100, 255.255.255.0자기 주소와 같은 네트워크의 범위
기본 게이트웨이192.168.1.1다른 네트워크로 나갈 때의 출구
DNS 서버192.168.1.1 또는 통신사의 서버이름을 주소로 바꿀 때 묻는 곳
임대 시간86400초주소를 쓸 수 있는 기간

임대의 갱신

클라이언트는 임대가 끝나기 전에 연장을 요청합니다. RFC 2131의 기본값에 따르면 임대 시간의 절반이 지나면(T1) 주소를 빌려준 서버에 직접 연장을 요청하고, 그 서버가 답하지 않은 채 87.5%가 지나면(T2) 다른 서버라도 답하라고 브로드캐스트로 요청합니다.

LEASE = 86_400                       # 임대 시간 24시간(초)
t1, t2 = LEASE * 0.5, LEASE * 0.875  # RFC 2131의 기본값
for name, sec in (("갱신(T1): 임대해 준 서버에 유니캐스트로 연장 요청", t1),
                  ("재바인딩(T2): 아무 서버에나 브로드캐스트로 연장 요청", t2),
                  ("만료: 주소를 더 쓸 수 없다", LEASE)):
    print(f"{sec / 3600:>4.1f}시간 뒤  {name}")
12.0시간 뒤  갱신(T1): 임대해 준 서버에 유니캐스트로 연장 요청
21.0시간 뒤  재바인딩(T2): 아무 서버에나 브로드캐스트로 연장 요청
24.0시간 뒤  만료: 주소를 더 쓸 수 없다

임대가 끝날 때까지 아무 서버도 답하지 않으면 클라이언트는 그 주소를 더 쓸 수 없고, 처음부터 Discover를 다시 시작합니다. DHCP 서버가 다른 서브넷에 있으면, 브로드캐스트는 라우터를 넘지 못하므로 라우터가 DHCP 릴레이(relay)로 메시지를 서버에 대신 전해 줍니다.

nmcli -f DHCP4 device show eth0    # Linux(NetworkManager): 받은 DHCP 옵션
ipconfig /all                      # Windows: DHCP 서버, 임대를 받은 시각과 끝나는 시각
ipconfig /release                  # Windows: 지금의 임대를 돌려준다
ipconfig /renew                    # Windows: 임대를 새로 요청한다

ipconfig /all에 나오는 임대를 받은 시각과 끝나는 시각의 차이가 임대 시간이며, 앞에서 계산한 것처럼 기본값으로는 그 절반이 지나면 클라이언트가 갱신을 시도합니다. /release는 받은 주소를 서버에 돌려주므로 그 순간 네트워크 연결이 끊깁니다. 원격 데스크톱처럼 네트워크로 접속한 컴퓨터에서 실행하면 /renew를 입력할 연결도 함께 사라지므로 주의해야 합니다.

공유기가 하는 일

집의 공유기는 여러 장비를 하나로 합친 것입니다. 내부와 외부 사이에서 패킷을 넘기는 라우터, 사설 주소와 공인 주소를 바꾸는 NAT, 내부 장치에 주소를 나누어 주는 DHCP 서버, 유선 포트 사이의 스위치, Wi-Fi를 제공하는 무선 AP, 바깥에서 들어오는 원치 않는 연결을 막는 방화벽이 한 상자에 들어 있습니다. 개발 중인 서버를 집에서 띄워 바깥에서 접속하려면 포트 포워딩이 필요한 이유도, 그 상자 안의 NAT 때문입니다.

정리

  • NAT는 패킷이 지나갈 때 주소를 바꾸며, 흔히 쓰는 PAT는 주소와 포트를 함께 바꾸어 여러 장치가 공인 주소 하나를 나누어 쓰게 합니다.
  • PAT는 내부에서 시작한 연결을 변환 표에 적어 두고, 돌아오는 응답의 목적지를 표에 따라 되돌립니다. 표에 없는 패킷은 갈 곳이 없습니다.
  • 바깥에서 먼저 들어오는 연결은 포트 포워딩 같은 정적인 DNAT 규칙과 방화벽의 허락이 있어야 내부로 들어옵니다.
  • CGNAT 아래에서는 공유기의 포트 포워딩만으로는 바깥에서 접속할 수 없어, 공인 주소나 IPv6, 터널이 필요합니다.
  • DHCP는 Discover, Offer, Request, ACK의 교환으로 주소와 게이트웨이, DNS를 빌려주며, 클라이언트는 임대의 절반과 87.5%에서 연장을 요청합니다.

연습 문제

1. 변환 표의 한 줄이 사라지면

본문의 표에서 B의 연결에 해당하는 줄만 사라졌습니다. 그 뒤 서버가 보낸 응답이 공인 주소의 40002번 포트로 도착했습니다. A의 줄이나 내부 포트 51514만 보고 응답을 어느 장치로 보낼지 정할 수 있나요?

해설 보기

정할 수 없습니다. A의 줄은 40001번 포트에 대한 것이고, 내부 포트 51514는 A와 B가 함께 썼으므로 그것만으로는 B를 가리킬 수 없습니다. 40002번 포트와 내부 장치를 잇던 줄이 사라졌으므로 공유기는 이 응답을 받을 장치를 알 수 없고, 다른 정적 규칙이 없다면 패킷을 버립니다. B의 연결은 끊긴 것과 같아서, B는 연결을 다시 맺어야 합니다. 공유기를 다시 시작하면 진행 중인 연결이 모두 끊기는 이유가 이것입니다.

2. Request까지만 보였다

패킷 캡처에서 Discover, Offer, Request까지는 보이지만 ACK는 보이지 않습니다. "DHCP 서버가 응답했으니 주소를 받았고 인터넷도 될 것"이라고 말할 수 있나요?

해설 보기

말할 수 없습니다. Offer는 서버가 주소를 제안했다는 것이고, Request는 클라이언트가 그 제안을 고르겠다고 알린 것일 뿐, 서버가 ACK로 확정해야 임대가 시작됩니다. ACK 대신 거절하는 NAK가 왔을 수도 있고, ACK가 도중에 사라졌을 수도 있으며, 그러면 클라이언트는 주소를 설정하지 못합니다. 또 주소를 제대로 받더라도 인터넷이 되려면 게이트웨이까지의 경로와 DNS, 바깥의 방화벽이 모두 정상이어야 하므로, 이는 따로 확인해야 합니다.

3. 포트 포워딩을 했는데 접속이 안 된다

집에서 띄운 웹 서버를 바깥에 공개하려고 공유기에 80번 포트의 포트 포워딩을 설정했지만, 바깥에서 접속하면 연결되지 않습니다. 공유기의 WAN 주소를 보니 100.72.15.4입니다. 무엇이 문제이고, 어떻게 해결할 수 있나요?

해설 보기

100.72.15.4는 CGNAT를 위한 공유 주소 공간 100.64.0.0/10에 속하므로, 공유기 위에 통신사의 NAT가 하나 더 있습니다. 바깥에서 오는 연결은 통신사의 NAT에서 멈추고, 통신사의 NAT에는 그 연결을 이 공유기로 넘기는 규칙이 없으므로 공유기의 포트 포워딩까지 닿지 못합니다. 통신사에 공인 IPv4 주소를 요청하거나, 통신사가 IPv6를 준다면 IPv6로 공개하거나, 집의 서버에서 바깥으로 먼저 연결을 맺어 두는 Cloudflare Tunnel이나 ngrok 같은 터널을 쓰면 됩니다. 또 많은 통신사가 가정용 회선의 80번 포트를 막아 두므로, 다른 포트를 써야 할 수도 있습니다.

다음 글 IPv6에서는 IPv4 주소의 고갈을 근본적으로 해결하려고 만든 IPv6의 주소 체계와, 주소를 스스로 정하는 방법을 살펴봅니다.