ตัวอย่างการทำ Firewall แบบ DMZ พร้อม Transparent Proxy (DMZ ใช้ Private IP)
ดัดแปลงจาก www.boingworld.com

บทนำ
การจัดเครือข่าย
Firewall แบบ DMZ (Demilitarized Zone) เป็นรูปแบบหนึ่งที่นิยมใช้กัน  ซึ่งเครือข่ายจะประกอบไปด้วยเครือข่าย 3 ส่วนด้วยกัน คือ
1 .เครือข่ายภายใน 
(trusted internal network) จะเป็นส่วนที่ไม่อนุญาตให้เครือข่ายภายนอกเข้ามาได้ ซึ่งส่วนใหญ่จะเป็นส่วนของ Client
2. เครือข่าย
DMZ เป็นส่วนที่เครือข่ายภายนอกและเครือข่ายภายในเข้ามาใช้งานได้ตามกฎที่ Firewall ได้ตั้งไว้
3.เครือข่ายภายนอก (Internet)

โดยการเชื่อมต่อใช้งานจะต้องมี
Linux Server ตัวหนี่งทำหน้าที่เป็น Firewall ซึ่งจะต้องประกอบด้วยการ์ดแลน 3 การ์ด ดังรูปที่ 1



รูปที่ 1

เพื่อให้เข้าใจได้ง่ายขึ้นจึงขอใช้รูปตัวอย่างการเชื่อมต่อจริง ๆ ดังรูปที่ 2  ซึ่งที่ Linux Firewall จะมี Ethernet Card 3 การ์ดคือ eth0 ใช้เชื่อมต่อกับเครือข่ายภายนอก, eth1 ใช้เชื่อมต่อกับเครือข่ายภายใน  และ eth2 ใช้เชื่อมต่อกับเครือข่าย DMZ  ในส่วนของ eth0 นั้นมี IP Address เป็น 3 ค่าคือ
1. 202.129.49.194
แทนตัวเองซึ่งเป็น Firewall
2. 202.129.49.195 ใช้แทน
HTTP
3. 202.129.49.196
ใช้แทน DNS

หมายเหตุ Proxy ไม่จำเป็นต้องให้บริการกับบุคคลภายนอก จึงไม่จำเป็นต้องใช้ IP จริง




รูปที่ 2

หน้าที่ของ Linux Firewall
1.ทำ NAT (Outbound) ให้เครือข่ายภายใน (trusted internal network) สามารถเชื่อมต่อไปยังเครือข่ายภายนอกได้
2.ในกรณีที่เครือข่ายภายในออกไปใช้งานเครือข่ายภายนอกเป็นการเรียกใช้ http ให้ redirect ไปยัง Proxy ของ DMZ (Transparent Proxy)
3.
Linux Server ต้องอนุญาตให้เครือข่ายภายในสามารถใช้งาน DNS Server ในวง DMZ ทั้งการเรียกโดยใช้ IP จริงและ IP ปลอมได้ (ทั้ง 202.129.49.196 และ 192.168.2.3)
4.
Linux Server ต้องอนุญาตให้เครือข่ายภายในสามารถใช้งาน Web Server ในวง DMZ ทั้งการเรียกโดยใช้ IP จริงและ IP ปลอม (ทั้ง 202.129.49.195 และ 192.168.2.2)
5
.ทำ NAT (Inbound) ให้เครือข่ายภายนอกเข้ามาใช้ Web Server และ DNS Server ในวง  DMZ ได้
6.ทำหน้าที่เป็น
Firewall

คำสั่ง
iptables ที่ใช้
คำสั่งที่ใช้ทั้งหมดเป็นดังนี้
:

#-----Start script------#

#Define variables
LAN_IP="192.168.1.1"
LAN_BCAST_ADRESS="192.168.1.255"
LAN_IFACE="eth1"

INET_IP="202.129.49.194"
INET_IFACE="eth0"

HTTP_IP="202.129.49.195"
DNS_IP="202.129.49.196"

DMZ_IP="192.168.2.1"
DMZ_IFACE="eth2"

DMZ_HTTP_IP="192.168.2.2"
DMZ_DNS_IP="192.168.2.3"
DMZ_PROXY_IP="192.168.2.4"

LO_IP="127.0.0.1"
LO_IFACE="lo"

#CRITICAL: Enable IP forwarding since it is disabled by default.
echo "1" > /proc/sys/net/ipv4/ip_forward

#Clear all chains of rule
iptables -F
iptables -X allowed
iptables -X icmp_packets
iptables -t nat -F

# Chain Policies gets set up before any bad packets gets through
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

# the allowed chain for TCP connections, utilized in the FORWARD chain
iptables -N allowed
iptables -A allowed -p TCP --syn -j ACCEPT
iptables -A allowed -p TCP -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A allowed -p TCP -j DROP

# ICMP rules, utilized in the FORWARD chain
iptables -N icmp_packets
iptables -A icmp_packets -p ICMP -s 0/0 --icmp-type 0 -j ACCEPT
iptables -A icmp_packets -p ICMP -s 0/0 --icmp-type 3 -j ACCEPT
iptables -A icmp_packets -p ICMP -s 0/0 --icmp-type 5 -j ACCEPT
iptables -A icmp_packets -p ICMP -s 0/0 --icmp-type 11 -j ACCEPT

# POSTROUTING chain in the nat table : Enable IP SNAT for all internal networks trying to get out on the Internet
iptables -t nat -A POSTROUTING -o $INET_IFACE -j SNAT --to-source $INET_IP

