#!/bin/sh # /etc/rc.d/rc.firewall-gateway # start/stop/restart iptables firewall rules # base script generated by Easy Firewall Generator # copyright 2002 Timothy Scott Morizot # http://easyfwgen.morizot.net/gen/ # slackware specific version available at # http://www.slackware.com/~alien/efg/ # # modified liberally thereafter # modified for colorized screen messages and local needs source /etc/functions-colors ############################################################################### # # Load Modules # # echo "Loading module support." # Unless you have kernel module auto-loading disabled, you should not # need to manually load each of these modules. Other than ip_tables, # ip_conntrack, and some of the optional modules, I've left these # commented by default. Uncomment if you have any problems or if # you have disabled module autoload. Note that some modules must # be loaded by another kernel module. # core netfilter module # $MODPROBE ip_tables # the stateful connection tracking module # $MODPROBE ip_conntrack # filter table module # $MODPROBE iptable_filter # mangle table module # $MODPROBE iptable_mangle # nat table module # $MODPROBE iptable_nat # LOG target module # $MODPROBE ipt_LOG # This is used to limit the number of packets per sec/min/hr # $MODPROBE ipt_limit # masquerade target module # $MODPROBE ipt_MASQUERADE # filter using owner as part of the match #$MODPROBE ipt_owner # REJECT target drops the packet and returns an ICMP response. # The response is configurable. By default, connection refused. # $MODPROBE ipt_REJECT # This target allows packets to be marked in the mangle table # $MODPROBE ipt_mark # This target affects the TCP MSS # $MODPROBE ipt_tcpmss # This match allows multiple ports instead of a single port or range # $MODPROBE multiport # This match checks against the TCP flags # $MODPROBE ipt_state # This match catches packets with invalid flags # $MODPROBE ipt_unclean # The ftp nat module is required for non-PASV ftp support if [ "$FTP_SERVER" = "yes" ] ; then $MODPROBE ip_nat_ftp # the module for full ftp connection tracking $MODPROBE ip_conntrack_ftp fi # the module for full irc connection tracking # $MODPROBE ip_conntrack_irc ############################################################################### # # Set Policies $IPT -P INPUT DROP $IPT -P OUTPUT DROP $IPT -P FORWARD DROP ############################################################################### # # User-Specified Chains # # Create user chains to reduce the number of rules each packet # must traverse. echo -e "${BOLDWHITE}Creating and populating rule chains.${COLOR_RESET}" # Create a chain to filter INVALID packets $IPT -N bad_packets # Create another chain to filter bad tcp packets $IPT -N bad_tcp_packets # Create separate chains for icmp, tcp (incoming and outgoing), # and incoming udp packets. $IPT -N icmp_packets # Used for UDP packets inbound from the Internet $IPT -N udp_inbound # Used to block outbound UDP services from internal network # Default to allow all $IPT -N udp_outbound # Used to allow inbound services if desired # Default fail except for established sessions $IPT -N tcp_inbound # Used to block outbound services from internal network # Default to allow all $IPT -N tcp_outbound ############################################################################### # # Populate User Chains # # bad_packets chain # # Drop packets received on the external interface claiming a source of the local network $IPT -A bad_packets -p ALL -i $INET_IFACE -s $LAN_NET -j LOG --log-prefix "Illegal source: " $IPT -A bad_packets -p ALL -i $INET_IFACE -s $LAN_NET -j DROP # Drop INVALID packets immediately $IPT -A bad_packets -p ALL -m state --state INVALID -j LOG --log-prefix "Invalid packet: " $IPT -A bad_packets -p ALL -m state --state INVALID -j DROP # Then check the tcp packets for additional problems $IPT -A bad_packets -p tcp -j bad_tcp_packets # All good, so return $IPT -A bad_packets -p ALL -j RETURN # bad_tcp_packets chain # # All tcp packets will traverse this chain. # Every new connection attempt should begin with # a syn packet. If it doesn't, it is likely a # port scan. This drops packets in state # NEW that are not flagged as syn packets. # Return to the calling chain if the bad packets originate # from the local interface. This maintains the approach # throughout this firewall of a largely trusted internal # network. $IPT -A bad_tcp_packets -p tcp -i $LAN_IFACE -j RETURN # However, I originally did apply this filter to the forward chain # for packets originating from the internal network. While I have # not conclusively determined its effect, it appears to have the # interesting side effect of blocking some of the ad systems. # Apparently some ad systems have the browser initiate a NEW # connection that is not flagged as a syn packet to retrieve # the ad image. If you wish to experiment further comment the # rule above. If you try it, you may also wish to uncomment the # rule below. It will keep those packets from being logged. # There are a lot of them. $IPT -A bad_tcp_packets -p tcp -i $LAN_IFACE ! --syn -m state --state NEW -j DROP # $IPT -A bad_tcp_packets -p tcp ! --syn -m state --state NEW -j LOG --log-prefix "New not syn: " $IPT -A bad_tcp_packets -p tcp ! --syn -m state --state NEW -j DROP $IPT -A bad_tcp_packets -p tcp --tcp-flags ALL NONE -j LOG --log-prefix "Stealth scan: " $IPT -A bad_tcp_packets -p tcp --tcp-flags ALL NONE -j DROP $IPT -A bad_tcp_packets -p tcp --tcp-flags ALL ALL -j LOG --log-prefix "Stealth scan: " $IPT -A bad_tcp_packets -p tcp --tcp-flags ALL ALL -j DROP $IPT -A bad_tcp_packets -p tcp --tcp-flags ALL FIN,URG,PSH -j LOG --log-prefix "Stealth scan: " $IPT -A bad_tcp_packets -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP $IPT -A bad_tcp_packets -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j LOG --log-prefix "Stealth scan: " $IPT -A bad_tcp_packets -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP $IPT -A bad_tcp_packets -p tcp --tcp-flags SYN,RST SYN,RST -j LOG --log-prefix "Stealth scan: " $IPT -A bad_tcp_packets -p tcp --tcp-flags SYN,RST SYN,RST -j DROP $IPT -A bad_tcp_packets -p tcp --tcp-flags SYN,FIN SYN,FIN -j LOG --log-prefix "Stealth scan: " $IPT -A bad_tcp_packets -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP # All good, so return $IPT -A bad_tcp_packets -p tcp -j RETURN # icmp_packets chain # # This chain is for inbound (from the Internet) icmp packets only. # Type 8 (Echo Request) is not accepted by default # Enable it if you want remote hosts to be able to reach you. # 11 (Time Exceeded) is the only one accepted # that would not already be covered by the established # connection rule. Applied to INPUT on the external interface. # # See: http://www.ee.siue.edu/~rwalden/networking/icmp.html # for more info on ICMP types. # # Note that the stateful settings allow replies to ICMP packets. # These rules allow new packets of the specified types. # ICMP packets should fit in a Layer 2 frame, thus they should # never be fragmented. Fragmented ICMP packets are a typical sign # of a denial of service attack. $IPT -A icmp_packets --fragment -p ICMP -j LOG --log-prefix "ICMP Fragment: " $IPT -A icmp_packets --fragment -p ICMP -j DROP # Uncomment the LOG command if you also want to log PING attempts # Know that some ISPs block all incoming pings, which will negate # these rules. if [ "$ALLOW_OUTSIDE_PINGS" = "yes" ] ; then echo -e "${BOLDYELLOW}Allowing outside pings.${COLOR_RESET}" $IPT -A icmp_packets -p ICMP -s 0/0 --icmp-type 8 -j ACCEPT if [ "$LOG_OUTSIDE_PINGS" = "yes" ] ; then echo -e "${BOLDYELLOW}Logging outside pings.${COLOR_RESET}" $IPT -A icmp_packets -p ICMP -s 0/0 --icmp-type 8 -j LOG --log-prefix "Ping detected: " else # By default, however, drop pings without logging. Blaster # and other worms have infected systems blasting pings. # Comment the line below if you want pings logged, but it # will likely fill your logs. $IPT -A icmp_packets -p ICMP -s 0/0 --icmp-type 8 -j DROP fi fi # Echo Reply $IPT -A icmp_packets -p ICMP -s 0/0 --icmp-type 0 -j ACCEPT # $IPT -A icmp_packets -p ICMP -s 0/0 --icmp-type 0 -j LOG --log-prefix "Ping-echo reply: " # Destination unreachable $IPT -A icmp_packets -p ICMP -s 0/0 --icmp-type 3 -j ACCEPT # $IPT -A icmp_packets -p ICMP -s 0/0 --icmp-type 3 -j LOG --log-prefix "Ping-dest unreachable: " # Time Exceeded $IPT -A icmp_packets -p ICMP -s 0/0 --icmp-type 11 -j ACCEPT # $IPT -A icmp_packets -p ICMP -s 0/0 --icmp-type 11 -j LOG --log-prefix "Ping-time exceeded: " # Not matched, so return so it will be logged $IPT -A icmp_packets -p ICMP -j RETURN # TCP & UDP # Identify ports at: # http://www.chebucto.ns.ca/~rakerman/port-table.html # http://www.iana.org/assignments/port-numbers # udp_inbound chain # # This chain describes the inbound UDP packets it will accept. # It's applied to INPUT on the external or Internet interface. # Note that the stateful settings allow replies. # These rules are for new requests. # It drops netbios packets (windows) immediately without logging. # Drop netbios calls # Please note that these rules do not really change the way the firewall # treats netbios connections. Connections from the localhost and # internal interface (if one exists) are accepted by default. # Responses from the Internet to requests initiated by or through # the firewall are also accepted by default. To get here, the # packets would have to be part of a new request received by the # Internet interface. You would have to manually add rules to # accept these. I added these rules because some network connections, # such as those via cable modems, tend to be filled with noise from # unprotected Windows machines. These rules drop those packets # quickly and without logging them. This prevents them from traversing # the whole chain and keeps the log from getting cluttered with # chatter from Windows systems. $IPT -A udp_inbound -p UDP -s 0/0 --dport 137 -j DROP $IPT -A udp_inbound -p UDP -s 0/0 --dport 138 -j DROP # Dynamic Address # If DHCP, the initial request is a broadcast. The response # doesn't exactly match the outbound packet. This explicitly # allow the DHCP ports to alleviate this problem. # If you receive your dynamic address by a different means, you # can probably comment this line. $IPT -A udp_inbound -p UDP -s 0/0 --sport 67 --dport 68 -j ACCEPT # Not matched, so return for logging $IPT -A udp_inbound -p UDP -j RETURN # udp_outbound chain # # This chain is used with a private network to prevent forwarding for # UDP requests on specific protocols. Applied to the FORWARD rule from # the internal network. Ends with an ACCEPT # No match, so ACCEPT $IPT -A udp_outbound -p UDP -s 0/0 -j ACCEPT # tcp_inbound chain # # This chain is used to allow inbound connections to the # system/gateway. Use with care. It defaults to none. # It's applied on INPUT from the external or Internet interface. # FTP Server (Control) if [ "$FTP_SERVER" = "yes" ] ; then echo -e "${BOLDYELLOW}Allowing outside FTP access.${COLOR_RESET}" $IPT -A tcp_inbound -p TCP -s 0/0 --dport 21 -j ACCEPT # FTP Client (Data Port for non-PASV transfers) $IPT -A tcp_inbound -p TCP -s 0/0 --sport 20 -j ACCEPT # Passive FTP # # With passive FTP, the server provides a port to the client # and allows the client to initiate the connection rather # than initiating the connection with the client from the data port. # Web browsers and clients operating behind a firewall generally # use passive ftp transfers. A general purpose FTP server # will need to support them. # # However, by default an FTP server will select a port from the entire # range of high ports. It is not particularly safe to open all # high ports. Fortunately, that range can be restricted. This # firewall presumes that the range has been restricted to a specific # selected range. That range must also be configured in the ftp server. # # Instructions for specifying the port range for the wu-ftpd server # can be found here: # http://www.wu-ftpd.org/man/ftpaccess.html # (See the passive ports option.) # # Instructions for the ProFTPD server can be found here: # http://proftpd.linux.co.uk/localsite/Userguide/linked/x861.html $IPT -A tcp_inbound -p TCP -s 0/0 --dport 62000:64000 -j ACCEPT fi # sshd if [ "$ALLOW_OUTSIDE_SSH" = "yes" ] ; then echo -e "${BOLDYELLOW}Allowing outside SSH access on port ${BOLDGREEN}$SSH_PORT${BOLDYELLOW}.${COLOR_RESET}" echo -e "Please verify ${BOLDGREEN}/etc/hosts.allow${COLOR_RESET} allows SSH access." $IPT -A tcp_inbound -p TCP -s 0/0 --dport $SSH_PORT -j ACCEPT fi # Not matched, so return so it will be logged $IPT -A tcp_inbound -p TCP -j RETURN # tcp_outbound chain # # This chain is used with a private network to prevent forwarding for # requests on specific protocols. Applied to the FORWARD rule from # the internal network. Ends with an ACCEPT # No match, so ACCEPT $IPT -A tcp_outbound -p TCP -s 0/0 -j ACCEPT ############################################################################### # # INPUT Chain # echo "Processing INPUT chain." # Allow all on localhost interface $IPT -A INPUT -p ALL -i $LO_IFACE -j ACCEPT # Drop bad packets $IPT -A INPUT -p ALL -j bad_packets # DOCSIS compliant cable modems # Some DOCSIS compliant cable modems send IGMP multicasts to find # connected PCs. The multicast packets have the destination address # 224.0.0.1. You can accept them. If you choose to do so, # Uncomment the rule to ACCEPT them and comment the rule to DROP # them. The firewall will drop them here by default to avoid # cluttering the log. The firewall will drop all multicasts # to the entire subnet (224.0.0.1) by default. To only affect # IGMP multicasts, change '-p ALL' to '-p 2'. Of course, # if they aren't accepted elsewhere, it will only ensure that # multicasts on other protocols are logged. # Drop them without logging. $IPT -A INPUT -p ALL -d 224.0.0.1 -j DROP # The rule to accept the packets. # $IPT -A INPUT -p ALL -d 224.0.0.1 -j ACCEPT # Rules for the private network (accessing gateway system itself) $IPT -A INPUT -p ALL -i $LAN_IFACE -s $LAN_NET -j ACCEPT $IPT -A INPUT -p ALL -i $LAN_IFACE -d $LAN_BCAST -j ACCEPT # Allow DHCP client request packets inbound from internal network if [ "$DHCP_SERVER" = "yes" ] ; then echo -e "${BOLDYELLOW}Allowing DHCP services on local network.${COLOR_RESET}" $IPT -A INPUT -p UDP -i $LAN_IFACE --sport 68 --dport 67 -j ACCEPT fi # Inbound Internet Packet Rules # Accept Established Connections $IPT -A INPUT -p ALL -i $INET_IFACE -m state --state ESTABLISHED,RELATED -j ACCEPT # Route the rest to the appropriate user chain $IPT -A INPUT -p TCP -i $INET_IFACE -j tcp_inbound $IPT -A INPUT -p UDP -i $INET_IFACE -j udp_inbound $IPT -A INPUT -p ICMP -i $INET_IFACE -j icmp_packets # Drop without logging broadcasts that get this far. # Cuts down on log clutter. # Comment this line if testing new rules that impact # broadcast protocols. $IPT -A INPUT -m pkttype --pkt-type broadcast -j DROP # Log packets that still don't match # Enable this only if curious who might be trying to bang into the box. #$IPT -A INPUT -m limit --limit 3/minute --limit-burst 3 -j LOG --log-prefix "INPUT packet died: " ############################################################################### # # FORWARD Chain # # Used when forwarding for a private network echo "Processing FORWARD chain." # Drop bad packets $IPT -A FORWARD -p ALL -j bad_packets # Accept TCP packets we want to forward from internal sources $IPT -A FORWARD -p tcp -i $LAN_IFACE -j tcp_outbound # Accept UDP packets we want to forward from internal sources $IPT -A FORWARD -p udp -i $LAN_IFACE -j udp_outbound # If not blocked, accept any other packets from the internal interface $IPT -A FORWARD -p ALL -i $LAN_IFACE -j ACCEPT # Deal with responses from the internet $IPT -A FORWARD -i $INET_IFACE -m state --state ESTABLISHED,RELATED -j ACCEPT # Log packets that still don't match $IPT -A FORWARD -m limit --limit 3/minute --limit-burst 3 -j LOG --log-prefix "FORWARD packet died: " ############################################################################### # # OUTPUT Chain # echo "Processing OUTPUT chain." # Generally trust the firewall on output # However, invalid icmp packets need to be dropped # to prevent a possible exploit. $IPT -A OUTPUT -m state -p icmp --state INVALID -j DROP # Localhost $IPT -A OUTPUT -p ALL -s $LO_IP -j ACCEPT $IPT -A OUTPUT -p ALL -o $LO_IFACE -j ACCEPT # To internal network $IPT -A OUTPUT -p ALL -s $LAN_IP -j ACCEPT $IPT -A OUTPUT -p ALL -o $LAN_IFACE -j ACCEPT # To internet $IPT -A OUTPUT -p ALL -o $INET_IFACE -j ACCEPT # Log packets that still don't match $IPT -A OUTPUT -m limit --limit 3/minute --limit-burst 3 -j LOG --log-prefix "OUTPUT packet died: " ############################################################################### # # nat table # ############################################################################### # The nat table is where network address translation occurs if there # is a private network. If the gateway is connected to the Internet # with a static IP, snat is used. If the gateway has a dynamic address, # masquerade must be used instead. There is more overhead associated # with masquerade, so snat is better when it can be used. # The nat table has a builtin chain, PREROUTING, for dnat and redirects. # Another, POSTROUTING, handles snat and masquerade. echo "Processing firewall NAT table." ############################################################################### # # PREROUTING chain # # Redirect HTTP through a transparent proxy if [ "$TRANS_PROXY" = "yes" ] ; then echo -e "${BOLDYELLOW}Forcing gateway services to transparent proxy.${COLOR_RESET}" # first provide prerouting exception rules from the LAN #echo "Providing transparent proxy rerouting exception for address 192.168.1.xx" #$IPT -t nat -A PREROUTING -p tcp -s 192.168.1.xx --dport 80 -j RETURN #$IPT -t nat -A PREROUTING -p tcp -s 192.168.1.xx --dport 443 -j RETURN # next define what from the LAN is routed through the proxy #$IPT -t nat -A PREROUTING -p tcp --dport 21 -j REDIRECT --to-ports $PROXY_PORT $IPT -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports $PROXY_PORT #$IPT -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-ports $PROXY_PORT # don't forget to route local users through the proxy $IPT -t nat -A OUTPUT -p tcp -m owner --dport 80 --uid-owner squid -j ACCEPT $IPT -t nat -A OUTPUT -p tcp -m owner --dport $PROXY_PORT --uid-owner squid -j ACCEPT # exempt certain local users #$IPT -t nat -A OUTPUT -p tcp --dport 80 -m owner --uid-owner x_user_name_x -j ACCEPT # now set final rule for the proxy $IPT -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-ports $PROXY_PORT fi ############################################################################### # # POSTROUTING chain # $IPT -t nat -A POSTROUTING -o $INET_IFACE -j MASQUERADE ############################################################################### # # mangle table # ############################################################################### # The mangle table is used to alter packets. It can alter or mangle them in # several ways. For the purposes of this generator, we only use its ability # to alter the TTL in packets. However, it can be used to set netfilter # mark values on specific packets. Those marks could then be used in another # table like filter, to limit activities associated with a specific host, for # instance. The TOS target can be used to set the Type of Service field in # the IP header. Note that the TTL target might not be included in the # distribution on your system. If it is not and you require it, you will # have to add it. That may require that you build from source. # echo "Load rules for mangle table ..."