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: