การทำ Inbound & Outbound NAT บน Linux ด้วย iptables

ในระบบของอินเตอร์เน็ต ในบางกรณีระบบ Server ขององค์กรอาจจะจำเป็นต้องใช้ Private IP เพราะมี Public IP ไม่พอเพียง ดังรูปตัวอย่างข้างล่าง สมมุติว่าเราได้ Public IP มาแค่ IP เดียว แต่มีความจำเป็นที่จะต้องให้ Server ภายในองค์กร เช่น DNS Server, Web Server, Mail Server ฯลฯ เป็นที่รู้จักของเครือข่ายภายนอกด้วย  การนำเอง Linux Server มาทำเป็น Gateway ที่มีการทำ NAT ก็เป็นทางออกทางหนึงที่สามารถทำได้

ิธีการ
จากรูปข้างบนก็นำ
Linux Server มาใช้งานโดยให้มีการ์ดแลน 2 การ์ด การ์ดหนี่งให้เป็น Public IP (202.129.16.30) และอีกการ์ดเป็น Private IP (192.168.1.1) ส่วนเครื่อง Server และ Client ก็ใช้ Private IP ดังรูป  โดยบนเครื่อง Linux Server ให้ใช้ iptables ในการควบคุมการไหลของข้อมูล 

ความต้องการของระบบ
มีความต้องการอยู่ 2 อย่างคือ
1
. Linux Server ต้องทำหน้าที่แปลง IP ของเครือข่ายภายในทั้งหมดซึ่งเป็น Private IP ให้กลายเป็น Public IP ซึ่งในที่นี้คือ 202.129.16.30 เพื่อให้สามารถติดต่อกับเครือข่ายภายนอกได้
2. เมื่อเครือข่ายภายนอกมีการเรียกใช้งานเข้ามาที่
DNS Server , Web Server และ Mail Server ซึ่งจะถูกประกาศให้เครือข่ายภานนอกรู้จักเป็น Public IP อันเดียวกันคือ 202.129.16.30 นั้น  ตัว Linux Server ต้องทำการแปลง Public IP ให้กลายเป็น Private IP เพื่อที่จะให้เครือข่ายภายนอกสามารถติดต่อเข้าสู่ Server ทั้ง 3 ได้  ด้วยความแตกต่างของ Port ดังนี้ :

     -
DNS Server ทำงานที่พอร์ต TCP:53 และ UDP:53
     -
Web Server (http) ทำงานที่พอร์ต TCP:80
     - Mail Server (smtp) ทำงานที่พอร์ต TCP:25

ในกรณีที่มี
Server อื่น ๆ นอกเหนือจากนี้ก็สามารถทำได้ด้วยหลักการเดียวกัน

คำสั่ง
iptables ที่ใช้

#Enable ip forward
echo 1 > /proc/sys/net/ipv4/ip_forward

#Clear all chains of rule
iptables -F
iptables -t nat -F

#NAT outbound
iptables -t nat -A POSTROUTING -o eth0 -s 192.168.1.0/24 -d 0/0 -j SNAT --to-source 202.129.16.30
iptables -A FORWARD -p tcp -i eth1 -o eth0 -s 192.168.1.0/24 -d 0/0 -j ACCEPT

#Allow outside access to nameserver (tcp)
iptables -t nat -A PREROUTING -p tcp -s 0/0 -d 202.129.16.30 --dport 53 -j DNAT --to-dest 192.168.1.2
iptables -A FORWARD -i eth0 -o eth1 -s 0/0 -d 192.168.1.2 -p tcp --dport 53 -j ACCEPT

#Allow outside access to nameserver (udp)
iptables -t nat -A PREROUTING -p udp -s 0/0 -d 202.129.16.30 --dport 53 -j DNAT --to-dest 192.168.1.2
iptables -A FORWARD -i eth0 -o eth1 -s 0/0 -d 192.168.1.2 -p udp --dport 53 -j ACCEPT

#Allow outside access to webserver
iptables -t nat -A PREROUTING -p tcp -s 0/0 -d 202.129.16.30 --dport http -j DNAT --to-dest 192.168.1.3
iptables -A FORWARD -i eth0 -o eth1 -s 0/0 -d 192.168.1.3 -p tcp --dport http -j ACCEPT

