debian: ลองติดตั้ง dns

เอามาจาก
ThaiLinuxCafe - debian : ติดตั้ง dns อย่างง่าย

เรื่องของ DNS (Domain Name Server) เป็นเรื่องหลักของการใช้งานอินเตอร์เน็ต เนื้อหาซับซ้อนและทำความเข้าใจยาก
สำหรับในที่นี้ เราเอาแค่ติดตั้งพอใช้งานได้
โดยเราจะติดตั้งเครื่องเซิร์ฟเวอร์เพื่อทำหน้าที่เป็น DNS สำหรับใช้งานเครือข่ายภายใน
โครงร่างคือ

  • เน็ตเวิร์กเราเป็น 192.168.1.0/24 มีโดเมนเป็น example.com
  • เครื่องที่ทำหน้าที่ name server มีชื่อว่า server1.example.com ไอพีเป็น 192.168.1.1 โดยมีชื่อเสมือนคือ ns1.example.com
  • มีเครื่องในวงเครื่องอื่น ๆ ดังนี้
    • ns2 = 192.168.1.2
    • client1 = 192.168.1.101
    • client2 = 192.168.1.102
    • client3 = 192.168.1.103

แพกเกจที่ทำหน้าที่ DNS ในเดเบียนชื่อ bind9 และแพกเกจที่เป็นโปรแกรมช่วยชื่อ dnsutils
งานปรับตั้งคือการสร้างไฟล์สำหรับให้ bind9 เรียกใช้ ดังนี้

  • โซนไฟล์ ไว้สำหรับค้นข้อมูลจากชื่อเป็นไอพี
  • รีเวิร์สไฟล์ ไว้สำหรับค้นข้อมูลย้อนกลับ คือจากไอพีเป็นชื่อ
  • คอนฟิกไฟล์ สำหรับบอก bind9 ว่าเราจะติดตั้ง DNS ในแบบไหน และประกอบด้วยไฟล์ข้อมูลอะไรบ้าง

เริ่มด้วย
ติดตั้ง DNS และโปรแกรมช่วย
# aptitude install bind9 dnsutils

ไปที่ไดเรกทอรี่ของการปรับตั้ง
# cd /etc/bind

เริ่มสร้างโซนไฟล์ ให้ชื่อว่า example.com.zone มีเนื้อไฟล์ดังนี้
# vi example.com.zone

$TTL    86400
@          IN      SOA    server1.example.com.    root.server1.example.com. (
                          51              ; serial (d. adams)
                          3H              ; refresh after 3 hours
                          15M             ; retry after 15 minutes
                          1W              ; expire after 7 days
                          1D )            ; minimum TTL (Time To Live) of 1 days
@          IN      NS      ns1.example.com.    ; primary NS
@          IN      NS      ns2.example.com.    ; secondary NS

ns1        IN      CNAME  server1

; append or edit host ip here
server1  IN      A      192.168.1.1
ns2      IN      A      192.168.1.2
client1  IN      A      192.168.1.101
client2  IN      A      192.168.1.102
client3  IN      A      192.168.1.103

สร้างรีเวิร์สไฟล์ ให้ชื่อว่า example.com.reverse มีเนื้อไฟล์ดังนี้
# vi example.com.reverse

$TTL    86400
@          IN      SOA    server1.example.com.    root.server1.example.com. (
                          51              ; serial (d. adams)
                          3H              ; refresh after 3 hours
                          15M             ; retry after 15 minutes
                          1W              ; expire after 7 days
                          1D )            ; minimum TTL (Time To Live) of 1 days
@          IN      NS      ns1.example.com.    ; primary NS
@          IN      NS      ns2.example.com.    ; secondary NS

; append or edit host name here
1        IN      PTR    server1.example.com.
2        IN      PTR    ns2.example.com.
101      IN      PTR    client1.example.com.
102      IN      PTR    client2.example.com.
103      IN      PTR    client3.example.com.

สร้างคอนฟิกไฟล์สำหรับโซน example.com ให้ชื่อว่า example.com.conf มีเนื้อไฟล์ดังนี้
# vi example.com.conf

zone "example.com" IN {
        type master;
        file "/etc/bind/example.com.zone";
        allow-update { none; };
};
zone "1.168.192.in-addr.arpa" IN {
        type master;
        file "/etc/bind/example.com.reverse";
        allow-update { none; };
};

เปลี่ยนสิทธ์ให้ bind เป็นเจ้าของไฟล์
# chown bind:bind example.com.*

บอกให้ bind9 เอาไฟล์ของเราไปใช้งาน โดยการเพิ่มลงในไฟล์ named.conf.local ดังนี้
# vi named.conf.local

...
include "/etc/bind/example.com.conf";

เสร็จแล้วก็สั่งเริ่ม bind9 ใหม่
# /etc/init.d/bind9 restart

ถ้ามีข้อผิดพลาด ให้ดูที่ /etc/log/syslog

