4. 내부 DNS 서버 설치 및 구성

Taeho Kim·2026년 1월 20일

DNS 서버를 먼저 설치/구성해야 Harbor를 harbor.home.internal 같은 고정 FQDN으로 운영할 수 있습니다.


1. DNS VM에 BIND 설치

Rocky/REHL 계열:

sudo dnf install -y bind bind-utils

2. /etc/named.conf 설정

vi /etc/named.conf

위 명령을 수행하면 아래와 같은 내용을 확인할 수 있습니다.

options 부분을 애라와 같이 수정합니다.

options {
    directory "/var/named";

    listen-on port 53 { 127.0.0.1; 192.168.56.53; };
    listen-on-v6 { none; };

    allow-query { localhost; 192.168.56.0/24; };

    recursion yes;
    allow-recursion { localhost; 192.168.56.0/24; };
    allow-query-cache { localhost; 192.168.56.0/24; };

    forwarders { 1.1.1.1; 8.8.8.8; };
};

3. zone 등록

/etc/named.rfc1912.zones을 수정하여 아래 내용을 추가합니다.

vi /etc/named.rfc1912.zones
zone "home.internal" IN {
    type master;
    file "home.internal.db";
    allow-update { none; };
};


4. zone 파일 생성

/var/named/home.internal.db 생성합니다.

$ORIGIN home.internal.
$TTL 60
@   IN SOA dns.home.internal. admin.home.internal. (
        2026012001
        3600
        900
        604800
        60 )

    IN NS  dns.home.internal.

dns     IN A   192.168.56.53
harbor  IN A   192.168.56.60

권한 정리

sudo chown root:named /var/named/home.internal.db
sudo chmod 640 /var/named/home.internal.db

5. 문법 체크

sudo named-checkconf
sudo named-checkzone home.internal /var/named/home.internal.db

6. 방화벽/서비스 기동

sudo firewall-cmd --add-service=dns --permanent
sudo firewall-cmd --reload

sudo systemctl enable --now named
sudo systemctl restart named
sudo systemctl status named --no-pager

아래와 같이 서비스가 정상적으로 기동된 것을 확인할 수 있습니다.


7. 동작 확인

DNS VM에서:

dig @127.0.0.1 harbor.home.internal

dig @127.0.0.1 dns.home.internal

dig @127.0.0.1 google.com

그런데 google.com 부분을 보면 status가 SERVFAIL인 것으로 확인됩니다.

;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 33059

문제 원인 파악을 위해 아래 2가지 명령을 실행해 보았습니다.

[root@dns-server etc]# ip route
[root@dns-server etc]# dig @1.1.1.1 google.com
[root@dns-server etc]# ip route
default via 192.168.56.1 dev enp0s1 proto static metric 100 
192.168.56.0/24 dev enp0s1 proto kernel scope link src 192.168.56.53 metric 100 

[root@dns-server etc]# dig @1.1.1.1 google.com

; <<>> DiG 9.16.23-RH <<>> @1.1.1.1 google.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45824
;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: a2a64f4086a8daeb01000000696f88de63c4b585f8123938 (good)
;; QUESTION SECTION:
;google.com.                    IN      A

;; ANSWER SECTION:
google.com.             86      IN      A       172.217.209.102
google.com.             86      IN      A       172.217.209.101
google.com.             86      IN      A       172.217.209.100
google.com.             86      IN      A       172.217.209.139
google.com.             86      IN      A       172.217.209.138
google.com.             86      IN      A       172.217.209.113

;; Query time: 0 msec
;; SERVER: 1.1.1.1#53(1.1.1.1)
;; WHEN: Tue Jan 20 22:53:40 KST 2026
;; MSG SIZE  rcvd: 163

결론은 아래와 같습니다.

  • DNS VM 자체는 인터넷으로 나갈 수 있다.
  • dig @1.1.1.1 google.com 성공
[root@dns-server etc]# dig @127.0.0.1 google.com +cdflag


; <<>> DiG 9.16.23-RH <<>> @127.0.0.1 google.com +cdflag
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41760
;; flags: qr rd ra cd; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: e38bdf5d89d4aab001000000696f8a379d2628305a9a1502 (good)
;; QUESTION SECTION:
;google.com.                    IN      A

;; ANSWER SECTION:
google.com.             54      IN      A       172.217.213.139
google.com.             54      IN      A       172.217.213.102
google.com.             54      IN      A       172.217.213.101
google.com.             54      IN      A       172.217.213.113
google.com.             54      IN      A       172.217.213.138
google.com.             54      IN      A       172.217.213.100

;; Query time: 10 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Tue Jan 20 22:59:19 KST 2026
;; MSG SIZE  rcvd: 163

+cdflag에서 NOERROR로 응답이 왔다는 건, DNSSEC 검증 때문에 SERVFAIL이 난다는 뜻입니다.


