소개
이 실습에서는 bind9을 사용하여 Linux 시스템에 로컬 권한 DNS 서버를 설정하고 구성하는 방법을 배웁니다. 가장 널리 사용되는 DNS 소프트웨어 패키지 중 하나를 직접 경험하며, 표준 Linux 머신을 로컬 네트워크의 사용자 지정 도메인 이름을 해석할 수 있는 서버로 변환합니다.
과정은 필요한 패키지를 설치하고 포워더 설정과 같은 전역 서버 옵션을 구성하는 것으로 시작됩니다. 그런 다음 도메인 이름을 IP 주소로 해석하기 위한 정방향 조회 영역 (forward lookup zone) 과 해당 IP 범위에 대한 역방향 조회 영역 (reverse lookup zone) 을 정의합니다. 실습을 마무리하기 위해 bind9 구성 파일의 구문이 올바른지 검증하고 dig 유틸리티를 사용하여 새 DNS 서버를 테스트하여 로컬 도메인에 대한 쿼리를 올바르게 해석하는지 확인합니다.
bind9 설치 및 전역 옵션 구성
이 단계에서는 DNS 서버의 핵심 구성 요소를 설정하는 것부터 시작합니다. 여기에는 Linux 에서 가장 널리 사용되는 DNS 서버 소프트웨어 패키지 중 하나인 bind9을 설치하는 작업이 포함됩니다. 또한 서버의 일반적인 동작을 제어하는 전역 옵션을 구성하여, 권한이 없는 도메인에 대한 요청을 어떻게 처리하는지 설정합니다.
먼저, 최신 버전의 소프트웨어를 확보하기 위해 시스템의 패키지 목록을 업데이트하는 것이 일반적인 절차입니다.
터미널에서 다음 명령을 실행합니다.
sudo apt-get update
다음으로, DNS 서버 데몬을 포함하는 bind9 패키지와 나중에 테스트 및 검증에 사용할 dig 및 named-checkconf와 같은 유용한 명령줄 도구를 제공하는 bind9-utils를 설치합니다.
sudo apt-get install bind9 bind9-utils
설치를 확인할지 묻는 메시지가 표시됩니다. Y를 입력하고 Enter 키를 누릅니다. 출력은 다음과 유사하게 나타납니다.
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
bind9-libs bind9-doc dns-root-data
...
After this operation, XX.X MB of additional disk space will be used.
Do you want to continue? [Y/n] Y
...
Setting up bind9 (1:9.18.X-XubuntuX.X) ...
bind9을 설치한 후 다음 작업은 전역 동작을 구성하는 것입니다. 기본 구성은 여러 파일로 분할되며, 모든 파일은 /etc/bind/ 디렉토리에 있습니다. 전역 옵션의 경우 named.conf.options 파일을 편집합니다.
nano 편집기를 사용하여 파일을 엽니다.
sudo nano /etc/bind/named.conf.options
options {
directory "/var/cache/bind";
// If there is a firewall between you and nameservers you want
// to talk to, you may need to fix the firewall to allow multiple
// ports to talk. See http://www.kb.cert.org/vuls/id/800113
// If your ISP provided one or more IP addresses for stable
// nameservers, you probably want to use them as forwarders.
// Uncomment the following block, and insert the addresses replacing
// the all-0's placeholder.
// forwarders {
// 0.0.0.0;
// };
//========================================================================
// If BIND logs error messages about the root key being expired,
// you will need to update your keys. See https://www.isc.org/bind-keys
//========================================================================
dnssec-validation auto;
listen-on-v6 { any; };
};
이 파일 안에서 options { ... }; 블록을 볼 수 있습니다. 이 블록에 포워딩, 쿼리 권한 및 수신 인터페이스에 대한 지시문이 포함되어 있는지 확인해야 합니다. 포워딩을 통해 DNS 서버는 다른 공개 DNS 서버에 문의하여 외부 도메인 (예: google.com) 을 해석할 수 있습니다.
options 블록을 다음과 같이 수정합니다. 누락된 줄을 추가하거나 이미 있는 줄의 주석을 해제하고 변경할 수 있습니다.
팁:
Ctrl+K를 눌러 파일 내용을 정리한 다음 다음 내용을 붙여넣을 수 있습니다.
options {
directory "/var/cache/bind";
// If there is not a line with forwarders, add the following section.
// If there is one, ensure it's not commented out and has valid IPs.
forwarders {
8.8.8.8;
8.8.4.4;
};
// Add or uncomment this line to allow queries from any host
allow-query { any; };
recursion yes;
listen-on { any; }; // Listen on all interfaces
listen-on-v6 { any; }; // Listen on all IPv6 interfaces
dnssec-validation auto;
auth-nxdomain no; ## conform to RFC1035
};
편집을 마친 후 Ctrl+O를 눌러 파일을 저장하고 파일 이름을 확인하기 위해 Enter 키를 누릅니다. Ctrl+X를 눌러 nano 편집기를 종료합니다. 이제 bind9을 성공적으로 설치하고 초기 구성을 설정했습니다.
mylocaldomain.net 에 대한 정방향 조회 영역 정의 및 생성
이 단계에서는 bind9 서버가 사용자 지정 도메인에 대해 권한을 갖도록 구성합니다. 이는 **정방향 조회 영역 (forward lookup zone)**을 생성하여 달성됩니다. 정방향 조회 영역은 사람이 읽을 수 있는 호스트 이름 (예: webserver.mylocaldomain.net) 을 해당 IP 주소에 매핑하는 데이터베이스입니다. 먼저 bind9 구성에서 영역을 정의한 다음 실제 DNS 레코드를 포함하는 영역 파일을 생성합니다.
먼저 bind9에 새 영역에 대해 알려야 합니다. 로컬 영역 구성은 기본 패키지 구성과 분리하기 위해 /etc/bind/named.conf.local에 보관됩니다. 이 파일은 다음 단계에서 완전히 구성됩니다.
영역이 정의되었으므로 해당 영역 파일을 생성해야 합니다. 이 파일에는 실제 DNS 레코드가 포함됩니다.
먼저 템플릿 파일을 복사하여 새 파일에 올바른 권한과 소유권이 있는지 확인합니다.
sudo cp /etc/bind/db.local /etc/bind/db.mylocaldomain.net
다음으로, 파일을 수동으로 편집하는 대신 다음 작업을 수행하는 단일 명령 블록을 실행할 수 있습니다.
- VM 의 IP 주소를 가져옵니다.
- 현재 날짜를 사용하여 동적 일련 번호를 생성합니다.
- 완전하고 올바른 영역 파일 내용을
/etc/bind/db.mylocaldomain.net에 씁니다.
먼저 영역 파일에 사용될 변수에 VM 의 IP 주소를 캡처합니다.
VM_IP=$(ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}')
이 명령은 정규 표현식을 사용하여 기본 네트워크 인터페이스 (eth0) 에서 IPv4 주소를 추출합니다. IP 주소는 DNS 레코드에 자동으로 삽입됩니다.
이제 적절한 DNS 레코드를 사용하여 영역 파일을 생성합니다. 이 단일 명령은 완전한 영역 파일을 생성합니다.
sudo bash -c "cat > /etc/bind/db.mylocaldomain.net" << EOF
\$TTL 604800
@ IN SOA ns1.mylocaldomain.net. admin.mylocaldomain.net. (
$(date +%Y%m%d)01 ; Serial (YYYYMMDDNN)
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
@ IN NS ns1.mylocaldomain.net.
ns1 IN A ${VM_IP}
webserver IN A ${VM_IP}
fileserver IN A ${VM_IP}
www IN CNAME webserver
EOF
이 명령은 VM 의 특정 IP 주소를 사용하여 영역 파일에 올바른 레코드를 자동으로 채웁니다. cat /etc/bind/db.mylocaldomain.net 명령으로 내용을 확인할 수 있습니다. 이제 첫 번째 정방향 조회 영역을 성공적으로 정의하고 생성했습니다.
모든 로컬 영역 정의 및 생성
이 단계에서는 필요한 모든 로컬 영역 구성을 생성합니다. 파일을 수동으로 편집하는 대신 스크립트를 사용하여 다음 작업을 수행하여 정확한 설정을 보장합니다.
/etc/bind/named.conf.local생성: 이 파일은 정방향 (mylocaldomain.net) 및 역방향 조회 영역 모두에 대한 정의를 포함하도록 처음부터 생성됩니다.- 역방향 영역 파일 생성: 스크립트는 필요한
PTR레코드를 포함하는db.REVERSE_IP파일도 생성합니다.
먼저 두 영역 구성 모두에 필요한 IP 주소 정보를 수집합니다.
IP=$(ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}')
REV_IP=$(echo $IP | awk -F. '{print $3"."$2"."$1}')
LAST_OCTET=$(echo $IP | awk -F. '{print $4}')
이 명령은 VM 의 IP 주소를 추출하고 역방향 조회 영역에 필요한 역방향 IP 형식으로 처리합니다. 예를 들어 IP 가 172.16.50.100인 경우 REV_IP는 50.16.172가 되고 LAST_OCTET은 100이 됩니다.
다음으로 두 영역 모두에 대해 bind9에 알려주는 기본 영역 구성 파일을 생성합니다.
sudo bash -c "cat > /etc/bind/named.conf.local" << EOF
//
// Do any local configuration here
//
// Forward lookup zone
zone "mylocaldomain.net" {
type master;
file "/etc/bind/db.mylocaldomain.net";
};
// Reverse lookup zone
zone "${REV_IP}.in-addr.arpa" {
type master;
file "/etc/bind/db.${REV_IP}";
};
EOF
이 파일은 이름에서 IP 로 확인하는 정방향 조회 영역과 IP 에서 이름으로 확인하는 역방향 조회 영역을 모두 정의합니다. type master는 이 서버가 해당 영역에 대한 권한이 있음을 나타냅니다.
마지막으로 PTR 레코드를 사용하여 역방향 영역 파일을 생성합니다.
sudo bash -c "cat > /etc/bind/db.${REV_IP}" << EOF
\$TTL 604800
@ IN SOA ns1.mylocaldomain.net. admin.mylocaldomain.net. (
$(date +%Y%m%d)01 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
@ IN NS ns1.mylocaldomain.net.
;
${LAST_OCTET} IN PTR ns1.mylocaldomain.net.
${LAST_OCTET} IN PTR webserver.mylocaldomain.net.
${LAST_OCTET} IN PTR fileserver.mylocaldomain.net.
EOF
이 자동화된 접근 방식은 named.conf.local에 두 영역이 올바르게 정의되고 역방향 영역 파일이 올바르게 생성되도록 하여 일반적인 구성 오류를 방지합니다.
bind9 구성 검증 및 dig 를 사용한 DNS 확인 테스트
이 단계에서는 수행한 모든 구성 변경 사항을 검증한 다음 실제 DNS 서버를 테스트합니다. 실수를 하면 bind9 서비스가 올바르게 시작되지 않을 수 있으므로 적용하기 전에 구성 파일의 구문 오류를 확인하는 것이 중요합니다. 유효성 검사가 완료되면 dig 유틸리티를 사용하여 DNS 조회를 수행하고 서버가 예상대로 작동하는지 확인합니다.
먼저 named-checkconf를 사용하여 기본 bind9 구성 파일에서 구문 오류가 있는지 확인합니다. 이 명령이 아무런 출력을 생성하지 않으면 구성 파일 (named.conf.local, named.conf.options 등) 이 유효하다는 의미입니다.
sudo named-checkconf
다음으로 정방향 조회 영역 파일의 구문을 검증합니다. named-checkzone 명령은 영역 파일의 정확성을 확인합니다.
sudo named-checkzone mylocaldomain.net /etc/bind/db.mylocaldomain.net
성공적인 검사는 "OK" 상태를 반환하고 영역 파일의 일련 번호를 표시합니다.
zone mylocaldomain.net/IN: loaded serial 2024052001
OK
이제 역방향 조회 영역을 검증합니다. 영역 이름과 파일 이름은 VM 의 IP 주소에 따라 달라지므로 먼저 필요한 정보를 수집합니다.
IP=$(ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}')
REV_IP=$(echo $IP | awk -F. '{print $3"."$2"."$1}')
ZONE_NAME="${REV_IP}.in-addr.arpa"
ZONE_FILE="/etc/bind/db.${REV_IP}"
이렇게 하면 VM 의 실제 IP 주소를 기반으로 올바른 영역 이름과 파일 경로가 생성됩니다.
이제 영역 검증 명령을 실행합니다.
echo "Checking reverse zone: ${ZONE_NAME}"
sudo named-checkzone ${ZONE_NAME} ${ZONE_FILE}
성공적인 검사는 다시 "OK" 상태를 표시합니다.
zone 50.16.172.in-addr.arpa/IN: loaded serial 2024052001
OK
다시 시작하기 전에 bind9 서비스가 영역 파일을 읽을 수 있도록 올바른 소유권을 설정해야 합니다. 먼저 IP 정보를 다시 가져와 올바른 파일 경로를 구성합니다.
IP=$(ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}')
REV_IP=$(echo $IP | awk -F. '{print $3"."$2"."$1}')
이제 두 영역 파일에 대한 올바른 소유권을 설정합니다.
sudo chown root:bind /etc/bind/db.mylocaldomain.net "/etc/bind/db.${REV_IP}"
모든 구성이 검증되었으므로 변경 사항을 적용하기 위해 bind9 서비스를 다시 시작할 차례입니다.
sudo systemctl restart bind9
서비스가 올바르게 시작되고 새 영역이 로드되었는지 확인하려면 시스템 로그를 확인하십시오.
sudo grep named /var/log/syslog | grep "loaded serial"
두 영역이 모두 성공적으로 로드되었음을 확인하는 출력이 표시되어야 합니다. 출력에는 localhost와 같은 기본 영역도 포함되며 이는 정상입니다. 중요한 것은 mylocaldomain.net 및 역방향 영역에 대한 줄을 찾는 것입니다.
... named[...]: zone mylocaldomain.net/IN: loaded serial 2025071401
... named[...]: zone 50.16.172.in-addr.arpa/IN: loaded serial 2025071401
...
이러한 줄이 표시되지 않으면 sudo systemctl status bind9의 출력에서 오류를 검토하십시오.
마지막으로 dig를 사용하여 DNS 서버를 테스트합니다. @127.0.0.1을 지정하여 로컬 서버에 직접 쿼리합니다.
먼저 webserver.mylocaldomain.net에 대한 정방향 조회를 테스트합니다.
dig @127.0.0.1 webserver.mylocaldomain.net
출력에서 ANSWER SECTION을 찾으십시오. VM 의 IP 주소를 가리키는 A 레코드를 표시해야 하며, 중요한 것은 헤더의 flags에 권한 있는 답변을 나타내는 aa가 포함되어야 합니다. 하단의 SERVER 줄은 127.0.0.1을 표시해야 합니다.
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: ...
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1
;; QUESTION SECTION:
;webserver.mylocaldomain.net. IN A
;; ANSWER SECTION:
webserver.mylocaldomain.net. 604800 IN A <your_vm_ip>
;; SERVER: 127.0.0.1#53(127.0.0.1)
...
다음으로 -x 플래그를 사용하여 역방향 조회를 테스트합니다. 먼저 VM 의 IP 주소를 캡처합니다.
IP=$(ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}')
이제 역방향 조회 테스트를 수행합니다.
dig @127.0.0.1 -x $IP
ANSWER SECTION은 이제 생성한 PTR 레코드를 표시하여 IP 를 호스트 이름에 다시 매핑해야 하며, flags에는 다시 aa가 포함되어야 합니다.
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: ...
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 1, ADDITIONAL: 1
;; QUESTION SECTION:
;<last_octet>.<your_reversed_network_part>.in-addr.arpa. IN PTR
;; ANSWER SECTION:
<last_octet>.<your_reversed_network_part>.in-addr.arpa. 604800 IN PTR fileserver.mylocaldomain.net.
<last_octet>.<your_reversed_network_part>.in-addr.arpa. 604800 IN PTR ns1.mylocaldomain.net.
<last_octet>.<your_reversed_network_part>.in-addr.arpa. 604800 IN PTR webserver.mylocaldomain.net.
;; SERVER: 127.0.0.1#53(127.0.0.1)
...
축하합니다! 기본 권한 있는 DNS 서버를 성공적으로 구성, 검증 및 테스트했습니다.
요약
이 실습에서는 bind9 소프트웨어 패키지를 사용하여 Linux 에서 로컬 권한 있는 DNS 서버를 구성했습니다. 이 과정은 bind9 및 필수 유틸리티를 설치하는 것으로 시작되었으며, 이후 외부 도메인 쿼리를 확인하기 위한 포워더 설정과 같은 서버 전체 동작을 정의하기 위해 전역 named.conf.options 파일을 편집했습니다.
그런 다음 기본 DNS 영역을 생성했습니다. 호스트 이름을 IP 주소에 매핑하는 mylocaldomain.net에 대한 정방향 조회 영역 (A 레코드 사용) 과 PTR 레코드를 사용하여 IP 주소를 호스트 이름에 다시 매핑하는 해당 역방향 조회 영역입니다. 실습은 named-checkconf 및 named-checkzone을 사용하여 구성 오류를 확인하는 중요한 검증 단계로 마무리되었으며, 이후 dig 유틸리티를 사용하여 성공적인 정방향 및 역방향 조회를 수행하여 실제 서버의 기능을 테스트했습니다.



