[Linux] DNS 서버 구축 with bind
리눅스에서 DNS(Domain Name System)의 개념과 구성 방법을 이해하고, BIND를 활용한 자체 DNS 서버 구축 실습을 진행합니다.
DNS 란
네트워크에서 컴퓨터는 IP 주소를 기반으로 서로를 식별하고 통신합니다. 하지만 IP 주소는 숫자로 되어 있어 기억하거나 사용하기 불편합니다. 이를 해결하기 위해 DNS(Domain Name System)가 등장했습니다. DNS는 도메인 이름을 IP 주소로 변환하거나, 반대로 IP 주소를 도메인 이름으로 변환해주는 시스템입니다. 예를 들어 “naver.com”과 같은 도메인은 사람이 기억하기 쉬운 문자열이며, DNS는 이를 실제 통신에 사용되는 IP 주소로 바꿔주는 역할을 합니다.
nslookup
명령어를 사용하면 도메인 이름을 DNS 서버에 질의하여 해당 IP 주소를 조회할 수 있습니다. 반대로 IP 주소를 입력해 도메인 이름을 확인하는 것도 가능합니다. 아래는 nslookup
명령어로 "naver.com"의 IP 주소를 조회하는 예입니다.
해당 질의에 응답한 DNS 서버의 IP는 “172.19.140.7”이며, 이 주소는 SKT에서 제공하는 DNS 서버입니다. 이처럼 통신사들은 자체적인 DNS 서버를 운영하고 있으며, DNS 서버는 인터넷 접속을 위한 필수 구성 요소입니다.
예를 들어 “kisa.or.kr”처럼 .kr로 끝나는 도메인은 우리나라 국가 도메인입니다. .kr 도메인을 관리하는 DNS 서버가 여러 곳에 분산되어 있으며, 만약 이 서버들이 모두 중단된다면 .kr 도메인을 사용하는 웹사이트는 전혀 접근할 수 없게 됩니다. 이런 이유로 주요 도메인에 대한 DNS 서버는 여러 위치에 분산 배치하여 안정적으로 운영됩니다.
<출처: https://krnic.kisa.or.kr/jsp/resources/dns/dnsInfo.jsp>
사용 가능한 외부 DNS 서버 주소
DNS 서버는 통신사뿐 아니라 다양한 기관에서도 운영 중입니다. 아래는 대표적인 외부 DNS 서버 주소 목록입니다. 이 외에도 수많은 DNS 서버가 존재하며, 필요에 따라 적절한 서버를 선택하여 사용할 수 있습니다.
KT DNS
168.126.63.1
168.126.63.2
SK Broadband
210.220.163.82
219.250.36.130
SKT
172.19.140.7
LG U+
164.124.101.2
203.248.252.2
61.41.153.2
1.214.68.2
그 밖에 통신사가 아닌 곳에서도 DNS 서버를 제공하고 있습니다.
8.8.8.8
8.8.4.4
환경
Redhat Enterprise linux (RHEL)
목표
앞에서 DNS의 기본 개념을 간단히 살펴보았습니다. 이제부터는 실제로 DNS 서버를 직접 구축해보겠습니다. 이번 실습의 목표는 내부 환경에서 아래 도메인 주소들이 원활히 사용될 수 있도록 DNS 서버를 구성하는 것입니다
-
api.sno.example.com ↔ 192.168.243.200
-
api-int.sno.example.com ↔ 192.168.243.200
-
*.apps.sno.example.com ↔ 192.168.243.200
DNS 서버가 위 도메인을 요청받으면 해당 IP로 응답하고, 반대로 IP를 입력받으면 도메인으로 응답하는 역방향 조회도 함께 설정합니다
DNS 서버 설치
DNS 서버를 직접 구축하는 이유는 다양합니다. 예를 들어 성능 개선, 보안 강화, 또는 외부 DNS 의존성 제거 등의 목적이 있습니다. 이번 실습에서는 bind
패키지를 활용해 DNS 서버를 구성합니다. bind
는 레드햇 계열 OS에서 기본으로 제공되는 패키지이며, 설치 이미지 또는 로컬 리포지터리를 통해 설치할 수 있습니다. (로컬 리포지터리 설정은 ‘Local Repo 구성’ 문서를 참조하세요.)
- dnf 명령을 사용하여 bind 패키지를 설치합니다.
# dnf install bind ... Complete!
DNS 설정 파일 편집
bind
패키지를 설치하면 DNS 서버의 주요 설정 파일인 /etc/named.conf
가 생성됩니다. 이 파일을 수정하여 외부에서 접근이 가능하도록 설정하고, example.com
도메인에 대한 zone 파일을 등록합니다.
다음은 named.conf
파일에 대한 주요 설정 항목입니다. 각 항목 옆에는 주석으로 설명을 추가했습니다
# vim /etc/named.conf ... options { listen-on port 53 { any; }; // 외부에서 포트 접근 가능하도록 설정 listen-on-v6 port 53 { ::1; }; // IPv6 설정 제거 directory "/var/named"; dump-file "/var/named/data/cache_dump.db"; statistics-file "/var/named/data/named_stats.txt"; memstatistics-file "/var/named/data/named_mem_stats.txt"; secroots-file "/var/named/data/named.secroots"; recursing-file "/var/named/data/named.recursing"; allow-query { any; }; // 외부에서 DNS 질의 가능하도록 설정 recursion yes; allow-recursion { localhost; 192.168.243.0/24; }; // 재귀 질의 허용 범위 지정 };
공인 IP 주소에 대해 무제한으로 재귀 질의를 허용하면, 악의적인 사용자가 대량의 질의를 발생시켜 DNS 서버의 리소스를 소모하거나 서비스 거부 공격(DoS)을 유도할 수 있습니다. 따라서 재귀 질의를 허용할 IP 범위를 내부 네트워크로 제한하는 것이 보안상 안전합니다.
이제 example.com
도메인을 처리할 수 있도록 zone 설정을 named.conf
파일에 추가합니다. DNS 서버는 zone 설정을 통해 어떤 도메인에 대해 어떤 파일을 참조할지를 결정합니다.
zone "example.com" IN { type master; file "example.com.zone"; allow-update { none; }; }; zone "243.168.192.in-addr.arpa" IN { type master; file "example.com.reverse.zone"; allow-update { none; }; };
위 설정에서 zone
블록은 도메인 이름(example.com)과 IP 주소(역방향)를 다루기 위한 정보를 담고 있습니다. 각 블록의 file
항목은 DNS 서버가 실제로 참조할 zone 파일의 경로를 나타내며, 이 파일은 /var/named
디렉터리에 위치해야 합니다.
따라서 이제 아래와 같은 두 개의 zone 파일을 생성해야 합니다
-
/var/named/example.com.zone
: 정방향 조회용 (도메인 → IP) -
/var/named/example.com.reverse.zone
: 역방향 조회용 (IP → 도메인)
ZONE 파일 생성
# vim /var/named/example.com.zone $TTL 1D @ IN SOA dns.sno.example.com. root.example.com. ( 2023083101 ; serial 3h ; refresh 15 ; retry 1w ; expire 3h ; minimum ) IN NS dns.sno.example.com. dns.sno IN A 192.168.243.169 api.sno IN A 192.168.243.200 api-int.sno IN A 192.168.243.200 *.apps.sno IN A 192.168.243.200
위 설정에서 192.168.243.169
는 현재 구성 중인 DNS 서버의 IP 주소입니다. 나머지 세 도메인(api.sno, api-int.sno, *.apps.sno)은 모두 192.168.243.200
으로 매핑됩니다.
이제 역방향 zone 파일을 생성합니다. 이 파일은 IP 주소를 도메인 이름으로 변환하는 레코드를 설정합니다
# vi /var/named/example.com.reverse.zone $TTL 1D @ IN SOA dns.sno.example.com. root.example.com. ( 2023083101 ; serial 3h ; refresh 15 ; retry 1w ; expire 3h ; minimum ) IN NS dns.sno.example.com. 200 IN PTR api.sno.example.com. 200 IN PTR api-int.sno.example.com.
DNS 설정은 여기까지 완료되었습니다. 이제 서비스를 재시작하기 전에, 방금 작성한 zone 파일들의 구조와 각 레코드의 의미를 살펴보겠습니다.
SOA 레코드 영역 설명
## SOA 레코드 영역
@ IN SOA dns.sno.example.com. root.example.com. (
2023083101 ; serial
3h ; refresh
15 ; retry
1w ; expire
3h ; minimum
)
- @(영역 이름): @를 사용할 경우 /etc/named.conf에서 설정한 영역 이름(example.com)으로 사용한다.
- IN(클래스): SOA 레코드에서는 이 필드를 항상 IN(Internet)으로 설정합니다.
- SOA(type): SOA 레코드에서는 이 필드를 항상 SOA로 설정합니다.
- dns.sno.example.com.: 이름, 서버의 호스트 이름
- root.example.com.: 관리자 메일 주소
(아래의 serial, refresh, expire, minimum은 DNS 서버를 이중화 할 시 사용하는 내용)
- serial: zone 파일의 버전 번호. 파일을 수정할 때마다 값을 증가시켜 보조 DNS 서버가 변경 사항을 인식하게 합니다.
- refresh: 보조 DNS 서버에서 주 DNS 서버의 정보 변경을 확인하는데 대기하는 시간.
- retry: 주 DNS 서버에서 쿼리를 실패할 경우 재시도 하기 위해 대기하는 시간.
- expire: 보조 DNS 서버가 주 DNS 서버로 접근이 되지 않을때 이전에 받아놓은 주 DNS서버의 정보를 언제까지 설정할지 지정하는 시간
- minimum: DNS 서버가 잘못된 도메인 이름 오류를 캐시하는 기간을 설정, 잘못된 정보가 오랫동안 캐시되지 않도록 보장하는 기능
DNS 서버 주소 영역 설명
IN NS dns.sno.example.com. # DNS서버 주소를 설정합니다.
example.com
)에 대한 네임서버(NS) 레코드를 지정합니다. 이 레코드는 DNS 요청을 처리할 서버의 호스트 이름을 나타냅니다.도메인에 대한 IP 주소 매핑
dns.sno IN A 192.168.243.169
api.sno IN A 192.168.243.200
api-int.sno IN A 192.168.243.200
*.apps.sno IN A 192.168.243.200
dns.sno
는 현재 DNS 서버의 호스트 이름이며, 실제 IP는 192.168.243.169
입니다.
api.sno
, api-int.sno
, 그리고 와일드카드 형식의 *.apps.sno
는 모두 동일한 IP로 매핑됩니다.- 와일드카드는
test.apps.sno
, admin.apps.sno
와 같은 하위 도메인 전체를 포함합니다.
dns.sno
는 현재 DNS 서버의 호스트 이름이며, 실제 IP는 192.168.243.169
입니다.api.sno
, api-int.sno
, 그리고 와일드카드 형식의 *.apps.sno
는 모두 동일한 IP로 매핑됩니다.test.apps.sno
, admin.apps.sno
와 같은 하위 도메인 전체를 포함합니다.방화벽 활성화 및 DNS서비스 시작
DNS는 내부적으로 53번 포트를 사용하지만, 방화벽에서는 서비스 이름 만으로도 편리하게 등록을 할 수 있습니다.
# firewall-cmd --add-service=dns success # firewall-cmd --add-service=dns --permanent success
설정이 완료되었으면 DNS 서비스를 시작합니다
# systemctl start named
도메인 주소 확인 (검증)
먼저 현재 테스트하는 서버가 올바른 DNS 서버를 참조하고 있는지 확인합니다. /etc/resolv.conf
파일에 설정된 nameserver가 구축한 DNS 서버의 IP 주소인지 확인합니다
# cat /etc/resolv.conf nameserver 192.168.243.169
이제 dig
명령어를 사용해 도메인 → IP 매핑이 정상적으로 작동하는지 확인합니다. 앞서 설정한 세 개의 도메인 모두 올바르게 응답하는지 테스트합니다
# dig api.sno.example.com | grep "ANSWER SECTION" -A 1 # dig api-int.sno.example.com | grep "ANSWER SECTION" -A 1 # dig test.apps.sno.example.com | grep "ANSWER SECTION" -A 1
이번에는 nslookup
명령어를 사용해 IP 주소 → 도메인 이름 변환이 정상적으로 작동하는지 확인합니다. 이는 앞서 구성한 역방향 zone 파일의 설정이 제대로 반영되었는지를 검증하는 절차입니다
# nslookup 192.168.243.200 200.243.168.192.in-addr.arpa name = api-int.sno.example.com. 200.243.168.192.in-addr.arpa name = api.sno.example.com.
이와 같이 하나의 IP 주소에 대해 복수의 도메인 이름이 매핑될 수 있으며, 등록한 PTR 레코드가 순서대로 응답됩니다.
마무리
이번 글에서는 리눅스 환경에서 BIND 패키지를 활용해 DNS 서버를 직접 구축하는 방법을 살펴보았습니다. 실습에서는 내부 도메인 이름에 대한 정방향 및 역방향 레코드를 설정하고, 이를 통해 DNS 질의가 정상적으로 작동하는지를 검증했습니다.
이와 같은 방식은 특히 테스트 환경이나 네트워크 분리 환경에서 유용하게 활용될 수 있습니다. 다만, 운영 환경에서 DNS 서버를 사용할 경우에는 이중화 구성, 보안 설정 강화, 쿼리 제한 정책 등 추가적인 고려가 필요합니다.
댓글
댓글 쓰기