ทดสอบโดย
# nslookup server1.example.com
จะแสดงผลเป็น 192.168.1.1
Server: 192.168.1.1
Address: 192.168.1.1#53

Name: server1.example.com
Address: 192.168.1.1

ทดสอบย้อนกลับ
# nslookup 192.168.1.1
จะแสดงผลเป็น server1.example.com
Server: 192.168.1.1
Address: 192.168.1.1#53

1.1.168.192.in-addr.arpa name = server1.example.com.

หมายเหตุ

  • เลขซีเรียลตามตัวอย่างเป็น 51 แต่ส่วนใหญ่นิยมใช้วันที่ เช่น 2006030401 เป็นต้น
  • ในเนื้อไฟล์ของโซนไฟล์และริเวิร์สไฟล์ เวลาพิมพ์ระวังอยาลืมเครื่องหมายจุด ท้ายชื่อโฮสต์
  • สำหรับเครื่อง DNS ที่ทำหน้าที่เกตเวย์ออกอินเตอร์เน็ต พบว่าเมื่อแก้ไขไฟล์ /etc/resolv.conf ให้ชี้ไปที่ DNS ของไอเอสพี เครื่องเราจะทำหน้าทีเป็น slave โดยอัตโนมัติ
  • ถ้าจะเพิ่มโดเมน และเป็นเน็ตเวิร์กคนละวง ก็ใช้วิธีเดียวกันได้ โดยสร้างโซนไฟล์ รีเวิร์สไฟล์ และคอนฟิกไฟล์สำหรับโดเมนที่เพิ่ม
  • ถ้าเพิ่มโดเมน และเป็นเน็ตเวิร์กวงเดียวกัน เช่น หนึ่งไอพี มีหลายโดเมน ให้สร้างเฉพาะโซนไฟล์ ไม่ต้องสร้างรีเวิร์สไฟล์ ซึ่งก็จะทำให้เรียกดูชื่อย้อนจากไอพีไม่ได้
  • ถ้าจะเพิ่มเน็ตเวิร์กเป็นสองวง โดยเป็นโดเมนเดียวกัน ให้ดูตัวอย่างที่ Debian Administration: Two-in-one DNS server with BIND9

เนื้อหาไม่ค่อยถูกตามหลักการนะครับ เพราะมันยาก ถ้าจะให้รู้เรื่องจริง ๆ ต้องเข้าใจระบบอินเตอร์เน็ตพอสมควร
ในที่นี้เอาแค่พอใช้งานได้ครับ

อ้างอิงเพิ่มเติม

debian: bind9 + chroot + internal/external

*** ยังเขียนไม่เสร็จ + ยังไม่ได้ตรวจทานซ้ำ ***

เป้า

  • ติดคุกให้ bind (chroot jail)
  • จะทำให้สามารถใช้งานได้ทั้งภายใน และภายนอก (ภายนอกไม่ค่อยจำเป็น แต่ติดตั้งไว้เผื่อจะทำอะไรเพิ่ม) คือโดเมนเดียวกัน แต่มีไอพี 2 กลุ่ม ภายในกลุ่มนึง และภายนอกอีกกลุ่มนึง
  • ติดตั้งเป็นแบบสามารถเปลี่ยนค่าไอพีได้ (allow-update)

สมมุติว่า

  • มีโดเมนภายในเป็น example.com อย่างเดียว มีไอพีเป็น 192.168.1.0/24 โดยจะทำเรื่อง reverse ip ด้วย (คือค้นย้อนกลับจากเลขไอพีได้)
  • โดเมนภายนอกเป็น example.com และ example.org โดยที่เราจะทำให้ทุกบริการมีไอพีเดียวกัน คือเครื่องนี้เครื่องเดียวทำหลายหน้าที่ เพียงเปลี่ยนชื่อ (CNAME) ไปตามบริการนั้น ๆ ติดตั้งเป็นแบบเปลี่ยนค่าได้ เพราะไอพีเราไม่คงที่
    โดเมนภายนอก จะไม่ทำ reverse ip เพราะเรามีหลายโดเมน และถึงแม้จะมีโดเมนเดียว ค่าที่โลกภายนอกค้นได้ก็คงไม่ใช่จากเครื่องเราอยู่ดี (ค้นได้จากชื่อโดเมนอย่างเดียว ค้นย้อนกลับจากเลขไอพีไม่ได้)

ติดตั้งแพกเกจ
# aptitude install bind9 dnsutils

ทำเรื่องติดคุก (chroot jail) จะย้ายคุกไปไว้ที่ /sys1/chroot/bind
# vi /etc/default/bind9

...
# OPTIONS="-u bind"
OPTIONS="-u bindinjail -t /sys1/chroot/bind"
...

สร้างผู้ใช้ชื่อ bindinjail ให้ใช้เชลล์ไม่ได้ อยู่ในกลุ่ม nogroup
# useradd -g nogroup -d /nonexistent -s /bin/false -u 65533 bindinjail
# passwd -l bindinjail

