ป้องกันเครื่อง Linux ให้ปลอดภัยด้วยไฟร์วอลล์ nftables

สำหรับผู้ดูแลระบบ Linux ตระกูล Redhat (รวมไปถึง CentOS Linux, Alma Linux และ Rocky Linux) ไม่รู้ว่าจะเลือกใช้งานไฟร์วอลล์ (Firewall) ด้วยอันไหน เพราะมีทั้ง firewalld และ nftables ไม่รู้ว่าต่างกันอย่างไร สำหรับแอดมินมือเก่า iptables ก็หายไปแล้ว แล้วจะทำอย่างไร เรามาดูรายละเอียดกัน

ระบบอยู่หลังไฟร์วอลล์เครือข่าย (Network Firewall) อยู่แล้ว ไม่จำเป็นต้องใช้งานก็ได้
จากคำกล่าวข้างต้นนั้นอาจจะไม่ถูกต้องทั้งหมด เนื่องจากไฟร์วอลล์เครือข่ายจะออกแบบมาเพื่อป้องกันทราฟฟิกจากเครื่องไคลเอนต์ไปยังเครื่องเซิร์ฟเวอร์ (North-South) เท่านั้น แต่ถ้าทราฟฟิกระหว่างเครื่องภายในเครือข่าย (East-West) นั้นอุปกรณ์ไฟร์วอลล์ก็จะไม่สามารถป้องกันได้ ดังนั้นการเรียนรู้ที่จะใช้งานไฟร์วอลล์บนเครื่องเซิร์ฟเวอร์ก็มีความจำเป็นอยู่ดี เพื่อเป็นการเพิ่มความปลอดภัยนั่นเอง

 nftables_01.png

จากภาพด้านบน แสดงรายละเอียดของทราฟฟิกที่เกิดขึ้นในระบบทั้งแบบ North-South และ East-West ซึ่งในทางปฎิบัติแล้วทราฟฟิกของ East-West มักจะป้องกันได้โดยใช้ “Personal Firewall” หรือหากใช้งานระบบ Virtualization อาจจะใช้งานฟีเจอร์บน Hypervisor เพื่อควบคุมทราฟฟิกดังกล่าวได้ โดยมากแล้วมักจะมีค่าใช้จ่ายเพิ่มเติม หรือในบางเครือข่ายอาจจะประยุกต์ใช้งาน “Microsegmentation” เพื่อลดความเสี่ยงได้อีกด้วย

 nftables_02.gif

เปรียบเทียบความแตกต่างระหว่าง firewalld nftables และ iptables
สำหรับ Linux ตระกูล Redhat เริ่มมีการใช้งาน firewalld มาตั้งแต่ Redhat Enterprise Linux เวอร์ชัน 7 เป็นต้นมา ส่วนตัวผมเองเริ่มใช้งาน Linux แบบจริงจังเมื่อตอน Redhat Enterprise Linux เวอร์ชัน 3 จึงถือว่าเป็นการเปลี่ยนแปลงที่มากพอสมควร ซึ่งเมื่อหาข้อมูลมาสามารถเปรียบเทียบได้ดังตารางด้านล่าง สำหรับบทความนี้ขออ้างอิงจาก Redhat Enterprise Linux เวอร์ชัน 9 (ปี 2024) เป็นหลัก

เครื่องมือ รูปแบบการใช้งาน เหมาะสำหรับ
firewalld ขั้นเริ่มต้น (simple) การใช้งานที่ไม่ซับซ้อน เช่น การเปิด/ปิดพอร์ทการเชื่อมต่อ
nftables ขั้นสูง (Complex) การใช้งานที่ซับซ้อน เช่น การใช้งานเป็นไฟร์วอลล์สำหรับเครือข่าย เป็น Gateway ของระบบ
iptables ขั้นสูง (Complex) ในปัจจุบันเป็นการแปลงคำสั่งให้เป็น nftables แทน ใช้งานเช่นเดียวกับ nftables แนะนำให้แปลงคอนฟิกเป็น iptables เพื่อความสะดวกในการใช้งาน

