## 이 문서는 "서버관리자를 위한 리눅스 네트워크-(출)베스트북" 책에 대한 독자의
## 질문 중, 비교적 비중이 있는 질문과 답변을 정리하여 옮겨놓은 것입니다.
##
## 독자의 개인 정보 보호와 스팸메일을 방지하기 위해서 이름과 메일주소는
## 제외시켰습니다.
##
## 책에 대한 질문은 가능한
## http://www.linuxchannel.net/board/?table=qna
## 에서 질문해 주십시오.
[제목] [3판] BIND9 key, rndc.conf, named.conf 설정에 관해서

1. rndc.conf 파일과 named.conf 파일에 설정한 key는 각각 어떤 용도로 사용되나요?
2. rndc.conf 파일과 named.conf 파일에서 server {} 구문의 key 설정이 다른가요?
3. rndc와 nsupdate는 어떻게 다른가요? 모두 사용해야 만 하나요?
4. rndc.conf, named.conf 파일에서 key 부분 설정 구분 정리



 
1. rndc.conf 파일과 named.conf 파일에 설정한 key는 각각 어떤 용도로 사용되나요?

  rndc.conf :
  이 파일에서 설정한 key는 localhost의 rndc가 사용하고 원격의 네임서버에
  인증 요청시 사용하는 key입니다.

  즉, localhost의 rndc가 rndc.conf 파일의 server {} 구문 또는
  default-server에 설정한 원격의 네임서버(localhost 포함)에 대해서 어떤
  제어 메지지를 보낼때 원격의 네임서버로 보내는 인증 key입니다(인증수단에
  사용). 제어 메시지는 stop, reload, status, .... 등의 rndc 명령어
  로써 start 명령어는 없습니다.

  그 대상이 되는 원격 네임서버의 named.conf 파일에서도 똑같은 key가
  있어야 합니다(rndc 요청 key와 원격의 네임서버 key가 같아야 함)

  참고로, 그 대상이 되는 원격의 네임서버는 rndc.conf 파일의 server {} 구문
  으로 설정하거나 rndc의 -s 옵션으로 지정합니다.

  named.conf :
  이 파일에서 설정한 key는 localhost의 named(네임서버)가 사용하며,
  이 key로 원격의 다른 네임서버에 인증을 요청하거나, 요청을 받을 때 사용하는
  key입니다.

  1)인증을 요청할 때 :
  '인증을 요청할 때'의 경우는 예를 들여, localhost가 2차 네임서버로써 1차
  네임서버의 zone 데이터베이스를 백업할 때 이 key로 인증 요청할 경우를
  의미합니다(그 외에 어떤 query 전송할 때도 요청에 속함)
  설정은 server {} 구문을 사용하여 요청할 원격의 네임서버 주소를 설정합니다.

  예)
  key "key_name" {
	...;
  };
  server NS1_ip_addr { // 1차 네임서버 IP 주소, "와 "로 묶지 않음
	...;
	keys { "key_name"; }; // NS1_ip_addr로 나가는 모든 요청은 key로 인증
	// 또는 keys "key_name";
  };

  그러나, 반드시 꼭 이 key로 인증하여 zone 데이터베이스를 백업하지는
  않습니다.
  즉 key가 아닌 호스트, 또는 IP주소로도 얼마든지 인증하여 zone 데이터베이스를
  백업할 수 있습니다. 이런 방법을 사용할 경우의 설정은 2차 네임서버의
  named.conf 파일에는 key {} 구문이나 server {} 구문은 필요없으며, 1차
  네임서버의 options {} 구문이나 각 zone {} 구문에서
  'allow-transfer { 2차네임서버_IP주소; };' 으로 설정하면 그만입니다.

  2)인증을 요청받을 때 :
  '인증을 요청받을 때'의 경우는 주로 원격(localhost포함)의 rndc나 원격의
  네임서버 또는 원격(localhost)의 nsupdate으로 부터 key를 이용한 인증 요청을
  받은 경우를 의미합니다.

  - 원격(localhost포함)의 rndc 요청 : rndc stop, rndc status, ....
  - 원격의 네임서버 요청 : zone 데이터베이스를 백업해 갈때, 기타 query
  - 원격(localhost포함)의 nsupdate 요청 : zone 데이터베이스를 동적으로 갱신할 때

  이때의 경우는 server {} 구문은 사용되지 않으며(설정되어 있거나 없거나 상관없음),
  key {} 구문과 controls {} 구문 설정이 필요합니다.

  예)
  key "key_name" {
	...;
  };
  controls { // 인증 요청을 받은 네임서버에서 인증 요청에 대한 어떤 control
	inet 127.0.0.1 allow { localhost; "요청을 허락할 호스트"; } keys { "key_name"; };
  }; // 127.0.0.1의 953번 포트번호 사용

  만약 localhost의 rndc나 원격의 rndc 또는 원격의 네임서버 또는 원격의
  nsupdate로부터 key를 이용한 아무런 인증을 요청받지 않을 경우에는 key {} 구문과
  controls {} 구문은 필요없습니다.

  그러나 RPM으로 패키지된 BIND9의 /etc/rc.d/init.d/named 제어 스크립트는 최소한
  localhost에서 rndc의 key를 이용한 요청(rndc stop, rndc status, ... 등등)을
  받아 named를 종료하기 때문에 key {} 구문 설정과 controls {} 구문이 필요합니다.
  (만약 자신이 직접 제어스크립트를 만들어 key 없이 named를 종료할 수도 있음)

  key를 만드는 방법 :
  # dnssec-keygen -a HMAC-MD5 -b 512 -n HOST key_name

  정리 :
  이 key의 사용 목적은 localhost의 rndc, named가 원격의 네임서버에 접속하여 어떤
  행동(named 제어, zone 데이터베이스의 동적인 갱신, 기타 query)을 취할때 사용되는
  인증 방법 중의 하나로써 localhost와 원격의 네임서버에 동일한 key를 가지고 있어야
  합니다.
  참고로 nsupdate 같은 경우 rndc.conf 또는 named.conf 파일에 설정한 key를
  직접적으로 이용하지 않고 dnssec-keygen으로 만든 파일의 key를 이용합니다.


 