สร้างคุก
# mkdir -p /sys1/chroot/bind/{etc,dev,var/cache/bind,var/log,var/run/bind/run}
# mv /etc/bind /sys1/chroot/bind/etc
# ln -sf /sys1/chroot/bind/etc/bind /etc
# mknod /sys1/chroot/bind/dev/null c 1 3
# mknod /sys1/chroot/bind/dev/random c 1 8
# chmod 666 /sys1/chroot/bind/dev/null /sys1/chroot/bind/dev/random
# chown -R bindinjail:nogroup /sys1/chroot/bind/var/*
# chown -R bindinjail:nogroup /sys1/chroot/bind/etc/bind/

ทำให้ระบบเก็บปูมของ bind (system logging - syslogd)
# vi /etc/default/syslogd

...
# SYSLOGD=""
SYSLOGD="-a /sys1/chroot/bind/dev/log"
...

ปรับตั้งระบบปูมของ bind
# vi /sys1/chroot/bind/etc/bind/named.conf.local

...
logging {
    channel "querylog" { file "/var/log/bind9-query.log"; print-time yes; };
    category queries { querylog; };
};
...

ปรับตั้งประวัติปูมของ bind
# vi /etc/logrotate.d/bind9-query

/sys1/chroot/bind/var/log/bind9-query.log {
    weekly
    missingok
    rotate 10
    postrotate
        /etc/init.d/bind9 reload > /dev/null
    endscript
    compress
    notifempty
}

# ln -sf /sys1/chroot/bind/var/log/bind9-query.log /var/log/bind9-query.log

แก้ไข options ให้มาใช้ pid ของคุก
# vi /sys1/chroot/bind/etc/bind/named.conf.options

