BIND 9 네임서버 설정

BIND9 네임서버 설정하기

목표 : BIND9를 이용하여 DNS 서버 운영하기
작성 기준 버전 : BIND 9.11
작성 예시 도메인 이름 : example.com


0. 기본환경 준비

- 설치

1
sudo yum install bind bind-libs bind-utils
cs
(Redhat 계열 기준)

- 포트 허용

일반적인 DNS는 TCP 53번 포트 및 UDP 53번 포트를 사용한다.
만일 방화벽 설정 등이 되어 있다면 풀어줘야 한다.

(참고 : DNS 일반 쿼리 등은 UDP로 이루어지고,
Zone-Transfer나 용량이 큰 응답 등은 TCP로 이루어진다)

- 도메인 등록

만일 본인의 실제 커스텀 도메인 이름을 BIND9를 통해 DNS 서비스를 하려는 경우,
다음 절차가 수행되어야 한다.

1. 도메인 등록대행사를 통해 도메인 등록
2. Public IP가 있는 서버 마련 및 TCP 53, UDP 53번 포트 접속 허용
3. 본인의 네임서버 호스트명을 정함 (예시 : ns1.example.com)
4. 해당 Public IP와 호스트명을 도메인 등록대행사를 통해 Glue Record(네임호스트) 등록
5. 네임서버 정보를 도메인 등록대행사를 통해 본인이 정한 네임서버 호스트명으로 업데이트
6. 서버에서 BIND 9 설정 및 DNS 서비스 개시


1. 본 설정에 앞서

BIND9의 경우 C, JAVA 등과 같이
- 주석은 // 혹은 /* */로 작성한다.
- 세미콜론(;)을 사용하여 문장의 끝을 알린다.
- ! 연산자 등도 사용이 가능하나 특정 제약 조건이 있다.


2. /etc/named.conf 수정

네임서버에 대한 전반적인 설정을 다루는 파일
options { 옵션들...; } 을 기재한다.

[자주 다루는 옵션 - 필수]

listen-on port 53 { 옵션; }; // IPv4
listen-on-v6 port 53 { 옵션; }; //IPv6
옵션) any / none / 단일 IP주소 / CIDR

- BIND9 데몬의 listen 정보를 지정 (인터페이스 주소, 포트 번호 등)
> 만일 53번이 아니라 타 포트를 사용할 경우, 여기서 포트 번호를 변경
> Public한 서비스의 경우 일반적으로 any를 기재한다.
ex) listen-on port 53 { 127.0.0.1; }; listen-on-v6 port 53 { ::1; };
ex) listen-on port 11111 { any; }; listen-on-v6 port 53 { any; };


allow-query { 옵션; };
옵션) any / none / 단일 IP주소 / CIDR

- DNS 서비스를 할 Client 대역을 지정
> Public한 서비스인 경우 any를 기재
> 특정 Client에게 제공하는 서비스인 경우 CIDR 혹은 단일 IP주소를 기재
ex) allow-query { any; };
ex) allow-query { 192.168.0.0/16; 10.0.0.0/8 };
ex) allow-query { 127.0.0.1; 1.2.3.4; 5.6.7.8; 9.10.11.12; }


recursion 옵션;
옵션) yes / no

yes -> 해당 DNS 서버를 recursive DNS 서버로 설정할 경우에 사용 (cache DNS server)
no -> 해당 DNS 서버를 authoritative DNS 서버로 설정할 경우 사용 (일반적)

주의) 만일 Public 서비스를 제공할 경우, 반드시 no를 선택할 필요가 있다. (매우 중요)
DNS의 경우 scanning이 워낙 빈번하기 때문에,
만일 실수로 여기서 yes를 했다가는 전 세계 수많은 PC들이 해당 네임서버에 자신의 도메인 네임과는 전혀 관계없는 내용을 마구 질의할 것이다.
심지어, 해당 서버가 DNS 관련 공격에 연관될 수도 있다. (직접 당하든 Relay 되든)

잘 모르면 no를 선택한다. (반드시!!!!!!!)
yes는 DNS 시스템과 BIND9를 잘 이해한 다음에 사용할 필요가 있다.

ex) recursion no;


[자주 다루는 옵션 - 선택]

dnssec-enable 옵션;
dnssec-validation 옵션;
옵션) yes / no

- 해당 DNS 서버에서 DNSSEC을 사용할 지 선택
(참고. DNSSEC이란? by KISA : https://xn--3e0bx5euxnjje69i70af08bea817g.xn--3e0b707e/jsp/resources/dns/dnssecInfo/dnssecInfo.jsp)
- 잘 모르면 yes 선택 추천

ex) dnssec-enable yes;
ex) dnssec-validation yes;


