RHEL 8.6 에 BIND 를 설치해 내부 도메인의 권한 DNS 겸 캐시 리졸버로 운영하는 절차다. 내부 도메인 질의는 직접 응답하고 그 밖의 질의는 외부 DNS 로 포워딩한다. 사내 DNS(AD 등) 가 이미 있고 BIND 는 질의만 넘기면 되는 경우에는 type forward 존 하나면 된다.
zone "corp.example" IN {
type forward;
forward only;
forwarders { 192.0.2.10; 192.0.2.11; };
};
아래 예시 값은 내부 도메인 corp.example, 내부 대역 192.0.2.0/24, DNS 서버 ns1.corp.example / 192.0.2.10 이다 (RFC 5737 문서용 대역). .local 은 mDNS 와 충돌하므로 내부 도메인명으로 쓰지 않는다.
고정 IP 와 호스트명을 먼저 잡고 패키지를 설치한다.
hostnamectl set-hostname ns1.corp.example
nmcli con mod <연결명> ipv4.addresses 192.0.2.10/24 ipv4.gateway 192.0.2.1 ipv4.method manual
nmcli con up <연결명>
dnf install -y bind bind-utils
rpm -q bind
cp /etc/named.conf /etc/named.conf.orig
/etc/named.conf 를 다음으로 교체한다. RHEL 계열은 Debian 과 달리 분리 파일 없이 한 파일에 담는다.
acl internal-net {
192.0.2.0/24;
localhost;
};
options {
listen-on port 53 { 127.0.0.1; 192.0.2.10; };
listen-on-v6 port 53 { none; };
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";
recursion yes;
allow-query { internal-net; };
allow-recursion { internal-net; };
allow-transfer { none; };
forwarders { 1.1.1.1; 8.8.8.8; };
forward first;
dnssec-enable yes;
dnssec-validation yes;
version "not disclosed";
};
logging {
channel default_debug {
file "data/named.run";
severity dynamic;
};
};
zone "." IN {
type hint;
file "named.ca";
};
zone "corp.example" IN {
type master;
file "corp.example.zone";
allow-update { none; };
};
zone "2.0.192.in-addr.arpa" IN {
type master;
file "2.0.192.rev";
allow-update { none; };
};
include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";
정방향 존 /var/named/corp.example.zone 과 역방향 존 /var/named/2.0.192.rev 를 만든다. Serial 은 존을 고칠 때마다 반드시 증가시킨다(YYYYMMDDnn 관례).
$TTL 3600
@ IN SOA ns1.corp.example. admin.corp.example. (
2026073001 ; Serial
3600 ; Refresh
900 ; Retry
604800 ; Expire
3600 ) ; Negative TTL
@ IN NS ns1.corp.example.
ns1 IN A 192.0.2.10
web IN A 192.0.2.20
db IN A 192.0.2.30
app IN CNAME web.corp.example.
$TTL 3600
@ IN SOA ns1.corp.example. admin.corp.example. (
2026073001
3600
900
604800
3600 )
@ IN NS ns1.corp.example.
10 IN PTR ns1.corp.example.
20 IN PTR web.corp.example.
30 IN PTR db.corp.example.
권한·SELinux 를 맞추고 문법 검사 뒤 기동한다. named-checkzone 이 OK 를 내지 않으면 기동하지 않는다.
chown root:named /var/named/corp.example.zone /var/named/2.0.192.rev
chmod 640 /var/named/corp.example.zone /var/named/2.0.192.rev
restorecon -Rv /var/named
named-checkconf
named-checkzone corp.example /var/named/corp.example.zone
named-checkzone 2.0.192.in-addr.arpa /var/named/2.0.192.rev
systemctl enable --now named
systemctl status named
firewall-cmd --permanent --add-service=dns
firewall-cmd --reload
dns 서비스는 UDP/TCP 53 을 모두 포함한다. 응답이 512바이트를 넘으면 TCP 로 재질의하므로 TCP 도 반드시 열어야 한다. 동적 갱신(DDNS) 을 쓸 때만 setsebool -P named_write_master_zones 1 을 추가한다.
dig @192.0.2.10 web.corp.example +short
dig @192.0.2.10 -x 192.0.2.20 +short
dig @192.0.2.10 www.google.com +short
rndc status
dig @1.1.1.1 corp.example
마지막 명령은 외부에서 응답이 나오지 않아야 정상이다. 개별 서버는 nmcli con mod <연결명> ipv4.dns "192.0.2.10" ipv4.dns-search "corp.example" ipv4.ignore-auto-dns yes 로 지정하고, 전사 적용은 DHCP 의 domain-name-servers 옵션으로 배포한다.
DNS 서버 자신도 자기를 바라봐도 된다. 이때는 자기 IP 보다 루프백을 앞에 둔다 — ipv4.dns "127.0.0.1,192.0.2.10". listen-on 에 127.0.0.1 이 있고 acl 에 localhost 가 있으므로 조건은 갖춰져 있다. named 는 /etc/resolv.conf 를 참조하지 않고 forwarders 로 직접 나가므로 순환은 생기지 않지만, forwarders 에 자기 IP 를 넣으면 진짜 루프가 된다.
rndc reload corp.example, 캐시만 비울 때는 rndc flush. 로그는 /var/named/data/named.run 과 journalctl -u named -f.type slave 로 두고(마스터에 allow-transfer { 보조IP; }; + also-notify) 클라이언트 DNS 목록에 함께 넣거나, 최소한 /etc/hosts 에 자기 자신과 핵심 노드를 적어 둔다.allow-query / allow-recursion 을 any 로 열면 DNS 증폭 공격 경유지가 된다. 반드시 내부 대역으로 제한한다.view(split-horizon) 를 쓴다.