...
options {
    directory "/var/cache/bind";
    pid-file    "/var/run/named.pid";
...

เสร็จขั้นต้น ทดสอบระบบครั้งแรก
# /etc/init.d/sysklogd restart
# /etc/init.d/bind9 restart

ต้องไม่มีรายงานข้อผิดพลาด

ต่อไปเป็นเรื่องการอัปเดตไอพี และการทำให้รองรับเครือข่ายภายในและภายนอก ผสมกัน

บอก bind ว่าเราจะใช้งาน dnssec
# vi /etc/bind/named.conf.options

...
options {
    ...
    recursion yes;
    dnssec-enable yes;
};
...

สร้างไดเรกทอรี่มารองรับการทำงาน
# mkdir -p /sys1/chroot/bind/etc/bind/{internal,external}

สร้างกฎ acl สำหรับเครือข่ายภายใน ตั้งชื่อว่า internal (นอกจากนั้นจะถือว่าเป็น external ทั้งหมด)
และให้มาอ่านไฟล์คอนฟิกที่เราจะสร้างขึ้นภายหลัง ของโซน example.com และ example.org
# cd /sys1/chroot/bind/etc/bind
# vi named.conf.local

...
acl internal {
    127.0.0.0/8;
    192.168.0.0/16;
};

include "/etc/bind/example.com.conf";
include "/etc/bind/example.org.conf";
...

สร้างไฟล์เปล่า ๆ กันเหนียวเผื่อทดสอบ จะได้มีไฟล์รองรับ
# touch /etc/bind/{example.com.conf,example.org.conf}

สร้างกุญแจ สำหรับอัปเดตไอพี example.com และ example.org

ของ example.com
สั่งสร้างกุญแจสำหรับลงทะเบียนโซน
# dnssec-keygen -r /dev/urandom -a rsasha1 -b 1024 -n ZONE example.com
ตัวอย่างได้ผลเป็น
Kexample.com.+005+11187

และได้ไฟล์ Kexample.com.+005+11187.key และ Kexample.com.+005+11187.private

และกุญแจสำหรับอัปเดตโซน
# dnssec-keygen -r /dev/urandom -k -a rsasha1 -b 1024 -n ZONE example.com
ตัวอย่างได้ผลเป็น

Kexample.com.+005+09453

และได้ไฟล์ Kexample.com.+005+09453.key และ Kexample.com.+005+09453.private

สร้างไฟล์คอนฟิกของโซน example.com
# vi example.com.conf

view "internal" {
    match-clients { internal; };
    zone "example.com" IN {
        type master;
        file "/etc/bind/internal/example.com.zone.signed";
        key-directory "/etc/bind";
        update-policy {
            grant example.com. subdomain example.com any;
        };
    };
    zone "0.168.192.in-addr.arpa" IN {
        type master;
        file "/etc/bind/internal/example.com.reverse.signed";
        key-directory "/etc/bind";
        update-policy {
            grant example.com. subdomain example.com any;
        };
    };
};

view "external" {
    match-clients { any; };
    zone "example.com" IN {
        type master;
        file "/etc/bind/external/example.com.zone.signed";
        key-directory "/etc/bind";
        update-policy {
            grant example.com. subdomain example.com any;
        };

    };
};

สร้างโซนไฟล์ของ internal
# vi internal/example.com.zone
อันนี้ลองเปลี่ยนตามจริงนะครับ สมมุติว่าเครื่องนี้เอาชื่อ server1 เป็นหลัก แล้วใช้ชื่ออื่นคือ www, ns1, ftp, mail เป็นชื่อรอง

$TTL    86400
@       IN  SOA server1.example.com. root.server1.example.com. (
                    41      ; serial (d. adams)
                    3H      ; refresh
                    15M     ; retry
                    1W      ; expiry
                    1D )    ; minimum
@           IN  NS  ns1.example.com.    ; primary NS
@           IN  NS  ns2.example.com.    ; secondary NS

www         IN  CNAME   server1
ns1         IN  CNAME   server1
ftp         IN  CNAME   server1
mail        IN  CNAME   server1
www         IN  A   192.168.1.1
ns2         IN  A   192.168.1.2
work1       IN  A   192.168.1.101
work2       IN  A   192.168.1.102
work3       IN  A   192.168.1.103

$INCLUDE /etc/bind/Kexample.com.+005+11187.key
$INCLUDE /etc/bind/Kexample.com.+005+09453.key

ลงทะเบียนโซน example.com ของ internal
# cd internal
# dnssec-signzone -r /dev/urandom -t -g -o example.com example.com.zone /etc/bind/Kexample.com.+005+11187.private

example.com.zone.signed
Signatures generated:                       21
Signatures retained:                         0
Signatures dropped:                          0
Signatures successfully verified:            0
Signatures unsuccessfully verified:          0
Runtime in seconds:                      0.063
Signatures per second:                 331.151

# cd ..

เปลี่ยนเจ้าของและกลุ่ม
# chown -R bindinjail:nogroup *

เสร็จโซนไฟล์ของ internal

ทดสอบขั้นต้น
# /etc/init.d/bind9 restart
ต้องไม่มีรายงานข้อผิดพลาด

ทดสอบอัปเดต
# nsupdate -d -v -k Kexample.com.+005+09453.private

Creating key...
> server 192.168.1.1
> zone example.com
> update add testing.example.com. 3600 A 192.168.1.5
> show
Outgoing update query:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id:      0
;; flags: ; ZONE: 0, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0
;; UPDATE SECTION:
testing.example.com.    3600    IN      A       192.168.1.5

> send
Sending update to 192.168.1.1#53
Outgoing update query:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id:  43656
;; flags: ; ZONE: 1, PREREQ: 0, UPDATE: 1, ADDITIONAL: 1
;; ZONE SECTION:
;example.com.                   IN      SOA

;; UPDATE SECTION:
testing.example.com.    3600    IN      A       192.168.1.5

;; SIG0 PSEUDOSECTION:
.                       0       ANY     SIG     0 5 0 0 20080223084852 20080223083852 9453 example.com. zpGfPIECwJ8V31lm7mlq7zMiKYSuh2TlIyOZgEUJjZUgYTRHYZrwi75Z mDaKAJGb7uG+r4SLmuFDRdjQQ1mvtZcuo8SK2yjHK59QzUoFnGJXz427 vRNj/do4DbMxMkJpJwqDiKU87lGiy+CXvpbQAm+4AeJutpCTsGnfhixx k4c=


Reply from update query:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id:  43656
;; flags: qr ra ; ZONE: 0, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0


> quit

ลองค้นดูอีกที
# nslookup testing.example.com localhost

Server:         localhost
Address:        127.0.0.1#53

Name:   testing.example.com
Address: 192.168.1.5

เสร็จ forward internal

ยังเขียนไม่เสร็จ หมดแรงก่อน ข้อเขียนข้างบนยังไม่ได้ตรวจทาน
- reverse internal example.com ทำเหมือนเดิม ยกเว้นตอนอัปเดตใช้คำสั่งเป็น
> update add 5.1.168.192.in-addr.arpa. 3600 IN PTR testing.example.com.
โดยอย่าให้มีคำสั่ง zone XXXX มาก่อนหน้า อัปเดตได้เลย

- forward external ทำเหมือนเดิม ---รอเขียนต่อ---

อ้างอิง
http://myrddin.org/howto/debian-bind9-chroot/
http://www.ops.ietf.org/dns/dynupd/secure-ddns-howto.html
http://garnser.blogspot.com/2008/02/how-to-enable-bind-with-dnssec-and.html
http://www.unixwiz.net/techtips/bind9-chroot.html

Topic: 

debian: bind9 แบบให้บริการเครือข่ายภายในและภายนอก

bind9 แบบให้บริการเครือข่ายภายในและภายนอก

การตั้งให้ name server ให้บริการเครือข่ายภายในและภายนอก โดยใช้โดเมนเดียวกัน มีข้อดีตรงที่เราไม่จำเป็นต้องแยกโดเมนให้จำยาก และเมื่อเวลาลูกข่ายภายในสั่งค้น การค้นก็ไม่ต้องเปลืองแพ็กเก็ตออกสู่ภายนอก เพียงแต่การปรับตั้งยุ่งนิดนึง
# aptitude install bind9

สมมุติว่า

  • เราให้บริการอยู่ 2 โดเมนคือ example.com กับ example.org
  • example.com ภายในเป็น 192.168.1.0/24 ส่วนภายนอกเป็น 111.112.113.114 (ไอพีสมมุติ)
  • example.org ภายในเป็น 10.0.0.0/24 ภายนอกเป็น 211.212.213.214 (ไอพีสมมุติ)
  • เครื่องที่เรากำลังตั้งอยู่ ให้ชื่อว่า ns1 (ซึ่งเราทำเป็น all-in-one ก็อาจมีชื่อเป็น www และ mail ด้วย)
    โดยมีไอพีของ ns1.example.com เป็น 192.168.1.1 และ ไอพีของ ns1.example.org เป็น 10.0.0.1

จะต้องมีไฟล์คอนฟิกคือ example.com.conf และ example.org.conf
มีโซนไฟล์คือ internal/example.com.zone กับ internal/example.org.zone และ external/example.com.zone กับ external/example.org.zone
ตามด้วยรีเวิร์สไฟล์คือ internal/example.com.reverse กับ internal/example.org.reverse และ external/example.com.reverse กับ external/example.org.reverse

เริ่มด้วย
# cd /etc/bind

เพิ่มกฎแยก internal และ external และให้อ่านไฟล์คอนฟิกของแต่ละโดเมนเข้ามาในระบบด้วย ผ่านไฟล์ named.conf.local
# vi named.conf.local

...
acl internals {
    127.0.0.0/8;
    10.0.0.0/24;
    192.168.1.0/24;
};

include "/etc/bind/example.com.conf";
include "/etc/bind/example.org.conf";

สร้างไฟล์คอนฟิกของ example.com
# vi example.com.conf

view "internal" {
    match-clients { internals; };
    zone "example.com" IN {
        type master;
        file "/etc/bind/internal/example.com.zone";
        allow-update { none; };
    };
    zone "1.168.192.in-addr.arpa" IN {
        type master;
        file "/etc/bind/internal/example.com.reverse";
        allow-update { none; };
    };
};

view "external" {
    match-clients { any; };
    zone "example.com" IN 
        type master;
        file "/etc/bind/external/example.com.zone";
        allow-update { none; };
    };
    zone "113.112.111.in-addr.arpa" IN {
        type master;
        file "/etc/bind/external/example.com.reverse";
        allow-update { none; };
    };
};