สำหรับเบื้องหลังการทำงานของ firewalld นั้น เราจะสร้างคอนฟิกของ firewalld ตามที่กำหนดขึ้นมา จากนั้นโปรแกรมจะแปลงค่าดังกล่าวไปเป็น nftables ในภายหลัง โดยที่เราไม่จำเป็นต้องเรียนรู้คำสั่งของ nftables แต่อย่างใด แต่เนื่องจากผมเองมีความคุ้นเคยกับ iptables เป็นหลัก และลองพยายามใช้งาน firewalld มาระยะหนึ่ง ค้นพบว่าไม่ถนัดจึงเลือกมาใช้งาน nftables โดยตรงน่าจะสะดวกมากกว่า ซึ่ง nftables เองก็เป็นการปรับปรุง iptables ให้มีประสิทธิภาพมากขึ้น (ก่อนหน้านี้ iptables จะแยกกันระหว่าง IPv4 และ IPv6 ที่ต้องเขียนแยกจากกัน และรันโปรแกรมแยกจากกัน แต่ nftables ได้รวมเข้าด้วยกันแล้ว) ในบทความนี้จึงขอใช้งาน nftables เป็นหลัก

 nftables_03.png

จากรูปด้านบน แสดงแผนผังการทำงานของ firewalld และ iptables โดยเป็นโครงสร้างใน Redhat Enterprise Linux เวอร์ชัน 7 ซึ่งจะพบว่าหากเราเขียนคอนฟิกของ firewalld แล้ว โปรแกรมก็จะมาสร้างไฟร์วอลล์บน iptables อยู่ดี

การแปลงคอนฟิกจาก iptables มาสู่ nftables
ก่อนอื่นเลย เราต้องปิดการใช้งาน firewalld และติดตั้งแพกเกจเพิ่มเติมเพื่อให้ใช้งาน nftables ได้ โดยให้เรารันคำสั่งดังนี้โดยใช้สิทธิของผู้ดูแลระบบ (root) ดังนี้

# yum install iptables-nft-services
# systemctl stop firewalld.service
# systemctl disable firewalld.service

ในกรณีที่เราเคยมีคอนฟิกของ iptables อยู่แล้ว ระบบ nftables รองรับการแปลง (translate) ได้โดยใช้คำสั่งดังนี้ 

# mkdir /root/iptables
# cd /root/iptables

Copy iptables from previous server to /root/iptables/iptables

# iptables-restore-translate -f iptables > nftables-convert.nft
# cp nftables-convert.nft nftables.nft

จากตัวอย่างเป็นการสร้างโฟลเดอร์ /root/iptables ขึ้นมา จากนั้นคัดลอกไฟล์ iptables เดิมที่เคยมีมาไว้เป็นชื่อไฟล์ /root/iptables/iptables แล้วทำการแปลงไฟล์มาเป็น /root/iptables/nftables-convert.nft มาอีกที จากนั้นทำการคัดลอกไฟล์ดังกล่าวให้เป็น /root/iptables/nftables.nft เพื่อปรับเปลี่ยนให้เหมาะสมสำหรับ nftables โดยรูปแบบการใช้งาน หากเราคุ้นเคยกับ iptables มาก่อนก็พอจะเดาคำสั่งได้ไม่ยาก

เรียนรู้การใช้งาน nftables เบื้องต้น
เมื่อทำการแปลงไฟล์มาแล้ว ขอยกเป็นตัวอย่างที่มักจะมีการใช้งานบ่อยๆ โดยสมมติเป็นการป้องกันเว็บเซิร์ฟเวอร์ซึ่งติดตั้งเอาไว้ในโซน DMZ ของไฟร์วอลล์ในระบบเครือข่าย ซึ่งเราต้องการความปลอดภัยเพิ่มเติมเผื่อในกรณีที่เกิดการโจมตีภายใน หรือป้องกันความผิดพลาดที่เกิดจากผู้ดูแลระบบ (Human Error) โดยมีรูปแบบการเชื่อมต่อเป็นดังรูปด้านล่าง

 nftables_04.png

โดยกำหนดกฎของไฟร์วอลล์ (Firewall Policy) เอาไว้ดังตารางด้านล่าง

Rule Source IP Address Destination IP Address Service (Port) Action Remark
1 Any Linux Server HTTP (TCP/80)
HTTPs (TCP/443)
Accept For web public access (input chain)
2 192.168.0.0/24
192.168.1.0/24
Linux Server SSH (TCP/22)
MySQL (TCP/3306)
Accept For administrative access (input chain)
3 Linux Server Any Any Accept For server access internet (output chain)
4 Any Any Any Drop Default drop

อ้างอิงจากตารางด้านบน เราสามารถเขียนเป็นคอนฟิกของ nftables ได้ โดยการเขียนไฟล์ /etc/nftables/nftables.nft ได้ดังนี้

###############################
# Remove all rule
flush ruleset

# Predefine NAT chain
add table ip nat
add chain ip nat PREROUTING { type nat hook prerouting priority -100; policy accept; }
add chain ip nat POSTROUTING { type nat hook postrouting priority 100; policy accept; }
add chain ip nat OUTPUT { type nat hook output priority -100; policy accept; }