2. rndc.conf 파일과 named.conf 파일에서 server {} 구문의 key 설정이 다른가요?

  rndc.conf 파일의 server {} 구문은 named.conf 파일의 server {} 구문과 약간
  사용법이 다릅니다.
  rndc.conf 파일의 설정 문법은 named.conf 파일 설정 문법과 비슷하지만
  전적으로 같지 않습니다.
  예를 들면, rndc.conf 파일에서 include 구문은 사용하면 에러를 낸 경우가 그
  일례입니다. rndc.conf 파일 설정 문법은 'man rndc.conf'에서 확인할 수 있습니다.

  rndc.conf :
  server remote_NS_ip_addr_or_host { // IP 주소로 설정할 때는 "와 "로 묶어줌
	key "key_name"; /*** keys가 아니라 key 임 ***/
  };

  이 server {} 구문은 localhost의 rndc가 설정한 원격의 네임서버(localhost포함)
  에 "key_name" key로 인증하여 rndc stop, rndc reload등과 같은 명령어를 사용하겠다
  는 의미입니다.

  key를 사용하는 주체는 locahost의 rndc입니다.

  named.conf :
  server ip_addr { // host name이 아닌 IP 주소로 "와 "없이 설정해야 함
	keys { "key_name"; }; /*** 이 때는 key가 아니라 keys 임 ***/
	// keys "key_name"; /*** 이것도 가능 ***/
  };

  이 server {} 구문은 localhost의 네임서버가 원격의 ip_addr으로 설정한 네임서버에
  대해서 "key_name" key로 인증하겠다는 의미입니다.
  즉, 이 설정은 주로 localhost의 2차 네임서버가 원격의 ip_addr으로 설정한 1차
  네임서버에 이 key로 인증하여, zone 데이터베이스를 백업할 때에 2차 네임서버에
  설정하는 내용입니다. key로 인증하여 zone 데이터베이스를 백업(동기화)하는 방법은
  책 p.409 [팁]란에 있습니다.

  key를 사용하는 주체는 locahost의 네임서버(주로 2차 네임서버)입니다.

  named.conf 파일에서 사용되는 server {} 구문 사용법은 다음과 같습니다.

  server ip_addr {
	[ bogus yes_or_no ; ]
	[ provide-ixfr yes_or_no ; ]
	[ request-ixfr yes_or_no ; ]
	[ edns yes_or_no ; ]
	[ transfers number ; ]
	[ transfer-format ( one-answer | many-answers ) ; ]]
	[ keys { string ; [ string ; [...]] } ; ]
  };

  server {} 구문의 용도 :
  server {} 구문은 localhost의 rndc 또는 named가 원격의 네임서버에게 어떤 요청을
  할때 사용되는 구문입니다.

  - 원격(localhost포함)의 rndc 요청 : rndc stop, rndc status, ....
  - 원격의 네임서버 요청 : zone 데이터베이스를 백업해 갈때, 기타 query

  *주)
  책에서는 rndc.conf 파일의 key 설명이 잘못되어 있으므로 아래 URL의
  정오를 확인하기 바랍니다.

  http://linuxchannel.net/books/bookmisp/bookmisp-dns-key.txt


 
