คอนฟิก BIND DNS เก็บข้อมูลโซนโดเมนไว้ใน SQLite บน CentOS 7

จากบทความ คอนฟิกเซิร์ฟเวอร์ BIND DNS บน CentOS 7 – ตอนที่ 2 เพิ่มโซนโดเมน ที่ผ่านมา หลังจากที่เราตัดสินใจตั้งเซิร์ฟเวอร์ DNS เพื่อเก็บข้อมูลโดเมนของเราเองแล้วนั้น หากมีการแก้ไขข้อมูลของโดเมน เช่นมีการเพิ่มหรือเปลี่ยนแปลง ชื่อ (hostname) กับ IP Address หรือข้อมูลอื่น ก็ต้องมีการแก้ไขไฟล์โซนของโดเมนนั้นๆ

ดีฟอลต์จากการติดตั้ง BIND ผู้ดูแลระบบต้องแก้ไขคอนฟิกโซนโดเมน ในรูปแบบการแก้ไขไฟล์ โดยใช้ editor เช่น vi หรือ nano และหลังการแก้ไขเสร็จสิ้น ก็ต้องรีสตาร์ตเซอร์วิส named ใหม่

เพื่อชีวิตที่ง่ายขึ้นของผู้ดูแลระบบ ในที่นี้ขอแนะนำการคอนฟิก BIND ให้เก็บข้อมูลโซนโดเมน ไว้ในรูปแบบฐานข้อมูล (SQLite) เวลาแก้ไขข้อมูล ก็ปรับปรุงข้อมูลในฐานข้อมูลโดยตรง แต่หลังแก้ไขเสร็จสิ้นแล้ว ไม่จำเป็นต้องรีสตาร์ตเซอร์วิส named ใหม่อีกครั้ง

ลองมาดูวิธีการคอนฟิกกัน

ก่อนอื่น ปิดเซอร์วิส named ก่อน

[root@cent7 ~]# systemctl stop named

ติดตั้งแพ็กเกจชื่อ bind-sdb

[root@cent7 ~]# yum install bind-sdb

แพ็กเกจ bind-sdb (Simplified Database Backend) จะรองรับการเก็บข้อมูลของโซนไว้ใน LDAP Server (ldapdb), PostgreSQL (pgsqldb), SQLite (sqlitedb) และอื่นๆ

เพื่อความง่าย ในที่นี้จะยกตัวอย่างการคอนฟิกให้เก็บข้อมูลโซนไว้ใน SQLite

จากการติดตั้งแพ็กเกจ bind-sdb จะมีโปรแกรม zone2sqlite ช่วยในการแปลงข้อมูลโซนจากไฟล์ ไปเป็นรูปแบบไฟล์ sql เพื่อใช้สร้างตาราง (CREATE TABLE) และเพิ่มข้อมูล (INSERT) ลงไปในฐานข้อมูล SQLite ได้

เนื่องจาก SQLite เก็บฐานข้อมูลในรูปแบบไฟล์ ในที่นี้จะสร้างไฟล์ .sqlite ไว้ในไดเรกทอรี /var/named/ ที่เดียวกันกับไฟล์โซน

[root@cent7 ~]# cd /var/named/
[root@cent7 named]#

รูปแบบการใช้คำสั่ง zone2sqlite

[root@cent7 named]# zone2sqlite
usage: zone2sqlite <zone> <zonefile> <dbfile> <dbtable>

คำอธิบาย

  • <zone> ชื่อโซนโดเมน เช่นในที่นี้คือ example.com
  • <zonefile> ชื่อไฟล์ที่เก็บข้อมูลโซน
  • <dbfile> ชื่อไฟล์สำหรับเก็บฐานข้อมูล SQLite ในที่นี้เพื่อให้แยกแยะความแตกต่างได้ง่าย จะตั้งชื่อไฟล์ลงท้าย .sqlite
  • <dbtable> ชื่อตาราง (table) ที่ใช้เก็บในฐานข้อมูล

ตัวอย่างการรันคำสั่ง zone2sqlite เพื่อแปลงข้อมูลโซนไฟล์ ของโดเมน example.com

[root@cent7 named]# zone2sqlite example.com example.com.zone example.com.sqlite example_com
Connecting to 'example.com.sqlite'
DROP TABLE 'example_com'
CREATE TABLE 'example_com' (NAME TEXT, TTL INTEGER, RDTYPE TEXT, RDATA TEXT)
INSERT INTO 'example_com' (NAME, TTL, RDTYPE, RDATA) VALUES ('example.com', 86400, 'SOA', 'ns1.example.com. hostmaster.example.com. 2015081201 21600 3600 604800 86400')
INSERT INTO 'example_com' (NAME, TTL, RDTYPE, RDATA) VALUES ('example.com', 86400, 'NS', 'ns1.example.com.')
INSERT INTO 'example_com' (NAME, TTL, RDTYPE, RDATA) VALUES ('ns1.example.com', 86400, 'A', '192.168.1.1')
INSERT INTO 'example_com' (NAME, TTL, RDTYPE, RDATA) VALUES ('www.example.com', 86400, 'A', '192.168.1.3')

