|
|
|||||||
Linux 2.4 Stateful Firewall : IPTABLES
เรียบเรียงโดย : ภูวดล ด่านระหาญ
เผยแพร่เมื่อ : 3 ธันวาคม 2544
เอกสารฉบับนี้จะอธิบายถึงการนำ Linux 2.4 มาใช้เป็นไฟร์วอลล์ เพื่อควบคุมการผ่านเข้าออกของ network traffic และเพิ่มความปลอดภัยให้กับระบบ หากยังไม่เข้าใจในเรื่องไฟร์วอลล์ ก็ขอแนะนำให้อ่านบทความเรื่องความรู้พื้นฐานเกี่ยวกับไฟร์วอลล์ หรือหากต้องการทำความรู้จักแบบลึกๆ กับ stateful firewall แล้ว ก็สามารถศึกษาได้จาก http://thaicert.nectec.or.th/paper/firewall/stateful.php เช่นเดียวกัน
ใครควรอ่านบทความฉบับนี้
เหมาะสำหรับผู้ที่มีเครื่องคอมพิวเตอร์จำนวนมากในความดูแล และ/หรือมีการเชื่อมต่อกับอินเทอร์เน็ต
มีเครื่องเซิร์ฟเวอร์เปิดให้บริการกับสาธารณชน เช่น web service, ftp service,
mail service เป็นต้น และต้องการเพิ่มความปลอดภัยให้กับระบบ เนื่องจากไฟร์วอลล์ทำหน้าที่ควบคุมการเข้าออกของข้อมูลใน
port ที่ได้รับอนุญาตเท่านั้น ดังนั้นผู้ที่จะเขียน rule ของไฟร์วอลล์ได้ต้องมีความรู้เกี่ยวกับ
TCP/IP พอสมควร และขอย้ำตรงนี้อีกว่า ไฟร์วอลล์ไม่ใช่อุปกรณ์ป้องกันการบุกรุกระบบที่สมบูรณ์
100% เพราะการโจมตีที่เกิดขึ้นในปัจจุบันนั้นมักจะโจมตีผ่าน port ที่เป็นที่รู้จัก
เช่น 21, 22, 25, 53, 80 ซึ่งไฟร์วอลล์มักจะอนุญาตให้ข้อมูลเข้าออกผ่านทาง port
เหล่านี้เสมอ ดังนั้นควรใช้เครื่องมืออื่นๆ ช่วย เช่น การตั้งนโยบายความปลอดภัยที่รัดกุม
การนำระบบ network intrusion detection มาใช้ หรือแม้แต่มีการจัดการระดับ host
based ที่ดี เช่น มีการทำ hardening OS. ใน NOS(network operating system) ทุกๆ
เครื่องที่เปิดให้บริการแก่สาธารณะ ก็จะช่วยเพิ่มความปลอดภัยให้กับระบบมากยิ่งขึ้น
กล่าวนำ
จากความรู้พื้นฐานเรื่องไฟร์วอลล์ ก็พอจะทราบว่าไฟร์วอลล์ในปัจจุบันนั้นแบ่งเป็นสองชนิดหลักๆ
คือ stateful packet filtering firewall และ proxy server ซึ่งจะมีการตรวจสอบข้อมูลที่ไหลผ่านเข้าออกที่คนละเลเยอร์กัน
โดย packet filtering นั้นจะตรวจสอบข้อมูลที่ network layer และ session layer
ในขณะที่ proxy นั้นสามารถตรวจสอบข้อมูลที่ application layer ได้ด้วย
Linux สามารถใช้งานเป็นไฟร์วอลล์ได้ตั้งแต่เคอร์เนล 1.1 ซึ่งเป็นเวอร์ชันแรก โดย Alan Cox ใช้ชื่อว่า ipfw (จาก BSD) ต่อมา Linux 2.0 ได้ถูกพัฒนาและปรับปรุงได้เครื่องมือที่มีชื่อว่า ipfwadm โดยเครื่องมือชิ้นนี้อนุญาตให้ผู้ใช้สามารถควบคุม filtering rule ได้ และต่อมา Linux 2.2 ก็ได้สร้างเครื่องมือตัวใหม่ชื่อ ipchains ซึ่งเผยแพร่ในปี 1998 โดย Rusty Russel และทีมงาน ทั้งนี้ ipchains นี้ถือได้ว่าเป็นพัฒนาการขั้นที่สามของ Linux Firewall จวบจนกระทั่งในปัจจุบัน ก็มี netfilter และ iptables ซึ่งถือว่าเป็นพัฒนาการขั้นที่สี่ของ Linux Firewall
Netfilter นั้นเป็นชื่อใหม่ของโค้ดที่ทำหน้าที่เป็น packet handler(stateful inspection) ใน Linux kernel 2.4 (จริงคือเวอร์ชัน 2.3.15 และเวอร์ชันต่อๆ มา) ซึ่งได้ถูกออกแบบและปรับปรุงใหม่จากเวอร์ชันก่อนหน้านี้ เป็นเรื่องที่น่ายินดีคือ netfilter นั้นสามารถทำงานย้อนหลังร่วมกับ ipchains และ ipfwadm ได้ และคำสั่งในการเรียกใช้งานคือ iptables
ความแตกต่างระหว่าง iptables และ ipchains
ดาวน์โหลด
ก่อนที่ใช้งานไฟร์วอลล์ตัวใหม่นี้ได้ ให้ล็อกอินเป็น root และทดลองพิมพ์คำว่า iptables
ดูว่าคำสั่งนี้มีอยู่หรือไม่ ถ้าไม่มี ต้องดาวน์โหลดจาก http://netfilter.samba.org
โดยให้ดาวน์โหลดเวอร์ชันล่าสุดมา ในที่นี้คือ iptables-1.2.4.tar.bz2 จากนั้นให้ขยายไฟล์และติดตั้งดังคำสั่งด้านล่าง
tar -jxvf iptables-1.2.4.tar.bz2
cd iptables-1.2.4
make
make install
ปรับแต่งเคอร์เนล
หลังจากที่มีคำสั่ง iptables อยู่ในระบบแล้ว บางระบบที่มีเคอร์เนลต่ำกว่า 2.4 จำเป็นต้องคอมไพล์เคอร์เนลใหม่
เพื่อให้ใช้งาน iptables ได้ ทั้งนี้ขอแนะนำให้ใช้เคอร์เนลเวอร์ชันล่าสุด ปัจจุบันคือ
2.4.14 ซึ่งสามารถดาวน์โหลดได้จาก http://www.kernel.org
หลังจากที่ดาวน์โหลดมาแล้วให้ขยายไฟล์ไปไว้ที่ /usr/src/linux จากนั้นใช้คำสั่ง make menuconfig หรืออาจใช้ make xconfig ในกรณีที่ได้ติดตั้ง XWindows ไว้แล้ว โดยต้องมั่นใจว่าได้ enable option ต่างๆ ด้านล่างนี้ ภายใต้ Networking options
<*> Packet socket
[*] Network packet filtering (replaces ipchains)
<*> Unix domain sockets
[*] TCP/IP networking
[*] IP: advanced router
[*] IP: policy routing
[*] IP: use netfilter MARK value as routing key
[*] IP: fast network address translation
[*] IP: use TOS value as routing key
และภายใต้เมนู "IP: Netfilter Configuration -- >" ให้ enable ทุกออปชันเพื่อให้ใช้งาน netfilter ได้เต็มประสิทธิภาพ
แต่มีอีกจุดหนึ่งที่ห้าม enable ภายใต้ "Networking options" คือ
[ ] IP: TCP Explicit Congestion Notification support
เพราะออปชันนี้ จะทำให้บาง packet ที่ออกจาก linux ถูกเซ็ตบิต ECN ไปด้วย ซึ่งจะทำให้ไม่สามารถสื่อสารกับ internet router บางตัวได้
จากนั้นก็ให้คอมไพล์และติดตั้งเคอร์เนลโดยใช้คำสั่งดังตัวอย่างใน Appendix A
รูปแบบการใช้งาน iptables เบื้องต้น
iptables จะมีรูปแบบการใช้งานดังนี้คือ
iptables [table] <command> <match> <target/jump>
โดย rule ที่เขียนขึ้นจะเป็นเป็นตัวบอกเคอร์เนลว่าให้กระทำ action อย่างไร ในกรณีที่พบ packet ตรงตามที่ระบุไว้
Table
iptables สามารถทำงานได้กับตาราง(table) 3 ตารางหลัก สามารถระบุตารางได้โดยใช้ออปชัน
-t ตามด้วยชื่อ table คือ
Command
การใช้ command ด้านบนนั้นสามารถใช้ร่วมกับออปชันบางอย่างได้ คือ
Match
การตั้งเงื่อนไขของการ match นั้นจะต้องอาศัยความเข้าใจในเรื่อง IP, TCP, UDP,
และ ICMP มาบ้างพอสมควร จึงจะสามารถตั้งเงื่อนไขที่เหมาะสมและตรงตามความต้องการได้
ซึ่งมีรายละเอียดดังนี้
ตาราง แสดงรายละเอียดของ ICMP message
TYPE CODE Description Query Error 0 0 Echo Reply x 3 0 Network Unreachable x 3 1 Host Unreachable 3 2 Protocol Unreachable 3 3 Port Unreachable 3 4 Fragmentation needed but no frag. bit set 3 5 Source routing failed 3 6 Destination network unknown 3 7 Destination host unknown 3 8 Source host isolated (obsolete) 3 9 Destination network administratively prohibited 3 10 Destination host administratively prohibited 3 11 Network unreachable for TOS 3 12 Host unreachable for TOS 3 13 Communication administratively prohibited by filtering 3 14 Host precedence violation 3 15 Precedence cutoff in effect 4 0 Source quelch 5 0 Redirect for network 5 1 Redirect for host 5 2 Redirect for TOS and network 5 3 Redirect for TOS and host 8 0 Echo request x 9 0 Router advertisement 10 0 Route sollicitation 11 0 TTL equals 0 during transit x 11 1 TTL equals 0 during reassembly 12 0 IP header bad (catchall error) 12 1 Required options missing 13 0 Timestamp request (obsolete) 14 0 Timestamp reply (obsolete) 15 0 Information request (obsolete) 16 0 Information reply (obsolete) 17 0 Address mask request 18 0 Address mask reply
ตัวอย่างการใช้ --limit และ --limit-burst ร่วมกัน เช่น
# iptables -A INPUT -m limit --limit 3/minute
--limit-burst 3 -j LOG
โดยส่วนใหญ่นิยมวาง rule นี้ไว้เป็น rule สุดท้ายใน chain โดยเฉพาะ chain
ที่มี default policy เป็น DROP เพื่อเป็นตัวเก็บหลักฐานว่ามี packet ใดที่ถูกส่งมาและไม่ผ่านการตรวจสอบจาก
rule และกำลังจะถูก DROP โดย default policy โดย rule ด้านบนนี้กำหนดจำนวน
match สูงสุดไว้ 3 ครั้งต่อนาที ซึ่งแสดงว่าใน 1 นาทีจะมีการบันทึกล็อกได้สูงสุด
3 ครั้งเท่านั้น และมีค่า burst เท่ากับ 3 ซึ่งอธิบายได้ว่า ถ้าสมมุติมี
packet ที่ match กับ rule นี้ 3 ครั้งภายใน 2 วินาที และถึงแม้ว่าจะมี
packet ที่ match ส่งมาอีกก็จะไม่มีการบันทึกลงล็อกแต่อย่างใด และจะต้องรอไปอีก
1 นาทีจึงจะมีการเริ่มการบันทึกล็อกใหม่อีกครั้ง ซึ่งมีประโยชน์ในกรณีที่มีคนต้องการส่ง
packet เพื่อ flood log หรือทำให้ล็อกในเครื่องเต็ม ทั้งนี้นิยมใช้ร่วมกับ
--log-level (อ้างอิงค่าจาก level
ใน syslogd เพื่อกำหนดค่า level สำหรับ syslog) และ --log-prefix
เพื่อใช้อธิบายเพิ่มเติม เช่น
# iptables -A INPUT -m limit --limit 3/minute --limit-burst 3 -j LOG
--log-level DEBUG --log-prefix "Packet died: "
นอกจากนี้ยังใช้ป้องกันการโจมตีแบบ Denial of Service เช่น SYN flood ได้ด้วย
เช่น
# iptables -A FORWARD -p tcp --syn -m limit
--limit 1/s -j ACCEPT
ใช้ป้องกันการโจมตีแบบ Ping of Death
#iptables -A FORWARD -p icmp --icmp-type echo-request
-m limit --limit 1/s -j ACCEPT
โดยปกติมักใช้วิธี drop icmp packet ทิ้งทั้งหมด เพราะถือว่า ICMP packet
เป็นข้อมูลที่มีอันตรายยิ่งและสามารถปลอมแปลงได้ง่าย
หรือใช้ป้องกันการถูก scan
# iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST
RST -m limit --limit 1/s -j ACCEPT
โดยปกติไม่นิยมใช้วิธีนี้นัก เพราะมีทางเลือกที่ดีกว่า คือการตรวจสอบสอบจาก
state match ว่าเป็นการเชื่อมต่อใหม่หรือไม่ (state = new) ถ้าใช่และ SYN
bit ไม่ถูก set ตัว packet นั้นก็จะถูก DROP ทิ้งไป
การระบุ target
เมื่อมี packet ที่ match กับ rule แล้ว ต้องกำหนด target สำหรับ packet ไว้ด้วย
โดยปกติจะใช้กัน 2 target คือ DROP และ ACCEPT นอกจากนี้ยังมี target แบบอื่นได้คือ
Packet เดินทางในระบบอย่างไร
เมื่อ packet เข้ามาถึงไฟร์วอลล์ มันจะผ่านฮาร์ดแวร์เข้ามายัง device ที่เหมาะสมในเคอร์เนล
จากนั้น packet จะเดินทางไปเป็นทอดๆ ก่อนที่จะถูกส่งไปยังปลายทางที่แท้จริง เช่น
แอพลิเคชันในเครื่องไฟร์วอลล์ หรือ forward ต่อไปยังเครื่องอื่น ซึ่งจะยกตัวอย่างเพื่อให้เห็นภาพอย่างชัดเจนดังนี้
| Step | Table | Chain | Comment |
|---|---|---|---|
| 1 | ข้อมูลอยู่ในระหว่างการเดินทาง เช่น กำลังมาจากอินเทอร์เน็ต | ||
| 2 | ข้อมูลเข้ามายังเครื่องไฟร์วอลล์ผ่านทาง incoming interface (เช่น eth0) | ||
| 3 | mangle | PREROUTING | ใช้สำหรับการทำ mangling packet เท่านั้น เช่น เปลี่ยนค่า TOS ของ packet ซึ่งในกรณีปกติแล้วแทบไม่ได้ใช้งาน |
| 4 | nat | PREROUTING | chain นี้ใช้สำหรับทำ Destination Network Address Translation ไม่ควรสร้าง rule เพื่อกรอง packet ที่ chain นี้ เพราะอาจจะมีบาง packet ที่ไม่เข้าสู่ chain นี้ (มีแค่ packet แรกเท่านั้นที่ผ่านเข้าสู่ chain ส่วน packet ถัดไปใน connection เดียวกันนั้น จะถูกกระทำเหมือนกับที่ packet แรกได้รับ) |
| 5 | เข้าสู่ Routing decision เพื่อตัดสินใจว่า packet จะถูกส่งไปที่ใด | ||
| 6 | filter | FORWARD | เนื่องจากในตัวอย่างนี้ packet จะถูกส่งไปยังเครื่องอื่นในเครือข่าย ดังนั้น packet จึงต้องเข้า FORWARD chain ของ filter table ซึ่งสามารถเขียน rule สำหรับควบคุมการผ่านเข้าออกของ packet สำหรับ forwarded packet ได้ที่นี่ |
| 7 | nat | POSTROUTING | และก่อนที่ packet จะออกไปจากเครื่องไฟร์วอลล์ โดยส่วนใหญ่(ไม่ใช่ทั้งหมด) จะผ่าน chain นี้ ซึ่งใช้ทำ Source Network Address Translation ไม่ควรสร้าง rule เพื่อกรอง packet ที่ chain นี้ เพราะอาจจะมีบาง packet ที่ไม่เข้าสู่ chain นี้ (มีแค่ packet แรกเท่านั้นที่ผ่านเข้าสู่ chain ส่วน packet ถัดไปใน connection เดียวกันนั้น จะถูกกระทำเหมือนกับที่ packet แรกได้รับ) |
| 8 | packet ออกไปทาง outgoing interface (เช่น eth1) | ||
| 9 | packet เดินทางไปสู่เป้าหมาย (เช่น ผ่านทาง LAN) | ||
| อย่างที่เห็นจากตาราง forwarded packet คือ packet ที่มีปลายทางที่ไม่ใช่เครื่องไฟร์วอลล์ อาจจะเป็น packet ที่มาจากอินเทอร์เน็ต หรืออาจจะเป็น packet ที่มาจากเครื่องลูกในเครือข่ายที่ต้องการส่งออกไปอินเทอร์เน็ต ซึ่งไม่ว่าจะส่งในทิศทางใด packet ก็จะต้องผ่าน chain ในลักษณะด้านบนนี้เสมอ | |||
| Step | Table | Chain | Comment |
|---|---|---|---|
| 1 | ข้อมูลอยู่ในระหว่างการเดินทาง เช่น กำลังมาจากอินเทอร์เน็ต | ||
| 2 | ข้อมูลเข้ามายังเครื่องไฟร์วอลล์ผ่านทาง incoming interface (เช่น eth0) | ||
| 3 | mangle | PREROUTING | ใช้สำหรับการทำ mangling packet เท่านั้น เช่น เปลี่ยนค่า TOS ของ packet ซึ่งในกรณีปกติแล้วแทบไม่ได้ใช้งาน |
| 4 | nat | PREROUTING | chain นี้ใช้สำหรับทำ Destination Network Address Translation ไม่ควรสร้าง rule เพื่อกรอง packet ที่ chain นี้ เพราะอาจจะมีบาง packet ที่ไม่เข้าสู่ chain นี้ (มีแค่ packet แรกเท่านั้นที่ผ่านเข้าสู่ chain ส่วน packet ถัดไปใน connection เดียวกันนั้น จะถูกกระทำเหมือนกับที่ packet แรกได้รับ) |
| 5 | เข้าสู่ Routing decision เพื่อตัดสินใจว่า packet จะถูกส่งไปที่ใด | ||
| 6 | filter | INPUT | ทุก packet ที่มีเป้าหมายเป็นเครื่องไฟร์วอลล์จะต้องเข้าสู่ chain นี้เสมอ ไม่ว่าจะมาจาก interface ใดก็ตาม |
| 7 | Local process/application (เช่น server/client program) | ||
| packet ที่มีปลายทางเป็นเครื่องไฟร์วอลล์นั้น จะต้องผ่าน INPUT chain เสมอ | |||
| Step | Table | Chain | Comment |
|---|---|---|---|
| 1 | Local process/application (เช่น server/client program) | ||
| 2 | Mangle | OUTPUT | ใช้สำหรับการทำ mangling packet เท่านั้น การกรอง packet ที่ chain นี้จะไม่มีผลใดๆ ต่อ packet |
| 3 | Nat | OUTPUT | ไม่ได้ใช้งาน |
| 4 | Filter | OUTPUT | ใช้สำหรับกรอง packet ที่ออกมาจาก localhost หรือเครื่องไฟร์วอลล์เอง |
| 5 | เข้าสู่ Routing decision เพื่อตัดสินใจว่า packet จะถูกส่งไปที่ใด | ||
| 6 | Nat | POSTROUTING | และก่อนที่ packet จะออกไปจากเครื่องไฟร์วอลล์ โดยส่วนใหญ่(ไม่ใช่ทั้งหมด) จะผ่าน chain นี้ ซึ่งใช้ทำ Source Network Address Translation ไม่ควรสร้าง rule เพื่อกรอง packet ที่ chain นี้ เพราะอาจจะมีบาง packet ที่ไม่เข้าสู่ chain นี้ (มีแค่ packet แรกเท่านั้นที่ผ่านเข้าสู่ chain ส่วน packet ถัดไปใน connection เดียวกันนั้น จะถูกกระทำเหมือนกับที่ packet แรกได้รับ) |
| 7 | packet ออกไปทาง outgoing interface (เช่น eth1) | ||
| 8 | Local process/application (เช่น server/client program) |
จากสามตัวอย่างด้านบน คงพอจะมองเห็นภาพออกแล้วว่า packet เดินทางเข้าออกในระบบอย่างไร อย่างไรก็ตาม จะสรุปความสำคัญของแต่ละตาราง (table) อีกครั้ง ดังนี้
I. Filter Table
เป็นตารางที่ใช้งานมากที่สุด เป็นจุดที่ใช้ในการตรวจสอบและควบคุมการผ่านเข้าออกของ
packet ถ้าหากจะพิจารณาการไหลเวียนของ packet เฉพาะในส่วนของ filter table โดยไม่สนใจ
table อื่นๆ นั้น ก็พอจะแสดงให้เห็นได้ดังภาพที่ 1 โดยเมื่อ packet เข้ามาในระบบ
มันจะเข้าไปยัง routing decision เพื่อตัดสินใจว่า packet จะถูกส่งไปที่ใด