3. rndc와 nsupdate는 어떻게 다른가요? 모두 사용해야 만 하나요?

  rndc :
  rndc는 'the Remote Name Daemon Control'로써 원격 네임서버를 제어하는 관리자용
  유틸리티 입니다.

  즉 원격(localhost포함)의 네임서버를 reload 하거나 refresh, stop, flush, status
  등등의 명령어 메시지를 보내 제어하는 툴입니다.

  [사용법]
  rndc [-c config] [-s server] [-p port] [-y key] command [command...]

  [command]
  reload
  reload zone
  refresh zone
  reconfig
  stats
  querylog
  dumpdb
  stop
  halt
  trace
  trace level
  notrace
  flush
  status

  -c 옵션이 없다면 /etc/rndc.conf 파일의 내용이 적용되며, 기본적으로 key를 사용합니다.

  RPM으로 패키지된 BIND9의 /etc/rc.d/init.d/named 제어 스크립트는 localhost에서
  rndc의 key를 이용하여 localhost 자신의 named를 종료하기 때문에 최소한 다음과 같은
  설정이 필요합니다.

  예) localhost의 rndc.conf 파일 :
  key rndc_key {
	algorithm "hmac-md5";
	secret "c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K";
  };
  options {
	default-server localhost;
	default-key    rndc_key;
  };

  예) localhost named.conf 파일 :
  key rndc_key {
	algorithm "hmac-md5";
	secret "c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K";
  };
  controls { // 127.0.0.1의 953번 포트 사용
	inet 127.0.0.1 allow { localhost; } keys { rndc_key; };
  };

  예) 원격의 네임서버 named.conf 파일 :
  key rndc_key {
	algorithm "hmac-md5";
	secret "c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K";
  };
  controls { // 127.0.0.1의 953번 포트 사용
	inet 127.0.0.1 allow { localhost; 허락할_호스트;} keys { rndc_key; };
  };

  이와 같은 설정이 되어 있다면,

  # rndc reload
  # rndc staus
  # rndc stop

  와 같은 명령을 사용할 수 있습니다.

  만약 rndc를 이용하지 않고 named 시작, 종료할 수 있다면(얼마든지 가능함) key 설정은
  반드시 필요하지는 않습니다. 이 key는 제어 메시지(명령어)를 보내어 named를 제어할
  인증에 관한 한가지 방법입니다.
  
  따라서 반드시 꼭 사용해야만 하는 어떤 규칙은 없지만 RPM으로 패키지된 BIND는 기본적
  으로 사용하도록 패키징되어 있을 뿐입니다.

  nsupdae :
  nsupdate는 localhost나 원격의 네임서버의 zone 데이터베이스를 동적으로
  갱신하고자 할 때 사용하는 관리자용 유틸리티입니다.

  1)key 없이 동적으로 원격의 zone 데이터베이스를 갱신할 때 :
  원격의 네임서버의 named.conf 파일은 최소한 다음과 같은 설정이 필요합니다.

  예) 원격의 named.conf 파일 :
  zone aaa.co.kr {
	...;
	allow-update { 동적으로_갱신가능한_호스트들; };
  };
  
  '동적으로_갱신가능한_호스트들' 부분에는 nsupdate 명령을 보내는 호스트 IP 주소나 호스트
  이름을 적어주면 됩니다.

  예) nsupdate 사용 예(대화식) :
  # nsupdate
  > server 123.123.123.123	/*** 원격의 네임서버 IP 또는 호스트 이름 ***/
  > zone aaa.co.kr.		/*** 업데이트할 zone 지정 ***/
  > prereq nxdomain w3.aaa.co.kr. /*** 현재 호스트(w3)가 없음을 조건으로 알림 ***/
  > update add w3.aaa.co.kr. 86400 CNAME www.aaa.co.kr. /*** w3 호스트 추가 ***/
  > show			/*** 현재까지 사용한 명령어 보기 ***/
  > send			/*** 명령어를 123.123.123.123에게 전송함 ***/
  > quit			/*** 종료함 ***/

  기타 자세한 명령어는 책 p.458에 설명되어 있으므로 참고하도록 하세요.
  (또는 man nsupdate)

  예) nsupdate 사용 예(비대화식) :
  # cat nsupdate-aaa.co.kr.cmd /*** 파일을 직접 작성함 ***/
  server 123.123.123.123
  zone aaa.co.kr.
  prereq nxdomain w3.aaa.co.kr.
  update add w3.aaa.co.kr. 86400 CNAME www.aaa.co.kr.
  show
  send
  quit
  #
  # nsupdate nsupdate-aaa.co.kr.com

  2)key를 사용하여 동적으로 원격의 zone 데이터베이스를 갱신할 때 :
  우선 localhost의 nsupdate가 사용할 key를 만들고 이 key를 원격의 named.conf
  파일에 설정해야 합니다. 예제에서는 key 이름을 'mykey'로 가정함.

  # dnssec-keygen -a HMAC-MD5 -b 512 -n HOST mykey
  #
  # ls
  Kmykey.+157+46093.key		/*** 매번 파일 이름이 다름 ***/
  Kmykey.+157+46093.private

  xxx.private을 열어서 key 부분을 원격의 네임서버에 다음과 같이 설정합니다.

  예) 원격의 named.conf 파일 :
  key mykey {
	algorithm "hmac-md5";
	secret "c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K";
  };
  controls { // 127.0.0.1의 953번 포트 사용
	inet 127.0.0.1 allow { localhost; 허락할_호스트;} keys { mykey; };
  };
  zone aaa.co.kr {
	...;
	allow-update { key "mykey"; }; /*** keys가 아니라 key ***/
  };

  예) nsupdate 사용 예 :
  # ls		/*** 다음 두개의 파일 모두 있어야 함 ***/
  Kmykey.+157+46093.key
  Kmykey.+157+46093.private
  #
  # nsupdate -k Kmykey.+157+46093.private
  > nsupdate

  나머지 nsupdate 명령어는 1)번과 동일하므로 생략합니다.

  제대로 업데이트되었는지 확인하는 방법은 nslookup, dig, host로 직접 확인해 보세요.
  원격의 네임서버에서는 임시로 zone-file.jnl 파일을 만들며 몇 분이 지나면
  자동적으로 zone-file(데이터베이스 파일)이 갱신하기 때문에 다른 조치를 취할 필요는
  없습니다.

  *주의할 점)
  원격의 네임서버의 zone 데이터베이스 디렉토리와 해당 zone 데이터베이스 파일은
  named의 유저(예:named, ps -ef | grep named로 확인)에게 쓰기 권한(퍼미션)이 있어야
  합니다. 그래야 업데이트되기 때문에...

  *참고로)
  2차 네임서버는 1차 네임서버에 실시간으로 접속하여 zone 데이터베이스를 백업하여
  자신(2차 네임서버)의 zone 데이터베이스를 갱신해야하기 때문에 allow-update { none; }
  와 같은 구문을 설정하면 안됩니다.


  정리 :
  - rndc : localhost나 원격의 네임서버에 stop, reload, staus 등의 제어 메시지를 보낼때
  - nsupdate : localhost나 원격의 네임서버의 zone 데이터베이스를 동적으로 갱신하고자 할 때

  따라서 네임서버를 운영할 때 반드시 이 두개의 유틸리티는 필요하지는 않지만 rndc를
  이용하여 localhost의 named를 제어할 뿐입니다.


 