ลองใช้คำสั่ง sqlite3 ดูข้อมูลในไฟล์ฐานข้อมูลที่ถูกสร้างขึ้น

[root@cent7 named]# sqlite3 example.com.sqlite
SQLite version 3.7.17 2013-05-20 00:56:22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> SELECT * FROM example_com;
example.com|86400|SOA|ns1.example.com. hostmaster.example.com. 2015081201 21600 3600 604800 86400
example.com|86400|NS|ns1.example.com.
ns1.example.com|86400|A|192.168.1.1
www.example.com|86400|A|192.168.1.3

แก้ไขไฟล์คอนฟิก named.conf ให้โซน example.com มาอ่านฐานข้อมูล (database) ในตารางชื่อ example_com จากไฟล์ example.com.sqlite แทน

[root@cent7 ~]# vi /etc/named.conf
...
zone "." IN {
 type hint;
 file "named.ca";
};

zone "example.com" IN {
 type master;
 // file "example.com.zone";
 database "sqlite /var/named/example.com.sqlite example_com";
 allow-update { none; };
};

ในตัวอย่างข้างบน จะใช้เครื่องหมาย // นำหน้าบรรทัดคอนฟิกเดิม (file) ไว้ เพื่อเป็นการอ้างอิง โดยคอนฟิกที่ตามหลังเครื่องหมายนี้จะไม่มีผล

เซอร์วิส named เดิม จะไม่รองรับการคอนฟิกแบบ sdb ต้องเปลี่ยนชื่อเซอร์วิสในการสตาร์ตใหม่ เป็น named-sdb

[root@cent7 ~]# systemctl start named-sdb

ลองใช้คำสั่ง dig เพื่อถามข้อมูลจากเซิร์ฟเวอร์

[alice@cent7 ~]$ dig @localhost www.example.com

; <<>> DiG 9.9.4-RedHat-9.9.4-18.el7_1.3 <<>> @localhost www.example.com
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63725
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.example.com. IN A

;; ANSWER SECTION:
www.example.com. 86400 IN A 192.168.1.3

;; AUTHORITY SECTION:
example.com. 86400 IN NS ns1.example.com.

;; ADDITIONAL SECTION:
ns1.example.com. 86400 IN A 192.168.1.1

;; Query time: 0 msec
;; SERVER: ::1#53(::1)
;; WHEN: Thu Aug 13 19:30:45 ICT 2015
;; MSG SIZE rcvd: 94

หากต้องการแก้ข้อมูลในโดเมน ก็ทำผ่าน sqlite โดยเพิ่มข้อมูลเข้าไปในตาราง example_com ซึ่งก็คือข้อมูลของโดเมน example.com

ตัวอย่างการเพิ่มชื่อกับ IP Address ใหม่ ของโดเมน

[root@cent7 ~]# sqlite3 /var/named/example.com.sqlite

sqlite> INSERT INTO example_com VALUES ('mail.example.com', 86400, 'A', '192.168.1.4');

ลองใช้คำสั่ง dig ถามข้อมูลที่เพิ่งเพิ่มเข้าไป โดยไม่ต้องรีสตาร์ตเซอร์วิส named-sdb

[alice@cent7 ~]$ dig @localhost mail.example.com

; <<>> DiG 9.9.4-RedHat-9.9.4-18.el7_1.3 <<>> @localhost mail.example.com
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25452
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;mail.example.com. IN A

;; ANSWER SECTION:
mail.example.com. 86400 IN A 192.168.1.4

;; AUTHORITY SECTION:
example.com. 86400 IN NS ns1.example.com.

;; ADDITIONAL SECTION:
ns1.example.com. 86400 IN A 192.168.1.1

;; Query time: 0 msec
;; SERVER: ::1#53(::1)
;; WHEN: Thu Aug 13 19:35:36 ICT 2015
;; MSG SIZE rcvd: 95

ลองนำไปปรับใช้กันดูนะครับ และถ้าคุณเขียนโปรแกรมได้ หรือมีโปรแกรมเมอร์ที่เขียนเว็บได้ อาจลองเขียนโปรแกรมให้แก้ไขข้อมูล DNS บนหน้าเว็บได้เลย

ข้อมูลอ้างอิง

Leave a Reply

Your email address will not be published.