본문 바로가기
TYLER SONGBlog
← Blog index
CS12 min read

DHCP: 임대 기반으로 네트워크 설정을 자동 할당하는 프로토콜

동적 호스트 구성 프로토콜(DHCP)은 클라이언트에 IP 주소, 서브넷 마스크, 기본 게이트웨이, DNS 서버 같은 네트워크 설정을 자동으로 제공한다. DHCPv4는 주로 발견, 제안, 요청, 확인의 네 단계와 임대 갱신 절차로 동작한다. 브로드캐스트가 라우터를 통과하지 못하는 환경에서는 DHCP 릴레이를 사용한다.

By 송민성

1. 개념

동적 호스트 구성 프로토콜(DHCP, Dynamic Host Configuration Protocol)은 네트워크에 접속한 장치가 필요한 설정을 서버에서 자동으로 받는 프로토콜이다.

DHCP 서버는 설정을 영구히 넘기지 않고 일정 기간 빌려준다. 이를 임대(lease)라고 한다. 임대 기간이 끝나기 전에 갱신하지 못하면 클라이언트는 해당 IP 주소를 계속 사용해서는 안 된다.

DHCPv4가 제공할 수 있는 대표 정보는 다음과 같다.

  • IP 주소
  • 서브넷 마스크(subnet mask)
  • 기본 게이트웨이(default gateway)
  • DNS 서버 주소
  • 도메인 이름
  • 임대 시간
  • 네트워크 시간 프로토콜(NTP) 서버
  • 정적 경로(static route)

DHCP 구성 요소는 다음과 같다.

  • DHCP 클라이언트(client): 네트워크 설정을 요청하는 장치
  • DHCP 서버(server): 주소와 설정을 할당하는 서버
  • 주소 풀(address pool): 동적으로 할당할 수 있는 IP 주소 범위
  • 임대 데이터베이스(lease database): 주소, 클라이언트, 만료 시각의 대응 관계
  • DHCP 릴레이 에이전트(relay agent): 다른 서브넷의 요청을 DHCP 서버로 전달하는 장치

고정 할당(reservation)을 사용하면 특정 장치의 매체 접근 제어 주소(MAC address)나 클라이언트 식별자(client identifier)에 항상 같은 IP 주소를 제공할 수 있다.

2. 왜 사용하는가

장치마다 IP 주소를 수동으로 설정하면 주소 중복, 잘못된 게이트웨이, DNS 누락 같은 오류가 발생하기 쉽다. 노트북과 휴대전화처럼 여러 네트워크를 이동하는 장치에는 수동 설정이 더 불편하다.

DHCP는 다음 문제를 해결한다.

  1. 장치가 네트워크에 접속할 때 설정을 자동으로 제공한다.
  2. 사용하지 않는 IP 주소를 회수해 다른 장치에 재할당한다.
  3. 게이트웨이와 DNS 서버 변경을 중앙에서 배포한다.
  4. 주소 중복 가능성을 줄인다.
  5. 고정 할당을 통해 서버나 프린터에 예측 가능한 주소를 제공한다.

예를 들어 192.168.10.0/24 네트워크에서 다음처럼 주소 풀을 구성할 수 있다.

text
네트워크: 192.168.10.0/24
게이트웨이: 192.168.10.1
동적 할당 범위: 192.168.10.100~192.168.10.200
DNS 서버: 192.168.10.2
임대 시간: 8시간

라우터, 서버, 네트워크 장비에 사용할 주소는 동적 할당 범위에서 제외해야 한다.

3. 동작 원리

DHCPv4의 DORA 절차

DHCPv4의 초기 주소 할당은 발견(Discover), 제안(Offer), 요청(Request), 확인(Acknowledgement) 순서로 진행된다. 각 단계의 앞 글자를 따서 DORA라고 부른다.