4. rndc.conf, named.conf 파일에서 key 부분 설정 구분 정리

  address_match_list = address_match_list_element ;
	[ address_match_list_element; ... ]

  address_match_list_element = [ ! ] (ip_address [/length] |
	key key_id | acl_name | { address_match_list } )

  *주)
  다음 표에서 address_match_list로 설정가능한 구문에서 key로 설정할 경우,
  keys "key_name"이 아니라 key "key_name"입니다.
named.conf rndc.conf
key "key_name" {
      ...;
};
or
include "/etc/rndc.conf";

보통 include "/etc/rndc.conf";로 설정되어 있음.

key "key_name" {} 구문은 named.conf와
동일하지만 include 구문을 사용할 수 없기
때문에 직접 구문을 설정해야 함.
server ip_addr {
      ...;
      keys { "key_name"; };
      // keys "key_name"; // 이것도 가능
};

*주)
ip_addr 부분에 host_name이나 "와 "로 묶어서 설정하면 구문에러가 나므로 "없이 ip 주소로만 설정해야 함

server ip_addr_or_host_name {
      key "key_name";
};

*주)
ip_addr_or_host_name 부분에 ip_addr로 설정할 경우 "와 "로 묶어줘야 구문에러가 없음

acl acl-name {
      address_match_list
};
-
controls {
      inet ( ip_addr | * ) [ port ip_port ]
      allow { address_match_list }
      keys { key_list };
      [ inet ...; ]
};

*주) key_list에 "key_name"하나 또는 ';'로 구분하여 여러개 설정함.

-
allow-notify { address_match_list };
allow-query { address_match_list };
allow-transfer { address_match_list };
allow-recursion { address_match_list };
allow-v6-synthesis { address_match_list };
blackhole { address_match_list };
listen-on { address_match_list };
listen-on-v6 { address_match_list };

*주) options {} 구문의 sub 구문에 모두 속함.

-
allow-notify { address_match_list };
allow-query { address_match_list };
allow-transfer { address_match_list };
allow-update { address_match_list };
update-policy { update_policy_rule [...] };
allow-update-forwarding { address_match_list };
masters { ip_addr [key "key_name"]; [...] };

*주) zone {} 구문의 sub 구문에 모두 속함.

-
match-clients { address_match_list };
match-destinations { address_match_list };

*주) view {} 구문의 sub 구문에 모두 속함.

-