# Filter chain
add table ip filter
add chain ip filter INPUT { type filter hook input priority 0; policy drop; }
add chain ip filter FORWARD { type filter hook forward priority 0; policy drop; }
add chain ip filter OUTPUT { type filter hook output priority 0; policy accept; }

# Loopback & Stateful firewall permit
add rule ip filter INPUT iifname lo counter accept
add rule ip filter INPUT ct state related,established  counter accept

# Allow web service
add rule ip filter INPUT tcp dport 80 counter accept
add rule ip filter INPUT tcp dport 443 counter accept

# Allow admin
add rule ip filter INPUT ip saddr 192.168.0.0/24 tcp dport 22 counter accept
add rule ip filter INPUT ip saddr 192.168.1.0/24 tcp dport 22 counter accept
add rule ip filter INPUT ip saddr 192.168.0.0/24 tcp dport 3306 counter accept
add rule ip filter INPUT ip saddr 192.168.1.0/24 tcp dport 3306 counter accept


จากตัวอย่างคอนฟิกด้านบน จะเห็นในส่วนของ “# Allow web service” ที่มีการเปิดพอร์ทส่วนของเว็บเซิร์ฟเวอร์เอาไว้ และมีการกำหนดส่วนของผู้ดูแลระบบเอาไว้ภายใต้ “# Allow admin” ซึ่ง nftables รองรับการสร้างตัวแปรและสามารถเรียกใช้งานได้ในกฎซึ่งช่วยลดความผิดพลาดในการเขียนคอนฟิกหากไฟล์มีขนาดใหญ่ได้ด้วย โดยสามารถปรับปรุงคอนฟิกด้านบนได้เป็นไฟล์ดังนี้

# Define interface
define LOOPBACK = lo

# Define trust host
define TRUST_ADDRESS = { 192.168.0.0/24 , 192.168.1.0/24 }

###############################
# Remove all rule
flush ruleset

# Predefine NAT chain
add table ip nat
add chain ip nat PREROUTING { type nat hook prerouting priority -100; policy accept; }
add chain ip nat POSTROUTING { type nat hook postrouting priority 100; policy accept; }
add chain ip nat OUTPUT { type nat hook output priority -100; policy accept; }

# Filter chain
add table ip filter
add chain ip filter INPUT { type filter hook input priority 0; policy drop; }
add chain ip filter FORWARD { type filter hook forward priority 0; policy drop; }
add chain ip filter OUTPUT { type filter hook output priority 0; policy accept; }

# Loopback & Stateful firewall permit
add rule ip filter INPUT iifname $LOOPBACK counter accept
add rule ip filter INPUT ct state related,established  counter accept

# Allow web service
add rule ip filter INPUT tcp dport 80 counter accept
add rule ip filter INPUT tcp dport 443 counter accept

# Allow admin
add rule ip filter INPUT ip saddr $TRUST_ADDRESS tcp dport 22 counter accept
add rule ip filter INPUT ip saddr $TRUST_ADDRESS tcp dport 3306 counter accept


จากนั้นทำการแก้ไขไฟล์ /etc/sysconfig/nftables.conf โดยเพิ่มรายละเอียดเข้าไปดังนี้
# Uncomment the include statement here to load the default config sample
# in /etc/nftables for nftables service.

#include "/etc/nftables/main.nft"

# To customize, either edit the samples in /etc/nftables, append further
# commands to the end of this file or overwrite it after first service
# start by calling: 'nft list ruleset >/etc/sysconfig/nftables.conf'.
include "/etc/nftables/nftables.nft"

จากนั้นเปิดการใช้งานโดยใช้คำสั่งดังนี้
# systemctl enable nftables.service
# systemctl start nftables.service

เราสามารถตรวจสอบการทำงานของ nftables โดยใช้คำสั่งดังนี้
# nft list ruleset

จากตัวอย่างทั้งหมดนี้ ผมคิดว่าน่าจะสามารถนำ nftables ไปประยุกต์ใช้งานเพื่อสร้างความปลอดภัยของเครื่องเซิร์ฟเวอร์ได้มากขึ้น ซึ่งอาจจะเขียนกฎด้วย firewalld ก็ได้เหมือนกัน แต่ความเห็นส่วนตัวคิดว่าเรียนรู้จาก nftables น่าจะใช้งานได้หลากหลายกว่า อีกทั้งหากใช้ firewalld แล้วการตรวจสอบก็ยังต้องอ่านรูปแบบของ nftables ได้อยู่ดี

อ้างอิง