allow-transfer { 옵션; };
옵션) any / none / 단일 IP주소 / CIDR

- Zone-Transfer를 허용할지 정하는 옵션(Master - Slave 구성시)
- 잘 모르면 none을 선택한다. (매우 권장함)

Zone-Transfer는 Master-Slave 구성 외에는 사용할 일이 사실상 없다. 자신의 Zone File 원본을 밖으로 유출되기를 원하는 서버관리자는 없을 것이다. 자신의 Zone File을 보호하기 위해 none을 선택하는 것을 강추한다.
만일 Master-Slave 구성을 할 경우(Zone-Transfer가 필요한 경우), 여기가 아닌 하단의 /etc/named.rfc1912.zones 파일에서 Zone-Transfer 설정을 할 것을 추천한다.

ex) allow-transfer {none;};


version "UNKNOWN";

- 현 BIND9의 버전을 감추는 옵션
- BIND9의 버전이 밖에 노출될 경우 좋을 것이 하나도 없다.

(참고로, dig version.bind CHAOS TXT @IP주소 명령어로 외부에서 BIND9 버전 조회 시도를 할 수 있다)

ex) version "UNKNOWN";


notify 옵션;
옵션) yes / no / explicit / master-only
(선택사항) also-notify { 단일 IP주소 / CIDR };

- DNS NOTIFY에 대한 옵션 (Master - Slave 구성시에 주로 사용)
yes (기본값) 선택시, Zone의 NS 리스트에 있는 주소 + also-notify에 기재한 주소로 NOTIFY 메시지를 발송한다.
단, SOA 레코드의 MNAME Field(주로 Primary Name Server)에 있는 주소로는 NOTIFY를 발송하지 않는다.
no 선택시, NOFITY 메시지는 발송되지 않는다.
master-only 선택시, 본인이 Master인 Zone File만 NOTIFY 메시지를 발송한다.
explicit 선택시, 사용자가 also-notify로 지정한 리스트에게만 NOTIFY 메시지가 발송된다.

(잘 모르면 yes를 선택하는 것을 추천)
(주로 Hidden-Master 설정시 explicit 옵션을 사용한다)

ex) notify yes; // 일반적인 구성
ex) also-notify { 1.2.3.4; }; notify yes; // Zone의 NS List + 1.2.3.4에게 NOTIFY 발송
ex) also-notify { 1.2.3.4; 5.6.7.8; }; notify explicit; // 1.2.3.4, 5.6.7.8에게만 NOTIFY 발송
ex) notify no; // NOTIFY 미발송


rate-limit
해당 포스팅 참고
https://dev.dwer.kr/2020/03/bind-9-rate-limiting.html


logging
https://kb.isc.org/docs/aa-01526
참고 바람.
버전이 최신이 아니라면 일부 로깅 옵션은 작동하지 않는다.


(/etc/named.conf 전체 예시)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
options {
        listen-on port 53 { any; };
        listen-on-v6 port 53 { any; };
        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";
        recursing-file  "/var/named/data/named.recursing";
        secroots-file   "/var/named/data/named.secroots";
        allow-query     { any; };
        recursion no;
 
        bindkeys-file "/etc/named.root.key";
        managed-keys-directory "/var/named/dynamic";
        pid-file "/run/named/named.pid";
        session-keyfile "/run/named/session.key";
 
        dnssec-enable yes;
        dnssec-validation yes;
        allow-transfer { none; };
        version "UNKNOWN";
        notify yes;
 
rate-limit {
  ipv4-prefix-length 24;
  ipv6-prefix-length 56;
  responses-per-second 5;
  referrals-per-second 5;
  nodata-per-second 5;
  nxdomains-per-second 5;
  errors-per-second 5;
  all-per-second 20;
  window 15;
  log-only no;
}
};
 
logging {
        channel default_debug {
                file "data/named.run";
                severity dynamic;
        };
};
 
zone "." IN {
        type hint;
        file "named.ca";
};
 
include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";
 
cs



3. /etc/named.rfc1912.zones 수정

Zone File에 대한 설정을 다루는 파일
일반적으로 자신이 서비스 할 도메인 영역에 대한 정보를 기재한다.

네임서버에서 관리할 Zone 영역에 대해
zone "example.com" IN { 옵션들... };
과 같이 기재한다.

- 한 네임서버에 여러 Zone이 존재할 수 있다.
- 한 네임서버에 Master와 Slave가 혼용될 수 있다.

[자주 다루는 옵션]