สร้างไฟล์คอนฟิกของ example.org
# vi example.org.conf

view "internal" {
    match-clients { internals; };
    zone "example.org" IN {
        type master;
        file "/etc/bind/internal/example.org.zone";
        allow-update { none; };
    };
    zone "0.0.10.in-addr.arpa" IN {
        type master;
        file "/etc/bind/internal/example.org.reverse";
        allow-update { none; };
    };
};

view "external" {
    match-clients { any; };
    zone "example.org" IN 
        type master;
        file "/etc/bind/external/example.org.zone";
        allow-update { none; };
    };
    zone "213.212.211.in-addr.arpa" IN {
        type master;
        file "/etc/bind/external/example.org.reverse";
        allow-update { none; };
    };
};

อย่าลืมสร้างไดเรกทอรี่ก่อน
# mkdir internal external

ตัวอย่างสร้างโซนไฟล์ของ internal/example.com
# vi internal/example.com.zone

$TTL    86400
@       IN  SOA ns1.example.com. root.ns1.example.com. (
                42      ; serial (d. adams)
                3H      ; refresh
                15M     ; retry
                1W      ; expiry
                1D )    ; minimum
@       IN  NS  ns1.example.com.    ; primary NS
@       IN  NS  ns2.example.com.    ; secondary NS

www     IN  CNAME   ns1
ftp     IN  CNAME   ns1
mail    IN  CNAME   ns1
; append or edit host file here
ns1     IN  A   192.168.1.1
ns2     IN  A   192.168.1.2
work1   IN  A   192.168.1.11
work2   IN  A   192.168.1.12
...

ตัวอย่างสร้างโซนไฟล์ของ external/example.com
# vi external/example.com.zone

$TTL    86400
@       IN  SOA ns1.example.com. root.ns1.example.com. (
                42      ; serial (d. adams)
                3H      ; refresh
                15M     ; retry
                1W      ; expiry
                1D )    ; minimum
@       IN  NS  ns1.example.com.    ; primary NS
@       IN  NS  ns2.example.com.    ; secondary NS

www     IN  CNAME   ns1
ftp     IN  CNAME   ns1
mail    IN  CNAME   ns1
; append or edit host file here
ns1     IN  A   111.112.113.114

ตัวอย่างสร้างโซนไฟล์ของ internal/example.org
# vi internal/example.org.zone