text
클라이언트                                  DHCP 서버
    |                                           |
    | DHCPDISCOVER                              |
    |------------------------------------------>|
    |                                           |
    | DHCPOFFER                                 |
    |<------------------------------------------|
    |                                           |
    | DHCPREQUEST                               |
    |------------------------------------------>|
    |                                           |
    | DHCPACK                                   |
    |<------------------------------------------|
    |                                           |
    | IP 주소와 네트워크 설정 사용 시작         |

1. DHCPDISCOVER

초기 클라이언트는 자신의 IP 주소와 DHCP 서버의 주소를 모른다. 따라서 DHCPDISCOVER 메시지를 브로드캐스트(broadcast)로 전송해 사용 가능한 서버를 찾는다.

DHCPv4는 사용자 데이터그램 프로토콜(UDP)을 사용한다.

  • 서버 포트: UDP 67
  • 클라이언트 포트: UDP 68

2. DHCPOFFER

요청을 받은 서버는 사용 가능한 IP 주소와 설정을 DHCPOFFER 메시지로 제안한다. 여러 서버가 응답하면 클라이언트는 여러 제안을 받을 수 있다.

제안에는 보통 다음 정보가 포함된다.

  • 제안된 IP 주소
  • 서버 식별자
  • 서브넷 마스크
  • 기본 게이트웨이
  • DNS 서버
  • 임대 시간

DHCPOFFER는 아직 최종 할당을 의미하지 않는다.

3. DHCPREQUEST

클라이언트는 선택한 제안을 DHCPREQUEST 메시지로 알린다. 초기 할당 단계에서는 브로드캐스트를 사용해 선택된 서버와 선택되지 않은 서버 모두가 결과를 알 수 있게 한다.

선택되지 않은 서버는 임시로 확보했던 주소를 다시 주소 풀로 돌려놓을 수 있다.

4. DHCPACK

선택된 서버가 DHCPACK 메시지를 보내면 임대가 확정된다. 클라이언트는 받은 주소와 옵션을 네트워크 인터페이스에 적용한다.

서버가 요청을 허용할 수 없으면 DHCPNAK 메시지를 보낼 수 있다. 클라이언트는 기존 설정을 버리고 주소 할당 절차를 다시 시작한다.

트랜잭션 식별자

각 DHCP 교환에는 트랜잭션 식별자(transaction ID)가 포함된다. 클라이언트는 이를 이용해 자신이 보낸 요청과 서버 응답을 연결한다.

IP 주소를 받기 전에는 여러 클라이언트가 동일한 브로드캐스트 채널을 사용하므로 트랜잭션 식별자가 필요하다.

임대 갱신

클라이언트는 임대 만료 직전까지 기다리지 않고 미리 갱신을 시도한다.

서버가 별도 값을 제공하지 않았을 때의 기본 시점은 다음과 같다.

  • 갱신 시각 T1: 임대 기간의 50%
  • 재결합 시각 T2: 임대 기간의 87.5%
  • 만료 시각: 임대 기간의 100%

T1에 도달하면 클라이언트는 기존 DHCP 서버에 DHCPREQUEST를 전송해 갱신을 요청한다. 서버가 DHCPACK로 응답하면 임대 시간이 다시 시작된다.

T1 이후에도 응답을 받지 못해 T2에 도달하면 클라이언트는 특정 서버가 아닌 사용 가능한 모든 DHCP 서버를 대상으로 재결합(rebinding)을 시도한다.

text
임대 시작          T1                  T2               임대 만료
   |---------------|-------------------|-------------------|
   | 주소 사용     | 기존 서버에 갱신 | 모든 서버에 요청  |
   |               | 요청             |                   |

임대가 만료될 때까지 갱신하지 못하면 클라이언트는 해당 IP 주소의 사용을 중단하고 초기 할당 절차를 다시 시작해야 한다.

주소 반환

클라이언트가 주소를 더 이상 사용하지 않을 때 DHCPRELEASE 메시지를 보낼 수 있다. 서버는 해당 주소를 주소 풀로 반환한다.

장치가 갑자기 종료되거나 네트워크에서 분리되면 DHCPRELEASE가 전달되지 않을 수 있다. 서버는 임대 만료 시각을 기준으로 주소를 회수한다.