#Allow outside access to mail server
iptables -t nat -A PREROUTING -p tcp -s 0/0 -d 202.129.16.30 --dport 25 -j DNAT --to-dest 192.168.1.4
iptables -A FORWARD -i eth0 -o eth1 -s 0/0 -d 192.168.1.4 -p tcp --dport 25 -j ACCEPT

ปรับปรุงให้ดีขึ้น

เราอาจจะเพิ่มเติมคำสั่งของ iptables เพื่อให้ Linux Gate ทำงานเป็น Stateful Firewall และกรอง Packet ที่ไม่ดีออกไป รวมถึงระบบ log  ด้วยการเพิ่มคำสั่งที่เป็นสีฟ้าเข้าไป  และทั้งหมดเป็นดังนี้
 

#Enable ip forward
echo 1 > /proc/sys/net/ipv4/ip_forward

#Clear all chains of rule
iptables -F
iptables -t nat -F

#Bad TCP packets we don't want
iptables -A FORWARD -p tcp ! --syn -m state --state NEW -j LOG --log-prefix "New not syn:"
iptables -A FORWARD -p tcp ! --syn -m state --state NEW -j DROP


#Set to Stateful
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A PREROUTING -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -m state --state ESTABLISHED,RELATED -j ACCEPT

#Foward log
#iptables -A FORWARD -m limit --limit 3/minute --limit-burst 3 -j LOG --log-level DEBUG --log-prefix "IPT FORWARD packet died"


#NAT outbound
iptables -t nat -A POSTROUTING -o eth0 -s 192.168.1.0/24 -d 0/0 -j SNAT --to-source 202.129.16.30
iptables -A FORWARD -p tcp -i eth1 -o eth0 -s 192.168.1.0/24 -d 0/0 -j ACCEPT

#Allow outside access to nameserver (tcp)
iptables -t nat -A PREROUTING -p tcp -s 0/0 -d 202.129.16.30 --dport 53 -j DNAT --to-dest 192.168.1.2
iptables -A FORWARD -i eth0 -o eth1 -s 0/0 -d 192.168.1.2 -p tcp --dport 53 -j ACCEPT

#Allow outside access to nameserver (udp)
iptables -t nat -A PREROUTING -p udp -s 0/0 -d 202.129.16.30 --dport 53 -j DNAT --to-dest 192.168.1.2
iptables -A FORWARD -i eth0 -o eth1 -s 0/0 -d 192.168.1.2 -p udp --dport 53 -j ACCEPT

#Allow outside access to webserver
iptables -t nat -A PREROUTING -p tcp -s 0/0 -d 202.129.16.30 --dport http -j DNAT --to-dest 192.168.1.3
iptables -A FORWARD -i eth0 -o eth1 -s 0/0 -d 192.168.1.3 -p tcp --dport http -j ACCEPT

#Allow outside access to mail server
iptables -t nat -A PREROUTING -p tcp -s 0/0 -d 202.129.16.30 --dport 25 -j DNAT --to-dest 192.168.1.4
iptables -A FORWARD -i eth0 -o eth1 -s 0/0 -d 192.168.1.4 -p tcp --dport 25 -j ACCEPT

อธิบายเพิ่มเติม
ในส่วนของการทำ
NAT outbound เนื่องจากเป็นการทำ NAT ที่ใช้ Public IP แค่ IP เดียว เราสามารถเปลี่ยนคำสั่งสองบรรทัดดังกล่าวให้เป็นการทำ masquerage ได้ ดังนี้

iptables - t nat -A POSTROUTING -o eth0 -j MASQUERADE

ในกรณีที่เครื่อง
Clients ภายในจะสอบถามโดเมนไปยัง DNS Server ก็ให้สอบถามไปที่ DNS Server ที่เป็น Private IP ในที่นี้คือ 192.168.1.2 เท่านั้น ไม่สามารถสอบถามไปยัง DNS Server ที่เป็น Public IP (ในที่นี้คือ 202.129.16.30) ได้

อีกอย่างหนึ่งนะครับ การที่เครื่องภายในจะเรียกใช้งาน
Web Server ขององค์กรตัวเอง การเรียกไม่สามารถเรียกผ่าน Public IP ได้นะครับ ดังนั้นก็ต้องเรียกใช้งานเป็น Private IP (ถ้ามีการจดทะเบียนโดเมนก็จะเรียกเป็นโดเมนไม่ได้เช่นกัน  ยกเว้นมีการทำ DNS ในลักษณะตอบการสอบถามโดเมนให้กับเครื่องภายในเป็น Private IP)