type 옵션;
옵션) master / slave


- 해당 Zone이 자신의 네임서버에서 Master인지 Slave인지를 설정한다.
- Master-Slave 구성에 대해 모르면 yes 선택 (해당 네임서버는 Master 서버)

ex) type master;
ex) type slave;


file 파일위치;
- Zone File의 위치를 지정한다.
일반적으로 Zone File은 /var/named/example.com.zone 에 위치한다.

ex) file "/var/named/example.com.zone"


masters { MASTER서버 IP주소; };


만일 해당 Zone이 Slave인 경우 Master 서버의 주소를 기재한다.
주의) Slave인 경우에만 사용

ex) masters { 1.2.3.4; };


allow-transfer { any / none / 단일 IP주소 / CIDR };

해당 Zone이 Master이고 (현재 해당 네임서버가 Master 이고),
Slave에게 Zone-Transfer(AXFR / IXFR)를 하려는 경우,
Transfer를 해 줄 Slave의 주소들을 쭉 기재하는 용도로 주로 사용한다.

위에서 비슷한 항목에서 설명했듯이, allow-transfer { any; }는 절대로 사용하지 말 것을 권장한다. 자신의 Zone File 전체가 외부로 누출되서 좋을 것은 하나도 없다.
/etc/named.conf에서 allow-transfer { none; }; 을 기재하고, 이곳 /etc/named.rfc1912.zones에서 allow-transfer { 1.2.3.4; }; 를 기재하면, 실제로 1.2.3.4에게 정상적으로 Zone-Transfer를 할 수 있다. 이곳의 우선순위가 named.conf의 options{}보다 우선순위가 높기 때문이다.

ex) allow-transfer { 1.2.3.4; 5.6.7.8; 9.10.11.12; };
ex) allow-transfer { 10.0.0.0/8; };
ex) allow-transfer { none; }


allow-update { any / none / 단일 IP주소 / CIDR };

Dynamic DNS에 대한 설정이다.

ex) allow-update { none; };



(/etc/named.rfc1912.zones - Zone이 MASTER 인경우)
1
2
3
4
5
6
zone "example.com" IN {
        type master;
        file "/var/named/example.com.zone";
        allow-transfer { none; };
        allow-update { none; };
};
cs

(/etc/named.rfc1912.zones - Zone이 Slave인경우)
1
2
3
4
5
zone "example.com" IN {
        type slave;
        masters { 1.2.3.4; };
        file "/var/named/example.com.zone";
};
cs


(/etc/named.rfc1912.zones 전체 예시)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
zone "example1.com" IN {
        type master;
        file "/var/named/example1.com.zone";
        allow-transfer { none; };
        allow-update { none; };
};
zone "example2.com" IN {
        type master;
        file "/var/named/example2.com.zone";
        allow-transfer { 1.2.3.4; };
        allow-update { 10.0.0.0/8; };
};
zone "example3.com" IN {
        type slave;
        masters { 1.2.3.4; };
        file "/var/named/example3.com.zone";
};
 
cs



4. /var/named/example.com.zone 생성 (Zone File 생성)

Zone File을 BIND 양식에 맞게 하나 생성한다.
일반적으로 [자신의 도메인 이름].zone 으로 생성한다.

[Zone File 작성 규칙]

- 모든 시간의 단위는 초(second) 이다.
단, M(Minute), H(Hour), D(Day), W(Week) 등을 사용할 수 있다.
ex) 300 -> 300초 == 5분
10M -> 10분
2H -> 2시간
3D -> 3일
4W -> 4주

- 주석은 세미콜론(;) 으로 한다.

- 호스트명 기재시, 맨 뒤에 점(.)을 꼭 붙여야 한다.
붙이지 않으면 {기재한 내용 + ORIGIN}으로 간주된다.
ex) ORIGIN이 example.com.일때,
www -> 실제로 www.example.com. 으로 작동
example.com -> 실제로 example.com.example.com. 으로 작동
www.example.com. -> 실제로 www.example.com. 으로 작동

- 만일 호스트명으로 공백을 기재하려는 경우, @ 을 기재한다.
ex) ORIGIN이 example.com.일때,
@ -> example.com. 으로 작동

- Zone Apex 경우에만 CNAME 레코드를 사용할 수 없다. 반드시 CNAME 레코드 대신 A 레코드를 사용해야 한다.
타 레코드에서는 타 host명을 기재해도 된다.
(즉, CNAME은 root domain에서 사용할 수 없다)
ex) ORIGIN이 example.com.일때,
@    300    IN    CNAME    host.com.      ; 올바르지 않은 문법
@    300    IN    A            1.2.3.4          ; 옳은 문법
@    300    IN    MX          mail.out.com. ; 옳은 문법

