Some notes on Linux as a Firewall: Note that "-m state --state" is being used instead of the newer "-m conntrack --ctstate", because not all versions of Linux support it yet. ----8<---- # Basic INPUT policy: # Drop packets with impossible TCP flag combinations before they hit conntrack rules. # Drop fragmented ICMP # Allow incoming ping. # Drop INVALID state traffic, and allowed any ESTABLISHED,RELATED # Allow incoming SSH, but limit to 3 connections per min. per IP to prevent brute force attack chatter in logs. # Drop anything else. iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -p tcp -m tcp --tcp-flags ALL ALL -j DROP iptables -A INPUT -p tcp -m tcp --tcp-flags SYN,FIN SYN,FIN -j DROP iptables -A INPUT -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP iptables -A INPUT -p tcp -m tcp --tcp-flags ALL FIN,URG,PSH -j DROP iptables -A INPUT -p tcp -m tcp --tcp-flags ALL NONE -j DROP iptables -A INPUT -p icmp -f -j DROP iptables -A INPUT -p icmp -m icmp --icmp-type echo-request -j ACCEPT iptables -A INPUT -m state --state INVALID -j DROP iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name DEFAULT --rsource iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 --name DEFAULT --rsource -j DROP iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -j ACCEPT # Other incoming traffic to allow here. iptables -A INPUT -j DROP # If you're super-paranoid you can lock down outgoing connections as well. # In this example only processes owned by the user or group root are allowed to send traffic. # This includes setuid tools like ping. # DNS traffic is premitted. iptables -A OUTPUT -o lo -j ACCEPT iptables -A OUTPUT -m state --state INVALID -j DROP iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -m state --state NEW -m owner --uid-owner root -j ACCEPT iptables -A OUTPUT -m state --state NEW -m owner --gid-owner root -j ACCEPT iptables -A OUTPUT -m state --state NEW -p udp -m udp --dport 53 -j ACCEPT iptables -A OUTPUT -m state --state NEW -p tcp -m tcp --dport 53 -j ACCEPT # Other outgoing traffic to allow here. iptables -A OUTPUT -j DROP # If NOTRACK is supported, don't pass loopback traffic through conntrack (better performance) iptables -t raw -A PREROUTING -i lo -j NOTRACK # If running a local proxy server, or service that makes a lot of outgoing TCP connections: # Edit "/usr/src/linux/include/net/tcp.h" and modify TCP_TIMEWAIT_LEN to be 15 seconds instead of 60 (default) and re-complile Linux. # 15 seconds is the system default used by IBM in AIX and is considered safe. # Increase the ephemeral port range: echo 1025 65535 > /proc/sys/net/ipv4/ip_local_port_range # Reserve any service ports in the new range from being used: echo 5000,6667-6669,10000 > /proc/sys/net/ipv4/ip_local_reserved_ports # If acting as a router or transparent firewall bridge: # Note it is important to drop INVALID packets if doing NAT, else INVALID state traffic will leak private addresses. # In this example eth0 is OUTSIDE and eth1 is INSIDE, all traffic from INSIDE is trusted. iptables -A FORWARD -p tcp -m tcp --tcp-flags ALL ALL -j DROP iptables -A FORWARD -p tcp -m tcp --tcp-flags SYN,FIN SYN,FIN -j DROP iptables -A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP iptables -A FORWARD -p tcp -m tcp --tcp-flags ALL FIN,URG,PSH -j DROP iptables -A FORWARD -p tcp -m tcp --tcp-flags ALL NONE -j DROP iptables -A FORWARD -p icmp -f -j DROP iptables -A FORWARD -m state --state INVALID -j DROP iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT # Rules to block or allow internal traffic here. iptables -A FORWARD -i eth1 -m state --state NEW -j ACCEPT iptables -A FORWARD -j DROP # Kernel options to verify: echo 1 > /proc/sys/net/ipv4/ip_forward # Enable IP forwarding echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirects # Don't accept ICMP redirect echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects # Don't send ICMP redirect either echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route # Don't accept source routed packets echo 1 > /proc/sys/net/ipv4/conf/all/log_martians # Log packets dropped by rp_filter echo 2 > /proc/sys/net/ipv4/ip_dynaddr # Permit and log dynamic source rewriting (required for FW) echo 0 > /proc/sys/net/ipv4/tcp_ecn # Disable Explicit Congestion Notification echo 1 > /proc/sys/net/ipv4/conf/all/arp_announce # Prefer local subnet IP to respond for ARP source echo 2 > /proc/sys/net/ipv4/conf/all/arp_ignore # Ignore ARP unless its on and from the local subnet echo 4096 > /proc/sys/net/netfilter/nf_conntrack_expect_max # Increases the default conntrack expect from 256 to 4096 echo 1 > /proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_be_liberal # Don't use TCP window scale as a determinant for packet validity echo 2048 > /proc/sys/net/ipv4/neigh/default/gc_thresh1 # ARP table minimum before GC echo 8192 > /proc/sys/net/ipv4/neigh/default/gc_thresh2 # ARP table soft maxium echo 16384 > /proc/sys/net/ipv4/neigh/default/gc_thresh3 # ARP table hard maxium echo 300 > /proc/sys/net/ipv4/neigh/default/base_reachable_time # ARP cache valid minimum of between 150 and 450 seconds (random) echo 128 > /proc/sys/net/ipv4/igmp_max_memberships # IGMP max member groups echo 1 > /proc/sys/net/ipv6/conf/all/forwarding # Enable IPv6 forwarding echo 0 > /proc/sys/net/ipv6/conf/all/accept_ra # Don't accept IPv6 RA from other hosts (rogue IPv6 routers) # If doing a transparent firewall: echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables # Enable netfilter processing on bridgged traffic # Note that if looping traffic in and out of bridged interfaces, conntrack will get confused. # The work-around for this is to use the NOTRACK target in the raw table for the specific interfaces being looped. # If running as a router or firewall with services, lock down INPUT chain for INSDIE traffic: iptables -A INPUT -i eth1 -m state --state NEW -p udp -m udp --sport 68 --dport 67 -j ACCEPT iptables -A INPUT -i eth1 -m state --state NEW -p udp -m udp --dport 53 -j ACCEPT iptables -A INPUT -i eth1 -m state --state NEW -p tcp -m tcp --dport 53 -j ACCEPT iptables -A INPUT -i eth1 -m state --state NEW -p udp -m udp --dport 123 -j ACCEPT ----8<----