# PREROUTING chain in the nat table

         
# Do some checks for obviously spoofed IP's
iptables -t nat -A PREROUTING -i $INET_IFACE -s 192.168.0.0/16 -j DROP
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 172.16.0.0/12 -j DROP
iptables -t nat -A PREROUTING -i $INET_IFACE -s $INET_IP -j DROP

          # Enable IP Destination NAT for DMZ zone (Inbound NAT)
iptables -t nat -A PREROUTING -p TCP -i $INET_IFACE -d $HTTP_IP --dport 80 -j DNAT --to-destination $DMZ_HTTP_IP
iptables -t nat -A PREROUTING -p TCP -i $INET_IFACE -d $DNS_IP --dport 53 -j DNAT --to-destination $DMZ_DNS_IP
iptables -t nat -A PREROUTING -p UDP -i $INET_IFACE -d $DNS_IP --dport 53 -j DNAT --to-destination $DMZ_DNS_IP

          # Enable Internal network connect to DMZ HTTP and DMZ DNS by public IP (update by Adisorn)
iptables -t nat -A PREROUTING -p TCP -i $LAN_IFACE -d $HTTP_IP --dport 80 -j DNAT --to-destination $DMZ_HTTP_IP
iptables -t nat -A PREROUTING -p TCP -i $LAN_IFACE -d $DNS_IP --dport 53 -j DNAT --to-destination $DMZ_DNS_IP
iptables -t nat -A PREROUTING -p UDP -i $LAN_IFACE -d $DNS_IP --dport 53 -j DNAT --to-destination $DMZ_DNS_IP

          #Redirect all http from internal network (not DMZ http destination) to Proxy Server (Transparent Proxy) (update by sorn)
iptables -t nat -A PREROUTING -p TCP -i $LAN_IFACE -s 192.168.1.0/24 -d ! $DMZ_HTTP_IP --dport 80 -j DNAT --to-dest 192.168.2.4:3128

# FORWARD chain

         
# Get rid of bad TCP packets
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

          # DMZ section : General rules
iptables -A FORWARD -i $DMZ_IFACE -o $INET_IFACE -j ACCEPT
iptables -A FORWARD -i $INET_IFACE -o $DMZ_IFACE -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i $LAN_IFACE -o $DMZ_IFACE -j ACCEPT
iptables -A FORWARD -i $DMZ_IFACE -o $LAN_IFACE -j ACCEPT

          # DMZ section : HTTP server
iptables -A FORWARD -p TCP -i $INET_IFACE -o $DMZ_IFACE -d $DMZ_HTTP_IP --dport 80 -j allowed
iptables -A FORWARD -p ICMP -i $INET_IFACE -o $DMZ_IFACE -d $DMZ_HTTP_IP -j icmp_packets         

          #DMZ section : DNS server
iptables -A FORWARD -p TCP -i $INET_IFACE -o $DMZ_IFACE -d $DMZ_DNS_IP --dport 53 -j allowed
iptables -A FORWARD -p UDP -i $INET_IFACE -o $DMZ_IFACE -d $DMZ_DNS_IP --dport 53 -j ACCEPT
iptables -A FORWARD -p ICMP -i $INET_IFACE -o $DMZ_IFACE -d $DMZ_DNS_IP -j icmp_packets                   

          # LAN section
iptables -A FORWARD -i $LAN_IFACE -j ACCEPT
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

          # LOG all packets reaching here
iptables -A FORWARD -m limit --limit 3/minute --limit-burst 3 -j LOG --log-level DEBUG --log-prefix "IPT FORWARD packet died: "

# Firewall rules

         
# INPUT chain

                    #Get rid of bad packets
iptables -A INPUT -p tcp ! --syn -m state --state NEW -j LOG --log-prefix "New not syn:"
iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP

                    # Packets from the Internet to this box
iptables -A INPUT -p ICMP -i $INET_IFACE -j icmp_packets

                    # Packets from LAN, DMZ or LOCALHOST

                              # From DMZ Interface to DMZ firewall IP
iptables -A INPUT -p ALL -i $DMZ_IFACE -d $DMZ_IP -j ACCEPT

                              # From LAN Interface to LAN firewall IP
iptables -A INPUT -p ALL -i $LAN_IFACE -d $LAN_IP -j ACCEPT
iptables -A INPUT -p ALL -i $LAN_IFACE -d $LAN_BCAST_ADRESS -j ACCEPT

                              # From Localhost interface to Localhost IP
iptables -A INPUT -p ALL -i $LO_IFACE -d $LO_IP -j ACCEPT

                    # All established and related packets incoming from the internet to the firewall
iptables -A INPUT -p ALL -d $INET_IP -m state --state ESTABLISHED,RELATED -j ACCEPT

                    # Logging rule
iptables -A INPUT -m limit --limit 3/minute --limit-burst 3 -j LOG --log-level DEBUG --log-prefix "IPT INPUT packet died: "

          # OUTPUT chain

                    # Get rid of bad TCP packets
iptables -A OUTPUT -p tcp ! --syn -m state --state NEW -j LOG --log-prefix "New not syn:"
iptables -A OUTPUT -p tcp ! --syn -m state --state NEW -j DROP

                    # Allow ourself to send packets not spoofed everywhere
iptables -A OUTPUT -p ALL -o $LO_IFACE -s $LO_IP -j ACCEPT
iptables -A OUTPUT -p ALL -o $LAN_IFACE -s $LAN_IP -j ACCEPT
iptables -A OUTPUT -p ALL -o $INET_IFACE -s $INET_IP -j ACCEPT

                    # Logging rule
iptables -A OUTPUT -m limit --limit 3/minute --limit-burst 3 -j LOG --log-level DEBUG --log-prefix "IPT OUTPUT packet died: "

#-----End script------#