รูปที่ 1 แสดงให้เห็นว่า packet มีเส้นทางการเดินทางอย่างไรเมื่อเข้ามาในระบบ (filter
table)
ดังภาพ iptables ประกอบไปด้วย built-in chain จำนวน 3 chain ซึ่งไม่สามารถลบได้คือ INPUT, OUTPUT, FORWARD เมื่อเครื่องคอมพิวเตอร์เริ่มทำงานในครั้งแรก ทั้งสาม chain จะมี default policy เป็น ACCEPT ซึ่งหมายความว่าอนุญาตให้ทุกอย่างผ่านเข้าออกได้หมด และสำหรับ FORWARD chain นั้น ถึงแม้จะได้กำหนดให้ policy เป็น ACCEPT แล้ว packet ก็จะยังไม่สามารถถูก forward ไปยังจุดหมายที่ต้องการได้ ตราบใดที่ยังไม่ได้เซ็ตให้ enable IP forwarding ทั้งนี้โดย default แล้ว forward=0 สามารถกำหนดให้ enable IP forwarding (forward=1) ได้ โดย
ใช้คำสั่ง echo "1" > /proc/sys/net/ip_forward เพื่อกำหนดให้ IP forwarding เป็น enable เพื่อให้ Linux box สามารถ forward ip packet ได้ ในบางครั้งนั้นการใช้คำสั่งดังกล่าวทุกครั้งอาจจะไม่สะดวก สามารถแก้ไขไฟล์ configuration ที่ /etc/sysctl.conf แล้ว set ให้ net.ipv4.ip_forward=1 เพื่อเป็นการแก้ไขแบบถาวร
ในกรณีที่ต้องการให้สนับสนุนการทำงานกับ dynamic IP ด้วย เช่น PPP, SLIP, DHCP ก็สามารถทำได้โดยใช้คำสั่ง echo "1" > /proc/sys/net/ipv4/ip_dynaddr ได้เช่นเดียวกัน
II. Mangle Table
เป็นตารางที่ใช้สำหรับแก้ไขข้อมูล TOS, TTL, MARK ของ packet ซึ่งโดยปกติแล้วแทบจะไม่ได้ใช้งาน
และไม่ควรทำ packet filtering หรือกรอง packet ที่ตารางนี้ รวมทั้งไม่ควรทำ DNAT,
SNAT หรือ Masquerading ที่ตารางนี้อย่างเด็ดขาดด้วย
III. Nat Table
เป็นตารางที่ใช้สำหรับทำ network address translation เช่น เปลี่ยนค่า source ip
address, destination ip address จุดสำคัญอีกอย่างหนึ่งที่ต้องรู้ก็คือ มีเพียง
packet แรกเท่านั้นที่เข้ามาที่ chain นี้ ส่วน packet ถัดไปนั้นจะถูกกระทำเหมือนที่
packet แรกได้รับ ดังนั้นจึงไม่ควรทำ packet filtering ที่ chain เหล่านี้
การใช้งาน Nat table นั้นก็เพียงแต่ใช้ออปชัน -t nat เท่านั้น และ target ที่สามารถใช้งานได้คือ SNAT, DNAT, Masquerade, Redirect ซึ่งมีรายละเอียดดังนี้
นอกจากนี้ยังสามารถสร้าง rule ที่ใช้ค่า address ร่วมกันได้ เช่น เปลี่ยน source address ของเครื่อง 192.168.1.1 และ 192.168.1.2 ไปเป็น 1.2.3.4 ร่วมกันได้ เพราะ NAT ฉลาดเพียงพอที่จะแยกแยะและป้องกันการชนกัน และมีตัวอย่างการใช้งานแบบอื่นอีกเช่น
# iptables -t nat -A POSTROUTING -s 192.168.0/24 -o eth1 -j SNAT --to 1.2.3.0/24
# iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth1 -j SNAT --to 1.2.3.0-1.2.3.4 --to 1.2.3.6-1.2.3.254
และสำหรับการทำ source NAT ต้องมั่นใจว่า เมื่อ packet เดินทางไปถึงเป้าหมายแล้ว packet นั้นๆ สามารถเดินทางกลับมาหาเครื่องที่เป็นเจ้าของ packet นั้นได้จริงๆ เช่น หากทำ SNAT จาก private IP เป็น 1.2.3.4 เมื่อ packet ถูกส่งไปถึงปลายทาง และปลายทางต้องการส่งกลับมา packet นั้นจะต้องเดินทางมาถึง linux box ที่รัน iptables นี้เท่านั้น การสื่อสารจึงจะสมบูรณ์ ซึ่งสามารถทำได้ด้วยวิธีต่างๆ ดังนี้คือ
#ip address add 1.2.3.99 dev eth0
หรืออาจจะเพิ่ม arp record ที่เครื่องที่ทำหน้าที่เป็น gateway ของ linux box
มีเอกสารอธิบายเกี่ยวกับความปลอดภัยในการใช้ NAT ที่ http://thaicert.nectec.or.th/paper/firewall/nat.php ซึ่งหลังจากอ่านแล้วจะช่วยให้มองเห็นภาพได้ชัดเจนว่า ต้องทำ NAT หรือไม่อย่างไร
ตัวอย่างที่ 1 การใช้งาน iptables แบบง่าย
ในการใช้งาน iptables ในระบบที่ใช้งานจริงนั้น โดยส่วนใหญ่จะเขียนเป็น script ขึ้นมา
ซึ่งมีความซับซ้อนพอสมควร ซึ่งก่อนจะไปถึงขั้นนั้นมีวิธีทดลองใช้คำสั่งง่ายๆ เพื่อทำความเข้าใจหลักการทำงานเบื้องต้นของ
iptables
เช่น ต้องการ drop packet ที่เป็น ICMP ทั้งหมด ที่ออกจากเครื่องนี้ ซึ่งในกรณีนี้ไม่จำเป็นต้องระบุ source ip address เพราะทุก packet ที่ออกจากเครื่องนี้จะต้องผ่านการตรวจสอบจาก OUTPUT chain
เริ่มการทดสอบโดยทดลอง ping ไปยัง www.nectec.or.th ซึ่งจะได้ผลลัพธ์คล้ายด้านล่างนี้
# ping -c 1 www.nectec.or.th
PING www.nectec.or.th (202.44.204.33) from 203.154.207.22 : 56(84) bytes of data.
64 bytes from www.nectec.or.th (202.44.204.33): icmp_seq=0 ttl=61 time=3.710 msec--- www.nectec.or.th ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max/mdev = 3.710/3.710/3.710/0.000 ms
ซึ่ง option -c 1 ระบุให้ส่ง packet ออกไปแค่ packet เดียว จากนั้นให้ใช้คำสั่งดังด้านล่างนี้ เพื่อ block ICMP packet ที่จะออกจากเครื่องนี้
# iptables -A OUTPUT -p icmp -j DROP
จากนั้นทดลอง ping อีกครั้ง เพื่อตรวจสอบผลลัพธ์ที่ได้
# ping -c 1 www.nectec.or.th
PING www.nectec.or.th (202.44.204.33) from 203.154.207.22 : 56(84) bytes of data.
ping: sendto: Operation not permitted--- www.nectec.or.th ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
ซึ่งผลลัพธ์แสดงให้เห็นว่า ICMP echo-request packet ดังกล่าวไม่ได้รับอนุญาตให้ผ่าน OUTPUT chain ไปได้ และถ้าหากต้องการลบ rule ดังกล่าวก็สามารถทำได้หลายวิธีคือ
# iptables -F OUTPUT (ซึ่งจะลบทุก rule ใน chain OUTPUT นี้)
# iptables -D OUTPUT 1 (เนื่องจากรู้ว่ามี rule เดียวจึงสามารถสั่งลบ rule ลำดับที่ 1 ได้เลย) หรือ
# iptables -D OUTPUT -p icmp -j DROP (ลบ rule โดยการระบุออปชันของ rule ที่ต้องการได้โดยตรง)
ตัวอย่างที่ 2 การทำ Masquerading
ตัวอย่างการใช้งาน masquerading ที่เห็นได้ชัดเจนในประเทศไทยก็คือ ร้านอินเทอร์เน็ตคาเฟ่(แบบประหยัด)
ซึ่งนิยมใช้โมเด็ม 1 ตัว connect ไปยัง ISP แล้วใช้ NAT เพื่อให้เครื่องลูกที่มีอยู่หลายๆ
เครื่องนั้น สามารถใช้งานอินเทอร์เน็ตผ่านโมเด็มตัวนั้นได้ โดยเครื่องลูกจะต้องใช้
private ip ซึ่งมีให้เลือกหลาย class เช่น 10.x.x.x 192.168.x.x เป็นต้น จากนั้นก็ตั้ง
gateway ให้ชี้ไปยัง linux box ที่ทำหน้าที่หมุนโมเด็มและรัน iptables ซึ่งสามารถใช้คำสั่งง่ายๆ
ดังด้านล่างก็ทำให้เครื่องลูกสามารถใช้งานอินเทอร์เน็ตได้แล้ว คือ
# iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
# echo "1" > /proc/sys/net/ip_forward
ตัวอย่างที่ 3 การเขียน rule จากเครือข่ายตัวอย่าง rc.firewall (ตัวอย่างเครือข่ายและ script นี้คัดลอกมาจากเว็บไซต์ www.boingworld.com)