$TTL    86400
@       IN  SOA ns1.example.org. root.ns1.example.org. (
                42      ; serial (d. adams)
                3H      ; refresh
                15M     ; retry
                1W      ; expiry
                1D )    ; minimum
@       IN  NS  ns1.example.org.    ; primary NS
@       IN  NS  ns2.example.org.    ; secondary NS

www     IN  CNAME   ns1
ftp     IN  CNAME   ns1
mail    IN  CNAME   ns1
; append or edit host file here
ns1     IN  A   10.0.0.1
ns2     IN  A   10.0.0.2
shop1   IN  A   10.0.0.11
shop2   IN  A   10.0.0.12
...

ตัวอย่างสร้างโซนไฟล์ของ external/example.org
# vi external/example.org.zone

$TTL    86400
@       IN  SOA ns1.example.org. root.ns1.example.org. (
                42      ; serial (d. adams)
                3H      ; refresh
                15M     ; retry
                1W      ; expiry
                1D )    ; minimum
@       IN  NS  ns1.example.org.    ; primary NS
@       IN  NS  ns2.example.org.    ; secondary NS

www     IN  CNAME   ns1
ftp     IN  CNAME   ns1
mail    IN  CNAME   ns1
; append or edit host file here
ns1     IN  A   211.212.213.214
...

ตัวอย่างสร้างรีเวิร์สไฟล์ของ internal/example.com
# vi internal/example.com.reverse

$TTL    86400
@       IN  SOA ns1.example.com. root.ns1.example.com. (
                42      ; serial (d. adams)
                3H      ; refresh
                15M     ; retry
                1W      ; expiry
                1D )    ; minimum
@       IN  NS  ns1.example.com.    ; primary NS
@       IN  NS  ns2.example.com.    ; secondary NS
;
; host in network 192.168.1.0
; append or edit host file here
1   IN  PTR ns1.example.com.
2   IN  PTR ns2.example.com.
11  IN  PTR work1.example.com.
12  IN  PTR work2.example.com.
...

ตัวอย่างสร้างรีเวิร์สไฟล์ของ external/example.com
# vi external/example.com.reverse

$TTL    86400
@       IN  SOA ns1.example.com. root.ns1.example.com. (
                42      ; serial (d. adams)
                3H      ; refresh
                15M     ; retry
                1W      ; expiry
                1D )    ; minimum
@       IN  NS  ns1.example.com.    ; primary NS
@       IN  NS  ns2.example.com.    ; secondary NS
;
; host in network 111.112.113.0
; append or edit host file here
114   IN  PTR ns1.example.com.

ตัวอย่างสร้างรีเวิร์สไฟล์ของ internal/example.org
# vi internal/example.org.reverse

$TTL    86400
@       IN  SOA ns1.example.org. root.ns1.example.org. (
                42      ; serial (d. adams)
                3H      ; refresh
                15M     ; retry
                1W      ; expiry
                1D )    ; minimum
@       IN  NS  ns1.example.org.    ; primary NS
@       IN  NS  ns2.example.org.    ; secondary NS
;
; host in network 10.0.0.0
; append or edit host file here
1   IN  PTR ns1.example.org.
2   IN  PTR ns2.example.org.
11  IN  PTR shop1.example.org.
12  IN  PTR shop2.example.org.
...

ตัวอย่างสร้างรีเวิร์สไฟล์ของ external/example.org
# vi external/example.org.reverse

$TTL    86400
@       IN  SOA ns1.example.org. root.ns1.example.org. (
                42      ; serial (d. adams)
                3H      ; refresh
                15M     ; retry
                1W      ; expiry
                1D )    ; minimum
@       IN  NS  ns1.example.org.    ; primary NS
@       IN  NS  ns2.example.org.    ; secondary NS
;
; host in network 211.212.213.0
; append or edit host file here
214   IN  PTR ns1.example.org.

เปลี่ยนสิทธิ์ทั้งหมด
# chown bind:bind * -R

เสร็จแล้ว
# /etc/init.d/bind9 restart

หมายเหตุ
ตัวเลข serial ไม่ค่อยจำเป็นเท่าไหร่ เป็นตัวเลขอะไรก็ได้ แต่ถ้าเราทำเป็น dynamic dns จะต้องเป็นตัวเลขที่เพิ่มค่าขึ้นไปเรื่อย ๆ ให้มากกว่าค่าเดิม ไม่งั้นเขาไม่ยอมอัปเดตค่าไอพีให้

อ้างอิง
Two-in-one DNS server with BIND9

Topic: 

ลองติดตั้ง dns แบบเปลี่ยนค่าได้

จะทดลองทำ DNS แบบยอมให้เปลี่ยนค่าไอพีได้

ขออนุญาตเริ่มใหม่ เพื่อให้บทความจบในตัว

เริ่มต้นด้วยการติดตั้ง bind9 ใหม่
# aptitude remove --purge bind9 dnsutils
# rm -rf /etc/bind
# aptitude install bind9 dnsutils