DHCP 릴레이

브로드캐스트 패킷은 일반적으로 라우터를 넘어가지 않는다. DHCP 서버가 다른 서브넷에 있다면 라우터나 계층 3 스위치에 DHCP 릴레이를 구성한다.

text
클라이언트
    |
    | 브로드캐스트
    v
DHCP 릴레이
    |
    | 유니캐스트
    v
DHCP 서버

릴레이는 클라이언트가 속한 네트워크 정보를 서버에 전달한다. 서버는 이 정보를 기준으로 알맞은 서브넷의 주소 풀을 선택한다.

DHCPv6

DHCPv6는 IPv6용 프로토콜이며 DHCPv4와 별도로 동작한다.

  • DHCPv6 클라이언트 포트: UDP 546
  • DHCPv6 서버 및 릴레이 포트: UDP 547
  • 브로드캐스트 대신 멀티캐스트(multicast) 사용
  • 대표 메시지: Solicit, Advertise, Request, Reply

IPv6에서는 라우터 광고(RA, Router Advertisement)가 기본 라우터와 접두사 정보를 제공한다. DHCPv6가 기본 게이트웨이를 직접 제공하는 구조가 아니다. 네트워크 설정에 따라 상태 유지 DHCPv6(stateful DHCPv6), 상태 비유지 DHCPv6(stateless DHCPv6), 상태 비저장 주소 자동 구성(SLAAC)을 조합한다.

4. 코드 예제

다음 코드는 DHCP 주소 풀의 핵심 동작을 단순화한 예제다. 클라이언트에 주소를 임대하고, 임대 시간을 갱신하며, 만료된 주소를 회수한다.

python
from dataclasses import dataclass from datetime import datetime, timedelta, timezone from ipaddress import IPv4Address from typing import Callable @dataclass class Lease: client_id: str ip_address: IPv4Address expires_at: datetime class DhcpPool: def __init__( self, start: str, end: str, lease_seconds: int, now: Callable[[], datetime] | None = None, ) -> None: start_ip = IPv4Address(start) end_ip = IPv4Address(end) if start_ip > end_ip: raise ValueError("시작 주소는 종료 주소보다 작거나 같아야 합니다.") if lease_seconds <= 0: raise ValueError("임대 시간은 1초 이상이어야 합니다.") self.available = [ IPv4Address(value) for value in range(int(start_ip), int(end_ip) + 1) ] self.lease_duration = timedelta(seconds=lease_seconds) self.leases: dict[str, Lease] = {} self.now = now or (lambda: datetime.now(timezone.utc)) def reclaim_expired(self) -> None: current_time = self.now() expired_clients = [ client_id for client_id, lease in self.leases.items() if lease.expires_at <= current_time ] for client_id in expired_clients: lease = self.leases.pop(client_id) self.available.append(lease.ip_address) self.available.sort() def allocate(self, client_id: str) -> Lease: self.reclaim_expired() existing = self.leases.get(client_id) if existing is not None: return existing if not self.available: raise RuntimeError("할당 가능한 IP 주소가 없습니다.") lease = Lease( client_id=client_id, ip_address=self.available.pop(0), expires_at=self.now() + self.lease_duration, ) self.leases[client_id] = lease return lease def renew(self, client_id: str) -> Lease: self.reclaim_expired() lease = self.leases.get(client_id) if lease is None: raise KeyError("갱신할 임대가 없습니다.") lease.expires_at = self.now() + self.lease_duration return lease def release(self, client_id: str) -> None: lease = self.leases.pop(client_id, None) if lease is None: return self.available.append(lease.ip_address) self.available.sort() def main() -> None: pool = DhcpPool( start="192.168.10.100", end="192.168.10.102", lease_seconds=3600, ) first = pool.allocate("노트북") second = pool.allocate("휴대전화") print("노트북 임대:", first) print("휴대전화 임대:", second) renewed = pool.renew("노트북") print("노트북 갱신:", renewed) pool.release("휴대전화") third = pool.allocate("태블릿") print("태블릿 임대:", third) assert first.ip_address == IPv4Address("192.168.10.100") assert second.ip_address == IPv4Address("192.168.10.101") assert third.ip_address == IPv4Address("192.168.10.101") if __name__ == "__main__": main()

