#!/bin/sh # $ID: killerwall,v 0.11.2test2 2001/02/27 02:25:45 defile Exp $ # # chkconfig: 2345 09 91 # description: Activates and deactivates killerwall (ipchains based) \ # firewall ruleset. # # Credits: # defile #kde@EFnet ipchains ruleset, shell scripting. # allegro #kde@EFnet without him killerwall would have never gotten off # the ground. he's responsible for a lot, but too # humble to admit it. much of the functionality in # initial versions of the script are due to his # efforts. he also prototyped AUTODNS. # Mistik1 #kde@EFnet for the prototype of the chkconfig interface, # exhaustive testing, tons of input, and RPMs. # RADKade1 #kde@EFnet patches to the $IPMASQ portion # rajak #linuxhelp@EFnet a very nice code patch, a awesome feedback # report, and a nudge in a new direction. # kevlinux #kde@EFnet Helping me figure out why this script would break in # RedHat (and only RedHat mind you). # moonpie #kde@EFnet made the 2.4 kernel ipchains capability checking a # lot more sane # # This code is released under the BSD license # # Copyright (c) 2000-2001,defile # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # start intelligent code # The first step is to edit the following variables to reflect your setup # Create some variables. 0==NO or FALSE, 1==YES or TRUE # in cases where 0 or 1 obviously wont do, look at the comment to the right CHAINS=/sbin/ipchains #your correct path to ipchains HOSTILE=ppp0 #This should be your interface to the Internet NOPING=0 #0 pass icmp 1 to block IPMASQ=0 #to masq...or not (0 no, 1 yes) * See Note 1 LOCALNET=192.168.0.1/24 #your internal LAN ip/mask (see RFC 1918) LOGGING=1 #Set to 0 if you want to turn off logging. NOTRACEROUTE=0 #1 to block, if you need udp 33433:33523 don't use NOFRAG=0 #1 to block fragmented packets (experimental) # *Note 1 If you are doing this with a RedHat based system (This includes # Caldera, Mandrake and TurboLinux among others) and you what to integrate this # script with your init via chkconfig, I suggest you edit # /etc/sysconfig/network and change the value of "FORWARD_IPV4" to # "FORWARD_IPV4=yes". Otherwise when your runlevel runs the network script # it'll use Linux's sysctl interface to turn off the ability to forward # packets. If you don't do this, then ipmasquerade won't work. If you don't # intend to do any ipmasquerading/NAT, then disregard. # This section is for naming your internal LAN interfaces. This allows you to # define as many as you need (keep in mind the kernel only allows so many # Ethernet cards and there isn't any sanity checking in the code). All the # interfaces are separated by ":" with no whitespace. Here is an Example: # "FRIENDLY=eth0:eth1:eth2:eth3" # This will allow all packets to come through these interfaces unhindered. # Make sure you don't screw up and accidently put $HOSTILE (external interface) # as well. If you don't have a internal LAN, then just leave it as # "FRIENDLY=0". FRIENDLY=0 # Set to 1 if you'd like this script to use /etc/resolv.conf to allow # access to DNS through the firewall. AUTODNS=1 # Set this to the TCP ports that you would like to leave open to *EVERYONE*. # This will open the TCP ports you specify to ALL on $HOSTILE. You *DON'T* # have to specify ports 1024 - 5999 and 6010 - 65535. They are allowed later # on in the script (trust me, you want it this way). If you don't want to # allow any extra ports (good choice :-), then set it as "ALLOW=0". # As it is right now, it allows port 113. Separate with ":". You can also # select a range of ports by using a "-". Here is an example using both: # "ALLOW=21-25:80:113". This would allow access to TCP ports 21 - 25, 80 # (httpd), and 113 (auth/ident). If you want to open UDP ports, see the next # variable. If you will be doing portforwarding (configured further down), # do not open the ports you'll be using for this here. This will be done for # you automatically. ALLOW=113 # Set this next variable to allow access to UDP ports by a external network # (e.g. the Internet). Confirm you actually need it first. You don't need to # allow 53/udp for your ISPs DNS server. This is done for you later auto- # magically through AUTODNS= . However, if you are running bind (for named), # and you want an external network to access it, then this is for you. If in # doubt, 'grep udp /etc/services' and see if you really need it. If still in # doubt, or all this seems like greek to you, then leave it with the default. # ALLOW_UDP=0 # You don't need to enable this for ports 1024-5999 and 6011-65535 (unless you # have NOTRACEROUTE=1. In that case 33434-33523/udp is blocked to stop trace- # routes). You can specify ports using a colon delimited list. For example, # ALLOW_UDP=53:111 would allow external networks to communicate with your # named and portmapper. Like it's TCP counterpart, it also accepts port # ranges, and is configured exactly the same way. Don't add any UDP ports # you'll be forwarding, this will be done automatically by the script. ALLOW_UDP=0 # This is for blocking out ports between 1023-6000 and 6011-65535. The default # is fine for most, but if you are running something like mysql (port 3306 # TCP/UDP), then this will prevent it from accepting connections on $HOSTILE. # Selecting port ranges works for this as well. For instance if you wanted to # block out anyone from your mysql port and ports 10000 - 20000 (I know, odd, # but it's just an example, work with me), then you'd use # "BLOCK_HIGH=3306:10000-20000". This effects both TCP and UDP. BLOCK_HIGH=0 # Use this to set trusted IPs. Any IPs you add will be allowed to do # anything. This has serious security implications, so use carefully. Better # yet, don't use it at all. It is only here for flexibility. You don't need to # add your ISPs DNS here, or your internal LAN IPs. This is meant to be # used to connect subnets or sites you really trust and must have total # connectivity with. It is defaulted to "TRUSTED=0", which means you are # living paranoid like a good firewall should. The bad thing about trusted # networks, is your security is only as good as theirs is. IOW if they are # compromised, you are screwed . You have been warned!!! Ok, now how # to use this, just change "TRUSTED=0" to # "TRUSTED=xxx.xxx.xxx.xxx:xxx.xxx.xxx.xxx:etc.etc.etc.etc" # Notice a trend? That is correct, all the ip's are separated by ":". TRUSTED=0 # Alright, I like this one much better. Use this to explicitly block all # packets from these IPs. So if someone is flood pinging you, or just doing # suspicious stuff, you just block them out altogether. You can even use Class # "A" (/8), Class "B" (/16) or Class "C" (/24) to block someone with a dynamic # IP (e.g. dialup and is just disconnecting and reconnecting to get a new IP. # Example use would be "BLACKBALL=168.191.215.1/24:151.198.130.11/16". There, # you just blocked out everyone using earthlink in my area, and a bunch of poor # souls at bellatlantic.net. It defaults to "BLACKBALL=0", which means no one # has given you a reason to block then out yet ;-). Make sure you restart the # script after you add IPs/Net masks. One major caveat, make sure that no one # is spoofing a IP you really need packets from and tricks you into adding a # rule for that IP. Could make you DoS yourself! The good news, this is setup # so that you could blackball your entire ISP, and still get traffic from their # DNS servers. Situational awareness should be employed here. BLACKBALL=0 # The next part has to do with configuration of killerwall for prevention of # Land type attacks and spoofing attempts using your external inteface IP. # The Linux kernel has been patched against Land attacks themselves for a long # time, but caution isn't a bad thing. This will also protect against varients # of Land that have not yet surfaced. A Land attack works by sending a TCP # packet to a IP with the same source and destination IP in the packet header. # What eventually happens is your computer goes nuts answering itself # (this is because the computer will continiously attempt increment sequence # numbers in a vain attempt to establish the three-way handshake) until it # either utilizes all it's resources, or erupts in a beautiful fireworks # display. This will also prevent spoofing attempts if the attacker tries to # send packets to you, as you (believe it or not, some firewalls don't block # these). If you don't have a static IP, than you aren't out of luck, just # rerun the script whenever the interface is brought up. If you're using ppp # just do this; 'echo "/path/to/killerwall start" >/etc/ppp/ip-up.local'. # This will rerun the script each time your ppp connection is established, and # make a rule to block packets from your external interface ($HOSTILE) with # your IP as the source IP in the packet header. If you don't have a static # IP, you don't need to set this to enable this protection. This will just # automatically build a rule if you do have a static IP. # Is your internet IP static or not (0 no, 1 yes)? STATIC=0 #If so, what is the IP (HINT: you'll probably need to edit this :)? STATIC_IP=1.1.1.1 # Advanced options: # 99% percent of you could stop here and be considered done. For you, the # script is ready to run (assuming its chmod 700 :). For the other 1%, I'm # including some advanced options. These options include the ability to turn # off automatic blocking of non-routable IPs, limiting outbound connections to # certain IPs and ports, and setting up a DMZ and portforwarding. If you think # any of this applies to you, read on. # The first thing I'm going to cover in this section is disabling non-routable # IPs. What I'm talking about here is the IP blocks reserved for internal LAN # IPs. This covers 10.0.0.1/8, 172.16.0.0/12, and 192.168.0.0/16. The reason I # have this here is because some people do host based firewalling and there are # cases where their $HOSTILE also happens to be their internal LAN interface. # If that happens to apply to you, then just change the variable below to # "OPEN_NO_ROUTE=1". OPEN_NO_ROUTE=0 # This will deal with outbound ports via the external interface ($HOSTILE) you'd # like to block. This script defaults to not blocking any outbound ports, as # long as it's "BLOCK_OUTBOUND_PORTS=0". Here is an example of how to use this; # "BLOCK_OUTBOUND_PORTS=21:23:6777" would block your $LOCALNET and $DMZNET (more # on this later) from connecting to outside FTP, TELNET and IRC servers, # assuming they are using standard ports. Notice that each port is separated # by a ":". You can also select port ranges by using a "-", for example: # "BLOCK_OUTBOUND_PORTS=25:135-140" would prevent your internal LAN and DMZ # from connecting to external mailservers and Netbios ports. This will effect # both TCP and UDP. BLOCK_OUTBOUND_PORTS=0 # You can use this to block your $LOCALNET and $DMZNET (there's that variable # again, it's explained below) from accessing certain IPs. It defaults to # "BLOCK_OUTBOUND_HOSTS=0" which means it doesn't prevent access to any IPs. An # example of how to use this would be; # "BLOCK_OUTBOUND_HOSTS=64.12.149.13:205.188.146.23:205.188.160.121". This will # allow you to prevent connections to aol.com (nslookup is your friend). Each # IP must be separated by a ":". BLOCK_OUTBOUND_HOSTS=0 # Set this variable to "LOCALNET_SECURE=1" if you don't want your internal LAN # to send packets directly to your firewall. For home use, this probably won't # be useful at all, but in a corporate/work environment, I'd say it's manditory # that you use this. The statistics for internal intrusion are various, but all # of them are alarmingly high. I realize that this means you have to administer # locally, but you'll sleep better at night. Setting "LOCALNET_SECURE=0" to # "LOCALNET_SECURE=1" will prevent your firewall from receiving packets directly # addressed to it from your internal LAN. Don't worry, this will not prevent # your internal LAN from using the firewall as a gateway or a router. LOCALNET_SECURE=0 # *PHEW* Now we get to the really heavy propellerhead stuff. # # Why a DMZ, you may ask? For one thing it can greatly enhance the security of # your network by running all the vulnerable serivces on the DMZ computers and # abstracting the DMZ from your LAN. There are a couple of key concepts # involved here. One, you want to limit the amount of services you do run on # your DMZ hosts (limiting the usefulness if they do get hacked, chroot is also # your friend here), and you want to limit or prevent any direct communication # with your Firewall and internal LAN. Second, with the abstraction provided # by the firewall, depending on what services you do offer on the DMZ, about # all a cracker will discover is just how useless the machine they just # conquered is to them. Even if they can use a buffer overflow to start # services, how can they get those services to be reachable to them? A little # planning a forethought can go a long way here. You could even go as far as # running killerwall as a host based firewall on each DMZ host and make things # really intresting. Just setting the variables below won't be enough, you'll # also have to use this in conjunction with the portforwarding setup provided # below. To realize the full benefit of a DMZ, ideally you'll need a # multi-homed firewall with one interface for your internet, one for your # internal LAN and one doglegged off for the DMZ hosts themselves (giving them # their own subnet is advisable as well). # If you want killerwall to configure for a DMZ, change "DMZ=0" to "DMZ=1". DMZ=0 # This is the separate interface you'll be using for your DMZ, try to be nice # and don't use one already reserved for $FRIENDLY DMZ_IFACE=eth3 # Network block you'll be using for the DMZ hosts. DMZNET=172.16.0.0/12 # You've finally made it to the portforwarding section. For this to work # you'll need ipmasqadm installed. If it didn't come with your distribution # you can find it at http://juanjox.linuxhq.com. You'll also need the # ip_masq_autofw.o kernel module (if you're running RedHat Linux, it's there # already by default). I'll be using the autofw portion of ipmasqadm for # purposes of flexability. It makes portforwarding interface IP independant # (read that to mean you don't need to know your IP to run it). If you have a # static IP and wish to use portfw instead, then make sure you have the # ip_masq_portfw.o kernel module and hack the code accordingly. This script # will allow you to specify up to four hosts you'd like to forward ports to. # Other than setting up the variables correctly, all you have to do is make # sure that services you wish to forward, aren't being offered on the firewall # itself. Do *NOT* add the ports you'll be forwarding to the $ALLOW* variables. # The script will do that automatically. One word of advice, FTP doesn't # always take too kindly to being forwarded. It may or may not work as # advertised and YMMV. If you must, consider using some sort of proxy. I'm not # encouraging you to run a FTP server anyhow, as they are far too vulnerable to # exploit and misconfiguration. I also don't suggest using this to forward # ports to localhost. If you wish to do that, man ipchains and throw a # REDIRECT rule into the code somewhere. If you need more than four hosts, you # are cordially invited to hack the code for that as well. # To specify the IP address of the first host you'd like to forward ports to, # change "PORTFW_HOST1=0" to "PORTFW_HOST1=ip.of.tar.get" (don't use that # example literally). Follow this same method with "PORTFW_HOST2-PORTFW_HOST4" # as well. If you don't need them, just leave them as "PORTFW_HOST?=0". PORTFW_HOST1=0 PORTFW_HOST2=0 PORTFW_HOST3=0 PORTFW_HOST4=0 # Here is where you specify which ports you'll be forwarding to which host. # Each host has separate controls for TCP and UDP. PORTFW_HOST1_PORTS_TCP and # PORTFW_HOST1_PORTS_UDP would correlate to PORTFW_HOST1 for TCP and UDP # respectively. Define which ports you'd like to have forwarded to # $PORTFW_HOST1-4 using a colon delimited list. For example, if you wanted to # forward UDP ports 22 and 53 to $PORTFW_HOST1, then set # "$PORTFW_HOST1_PORTS_UDP=0" to "$PORTFW_HOST1_PORTS_UDP=22:53". That would # forward all SSH and DNS connections to PORTFW_HOST1. There isn't a limit to # how many ports you can forward per host (assuming they aren't used on another # host and doesn't go any higher then 65535), but it's probably prudent to # limit how many useful services you're offering. This is far easier to manage, # and assuming you're using this in conjunction with a DMZ, will make it far # more effective. These variables do not accept port ranges. If someone can # give me a compelling reason why they should, I'll make it happen. # Forward the following TCP ports to $PORTFW_HOST1 PORTFW_HOST1_PORTS_TCP=53 # Forward the following UDP ports to $PORTFW_HOST1 PORTFW_HOST1_PORTS_UDP=53 # Forward the following TCP ports to $PORTFW_HOST2 PORTFW_HOST2_PORTS_TCP=80 # Forward the following UDP ports to $PORTFW_HOST2 PORTFW_HOST2_PORTS_UDP=80 # Forward the following TCP ports to $PORTFW_HOST3 PORTFW_HOST3_PORTS_TCP=25 # Forward the following UDP ports to $PORTFW_HOST3 PORTFW_HOST3_PORTS_UDP=25 # Forward the following TCP ports to $PORTFW_HOST4 PORTFW_HOST4_PORTS_TCP=0 # Forward the following UDP ports to $PORTFW_HOST4 PORTFW_HOST4_PORTS_UDP=0 # ---- DO NOT MAKE CHANGES BELOW THIS LINE export VERSION=0.11.2test2 # initlog (if present) can interface with syslogd and make entries to # /var/log/messages, otherwise use logger. export SYSLOGGER=/usr/bin/logger # Verify root if [ $UID != 0 ]; then if [ -x $SYSLOGGER ]; then # Give root a heads up that their permissions on this script are not # correct if a normal user is able to access this file. It should be # chmod 700 and chown root.root $SYSLOGGER -t killerwall "$USERNAME has attempted to run Killerwall." $SYSLOGGER -t killerwall "Verify permissions for the script are 700." $SYSLOGGER -t killerwall "Verify the script chowned root.root." fi echo "You must be root to run this script!" ; exit 1 fi # Check and see if we're using one of the 2.4.x or 2.2.x kernels and if we have # ipchains support in the kernel export UNAME=`awk '{printf("%3.3s\n",$3)}' /proc/version` if [ $UNAME = 2.4 ]; then echo "Checking kernel for ipchains compatability..." sleep 1 # This first check tests to see if ipchains is configured as a module modprobe ipchains > /dev/null 2>&1 IPCHAINS_COMPAT=`lsmod |grep ipchains` if [ "$IPCHAINS_COMPAT" = "" ]; then # A check to test if ipchains support is compiled directly into the # kernel ipchains -L &>/dev/null if [ $? != 0 ];then echo "This kernel does not have ipchains support!" echo "Make sure you compile ipchains into the kernel" echo "or as a kernel module with IPCHAINS_BACKWARD_COMPAT" exit 1 fi fi else if [ $UNAME != 2.2 ]; then echo "You are using the wrong kernel for this firewall!" ; exit 1 fi fi # Look for the presence of a /etc/rc.d/init.d/functions file and source it. if [ -f /etc/rc.d/init.d/functions ]; then . /etc/rc.d/init.d/functions fi case "$1" in start) # Temporarily turn on forwarding to silence warnings. if [ -f /proc/sys/net/ipv4/ip_forward ]; then echo 1 > /proc/sys/net/ipv4/ip_forward fi # Verify $CHAINS var if [ -x $CHAINS ]; then echo "Activating firewall ruleset..." else echo "" echo "Cant find the ipchains binary. $CHAINS doesn't exist." echo "Please ensure CHAINS= reflects where ipchains is installed." echo "You may have to install ipchains. It should be on the" echo "distribution CDROM." ; exit 1 fi # See if /etc/firewall.conf is there, and if so, parse it and use it for # config options. if [ -f /etc/firewall.conf ]; then source /etc/firewall.conf fi # flush old ruleset $CHAINS -F input $CHAINS -F output $CHAINS -F forward # set default policies $CHAINS -P input DENY $CHAINS -P output ACCEPT $CHAINS -P forward DENY # use Linux's sysctl to take care of some of ipchains shortcomings if [ -e /proc/sys/net/ipv4/conf/all/rp_filter ]; then echo -n "Enabling kernel level IP spoofing protection..." for f in /proc/sys/net/ipv4/conf/all/rp_filter; do echo 2 > $f done echo "done." else echo "" echo "Attempted to enable kernel level IP spoofing protection." echo "This kernel does not support that option." fi if [ -e /proc/sys/net/ipv4/conf/all/accept_redirects ]; then echo -n "Disabling ICMP redirect acceptance..." for f in /proc/sys/net/ipv4/conf/all/accept_redirects; do echo 0 > $f done echo "done." else echo "" echo "Attemted to disable ICMP redirect acceptance." echo "This kernel does not support that option." fi if [ -e /proc/sys/net/ipv4/conf/all/accept_source_route ]; then echo -n "Disabling source routed packets..." for f in /proc/sys/net/ipv4/conf/all/accept_source_route; do echo 0 > $f done echo "done." else echo "" echo "Attempted to disable source routed packets." echo "This kernel does not support that option." fi # a little anti syn flood action if [ -e /proc/sys/net/ipv4/tcp_syncookies ]; then echo -n "Attempting to enable SYN packet flood protection..." for f in /proc/sys/net/ipv4/tcp_syncookies; do echo 1 > $f echo 3 > /proc/sys/net/ipv4/tcp_syn_retries echo 3 > /proc/sys/net/ipv4/tcp_retries1 echo 7 > /proc/sys/net/ipv4/tcp_retries2 done echo "done." else echo "" echo "Unable to load SYN flood protection. The kernel needs to be " echo "compiled with ENABLE_TCP_COOKIES. " fi # determine if logging is enabled and setting a flag to avoid $LOGGING var # checks for each rule if [ $LOGGING = 1 ]; then export FLAG="-l" fi # this is standard for loopback $CHAINS -A input -i lo -j ACCEPT # doing a preliminary check for local DNS servers. this will be used later for # both AUTODNS and allowing the firewall to get DNS traffic from either your # $LOCALNET and/or $DMZ DNS_SERVER_CHECK=`/sbin/route -n | grep UH | grep -v $HOSTILE` if [ "$DNS_SERVER_CHECK" != "" ]; then DNS_SERVER=`echo $DNS_SERVER_CHECK | awk '{print $1}'` fi # build a rule to allow internal DNS traffic to pass from the DMZ or internal # LAN. if [ $LOCALNET_SECURE = 1 ] || [ $DMZ = 1 ]; then # god help you if you're running named on your firewall, but I'll check # anyhow before just blindly adding a rule if [ "$DNS_SERVER_CHECK" != "" ]; then DNS_SERVER_IFACE=`echo $DNS_SERVER_CHECK | awk '{print $8}'` INT_DNS_SERVER=`ifconfig $DNS_SERVER_IFACE | grep $DNS_SERVER` if [ "$INT_DNS_SERVER" = "" ]; then $CHAINS -A input -i $DNS_SERVER_IFACE -p udp -s $DNS_SERVER \ --dport 53 -j ACCEPT echo "Allowing DNS traffic from $DNS_SERVER" else echo "Warning!!! You are running named on your firewall." echo "This can be potentually devastating to the security" echo "of your network." fi fi fi # block internal LAN packets destined to the firewall if LOCALNET_SECURE=1 # the above will still allow internal DNS traffic to pass if [ $LOCALNET_SECURE = 1 ]; then export FRIENDLYP=`echo $FRIENDLY | sed -e s/":"/" "/g` for FRIENDLYPII in `echo $FRIENDLYP` do # detect the ip of the LAN interface # block packets from the internal LAN addressed to the firewall if /sbin/ifconfig $FRIENDLYPII 2>/dev/null | grep UP \ >/dev/null 2>&1 ; then IFACE_IP=`/sbin/ifconfig $FRIENDLYPII | grep 'inet addr' \ | awk '{print $2}' | sed -e 's/.*://'` $CHAINS -A input -i $FRIENDLYPII -p tcp -s $LOCALNET -d $IFACE_IP \ -j REJECT -l $CHAINS -A input -i $FRIENDLYPII -p udp -s $LOCALNET -d $IFACE_IP \ -j REJECT -l echo "Blocking internal LAN packets addressed to the firewall." # if unable to detect the ip of the interface, go aggressive # cut off the network and go into a standalone mode this will have no # effect on the DMZ if it exist else $CHAINS -A input -s $LOCALNET -d 0.0.0.0/0 -j REJECT -l echo "Local LAN interface is down. Unable to make a rule to" echo "protect the firewall from the internal LAN. If connectivity" echo "is more important than security, then set LOCALNET_SECURE=0" echo "and rerun the script. Or rerun the script once $FRIENDLYPII" echo "is back up." FRIENDLY=0 if [ $DMZ = 0 ]; then PORTFW_HOST1=0 PORTFW_HOST2=0 PORTFW_HOST3=0 PORTFW_HOST4=0 fi fi done fi if [ $FRIENDLY = 0 ]; then echo "Configuring stand alone, no internal LAN interface selected." else export FRIENDLYP=`echo $FRIENDLY | sed -e s/":"/" "/g` for FRIENDLYPII in `echo $FRIENDLYP` do $CHAINS -A input -p tcp -i $FRIENDLYPII -j ACCEPT $CHAINS -A input -p udp -i $FRIENDLYPII -j ACCEPT $CHAINS -A input -p icmp -i $FRIENDLYPII -j ACCEPT done if [ $LOCALNET_SECURE = 1 ]; then echo "Allowing the internal LAN to use firewall as a router." else echo -n "Allowing all packets from the following internal interfaces: " echo $FRIENDLYP | sed -e s/":"/" "/g fi fi # drop non-routable packets if [ $OPEN_NO_ROUTE = 0 ]; then $CHAINS -A input -i $HOSTILE -s 10.0.0.0/8 -j DENY --log $CHAINS -A input -i $HOSTILE -s 127.0.0.1/8 -j DENY --log $CHAINS -A input -i $HOSTILE -s 172.16.0.0/12 -j DENY --log $CHAINS -A input -i $HOSTILE -s 192.168.0.0/16 -j DENY --log fi # determine current IP (if $HOSTILE is up) and make an appropriate rule to # prevent possible land type attacks. if [ $STATIC != 0 ]; then $CHAINS -A input -i $HOSTILE -s $STATIC_IP -j DENY -l else if /sbin/ifconfig $HOSTILE 2>/dev/null | grep UP >/dev/null 2>&1 ; then EXTERNAL_IP=`/sbin/ifconfig $HOSTILE | grep 'inet addr' \ | awk '{print $2}' | sed -e 's/.*://'` $CHAINS -A input -i $HOSTILE -s $EXTERNAL_IP -j DENY -l echo "Blocking packets spoofing the IP of $HOSTILE." fi fi # code to setup the DMZ if [ $DMZ != 0 ]; then # accept solicited packets from the DMZ to the internal LAN $CHAINS -A input -i $DMZ_IFACE -p tcp -d $LOCALNET ! -y -j ACCEPT # if the DMZ interface is up, find IP and make a rule to block # packets addressed to the firewall if /sbin/ifconfig $DMZ_IFACE 2>/dev/null | grep UP \ >/dev/null 2>&1 ; then IFACE_IP=`/sbin/ifconfig $DMZ_IFACE | grep 'inet addr' \ | awk '{print $2}' | sed -e 's/.*://'` $CHAINS -A input -i $DMZ_IFACE -p tcp -s $DMZNET -d $IFACE_IP \ -j REJECT -l $CHAINS -A input -i $DMZ_IFACE -p udp -s $DMZNET -d $IFACE_IP \ -j REJECT -l $CHAINS -A input -p tcp -i $DMZ_IFACE ! -d $LOCALNET -j ACCEPT $CHAINS -A input -p udp -i $DMZ_IFACE ! -d $LOCALNET -j ACCEPT $CHAINS -A input -p icmp -i $DMZ_IFACE ! -d $LOCALNET -j ACCEPT echo "Blocking DMZ packets addressed to the firewall." echo "Allowing the DMZ to use firewall as a router to the internet." # otherwise, we choke off the DMZ until the interface is up # and the script is restarted else $CHAINS -A input -i $DMZ_IFACE -j REJECT -l echo "DMZ interface is down, making a rule to block the DMZ until" echo "the IP address of the DMZ interface can be determined." echo "Please rerun the script once $DMZ_IFACE is back up." DMZ=0 if [ $FRIENDLY = 0 ]; then PORTFW_HOST1=0 PORTFW_HOST2=0 PORTFW_HOST3=0 PORTFW_HOST4=0 fi fi fi # covering all the bases with a variable shift in case the above turned off $DMZ # and $FRIENDLY. if that is the case, then we don't need to masq if [ $FRIENDLY = 0 ] && [ $DMZ = 0 ]; then IPMASQ=0 fi # setting up portforwarding if [ $PORTFW_HOST1 != 0 ] || [ $PORTFW_HOST2 != 0 ] || [ $PORTFW_HOST3 != 0 ]\ || [ $PORTFW_HOST4 != 0 ]; then # attempt to load and verify loading of ip_masq_autofw kernel module echo -n "Attempting to load ip_masq_autofw kernel module..." modprobe ip_masq_autofw > /dev/null 2>&1 MASQADM_COMPAT=`lsmod | grep ip_masq_autofw` if [ "$MASQADM_COMPAT" != "" ]; then echo "done." else echo "" echo "Unable to load module, you may have to recompile your" echo "kernel with that option. Portforwarding disabled." PORTFW_HOST1=0 PORTFW_HOST2=0 PORTFW_HOST3=0 PORTFW_HOST4=0 fi # verify the existance of ipmasqwadm if [ -x /usr/sbin/ipmasqadm ]; then MASQADM=/usr/sbin/ipmasqadm $MASQADM autofw -F if [ $PORTFW_HOST1 != 0 ]; then if [ $PORTFW_HOST1_PORTS_TCP != 0 ]; then # setup for TCP portforwarding and resetting $ALLOW export PORTFW_HOST1_PORTS_TCPP=`echo $PORTFW_HOST1_PORTS_TCP \ | sed -e s/":"/" "/g` for PORTFW_HOST1_PORTS_TCPPII in `echo $PORTFW_HOST1_PORTS_TCPP` do $MASQADM autofw -A -r tcp $PORTFW_HOST1_PORTS_TCPPII \ $PORTFW_HOST1_PORTS_TCPPII -h $PORTFW_HOST1 done echo -n "Forwarding the following TCP ports to $PORTFW_HOST1: " echo $PORTFW_HOST1_PORTS_TCPP | sed -e s/":"/" "/g if [ $ALLOW = 0 ]; then ALLOW=$PORTFW_HOST1_PORTS_TCP else ALLOW=$ALLOW:$PORTFW_HOST1_PORTS_TCP fi fi if [ $PORTFW_HOST1_PORTS_UDP != 0 ]; then # setup for UDP portforwarding and restting $ALLOW_UDP export PORTFW_HOST1_PORTS_UDPP=`echo $PORTFW_HOST1_PORTS_UDP \ | sed -e s/":"/" "/g` for PORTFW_HOST1_PORTS_UDPPII in `echo $PORTFW_HOST1_PORTS_UDPP` do $MASQADM autofw -A -r udp $PORTFW_HOST1_PORTS_UDPPII \ $PORTFW_HOST1_PORTS_UDPPII -h $PORTFW_HOST1 done echo -n "Forwarding the following UDP ports to $PORTFW_HOST1: " echo $PORTFW_HOST1_PORTS_UDPP | sed -e s/":"/" "/g if [ $ALLOW_UDP = 0 ]; then ALLOW_UDP=$PORTFW_HOST1_PORTS_UDP else ALLOW_UDP=$ALLOW_UDP:$PORTFW_HOST1_PORTS_UDP fi fi fi if [ $PORTFW_HOST2 != 0 ]; then if [ $PORTFW_HOST2_PORTS_TCP != 0 ]; then # setup for TCP portforwarding and resetting $ALLOW export PORTFW_HOST2_PORTS_TCPP=`echo $PORTFW_HOST2_PORTS_TCP \ | sed -e s/":"/" "/g` for PORTFW_HOST2_PORTS_TCPPII in `echo $PORTFW_HOST2_PORTS_TCPP` do $MASQADM autofw -A -r tcp $PORTFW_HOST2_PORTS_TCPPII \ $PORTFW_HOST2_PORTS_TCPPII -h $PORTFW_HOST2 done echo -n "Forwarding the following TCP ports to $PORTFW_HOST2: " echo $PORTFW_HOST2_PORTS_TCPP | sed -e s/":"/" "/g if [ $ALLOW = 0 ]; then ALLOW=$PORTFW_HOST2_PORTS_TCP else ALLOW=$ALLOW:$PORTFW_HOST2_PORTS_TCP fi fi if [ $PORTFW_HOST2_PORTS_UDP != 0 ]; then # setup for UDP portforwarding and restting $ALLOW_UDP export PORTFW_HOST2_PORTS_UDPP=`echo $PORTFW_HOST2_PORTS_UDP \ | sed -e s/":"/" "/g` for PORTFW_HOST2_PORTS_UDPPII in `echo $PORTFW_HOST2_PORTS_UDPP` do $MASQADM autofw -A -r udp $PORTFW_HOST2_PORTS_UDPPII \ $PORTFW_HOST2_PORTS_UDPPII -h $PORTFW_HOST2 done echo -n "Forwarding the following UDP ports to $PORTFW_HOST2: " echo $PORTFW_HOST2_PORTS_UDPP | sed -e s/":"/" "/g if [ $ALLOW_UDP = 0 ]; then ALLOW_UDP=$PORTFW_HOST2_PORTS_UDP else ALLOW_UDP=$ALLOW_UDP:$PORTFW_HOST2_PORTS_UDP fi fi fi if [ $PORTFW_HOST3 != 0 ]; then if [ $PORTFW_HOST3_PORTS_TCP != 0 ]; then # setup for TCP portforwarding and resetting $ALLOW export PORTFW_HOST3_PORTS_TCPP=`echo $PORTFW_HOST3_PORTS_TCP \ | sed -e s/":"/" "/g` for PORTFW_HOST3_PORTS_TCPPII in `echo $PORTFW_HOST3_PORTS_TCPP` do $MASQADM autofw -A -r tcp $PORTFW_HOST3_PORTS_TCPPII \ $PORTFW_HOST3_PORTS_TCPPII -h $PORTFW_HOST3 done echo -n "Forwarding the following TCP ports to $PORTFW_HOST3: " echo $PORTFW_HOST3_PORTS_TCPP | sed -e s/":"/" "/g if [ $ALLOW = 0 ]; then ALLOW=$PORTFW_HOST3_PORTS_TCP else ALLOW=$ALLOW:$PORTFW_HOST3_PORTS_TCP fi fi if [ $PORTFW_HOST3_PORTS_UDP != 0 ]; then # setup for UDP portforwarding and restting $ALLOW_UDP export PORTFW_HOST3_PORTS_UDPP=`echo $PORTFW_HOST3_PORTS_UDP \ | sed -e s/":"/" "/g` for PORTFW_HOST3_PORTS_UDPPII in `echo $PORTFW_HOST3_PORTS_UDPP` do $MASQADM autofw -A -r udp $PORTFW_HOST3_PORTS_UDPPII \ $PORTFW_HOST3_PORTS_UDPPII -h $PORTFW_HOST3 done echo -n "Forwarding the following UDP ports to $PORTFW_HOST3: " echo $PORTFW_HOST3_PORTS_UDPP | sed -e s/":"/" "/g if [ $ALLOW_UDP = 0 ]; then ALLOW_UDP=$PORTFW_HOST3_PORTS_UDP else ALLOW_UDP=$ALLOW_UDP:$PORTFW_HOST3_PORTS_UDP fi fi fi if [ $PORTFW_HOST4 != 0 ]; then if [ $PORTFW_HOST4_PORTS_TCP != 0 ]; then # setup for TCP portforwarding and resetting $ALLOW export PORTFW_HOST4_PORTS_TCPP=`echo $PORTFW_HOST4_PORTS_TCP \ | sed -e s/":"/" "/g` for PORTFW_HOST4_PORTS_TCPPII in `echo $PORTFW_HOST4_PORTS_TCPP` do $MASQADM autofw -A -r tcp $PORTFW_HOST4_PORTS_TCPPII \ $PORTFW_HOST4_PORTS_TCPPII -h $PORTFW_HOST4 done echo -n "Forwarding the following TCP ports to $PORTFW_HOST4: " echo $PORTFW_HOST4_PORTS_TCPP | sed -e s/":"/" "/g if [ $ALLOW = 0 ]; then ALLOW=$PORTFW_HOST4_PORTS_TCP else ALLOW=$ALLOW:$PORTFW_HOST4_PORTS_TCP fi fi if [ $PORTFW_HOST4_PORTS_UDP != 0 ]; then # setup for UDP portforwarding and restting $ALLOW_UDP export PORTFW_HOST4_PORTS_UDPP=`echo $PORTFW_HOST4_PORTS_UDP \ | sed -e s/":"/" "/g` for PORTFW_HOST4_PORTS_UDPPII in `echo $PORTFW_HOST4_PORTS_UDPP` do $MASQADM autofw -A -r udp $PORTFW_HOST4_PORTS_UDPPII \ $PORTFW_HOST4_PORTS_UDPPII -h $PORTFW_HOST4 done echo -n "Forwarding the following UDP ports to $PORTFW_HOST4: " echo $PORTFW_HOST4_PORTS_UDPP | sed -e s/":"/" "/g if [ $ALLOW_UDP = 0 ]; then ALLOW_UDP=$PORTFW_HOST4_PORTS_UDP else ALLOW_UDP=$ALLOW_UDP:$PORTFW_HOST4_PORTS_UDP fi fi fi else echo "Cannot find the ipmasqadm binary. Please verify that it is" echo "installed. Without it, killerwall cannot accomplish port-" echo "forwarding." fi fi # attempt to block fragmented packets, these can be nasty if [ $NOFRAG = 1 ]; then echo "Blocking fragmented packets." $CHAINS -A input -i $HOSTILE -f -s 0.0.0.0/0 -j DENY $FLAG fi # this is the closest I can get to a keepstate in Linux, we'll see $CHAINS -A input -i $HOSTILE -p tcp ! -y -j ACCEPT # block > 1023 ports if [ $BLOCK_HIGH != 0 ]; then export BLOCK_HIGHP=`echo $BLOCK_HIGH | sed -e s/":"/" "/g \ | sed -e s/"-"/":"/g` for BLOCK_HIGHPII in `echo $BLOCK_HIGHP` do $CHAINS -A input -i $HOSTILE -p tcp --dport $BLOCK_HIGHPII -j DENY $CHAINS -A input -i $HOSTILE -p udp --dport $BLOCK_HIGHPII -j DENY done echo -n "Blocking the following ports above 1023 on $HOSTILE: " echo $BLOCK_HIGHP | sed -e s/":"/"-"/g fi # allow dns replies if [ -f /etc/resolv.conf ]; then if [ "$DNS_SERVER_CHECK" != "" ]; then DNS_SERVER=`echo $DNS_SERVER_CHECK | awk '{print $1}'` fi if test $AUTODNS==1; then echo -n "Setting up rules for DNS..." DNS=`grep nameserver /etc/resolv.conf \ | grep -vE "^[[:space:]]*#" \ | awk '{print $2}' | sort | uniq` if [ "$DNS_SERVER" != "" ]; then for ARGS in `echo $DNS | sed -e s/"$DNS_SERVER"//g` do function arguments { $CHAINS -A input -i \ $HOSTILE -p udp -s \ $ARGS 53 -j ACCEPT ;} arguments $DNS done echo "done." else for ARGS in `echo $DNS` do function arguments { $CHAINS -A input -i \ $HOSTILE -p udp -s \ $ARGS 53 -j ACCEPT ;} arguments $DNS done echo "done." fi else echo "Skipping DNS configuration." fi else echo "You don't have /etc/resolv.conf." fi # this is how we blackball ;-) if [ $BLACKBALL != 0 ]; then export BLACKBALLP=`echo $BLACKBALL | sed -e s/":"/" "/g` for BLACKBALLPII in `echo $BLACKBALLP` do $CHAINS -A input -p all -s $BLACKBALLPII -j DENY $CHAINS -A input -i $HOSTILE -f -s $BLACKBALLPII -j DENY done echo -n "Blocking all packets from the following IPs: " echo $BLACKBALLP | sed -e s/":"/" "/g fi # allow specific connections to TCP ports if [ $ALLOW != 0 ]; then export ALLOWP=`echo $ALLOW | sed -e s/":"/" "/g | sed -e s/"-"/":"/g` for ALLOWPII in `echo $ALLOWP` do $CHAINS -A input -i $HOSTILE -p tcp -s 0.0.0.0/0 \ --dport $ALLOWPII -j ACCEPT done echo -n "Allowing TCP connections on interface $HOSTILE to these ports: " echo $ALLOWP | sed -e s/":"/"-"/g fi # allow specific connections to UDP ports if [ $ALLOW_UDP != 0 ]; then export ALLOW_UDPP=`echo $ALLOW_UDP | sed -e s/":"/" "/g \ | sed -e s/"-"/":"/g` for ALLOW_UDPPII in `echo $ALLOW_UDPP` do $CHAINS -A input -i $HOSTILE -p udp -s 0.0.0.0/0 \ --dport $ALLOW_UDPPII -j ACCEPT done echo -n "Allowing UDP connections on interface $HOSTILE to these ports: " echo $ALLOW_UDPP | sed -e s/":"/"-"/g fi # allow all packets to all open ports from the following IPs if [ $TRUSTED != 0 ]; then echo "WARNING! You have activated TRUSTED networking!!! " export TRUSTEDP=`echo $TRUSTED | sed -e s/":"/" "/g` for TRUSTEDPII in `echo $TRUSTEDP` do $CHAINS -A input -p tcp -s $TRUSTEDPII -j ACCEPT $CHAINS -A input -p udp -s $TRUSTEDPII -j ACCEPT done echo -n "Allowing all packets on all open ports from the following IPs: " echo $TRUSTEDP | sed -e s/":"/" "/g fi # block outbound packets from internal LAN and DMZ to certain destination ports if [ $BLOCK_OUTBOUND_PORTS != 0 ]; then export BLOCK_OUTBOUND_PORTSP=`echo $BLOCK_OUTBOUND_PORTS \ | sed -e s/":"/" "/g | sed -e s/"-"/":"/g` for BLOCK_OUTBOUND_PORTSPII in `echo $BLOCK_OUTBOUND_PORTSP` do $CHAINS -A output -i $HOSTILE -p tcp -s $LOCALNET --dport \ $BLOCK_OUTBOUND_PORTSPII -j REJECT $CHAINS -A output -i $HOSTILE -p udp -s $LOCALNET --dport \ $BLOCK_OUTBOUND_PORTSPII -j REJECT $CHAINS -A output -i $HOSTILE -p tcp -s $DMZNET --dport \ $BLOCK_OUTBOUND_PORTSPII -j REJECT $CHAINS -A output -i $HOSTILE -p udp -s $DMZNET --dport \ $BLOCK_OUTBOUND_PORTSPII -j REJECT done echo "Blocking outbound packets from $LOCALNET and $DMZNET to the" echo -n "following destination ports: " echo $BLOCK_OUTBOUND_PORTSP | sed -e s/":"/"-"/g fi # block outbound packets from internal LAN and DMZ to certain destination IPs if [ $BLOCK_OUTBOUND_HOSTS != 0 ]; then export BLOCK_OUTBOUND_HOSTSP=`echo $BLOCK_OUTBOUND_HOSTS \ | sed -e s/":"/" "/g` for BLOCK_OUTBOUND_HOSTSPII in `echo $BLOCK_OUTBOUND_HOSTSP` do $CHAINS -A input -p tcp -s $LOCALNET -d $BLOCK_OUTBOUND_HOSTSPII \ -j REJECT $CHAINS -A input -p udp -s $LOCALNET -d $BLOCK_OUTBOUND_HOSTSPII \ -j REJECT $CHAINS -A input -p tcp -s $DMZNET -d $BLOCK_OUTBOUND_HOSTSPII \ -j REJECT $CHAINS -A input -p udp -s $DMZNET -d $BLOCK_OUTBOUND_HOSTSPII \ -j REJECT done echo "Blocking outbound packets from $LOCALNET and $DMZNET to the" echo -n "following destination IPs: " echo $BLOCK_OUTBOUND_HOSTSP | sed -e s/":"/" "/g fi # allow TCP/UDP packets above 1023 $CHAINS -A input -i $HOSTILE -p tcp --dport 1024:5999 -j ACCEPT $CHAINS -A input -i $HOSTILE -p udp --dport 1024:5999 -j ACCEPT $CHAINS -A input -i $HOSTILE -p tcp --dport 6010:65535 -j ACCEPT # surgically block traceroutes if NOTRACEROUTE=1 if [ $NOTRACEROUTE = 1 ]; then $CHAINS -A input -i $HOSTILE -p udp --dport 6010:33433 -j ACCEPT echo "Blocking traceroutes." $CHAINS -A input -i $HOSTILE -p udp --dport 33434:33523 -j DENY $FLAG $CHAINS -A input -i $HOSTILE -p udp --dport 33524:65535 -j ACCEPT else $CHAINS -A input -i $HOSTILE -p udp --dport 6010:65535 -j ACCEPT fi # now see where the pings are coming from, this doesn't always mean an attack if [ $LOGGING = 1 ]; then if [ $NOPING = 0 ]; then $CHAINS -A input -p icmp -j ACCEPT -l echo "ICMP accepted, logging enabled." else $CHAINS -A input -p icmp -j DENY -l echo "ICMP denied, logging enabled." fi else if [ $NOPING = 0 ]; then $CHAINS -A input -p icmp -j ACCEPT echo "ICMP accepted, logging disabled." else $CHAINS -A input -p icmp -j DENY echo "ICMP denied, logging disabled." fi fi # block all others and log just to see what we catch $CHAINS -A input -j DENY $FLAG # ipmasq stuff if [ $IPMASQ = 0 ]; then # if $IPMASQ isn't enabled, we don't need to be forwarding packets echo 0 > /proc/sys/net/ipv4/ip_forward echo "MASQ not enabled. If this a stand alone computer...good!" else echo -n "Loading kernel modules for proxying FTP and IRC..." modprobe ip_masq_ftp modprobe ip_masq_irc \ ports=6667,8448,7767,1024,1025,1026,1027,1028,1029,1030 echo "done." echo 1 > /proc/sys/net/ipv4/ip_forward # determine if we are using a interface that normally uses a dynamic IP address # if so, then enable dynamic IP address following. this will hasten the expir- # ation of the old masq tables in the event of a lost connection. if [ $HOSTILE = ppp0 ]; then echo 7 > /proc/sys/net/ipv4/ip_dynaddr fi if [ $FRIENDLY != 0 ]; then $CHAINS -A forward -j MASQ -d $LOCALNET $CHAINS -A forward -j MASQ -s $LOCALNET echo "MASQ enabled for $LOCALNET." fi if [ $DMZ != 0 ]; then $CHAINS -A forward -j MASQ -d $DMZNET $CHAINS -A forward -j MASQ -s $DMZNET echo "MASQ enabled for $DMZNET." fi fi if [ -x $SYSLOGGER ]; then $SYSLOGGER -t killerwall "Killerwall $VERSION activated." fi echo -n "Killerwall $VERSION activated:" if [ -f /etc/rc.d/init.d/functions ]; then echo_success echo "" else echo -e \ "Killerwall $VERSION activated:\t\t\t[ \\033[1;32m OK \\033[0;39m ]\r" fi ;; stop) echo "Shutting down firewall rules." # turn off forwarding if [ -f /proc/sys/net/ipv4/ip_forward ]; then echo 0 > /proc/sys/net/ipv4/ip_forward fi # flush any ipmasqadm rules if [ $PORTFW_HOST1 != 0 ] || [ $PORTFW_HOST2 != 0 ] \ || [ $PORTFW_HOST3 != 0 ] || [ $PORTFW_HOST4 != 0 ]; then $MASQADM autofw -F fi # reset default policies, flush all rules $CHAINS -P input ACCEPT $CHAINS -P output ACCEPT $CHAINS -P forward DENY $CHAINS -F input $CHAINS -F output $CHAINS -F forward if [ -x $SYSLOGGER ]; then $SYSLOGGER -t killerwall "Killerwall $VERSION stopped!!!" fi echo -n "Killerwall $VERSION deactivated:" if [ -f /etc/rc.d/init.d/functions ]; then echo_success echo "" else echo -e \ "Killerwall $VERSION deactivated:\t\t\t[ \\033[1;32m OK \\033[0;39m ]\r" fi ;; restart) $0 stop && $0 start ;; *) echo "Usage: killerwall {start|stop|restart}" esac exit 0