เนื่องจากต้องมีการเปลี่ยนค่าไอพีโดยใช้สิทธิ์ของผู้ใช้ชื่อ bind เราจึงควรสร้างไดเรกทอรีขึ้นมาเพื่อให้ผู้ใช้ bind มีสิทธิ์ในการเขียนไฟล์
# cd /etc/bind
# mkdir example.com
# chown bind:bind example.com
# cd example.com

สร้างกุญแจสำหรับใช้ในการอัปเดตค่าไอพี (โดยใช้อัลกอริธึม HMAC-MD5 ขนาด 512บิต ตั้งชื่อกุญแจว่า server1.example.com.)
# dnssec-keygen -a HMAC-MD5 -b 512 -n HOST server1.example.com.
ผลลัพธ์ของผมคือ

Kserver1.example.com.+157+49285

เราจะได้ไฟล์มาสองไฟล์ซึ่งมีลักษณะคือ K(ชื่อกุญแจ)+NNN+NNNNN โดยมีนามสกุลเป็น .key และ .private

ตามตัวอย่างได้เนื้อไฟล์ Kserver1.example.com.+157+49285.key เป็น

server1.example.com. IN KEY 512 3 157 wLuCYKvKDqM2XJsqcspdycoJgLNJKUKga4bHANjE7FY0HCujucYhDUKt FD5wgGXGPCNVsZi7NOYDgVZSIJ8LbA==

และเนื้อไฟล์ Kserver1.example.com.+157+49285.private เป็น

Private-key-format: v1.2
Algorithm: 157 (HMAC_MD5)
Key: wLuCYKvKDqM2XJsqcspdycoJgLNJKUKga4bHANjE7FY0HCujucYhDUKtFD5wgGXGPCNVsZi7NOYDgVZSIJ8LbA==

เราจะเอาค่า private key มาใช้ โดยสร้างไฟล์คอนฟิกขึ้นมา ตั้งชื่อว่า dnskeys.conf และนำเนื้อหาของกุญแจ private key มาใช้เป็นค่า secret
# vi dnskeys.conf

key server1.example.com. {
    algorithm hmac-md5;
    secret "wLuCYKvKDqM2XJsqcspdycoJgLNJKUKga4bHANjE7FY0HCujucYhDUKtFD5wgGXGPCNVsZi7NOYDgVZSIJ8LbA==";
};

เพิ่มไฟล์คอนฟิกของคีย์ลงใน named.conf.local
# vi ../named.conf.local

...
include "/etc/bind/example.com/dnskeys.conf";
...

งานต่อไปเป็นงานซ้ำของเก่าคือสร้างโซนไฟล์ และรีเวิร์สไฟล์ และคอนฟิกไฟล์ โดยปรับเปลี่ยนค่าคอนฟิกไฟล์ตรงคำสั่ง allow-update เท่านั้น

สร้างโซนไฟล์ชื่อ example.com.zone เหมือนเดิม
# vi example.com.zone

$TTL    86400
@          IN      SOA    server1.example.com.    root.server1.example.com. (
                          51              ; serial (d. adams)
                          3H              ; refresh after 3 hours
                          15M             ; retry after 15 minutes
                          1W              ; expire after 7 days
                          1D )            ; minimum TTL (Time To Live) of 1 days
@          IN      NS      ns1.example.com.    ; primary NS
@          IN      NS      ns2.example.com.    ; secondary NS

ns1        IN      CNAME  server1

; append or edit host ip here
server1  IN      A      192.168.1.1
ns2      IN      A      192.168.1.2
client1  IN      A      192.168.1.101
client2  IN      A      192.168.1.102
client3  IN      A      192.168.1.103

สร้างรีเวิร์สไฟล์ชื่อ example.com.reverse เหมือนเดิม
# vi example.com.reverse

$TTL    86400
@          IN      SOA    server1.example.com.    root.server1.example.com. (
                          51              ; serial (d. adams)
                          3H              ; refresh after 3 hours
                          15M             ; retry after 15 minutes
                          1W              ; expire after 7 days
                          1D )            ; minimum TTL (Time To Live) of 1 days
@          IN      NS      ns1.example.com.    ; primary NS
@          IN      NS      ns2.example.com.    ; secondary NS

; append or edit host name here
1        IN      PTR    server1.example.com.
2        IN      PTR    ns2.example.com.
101      IN      PTR    client1.example.com.
102      IN      PTR    client2.example.com.
103      IN      PTR    client3.example.com.

สร้างคอนฟิกไฟล์ชื่อ example.com.conf โดยกำหนดให้สามารถเปลี่ยนแปลงค่าไอพีได้ (allow-update)
# vi example.com.conf

zone "example.com" IN {
    type master;
    file "/etc/bind/example.com/example.com.zone";
    allow-update { key "server1.example.com."; };
};
zone "1.168.192.in-addr.arpa" IN {
    type master;
    file "/etc/bind/example.com/example.com.reverse";
    allow-update { key "server1.example.com."; };
};