실제 DHCP 서버는 이 예제보다 많은 상태를 관리한다.

  • 제안했지만 아직 확정되지 않은 주소
  • 고정 할당 정보
  • 클라이언트 식별자
  • 중계된 서브넷 정보
  • DHCP 옵션
  • 서버 재시작 후에도 유지되는 임대 데이터
  • 주소 충돌 검사와 감사 기록

리눅스에서는 다음 명령으로 인터페이스의 주소와 경로를 확인할 수 있다.

shell
ip address show ip route show

네트워크 관리자(NetworkManager)를 사용하는 환경에서는 받은 DHCP 설정을 다음처럼 확인할 수 있다.

shell
nmcli device show

DHCP 패킷 흐름은 다음처럼 캡처할 수 있다. 패킷 캡처에는 관리자 권한이 필요할 수 있다.

shell
sudo tcpdump -ni any 'udp port 67 or udp port 68'

5. 시간 복잡도 또는 성능 특성

DHCP는 알고리즘의 시간복잡도보다 주소 풀 관리 방식, 브로드캐스트 범위, 임대 시간, 서버 가용성이 성능에 더 큰 영향을 준다.

기본 주소 할당에는 일반적으로 네 개의 메시지가 필요하다.

text
DHCPDISCOVER → DHCPOFFER → DHCPREQUEST → DHCPACK

패킷 손실이 없다면 두 번의 요청·응답 왕복으로 볼 수 있다. UDP는 전송 보장과 재전송을 제공하지 않으므로 응답이 없으면 DHCP 클라이언트가 타이머에 따라 요청을 다시 보낸다.

앞의 Python 예제에서 주소 풀 크기를 n, 활성 임대 수를 m이라고 하면 다음과 같다.

연산시간복잡도이유
기존 클라이언트 조회평균 O(1)해시 테이블 조회
만료 임대 탐색O(m)전체 활성 임대 검사
첫 주소 제거O(n)Python 리스트의 나머지 원소 이동
주소 반환 후 정렬O(n log n)전체 가용 주소 정렬

실제 서버는 해시 테이블, 우선순위 큐(priority queue), 데이터베이스 인덱스 등을 사용해 큰 주소 풀과 많은 임대를 관리할 수 있다.

임대 시간이 짧으면 주소를 빠르게 회수할 수 있지만 갱신 트래픽과 서버 부하가 증가한다. 임대 시간이 길면 갱신 트래픽은 감소하지만 떠난 장치의 주소가 더 오래 남는다.

6. 실무 사용 사례

사내 네트워크

직원 노트북과 휴대전화에 IP 주소, 사내 DNS 서버, 기본 게이트웨이를 자동으로 제공한다. 사용자용, 서버용, 게스트용 가상 근거리 통신망(VLAN)마다 별도 주소 풀을 구성할 수 있다.

가정용 공유기

공유기가 DHCP 서버 역할을 맡아 내부 장치에 사설 IP 주소를 할당한다.

text
공유기 내부 주소: 192.168.0.1
DHCP 주소 풀: 192.168.0.100~192.168.0.200

공유기는 일반적으로 DHCP, 네트워크 주소 변환(NAT), DNS 전달 기능을 함께 제공한다.

서버와 프린터의 고정 할당

서버, 프린터, 카메라처럼 주소가 자주 바뀌면 불편한 장치에는 DHCP 고정 할당을 사용한다. 장치에서는 자동 설정을 유지하면서 DHCP 서버가 항상 같은 주소를 제공한다.

여러 서브넷의 중앙 관리

