จุดประสงค์ของผมคือ ผมมี Server ที่ให้บริการเฉพาะลูกค้าในประเทศไทย ไอพีก็ต้องเป็นของประเทศไทย ผมจึงต้องบล๊อก IP จากต่างประเทศทั้งหมดไม่ให้เข้ามาใน Server ได้ จะได้ไม่มีคนมาคอย Hack หรือมาโจมตี Server ผมได้ ส่วนใหญ่พวกที่ส่งข้อมูลแบบแปลกๆเข้ามา พวกที่คอยเดาพาสเวอร์ด ssh พวกที่คอยเดา Asterisk accounts พวกที่จ้องจะแอบใช้ Asterisk โทรออกฟรีๆ จะมาจากต่างประเทศเกือบ 100% ครับ
จริงๆเทคนิคมันก็ไม่ได้มีอะไรยุ่งยากครับ เขียน iptables rule แค่บรรทัดเดียวก็สามารถ Deny หรือ Allow ไอพีได้ทั้งประเทศแล้ว โดยอาศัยการทำงานของ iptables ร่วมกับ GeoIP ซึ่ง GeoIP นี้นะครับผมเรียกมันว่าเป็นฐานข้อมูลใหญ่ที่คอยเก็บว่าไอพีนี้อยู่ในประเทศอะไร
มีบทความเกี่ยวกับ iptables + GeoIP เยอะแยกมากมายในเน็ต ผมก็เอามาจากบทความเหล่านั้นแหล่ะครับ แต่เทสจนเวอร์คแล้วสรุปเป็นขั้นตอนง่ายๆแบบ Step-by-Step มาให้พวกเราได้ลองอ่าน ลองทำกันดู รับประกันว่าเวอร์คแน่นอนครับ
** ข้อตกลง **
1. บทความนี้ใช้ได้กับ CentOS 5.x ได้ทั้ง x86_64 และ i386
2. ใช้ได้กับ Asterisk (ถ้าในเครื่องมีการ์ด Asterisk จะต้องคอมไพล์ DAHDI ใหม่)
3. ใช้ได้กับ Elastix/Trixbox (ถ้าในเครื่องมีการ์ด Asterisk จะต้องคอมไพล์ DAHDI ใหม่)
4. ใช้ไม่ได้กับ VOS3000
เมื่อเข้าใจถึงข้อตกลงแล้วก็มาเริ่มลงมือทำกันเลยครับ
1. ติดตั้ง kernel-ml
ต้องเป็น kernel ตัวที่ผมจะให้โหลดต่อไปนี้นะครับ ตัวเก่าที่ติดตั้งมาพร้อมกับ CentOS ใช้ไม่ได้ครับ เวอร์ชั่นอาจจะเปลี่ยนไปจากตัวที่ผมใช้งานอยู่ เช็คเวอร์ชั่นใหม่ๆได้จากเว็บไซต์นี้ http://elrepo.org/linux/kernel/el5
สำหรับ CentOS x86_64
- โค้ด: เลือกทั้งหมด
wget http://elrepo.org/linux/kernel/el5/x86_64/RPMS/kernel-ml-2.6.39-4.el5.elrepo.x86_64.rpm
wget http://elrepo.org/linux/kernel/el5/x86_64/RPMS/kernel-ml-headers-2.6.39-4.el5.elrepo.x86_64.rpm
wget http://elrepo.org/linux/kernel/el5/x86_64/RPMS/kernel-ml-devel-2.6.39-4.el5.elrepo.x86_64.rpm
หรือจะโหลดจากเว็บนี้ก็ได้
- โค้ด: เลือกทั้งหมด
wget http://www.voip4share.com/sources/kernel-ml-2.6.39-4.el5.elrepo.x86_64.rpm
wget http://www.voip4share.com/sources/kernel-ml-headers-2.6.39-4.el5.elrepo.x86_64.rpm
wget http://www.voip4share.com/sources/kernel-ml-devel-2.6.39-4.el5.elrepo.x86_64.rpm
สำหรับ CentOS i386
- โค้ด: เลือกทั้งหมด
wget http://elrepo.org/linux/kernel/el5/i386/RPMS/kernel-ml-2.6.39-4.el5.elrepo.i686.rpm
wget http://elrepo.org/linux/kernel/el5/i386/RPMS/kernel-ml-devel-2.6.39-4.el5.elrepo.i686.rpm
wget http://elrepo.org/linux/kernel/el5/i386/RPMS/kernel-ml-headers-2.6.39-4.el5.elrepo.i386.rpm
หรือจะโหลดจากเว็บนี้ก็ได้
- โค้ด: เลือกทั้งหมด
wget http://www.voip4share.com/sources/kernel-ml-2.6.39-4.el5.elrepo.i686.rpm
wget http://www.voip4share.com/sources/kernel-ml-devel-2.6.39-4.el5.elrepo.i686.rpm
wget http://www.voip4share.com/sources/kernel-ml-headers-2.6.39-4.el5.elrepo.i386.rpm
2. ลบ kernel-headers ตัวเก่าออก
- โค้ด: เลือกทั้งหมด
rpm -e kernel-headers --nodeps
3. ติดตั้ง kernel-ml
เครื่องผมเป็น CentOS x64_64 จึงต้องใช้แบบ x86_64
- โค้ด: เลือกทั้งหมด
rpm -ivh kernel-ml-2.6.39-4.el5.elrepo.x86_64.rpm
rpm -ivh kernel-ml-devel-2.6.39-4.el5.elrepo.x86_64.rpm
rpm -ivh kernel-ml-headers-2.6.39-4.el5.elrepo.x86_64.rpm
4. Patch ไฟล์ /etc/rc.d/rc.sysinit
ต้อง Patch ไฟล์นี้ด้วยครับไม่อย่างนั้น kernel-ml ตัวใหม่จะเรียกใช้งาน Hardware clock ไม่ได้
โหลดไฟล์ Patch Script ที่ผมเตรียมไว้ให้แล้ว
- โค้ด: เลือกทั้งหมด
cd /tmp
wget http://www.voip4share.com/sources/rc.sysinit-rtc.el5.elrepo.patch
- โค้ด: เลือกทั้งหมด
cp /etc/rc.d/rc.sysinit /etc/rc.d/rc.sysinit.backup
patch -p0 /etc/rc.d/rc.sysinit < /tmp/rc.sysinit-rtc.el5.elrepo.patch
โดยข้อมูลในไฟล์ rc.sysinit-rtc.el5.elrepo.patch เป็นแบบนี้ครับ
- โค้ด: เลือกทั้งหมด
--- rc.sysinit.distro 2010-07-02 16:16:45.000000000 +0100
+++ rc.sysinit 2010-12-18 16:34:13.000000000 +0000
@@ -269,6 +269,18 @@ if [ "$PROMPT" != "no" ]; then
echo
fi
+### ELREPO: See if the RTC driver is built-in, otherwise load it
+if [ ! -f /proc/driver/rtc ]; then
+ action $"Loading rtc_cmos driver: " /sbin/modprobe rtc_cmos
+fi
+
+### ELREPO: Make the newer device nodes to accomodate hwclock
+RTC_MAJOR_NO=`/bin/awk '/rtc/ { print $1 }' /proc/devices`
+if [ -n "$RTC_MAJOR_NO" ]; then
+ action $"Creating /dev/rtc0: " /bin/mknod /dev/rtc0 c $RTC_MAJOR_NO 0
+ action $"Creating /dev/rtc: " /bin/ln -sf /dev/rtc0 /dev/rtc
+fi
+
# Set the system clock.
update_boot_stage RCclock
ARC=0
5. แก้ไขลำดับบู๊ต kernel ในไฟล์ /boot/grub/grub.conf
- โค้ด: เลือกทั้งหมด
vi /boot/grub/grub.conf
- โค้ด: เลือกทั้งหมด
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title CentOS (2.6.39-4.el5.elrepo)
root (hd0,0)
kernel /vmlinuz-2.6.39-4.el5.elrepo ro root=/dev/VolGroup00/LogVol00
initrd /initrd-2.6.39-4.el5.elrepo.img
title CentOS (2.6.18-238.12.1.el5)
root (hd0,0)
kernel /vmlinuz-2.6.18-238.12.1.el5 ro root=/dev/VolGroup00/LogVol00
initrd /initrd-2.6.18-238.12.1.el5.img
title Elastix (2.6.18-194.3.1.el5)
root (hd0,0)
kernel /vmlinuz-2.6.18-194.3.1.el5 ro root=/dev/VolGroup00/LogVol00
initrd /initrd-2.6.18-194.3.1.el5.img
เครื่องผมมี kernel ติดตั้งอยู่ตอนนี้ 3 เวอร์ชั่น คือ 2.6.39-4.el5.elrepo ซึ่งเป็นอันที่ได้จากการติดตั้ง kernel-ml เมื่อกี้นี้ ส่วนอีก 2 อันที่เหลือเป็น kernel ตัวเก่า สังเกตุลำดับการเรียงบรรทัดของ kernel นะครับ อันบนสุดมีลำดับเป็น 0 อันที่สองและสามมีลำดับเป็น 1 และ 2 ตามลำดับ
ดังนั้นถ้าผมต้องการให้โหลด kernel 2.6.39-4.el5.elrepo ผมก็ต้องแก้ไขบรรทัด default นะครับ เป็น default=0 เซฟไฟล์แล้วรีบู๊ตเครื่อง
- โค้ด: เลือกทั้งหมด
reboot
6. เช็คเวอร์ชั่น kernel
- โค้ด: เลือกทั้งหมด
uname -r
ผลลัพท์
2.6.39-4.el5.elrepo
แสดงว่า Kernel เปลี่ยนเป็นเวอร์ชั่นใหม่แล้ว
7. เช็คว่า kernel สามารถเข้าถึง hardware clock ได้หรือไม่
- โค้ด: เลือกทั้งหมด
/sbin/hwclock --debug
ถ้าได้ข้อความคล้ายๆแบบนี้ แสดงว่า kernel ติดต่อกับ hardware clock ได้
- โค้ด: เลือกทั้งหมด
hwclock from util-linux-2.13-pre7
Using /dev/rtc interface to clock.
Last drift adjustment done at 1324436785 seconds after 1969
Last calibration done at 1324436785 seconds after 1969
Hardware clock is on UTC time
Assuming hardware clock is kept in UTC time.
Waiting for clock tick...
/dev/rtc does not have interrupt functions. Waiting in loop for time from /dev/rtc to change
...got clock tick
Time read from Hardware Clock: 2011/12/21 03:09:21
Hw clock time : 2011/12/21 03:09:21 = 1324436961 seconds since 1969
Wed 21 Dec 2011 10:09:21 AM ICT -0.314747 seconds
แต่ถ้าได้ข้อความแบบนี้ แสดงว่า kernel ติดต่อกับ hardware clock ไม่ได้
- โค้ด: เลือกทั้งหมด
hwclock from util-linux-2.13-pre7
hwclock: Open of /dev/rtc failed, errno=19: No such device.
No usable clock interface found.
Cannot access the Hardware Clock via any known method.
ซึ่งถ้า kernel ติดต่อ hardware clock ไม่ได้ ต้องทำการ Patch ไฟล์ /etc/rc.d/rc.sysinit ใหม่ครับ โดยใช้ไฟล์เดิมที่เราได้แบ็คอัพไว้ก่อนหน้านี้แล้ว แบบนี้
- โค้ด: เลือกทั้งหมด
cd /etc/rc.d
rm -rf rc.sysinit
cp rc.sysinit.backup rc.sysinit
patch -p0 < /tmp/rc.sysinit-rtc.el5.elrepo.patch
8. ติดตั้ง Packages เพิ่มเติม
- โค้ด: เลือกทั้งหมด
yum -y install rpm-build redhat-rpm-config unifdef perl-Text-CSV_XS
9. อัพเกรดหรือติดตั้ง iptables
- โค้ด: เลือกทั้งหมด
yum -y install iptables iptables-devel
หรือดาวน์โหลดและติดตั้งจากเว็บนี้ก็ได้ครับ เป็น iptables 1.4.9 ซึ่งใหม่กว่า โดยผมดาวน์โหลด Source RPM จากลิ้งค์นี้ wget http://web.bethere.co.uk/ic/iptables-1.4.9-1.src.rpm แล้วใช้ rpmbuild ทำเป็นไฟล์ RPM
สำหรับ CentOS x86_64
- โค้ด: เลือกทั้งหมด
rpm -Uvh 'http://www.voip4share.com/sources/iptables-1.4.9-1.x86_64.rpm'
rpm -Uvh 'http://www.voip4share.com/sources/iptables-devel-1.4.9-1.x86_64.rpm'
และสำหรับ CentOS i386
- โค้ด: เลือกทั้งหมด
rpm -Uvh 'http://www.voip4share.com/sources/iptables-1.4.9-1.i386.rpm'
rpm -Uvh 'http://www.voip4share.com/sources/iptables-devel-1.4.9-1.i386.rpm'
10. ติดตั้ง xz
xz เป็นโปรแกรมประเภทบีบอัดไฟล์ ซึ่งบีบได้เล็กกว่า gz 30 เท่า และ bz2 15 เท่า
สำหรับ CentOS x86_64
- โค้ด: เลือกทั้งหมด
yum -y install xz xz-devel.x86_64 xz-libs xz-lzma-compat
สำหรับ CentOS i386
- โค้ด: เลือกทั้งหมด
yum -y install xz zx-devel xz-libs xz-lzma-compat
11. ติดตั้ง xtables-addons
เวอร์ชั่น 1.31
- โค้ด: เลือกทั้งหมด
wget http://www.voip4share.com/sources/xtables-addons-1.31.tar.bz2
tar xvf xtables-addons-1.31.tar.bz2 -C /usr/src
cd /usr/src/xtables-addons-1.31
./configure --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --sysconfdir=/etc --localstatedir=/var
make && make install
12. ติดตั้ง xtables-geoip
ทั้ง CentOS x86_64 และ i386 ใช้ไฟล์เดียวกันครับ
- โค้ด: เลือกทั้งหมด
rpm -ivh 'http://www.voip4share.com/sources/xtables-geoip-2010.11-1.noarch.rpm'
13. สร้างไฟล์ /etc/sysconfig/iptables
ผมมีตัวอย่างไฟล์คอนฟิกของ iptables ครับ
- โค้ด: เลือกทั้งหมด
# Firewall configuration written by system-config-securitylevel
# Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:RH-Firewall-1-INPUT - [0:0]
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
-A RH-Firewall-1-INPUT -p icmp --icmp-type any -m geoip --src-cc TH -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m udp -p udp -m geoip --src-cc TH --dport 1000:65535 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW,ESTABLISHED,RELATED -p tcp -m multiport -m geoip --src-cc TH --dport 22,80,443,8880 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A RH-Firewall-1-INPUT -j DROP
COMMIT
สังเกตุว่ามี -m geoip แล --src-cc TH เพิ่มขึ้นมา ซึ่งจะเช็ค source ip address ว่าอยู่ใน Thailand หรือไม่
อีกตัวอย่างนึงครับ ซึ่งจะมีเฉพาะไอพีใน Thailand เท่านั้นที่ ping, คอนเน็คพอร์ต 22 และ 80 ได้
- โค้ด: เลือกทั้งหมด
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:RH-Firewall-1-INPUT - [0:0]
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
-A RH-Firewall-1-INPUT -p icmp --icmp-type any -m geoip --src-cc TH -j ACCEPT
-A RH-Firewall-1-INPUT -m state -p tcp -m multiport -m geoip --src-cc TH --dport 22,80 -j ACCEPT
-A RH-Firewall-1-INPUT -i eth0 -j ACCEPT
-A RH-Firewall-1-INPUT -j DROP
COMMIT
อีกตัวอย่างนึง ให้เฉพาะไอพีใน Thailand เท่านั้นที่คอนเน็คได้
- โค้ด: เลือกทั้งหมด
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:RH-Firewall-1-INPUT - [0:0]
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
-A RH-Firewall-1-INPUT -i eth0 -m geoip --src-cc TH -j ACCEPT
-A RH-Firewall-1-INPUT -j DROP
COMMIT
ถ้าจะเพิ่มไอพีจากประเทศ Singapore ด้วย ก็ใส่แบบนี้
- โค้ด: เลือกทั้งหมด
-A RH-Firewall-1-INPUT -i eth0 -m geoip --src-cc TH,SG -j ACCEPT
ถ้าจะ Deny ก็เปลี่ยน ACCEPT เป็น DROP ครับ
14. รัน iptables แบบเป็น service และสตาร์ท iptables
- โค้ด: เลือกทั้งหมด
chkconfig iptables on
service iptables start
เป็นอันว่าเทคนิคการใช้งาน iptables ร่วมกับ geoip ก็มีเท่านี้ครับ หวังว่าคงจะตอบสนองความต้องการของท่านที่ต้องการใช้งานไม่มากก็น้อยครับ ลองปรับ rules ให้เหมาะสมกับความต้องการใช้งานได้
บทความที่เกี่ยวข้อง
โปรแกรม iptables
เทคนิคการเพิ่มความปลอดภัยให้ Asterisk/Elastix