PHP 7 ZTS on CentOS (PowerDNS as RBL)

ล่าสุด setup เครื่องนึง สำหรับทำหน้าที่เช็ค RBL (Realtime Blackhole List) เพื่อจะให้อีเมลเซิร์ฟเวอร์ทุกเครื่องมาเช็คผ่านตรงนี้. สาเหตุจริงๆ ที่ต้องทำแบบนี้เป็นเพราะว่า IP DNS ของ IDC บางที่โดน RBL บางที่บล็อคไม่ให้ใช้งาน ก็เลยตั้งใจมาเปิดเครื่องนึงสำหรับทำหน้าที่นี้โดยเฉพาะแล้วกัน โดยวางไว้ที่ IDC ที่ไม่โดน RBL บล็อค จะได้เช็คได้ครบทุกที่ แล้วเซิร์ฟเวอร์ที่อื่นก็มาวานให้เจ้าตัวนี้มันเป็นผู้ตรวจสอบให้.

ตัวเซิร์ฟเวอร์ติดตั้งเป็น PowerDNS + Pipe backend โดยเขียน php script เพื่อไปเช็คกับ RBL แต่ละที่. ตอนแรกเขียนเป็น for loop ง่ายๆ ในการไล่เช็คกับ RBL แต่ละที่ แต่ปัญหา คือ มันทำให้ response time ของเรามันนานเกินไป. เพื่อที่จะแก้ปัญหานี้ เราเลยลองหาวิธีเขียน pararell บน PHP เพื่อให้มันเช็ค RBL ทุกๆ ที่ไปพร้อมๆ กันเลย  เป็นครั้งแรกที่ใช้ PHP แบบนี้ ก็เลยจะบันทึกเก็บไว้หน่อยแล้วกัน.

ในการติดตั้ง PHP 7 เราใช้ yum เลย โดยใช้ repo ของ webtatic สะดวก สบาย~~~. สำหรับการเขียน pararell บน PHP เราเจอว่าวิธีที่มันเป็น pararell จริงๆ ต้องใช้ pthreads . แต่ตัว pthreads เนี่ย มันต้องใช้ PHP ที่เป็น ZTS (Zen thread safety) ซึ่งที่ผ่านมา เราติดตั้ง/ใช้งาน PHP  แบบ NTZ มาตลอด ก็เลยเสียเวลานานเลย พยายามหาวิธีที่จะติดตั้ง PHP ZTS และแล้วก็ถึงบางอ้อ ว่าที่เราหาข้อมูลไม่ค่อยได้ เพราะว่า ตอนติดตั้ง PHP 7 (php70w) จาก repo webtatic เนี่ย คือมันได้ติดตั้ง PHP ZTS มาด้วยเลย (เป็นสาเหตุที่ มันแทบไม่มีใครพูดถึงวิธีการติดตั้ง PHP ZTS เลย -_-” ). สรุปก็คือถ้าจะใช้ ZTS ก็ใช้คำสั่ง zts-php แทนคำสั่ง php ได้เลย ( กรณีงานนี้ เราใช้ CLI เป็น SAPI ).  ซึ่งเวลาจะ compile from source ตรงขั้นตอนที่จะต้องใช้ phpize ก็สามารถใช้ zts-phpize ได้เลยเช่นกัน.

สำหรับคำสั่งที่ใช้ตอน compile pthreads ก็ประมาณนี้ (ไม่รู้ copy มาครบมั้ย เพราะนี้แกะๆ มาจาก history ในเซิร์ฟเวอร์)

cd /tmp
git clone https://github.com/krakjoe/pthreads.git
cd pthreads<br>zts-phpize
./configure --with-php-config=/usr/bin/zts-php-config
make<br>cp modules/pthreads.so /usr/lib64/php-zts/modules/
echo 'extension=pthreads.so' > /etc/php-zts.d/pthreads.ini

ที่มาเขียนบล็อคนี้ เพราะว่าแค่อยากจะบันทึกเรื่องการติดตั้ง ZTS เท่านั้นเองนะ แต่ไหนๆ แล้วเขียนประเด็นอื่นที่เจอวันนี้ไปด้วยแล้วกัน

ปัญหาฟังก์ชั่น gethostbyname

ถ้าใช้ gethostbyname ในการเช็ค RBL เราจะไม่สามารถกดหนด timeout ได้ เราเลยจะเอามาใช้ไม่ได้ เพราะว่าเราต้องควบคุม response time ของ powerdns เราด้วย ดังนั้นเราจึงไปใช้คำสั่งนี้แทนในการเช็ค ซึ่งกำหนดได้ทั้ง timeout และ retry (ใช้ nslookup ก็ได้ ลอง google โลด)

dig +time=1 +tries=1 ${hostname} A

code ส่วนที่ตรวจสอบ RBL ของเราก็จะประมาณนี้

<?php
$query = `dig +time=1 +tries=1 {$this->hostname} A`;
if (preg_match('/^'.$this->hostname.'.\s+(?<ttl>\d+)\s+IN\s+A\s(?<response>.*)\n/m', $query, $matches)) {
    $this->response = $matches['response'];
}
else {
    $this->response = false;
}

เพิ่งรู้จัก Sudoers

โตมากับสาย CentOS เวลาติดตั้ง OS เสร็จ ก็ใช้งานแบบเป็น root ตลอด ไม่เคยใช้ sudo เลย.  วันนี้ตอนท้ายงาน พยายามจะ monitor การทำงานของ PowerDNS ด้วย Zabbix ก็เลยจำเป็นจะต้องให้ user zabbix มันสามารถ execute คำสั่ง /usr/bin/pdns_control นี้ให้ได้. ถ้าเป็นสมัยก่อน คงจะ chmod ไฟล์นั้นไปแบบเถื่อนๆ แต่วันนี้ได้มารู้จักกับ Sudoers ซึ่งทำให้ user zabbix สามารถ sudo เพื่อรันคำสั่งที่เราต้องการได้.

ติดตั้ง sudo ก่อน

yum install sudo

เสร็จแล้วเราจะมีคำสั่งนี้ให้ใช้แก้ไฟล์ /etc/sudoers (ในเน็ตบอกว่าอย่าเอา text editor ไปแก้ไฟล์นี้เองโดยตรง ให้แก้ผ่านคำสั่งของมันเท่านั้น)

visudo

เราก็ไปเติม config นี้ที่ท้ายไฟล์ เพื่ออนุญาตให้ user zabbix ใช้ sudo เพื่อรันคำสั่งที่ระบุได้

zabbix ALL=NOPASSWD: /usr/bin/pdns_control
zabbix ALL=NOPASSWD: /usr/bin/rec_control

เวลา user zabbix จะรันคำสั่ง /usr/bin/pdns_control ก็ให้เรียกแบบ sudo ก่อน ลักษณะนี้

/usr/bin/sudo /usr/bin/pdns_control

Leave a Reply

Your email address will not be published. Required fields are marked *