각 서브넷마다 DHCP 서버를 둘 필요 없이 DHCP 릴레이를 통해 중앙 서버 하나가 여러 주소 풀을 관리할 수 있다.

text
개발망 10.10.10.0/24 ─┐
운영망 10.10.20.0/24 ─┼─ DHCP 릴레이 ─ 중앙 DHCP 서버
게스트망 10.10.30.0/24 ─┘

클라우드와 가상화 환경

가상 머신이나 컨테이너 네트워크에서도 DHCP가 사용될 수 있다. 다만 일부 플랫폼은 자체 메타데이터 서비스, 가상 네트워크 제어 계층, 고정 주소 주입 방식을 함께 사용한다.

7. 주의할 점

불법 DHCP 서버

같은 네트워크에 승인되지 않은 DHCP 서버가 있으면 잘못된 게이트웨이나 DNS 서버를 배포할 수 있다. 공격자가 트래픽을 자신에게 보내 중간자 공격(man-in-the-middle attack)을 시도할 수도 있다.

관리형 스위치의 DHCP 스누핑(DHCP snooping)을 사용하면 신뢰할 수 있는 포트에서 온 서버 응답만 허용할 수 있다.

DHCP 고갈 공격

공격자가 많은 클라이언트 식별자를 만들어 주소 풀을 소진하는 공격을 DHCP 고갈 공격(DHCP starvation attack)이라고 한다. 포트 보안, 요청 속도 제한, DHCP 스누핑으로 위험을 줄일 수 있다.

주소 풀 중복

동적 주소 풀에 서버의 수동 고정 IP가 포함되면 서로 같은 주소를 사용하는 충돌이 발생할 수 있다.

text
잘못된 구성:
동적 주소 풀: 192.168.10.100~192.168.10.200
수동 설정 서버: 192.168.10.150

수동 주소는 동적 주소 풀에서 제외하거나 DHCP 고정 할당으로 통합한다.

브로드캐스트 경계

클라이언트와 DHCP 서버가 다른 서브넷에 있으면 초기 브로드캐스트가 서버까지 도달하지 않는다. 해당 네트워크의 라우터나 계층 3 스위치에 DHCP 릴레이를 구성해야 한다.

방화벽 규칙

DHCPv4의 UDP 67·68 포트와 DHCPv6의 UDP 546·547 포트를 잘못 차단하면 주소 할당이나 갱신이 실패한다. 릴레이 환경에서는 클라이언트 구간과 서버 구간의 통신 방식을 각각 확인한다.

주소는 신원 정보가 아니다

동적 IP 주소는 임대 만료 후 다른 장치에 재할당될 수 있다. 보안 정책이나 감사 기록에서 IP 주소만으로 사용자를 식별하면 안 된다. 시각, 임대 기록, 장치 식별자, 인증 기록을 함께 확인해야 한다.

DNS와 DHCP의 역할 구분

DHCP는 클라이언트에 DNS 서버 주소를 전달할 수 있지만 도메인 이름을 IP 주소로 해석하지는 않는다. 이름 해석은 DNS가 담당한다.

8. 핵심 정리

  • DHCP는 IP 주소와 네트워크 설정을 임대 방식으로 자동 제공한다.
  • DHCPv4의 초기 할당은 DHCPDISCOVER, DHCPOFFER, DHCPREQUEST, DHCPACK 순서로 진행된다.
  • DHCPv4는 UDP 67·68 포트를 사용하며 초기 통신에서 브로드캐스트를 사용한다.
  • 다른 서브넷의 DHCP 서버를 사용하려면 DHCP 릴레이가 필요하다.
  • 클라이언트는 T1에 기존 서버로 갱신하고 T2에 사용 가능한 서버로 재결합을 시도한다.
  • DHCPv6는 UDP 546·547 포트와 멀티캐스트를 사용하며 IPv6 라우터 광고와 역할을 나눠 가진다.
  • 주소 풀 중복, 불법 DHCP 서버, DHCP 고갈 공격, 잘못된 방화벽 설정을 함께 점검해야 한다.