เพิ่มค่าคอนฟิกไฟล์ให้ระบบรับรู้ โดยเติมลงใน named.conf.local
# vi ../named.conf.local

...
include "/etc/bind/example.com/example.com.conf";

แก้ไขให้กรุ๊ป bind เขียนลงโซนไฟล์ รีเวิร์สไฟล์ และในไดเรกทอรี่นี้ได้ ทั้งนี้เพื่อประโยชน์ตอนอัปเดตค่าไอพี
# chmod g+w example.com.zone example.com.reverse
# chmod g+w ../example.com

เมื่อเสร็จเรียบร้อยแล้ว ก็สั่งเริ่ม bind9 ใหม่
# /etc/init.d/bind9 restart

ติดตั้ง ntpdate ซึ่งต้องใช้ตอนอัปเดตไอพี
# aptitude install ntpdate

จบการติดตั้งแค่นี้ครับ
ต่อไปเป็นการทดสอบการอัปเดตค่าไอพี
ก่อนอื่นต้องซิงก์เวลาก่อน ผมลองใช้เซิร์ฟเวอร์ที่ thaicert
# ntpdate -s -b clock.thaicert.nectec.or.th

อัปเดตโดยนำไฟล์ private key มาใช้
# nsupdate -k Kserver1.example.com.+157+49285.private -d
ทดลองเปลี่ยนค่า server1.example.com เป็น 192.168.1.4

server localhost
zone example.com.
update delete server1.example.com.
update add server1.example.com. 60 IN A 192.168.1.4
send
quit

ตัวอย่างหน้าจอภาพเครื่องทดสอบ

Sending update to 127.0.0.1#53
Outgoing update query:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id:  11566
;; flags: ; ZONE: 1, PREREQ: 0, UPDATE: 2, ADDITIONAL: 1
;; ZONE SECTION:
;example.com.                   IN      SOA

;; UPDATE SECTION:
server1.example.com.    0       ANY     ANY
server1.example.com.    60      IN      A       192.168.1.4

;; TSIG PSEUDOSECTION:
server1.example.com.    0       ANY     TSIG    hmac-md5.sig-alg.reg.int. 1165632027 300 16 yjgvsLCdFobUj/p7lex21g== 11566 NOERROR 0


Reply from update query:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id:  11566
;; flags: qr ra ; ZONE: 0, PREREQ: 0, UPDATE: 0, ADDITIONAL: 1
;; TSIG PSEUDOSECTION:
server1.example.com.    0       ANY     TSIG    hmac-md5.sig-alg.reg.int. 1165632027 300 16 j9mG82rwthDTBJyCopHyUw== 11566 NOERROR 0

ตรงฟิลด์ status ต้องเป็น NOERROR การทำงานจึงจะสมบูรณ์ครับ

ทดลองค้นค่า server1.example.com
# nslookup server1.example.com localhost

Server:         localhost
Address:        127.0.0.1#53

Name:   server1.example.com
Address: 192.168.1.4

เรียบร้อยแล้วครับ

หมายเหตุ

  • ในระหว่างการทำงานอัปเตด โปรแกรมจะสร้างโซนไฟล์สำรองขึ้นมาในชื่อว่า example.com.zone.jnl
  • เมื่อสั่งเริ่ม bind9 ใหม่ จะพบว่าเนื้อหาของโซนไฟล์ถูกเปลี่ยนแปลงไปตามการอัปเดต
  • ส่วนการอัปเดตรีเวิร์สไฟล์ด้วย ยังทำไม่เป็นครับ :)
  • ใจจริง อยากปรับเปลี่ยนเนื้อโซนไฟล์กับรีเวิร์สไฟล์ ให้เอาเรื่อง ลูกเล่นของ BIND9 DNS Server! มารวมเสียทีเดียว แต่กลัวตัวเองงง เลยปล่อยไว้อย่างเดิม :)

หมายเหตุ 2
ข้อเขียนนี้เป็นเพียงการทดลองเท่านั้น แต่ใจสู้เขียน ด้วยค้นหาวิธีการแบบง่าย ๆ ไม่พบ (step by step) เลยต้องทดลองเอง และต้องการบันทึกผลการทดลองที่สามารถใช้งานได้แล้ว ดังนั้นจึงยังไม่ทราบผลข้างเคียงเรื่องความปลอดภัย และความถูกต้องตามระเบียบแบบแผนที่ควรเป็น
จึงต้องการขอคอมเมนต์และคำแนะนำเพื่อให้ได้รู้เรื่องกันในวงกว้างครับ
(ก่อนหน้านี้ เวลาต้องการอัปเดตเลขไอพี ผมใช้สคริปต์ในการสร้างโซนไฟล์ และรีเวิร์สไฟล์ขึ้นมาใหม่ แลัวจึงสั่งเริ่ม bind9 ใหม่ จึงไม่มีปัญหาเรื่องความปลอดภัยมาเกี่ยว)

อ้างอิง