จากภาพแสดงเครือข่ายที่มีการเชื่อมต่อกับอินเทอร์เน็ตแบบถาวร โดยไม่ได้ใช้ DHCP, PPP, SLIP ซึ่งสามารถใช้ script จากไฟล์ rc.firewall.txt
ตัวอย่างที่ 4 การเขียน rule จากเครือข่ายตัวอย่าง rc.DMZ.firewall (ตัวอย่างเครือข่ายและ script นี้คัดลอกมาจากเว็บไซต์ www.boingworld.com)

สำหรับ script ของเครือข่ายด้านบนนี้ ดูได้ที่ rc.DMZ.firewall.txt ซึ่งเขียนขึ้นสำหรับผู้ที่มีการใช้งานเครือข่ายดังรูปด้านบน ซึ่งประกอบไปด้วย trusted internal network หรือเครือข่ายภายในที่ไว้ใจได้ และ DMZ (De-Militarized Zone) และมีการเชื่อมต่ออินเทอร์เน็ต ในกรณีนี้ไอพีปลอมที่ใช้ภายใน DMZ จะถูกทำ NAT แบบ 1 ต่อ 1 ซึ่งจำเป็นต้องทำ IP alias ที่ eth0 ของเครื่องไฟร์วอลล์ เพื่อให้ packet สามารถเดินทางกลับมาถึงเครื่องไฟร์วอลล์ได้
ส่วนของ trusted internal network นั้น จะใช้ไอพี 192.168.0.0/24 และส่วนของ DMZ นั้นใช้ 192.168.1.0/24 ซึ่งจะถูกทำ NAT แบบ 1ต่อ 1 กับไอพีที่ได้รับจัดสรรมาจาก ISP ตัวอย่าง ถ้ามี packet จากอินเทอร์เน็ตส่งมายัง DNS_IP ก็จะถูกทำ DNAT (destination network address translation) ที่เครื่องไฟร์วอลล์ ซึ่งจะส่ง packet ไปยัง DNS ใน DMZ โดยใช้ไอพีภายใน (คือ 192.168.1.3) มีโค้ดตัวอย่างการทำ DNAT คือ
$IPTABLES -t nat -A PREROUTING -p TCP -i $INET_IFACE -d $DNS_IP --dport 53 -j DNAT --to-destination $DMZ_DNS_IP
ตัวอย่างที่ 5 การเขียน rule จากเครือข่ายตัวอย่าง rc.DHCP.firewall (ตัวอย่างเครือข่ายและ script นี้คัดลอกมาจากเว็บไซต์ www.boingworld.com)