- 레코드에 별도의 시간을 명시하지 않은 경우 $TTL을 따른다.

- 만일 NS의 호스트명이 자신의 $ORIGIN 호스트명에 속해있을 경우,
해당 호스트명에 해당하는 A레코드가 명시적으로 해당 Zone File에 기재되어야 한다.
ex) ORIGIN이 example.com. 이고 네임서버가(NS 레코드가) ns1.example.com. 인 경우,
ns1    IN    A    10.20.30.40
이 반드시 Zone File에 있어야 한다.


=== (Zone File 예시) ===

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
$ORIGIN example.com.         ; 서비스 할 도메인 이름을 기재한다.
$TTL 300                     ; 레코드의 TTL을 지정한다. 단위 : 초
 
; 현 네임서버가 권한이 있음을 알리는 SOA 레코드를 양식에 맞게 기재
; SOA 레코드 첫줄에는 Primary Name Server(MNAME),
; 관리자 E-mail주소(RNAME)를 기재한다. (단 RNAME은 @을 .으로 대체)
@               IN      SOA     ns1.example.com. admin.example.com. (
                                2020041501 ; serial, Zone File의 버전을 의미
                                1H         ; refresh, Master-Slave 구성시 사용
                                30M        ; retry, Master-Slave 구성시 사용
                                2W         ; expire, Master-Slave 구성시 사용
                                1D )       ; minimum, Negative Caching(RFC 2308)
 
; 실제 네임서버 정보에 알맞게 NS 레코드 기재
@       3600    IN      NS      ns1.dwicd.com.  
@       3600    IN      NS      ns2.dwicd.com.
 
; Zone Apex, CNAME은 root domain에 기재할 수 없다.
; @             IN      CNAME     asdfasdf.com. 은 잘못된 문법이다.
 
; TTL 값은 명시하지 않으면 $TTL로 간주
www             IN      A       1.2.3.4
@               IN      MX      mail.asdfasdfasdf.com.
asdf            IN      TXT     " T E S T "
 
; 맨 뒤에 점(.)을 기재하지 않아 실제로 www.example.com.으로 연결됨
test            IN      CNAME   www
 
; ns1.example.com.과 ns2.example.com.이 NS 레코드에 기재되어 있으므로,
; 해당하는 A레코드가 필수적으로 기재되어야 한다.
; (만일 NS레코드가 다른 도메인 이름을 사용한다면 기재할 필요가 없다)
ns1             IN      A       10.10.10.10
ns2             IN      A       20.20.20.20
 
cs

- SOA 레코드, NS 레코드는 필수로 있어야 한다.
- 커스텀 도메인을 Public한 서비스를 할 경우, Zone File의 NS 레코드들은 실제 네임서버 정보와 일치해야 한다.



모든 설정이 완료되면, 데몬을 실행하여 실제 서비스를 시작한다.
1
sudo service named start
cs


5. 기타

테스트는 간단하다. /etc/named.conf에서 허용된 클라이언트에서 DNS 요청을 하면 된다.
nslookup 혹은 dig 를 사용하면 쉽게 테스트를 할 수 있다.

해당 포스팅의 사이트들도 테스트하기에 괜찮은 도구들이다.


nslookup [-q=레코드 타입] host명 [server주소]
ex) nslookup example.com
-> 해당 PC의 기본 네임서버를 향해 example.com의 A레코드 값을 질의한다.

ex) nslookup -q=txt asdf.example.com 1.2.3.4
-> 1.2.3.4 네임서버를 향해 asdf.example.com의 TXT레코드 값을 질의한다.


dig host명 [레코드 타입] [@server주소]
ex) dig example.com
-> 해당 PC의 기본 네임서버를 향해 example.com의 A레코드 값을 질의한다.

ex) dig example.com txt @1.2.3.4
-> 1.2.3.4 네임서버를 향해 asdf.example.com의 TXT레코드 값을 질의한다.


본인이 Zone File에 기재해둔 내용이 정상 반환된다면 세팅 성공.


(dig www.example.com A @1.1.1.1)



참고) Master-Slave 이론 포스팅
https://dev.dwer.kr/2020/03/dns-master-slave.html

참고) DNSSEC 구성에 대한 포스팅
https://dev.dwer.kr/2020/03/bind9-dnssec.html

[레퍼런스]
https://downloads.isc.org/isc/bind9/cur/9.11/doc/arm/Bv9ARM.pdf

댓글