DNSSEC 검증이 무엇인가?

DNSSEC(DNS Security Extensions)는 DNS 응답이 위조/변조되지 않았는지 확인하기 위한 서명(전자서명) 기반 보안 확장입니다.
도메인 소유자는 DNS 레코드에 대해 서명(RRSIG)을 생성하고, 리졸버(named)는 이 서명을 상위 도메인(DS) → 루트 키(Trust Anchor)로 이어지는 신뢰 사슬(chain of trust)로 검증합니다.

검증이 성공하면 “이 DNS 응답은 신뢰할 수 있다”가 되고, 검증에 실패하면 보안상 이유로 응답을 폐기하여 SERVFAIL을 반환할 수 있습니다.


+cdflag가 NOERROR로 성공한 이유

+cdflag는 Checking Disabled 플래그로, 리졸버에게 “DNSSEC 검증을 하지 말고 결과만 반환하라”는 의미입니다.

즉,

  • dig @127.0.0.1 google.com → DNSSEC 검증 수행 → 검증 실패 → SERVFAIL
  • dig @127.0.0.1 google.com +cdflag → 검증 생략 → 레코드 자체는 정상 조회 → NOERROR

이 결과로부터, 네트워크/포워더 문제가 아니라 DNSSEC 검증 단계에서 실패하고 있음을 확정할 수 있습니다.


(우회) 당장만 필요하면 DNSSEC 검증을 끄는 방법

테스트/랩에서 빠르게 진행해야 한다면, 아래처럼 DNSSEC 검증을 끌 수도 있습니다.

/etc/named.conf:

dnssec-validation no;

재시작 후 확인:

named-checkconf
systemctl restart named
dig @127.0.0.1 google.com

단, 실무 운영 관점에서는 “검증을 정상화”하는 정석 방법을 권장합니다.

DNSSEC 검증 실패는 다음 상황에서도 발생할 수 있습니다.

  • 시스템 시간이 어긋난 경우(서명 유효기간 검증 실패)
  • named가 trust anchor 파일을 읽거나 managed-keys 디렉터리에 쓰지 못하는 경우(권한/SELinux)
  • IPv6 경로가 없는 환경에서 루트 프라이밍/검증 과정이 꼬이는 경우(필요 시 prefer-ipv4 yes;)

쿠버네티스 노드에서:

dnf install -y bind-utils
dig @192.168.56.53 harbor.home.internal

이제 쿠버네티스 노드의 네임서버를 내부 DNS 서버로 변경하겠습니다.

[root@k8s-master ~]# nmcli con show
NAME          UUID                                  TYPE      DEVICE       
enp0s1        edd3945d-f18c-384a-9427-aa34b4e53365  ethernet  enp0s1       
lo            ea08f3f6-bd81-496d-ae75-90510bcd8188  loopback  lo           
vxlan.calico  98a67ca7-aaf3-4beb-9188-80473d672462  vxlan     vxlan.calico 
nmcli con mod enp0s1 ipv4.dns "192.168.56.53 1.1.1.1" ipv4.ignore-auto-dns yes
nmcli con mod enp0s1 ipv6.ignore-auto-dns yes
nmcli con up enp0s1

이제 정상적으로 적용되었는지 확인합니다.

[root@k8s-master ~]# dig harbor.home.internal

; <<>> DiG 9.16.23-RH <<>> harbor.home.internal
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61982
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 4e5dbd81d3cb6c8301000000696f9307882ca9ee719c9b0a (good)
;; QUESTION SECTION:
;harbor.home.internal.          IN      A

;; ANSWER SECTION:
harbor.home.internal.   60      IN      A       192.168.56.60

;; Query time: 0 msec
;; SERVER: 192.168.56.53#53(192.168.56.53)
;; WHEN: Tue Jan 20 23:36:55 KST 2026
;; MSG SIZE  rcvd: 93
[root@k8s-master ~]# dig google.com

; <<>> DiG 9.16.23-RH <<>> google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 37646
;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 53c321e22fbffe6001000000696f93114dacfe8c2b885a08 (good)
;; QUESTION SECTION:
;google.com.                    IN      A

;; ANSWER SECTION:
google.com.             123     IN      A       142.251.119.138
google.com.             123     IN      A       142.251.119.100
google.com.             123     IN      A       142.251.119.139
google.com.             123     IN      A       142.251.119.102
google.com.             123     IN      A       142.251.119.101
google.com.             123     IN      A       142.251.119.113

;; Query time: 20 msec
;; SERVER: 192.168.56.53#53(192.168.56.53)
;; WHEN: Tue Jan 20 23:37:05 KST 2026
;; MSG SIZE  rcvd: 163
profile
interested in operating Kubernetes efficiently.

0개의 댓글