script สำหรับเครือข่ายนี้ดูได้ที่ rc.DHCP.firewall.txt ซึ่งเหมาะสำหรับเครือข่ายที่ได้รับไอพีมาแบบไม่คงที่ โดยใช้งานได้ทั้งกับ DHCP, PPP และ SLIP ซึ่ง script นี้มีความปลอดภัยน้อยกว่า rc.firewall.txt เพราะมีการเปิดกว้างมากกว่า
ตัวอย่างที่ 6 การเขียน rule จากเครือข่ายตัวอย่าง rc.UTIN.firewal (ตัวอย่างเครือข่ายและ script นี้คัดลอกมาจากเว็บไซต์ www.boingworld.com)

script สำหรับเครือข่ายนี้ดูได้ที่ rc.UTIN.firewall.txt ซึ่งเหมาะสำหรับเครือข่ายที่ที่ต้องการความปลอดภัยสูง เพราะเป็นเครือข่ายที่ไม่ไว้ใจแม้กระทั่งเครือข่ายภายใน
ตัวอย่างที่ 7 rc.flush-iptables.txt (script นี้คัดลอกมาจากเว็บไซต์ www.boingworld.com)
script สำหรับตัวอย่างนี้ดูได้ที่ rc.flushiptables.txt ซึ่ง script นี้มีไว้เพื่อ reset และลบ rule ทั้งหมดในทุก table และทุก chain ทิ้งไป
คำอธิบายเพิ่มเติม
เนื่องจากในตัวอย่างที่ 3 - 6 นั้น มีการสร้าง rule ที่ค่อนข้างซับซ้อน จึงจะยกมาขยายความเพิ่มเติมคือ
คำแนะนำเพิ่มเติม
for x in lo eth0 eth1
do
echo 1 > /proc/sys/net/ipv4/conf/${x}/rp_filter
done
แต่ script ดังกล่าวนี้ไม่ได้ป้องกันการปลอมไอพีสำหรับทั้งเครือข่าย ดังนั้นจึงต้องสร้าง rule ไว้ที่ PREROUTING chain เพื่อป้องกันปัญหานี้อีกครั้ง เช่น
$IPTABLES -t nat -A PREROUTING -i $INET_IFACE -s 10.0.0.0/8 -j DROP
$IPTABLES -t nat -A PREROUTING -i $INET_IFACE -s 127.0.0.0/8 -j DROP
$IPTABLES -t nat -A PREROUTING -i $INET_IFACE -s 172.16.0.0/12 -j DROP
$IPTABLES -t nat -A PREROUTING -i $INET_IFACE -s 192.168.1.0/16 -j DROP
การป้องกันการปลอมไอพีดัง rule ด้านบนนี้ สามารถลดปัญหาที่จะเกิดขึ้นจากการโจมตีแบบ Denial of Service เช่น Land attack ได้เป็นอย่างดี
การนำไปใช้งาน
การนำ iptables ไปใช้งานจริงนั้น จะต้องสร้าง rule ขึ้นมาให้สอดคล้องกับเครือข่ายที่มีอยู่
และระดับความปลอดภัยที่ต้องการ ทั้งนี้มีข้อแนะนำมากมายเกี่ยวกับการเขียน rule
ของ iptables และเนื่องจากมีรายละเอียดและตัวอย่างค่อนข้างเยอะ รวมทั้งวิธีการ
audit firewall ที่ implement ไปแล้วว่าตรงกับความต้องการหรือไม่ ดังนั้นจึงจำเป็นต้องแยกเอกสารออกเป็นอีกฉบับหนึ่ง
เพื่อไม่ให้เอกสารนี้มีความยาวมากเกินไป ซึ่งจะนำเสนอในโอกาสต่อไป
คำสั่งที่ใช้ในการคอมไพล์เคอร์เนล
make dep
make clean
make bzImage
make modules
#รันคำสั่งนี้ในกรณีที่คอมไพล์เคอร์เนลแบบเลือก module ด้วย
make modules_install
#รันคำสั่งนี้ในกรณีที่คอมไพล์เคอร์เนลแบบเลือก module ด้วย
cp /usr/src/linux/arch/i386/boot/bzImage /boot/vmlinuz-2.4.14
#การ copy bzImage นั้น ขึ้นอยู่กับสถาปัตยกรรมของเครื่องคอมพิวเตอร์นั้นๆ ซึ่งในที่นี้ใช้ i386
cp /usr/src/linux/System.map /boot/System.map-2.4.14
ln -s /boot/System.map-2.4.14 .boot/System.map
#ถ้าได้รับ error ให้ลบไฟล์ /boot/System.map ทิ้งก่อนจากนั้นให้แก้ไข /etc/lilo.conf เพื่อเพิ่ม configuration ใหม่ ตัวอย่างด้านล่างแสดง Red Hat Linux ที่มีเคอร์เนลเดิมเป็น 2.4.3-12 และเคอร์เนลใหม่เป็น 2.4.14
boot=/dev/hda
map=/boot/map
install=/boot/boot.b
prompt
timeout=50
message=/boot/message
default=linux-2.4.14image=/boot/vmlinuz-2.4.14
label=linux-2.4.14
read-only
root=/dev/hda1image=/boot/vmlinuz-2.4.3-12
label=linux-2.4.3-12
read-only
root=/dev/hda1
หลังจากนั้นรันคำสั่ง lilo -v และรีบูตใหม่
ถ้าไม่มีข้อผิดพลาดใดๆ ก็จะได้เคอร์เนลของ Linux เวอร์ชันล่าสุดที่สนับสนุนการทำงานของ
iptables อย่างเต็มที่ ทั้งนี้ขอแนะนำให้ใช้เวอร์ชันล่าสุดที่สูงกว่า 2.4.3 เพราะเวอร์ชัน
2.4.3 (และต่ำกว่า) นั้นมีข้อผิดพลาด (bug) ของ ftp port รายละเอียดของข้อผิดพลาดนี้อ่านได้ที่
http://netfilter.samba.org/security-fix/index.html#desc-ftp-160401
และสำหรับผู้ที่มีปัญหากับการคอมไพล์และติดตั้งเคอร์เนลนั้น สามารถศึกษาเพิ่มเติมได้จาก
The Linux Kernel HOWTO
หมายเหตุ คำสั่งทั้งหมดที่ใช้ในการอัพเกรดเคอร์เนลด้านบนนั้น ได้ผ่านการทดลองใช้บน
Red Hat Linux 7.1 เท่านั้น
ข้อมูลอ้างอิง
| Home
|| เอกสารเผยแพร่ || Firewall
ThaiCERT Disclaimer | Copyright © 2001 ThaiCERT(NECTEC). All rights reserved. |