securing a linux box

  • @author: c0re 
    @copyright: CreativeCommons 
    @version: 1.3 | 09.13.2011
    
    
    [TOC - TableOfContent]
    --------------------------------
    0x00 | Introduction
    0x01 | Basics
    0x02 | Hardening SSH
    0x03 | Simple Firewall
    0x04 | Port Knocking
    0x05 | ARPalert
    0x06 | Tunneling Traffic
    0x07 | Final words
    0x08 | Further reading
    --------------------------------
    
    
    --[0x00 - Introduction]--
    this paper should cover most of the basic stuff to secure your linux box and your LAN.
    it is in no way advanced (you can do too many things to "lock-down" your system or monitor your LAN), but it should get you the idea of what you can do.
    I'm using debian(squeeze) to demonstrate things in this paper, so the commands and paths may vary on other distros - this shouldn't be a copy&paste anyway!
    please note that I can't explain every parameter used in the commands below as this would take another 150+ lines of writing, just read the man pages on those commands/parameters.
    I will try to keep this paper updated whenever I can, so check back once in a while to see if anything new got added to it.
    
    
    
    --[0x01 - Basics]--
    1. before we can start to secure our system we need to make sure that all unnecessary software is removed.
    start by going through all installed software and remove those packages you don't need. you can list the packages installed by dpkg using the following command.
      root@c0re:/# dpkg --list
    
    2. disable DHCP whenever possible, use static IPs instead. start planning your LAN with a limited range of IPs (Class C Network).
    or, to be even more secure, start subnetting your LAN for only a range of 20 or 30 IPs in total.
    a sample IP assigning scheme can look like this:
      192.168.0.1   - 192.168.0.9   #1-9 for you and your roommate (pc,iphone,pda..)
      192.168.0.10  - 192.168.0.19  #10-19 hardware devices (printers,xbox,ps3,..)
      192.168.0.20  - 192.168.0.39  #20-39 friends/people who come to your home regularly
      192.168.0.250 - 192.168.0.254	#your router/modem
    
    in debian you can set static IPs in "/etc/network/interfaces" and DNS servers in "/etc/resolv.conf"
      root@c0re:/# cat /etc/network/interfaces
      #loopback
       auto lo
       iface lo inet loopback
      #home-LAN
       auto eth0
       iface eth0 inet static
       address 192.168.0.1
       network 192.168.0.0
       netmask 255.255.255.0
       gateway 192.168.0.254
    
    ..and do yourself a favor and remove the network-manager, it causes a lot of trouble and you really don't need it if you have static IPs.
    
    3. since we expect our box to be offline/shutdown for at least some time each day we set some anacron-jobs (cron is more for 24x7 systems) to securely destroy data we don't need anymore.
    a few examples given, just define some jobs you need.
      root@c0re:/# cat /etc/anacrontab
      # /etc/anacrontab: configuration file for anacron
      SHELL=/bin/sh
      PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
      # These replace cron's entries
      1   5   cron.daily    nice run-parts --report /etc/cron.daily
      7   10   cron.weekly    nice run-parts --report /etc/cron.weekly
      @monthly   15   cron.monthly nice run-parts --report /etc/cron.monthly
      # shred all files in /tmp and /var/tmp not used since 3 days 
      1   10   shred.tmp    find /tmp -type f -atime +3 -exec shred -f -u -z -n 35 {} +
      1   11   shred.var.tmp    find /var/tmp -type f -atime +3 -exec shred -f -u -z -n 35 {} +
      # shred roots and c0res .bash_history after two days
      2   10   shred.root.bashhistory    find /root/.bash_history -type f -exec shred -f -u -z -n 35 {} + && touch /root/.bash_history
      2   11   shred.c0re.bashhistory    find /home/c0re/.bash_history -type f -exec shred -f -u -z -n 35 {} + && touch /home/c0re/.bash_history && chown c0re:c0re /home/c0re/.bash_history
      # shred all files in trash every third day
      3   10   shred.c0re.files.trash    find /home/c0re/.local/share/Trash/files/ -type f -exec shred -f -u -z -n 35 {} +
      3   20   shred.c0re.trash.infos    find /home/c0re/.local/share/Trash/info/ -type f -exec shred -f -u -z -n 35 {} +
      3   22   rmRf.c0re.folder.trash    find /home/c0re/.local/share/Trash/files/ -type d -print0 | xargs -0 rm -Rf
    
    to check if those jobs completed successfully just watch syslog, all info should be there.
      root@c0re:/# cat /var/log/syslog | grep anacron
      Mar 31 07:13:15 c0re anacron[1916]: Job `cron.daily' terminated
      Mar 31 07:13:15 c0re anacron[1916]: Job `shred.tmp' started
      Mar 31 07:13:15 c0re anacron[1916]: Job `shred.tmp' terminated
      Mar 31 07:13:15 c0re anacron[1916]: Job `shred.c0re.files.trash' started
      Mar 31 07:13:27 c0re anacron[1916]: Job `shred.c0re.files.trash' terminated
      Mar 31 07:13:27 c0re anacron[1916]: Job `shred.var.tmp' started
      Mar 31 07:13:27 c0re anacron[1916]: Job `shred.var.tmp' terminated
      Mar 31 07:23:07 c0re anacron[1916]: Job `shred.c0re.folder.trash' started
      Mar 31 07:23:07 c0re anacron[1916]: Job `shred.c0re.folder.trash' terminated
      Mar 31 07:25:07 c0re anacron[1916]: Job `rmRf.c0re.folder.trash' started
      Mar 31 07:25:07 c0re anacron[1916]: Job `rmRf.c0re.folder.trash' terminated
      Mar 31 07:25:07 c0re anacron[1916]: Normal exit (6 jobs run)
    
    4. many simple exploits rely upon being able to execute commands in "/tmp". this is why you should consider mounting "/tmp" as "noexec" and "nosuid". 
    you can do this by changing the entry in "/etc/fstab" from "exec" to "noexec" and adding "nosuid". (assuming that you don't have just a single partition for your whole file system...)
    NOTE: this method fools any simplistic attack that relies upon putting a script in "/tmp" and running it, but it doesn't really stop it completely from executing, because
    a simple "/lib/ld-linux.so.2 /tmp/programm-to-execute" can execute it anyway, but enough of this, I'll show you how to mount "/tmp" as "noexec".
      root@c0re:/# vi /etc/fstab
      #Entry for /dev/sdc5:   
      UUID=f4e1b18a-62be-4f60-9b0d-5ee81005ea66   /tmp   ext4   noatime,noexec,nosuid 0 0
    
    now remount it to make the changes take effect and verify it
      root@c0re:/# mount -o remount /tmp && mount | grep /tmp
      /dev/sdc5 on /tmp type ext4 (rw,noexec,nosuid)
    
    5. check for open ports and services listening on your loopback interface and close all you don't really need. it is also a good idea to disable IPv6.
      root@c0re:/# netstat -tulpen
      Active Internet connections (only servers)
      Proto Recv-Q Send-Q Local Address           Foreign Address         State       User       Inode       PID/Program name
      tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      0          7032        2105/cupsd      
      tcp        0      0 0.0.0.0:22	      0.0.0.0:*               LISTEN      0          6592        1925/sshd      
      udp        0      0 0.0.0.0:631             0.0.0.0:*                           0          7035        2105/cupsd      
      udp        0      0 0.0.0.0:51789           0.0.0.0:*                           104        6799        1998/avahi-daemon:
      udp        0      0 0.0.0.0:5353            0.0.0.0:*                           104        6798        1998/avahi-daemon:
    
      root@c0re:/# nmap -v -sT localhost
      Starting Nmap 5.00 ( http://nmap.org ) at 2011-03-21 14:33 CET
      NSE: Loaded 0 scripts for scanning.
      Initiating Connect Scan at 14:33
      Scanning localhost (127.0.0.1) [1000 ports]
      Discovered open port 631/tcp on 127.0.0.1
      Completed Connect Scan at 14:33, 0.01s elapsed (1000 total ports)
      Host localhost (127.0.0.1) is up (0.00026s latency).
      Interesting ports on localhost (127.0.0.1):
      Not shown: 999 closed ports
      PORT    STATE SERVICE
      631/tcp open  ipp
    
      Read data files from: /usr/share/nmap
      Nmap done: 1 IP address (1 host up) scanned in 0.04 seconds
         Raw packets sent: 0 (0B) | Rcvd: 0 (0B)
    
    as you can see I have already disabled IPv6, if you want to do the same do the following (a reboot is required):
      root@c0re:/# echo "#disable IPv6" >> /etc/sysctl.conf
      root@c0re:/# echo "net.ipv6.conf.all.disable_ipv6 = 1" >> /etc/sysctl.conf
      root@c0re:/# echo "#" >> /etc/sysctl.conf
      root@c0re:/# reboot
    
    NOTE: there is a high possibility that exim4 is not working properly after that, because in its config it's set to IPv4&IPv6 by default.
    to handle this just change the line which says "dc_local_interfaces='127.0.0.1 ; ::1'" to "dc_local_interfaces='127.0.0.1'" so exim4 will only use IPv4.
      root@c0re:/# vi /etc/exim4/update-exim4.conf.conf
    
    6. you should also consider storing all your passwords for all your websites/computers/etc in a key-database, instead of using sticky notes on your computer.
    'keepassx' comes in handy here, which is a port of "keepass" for windows, but sadly it can only handle old "1.x keepass databases".
    make sure to use the database only with a .key file and keep either the database itself or the keyfile on an usb stick.
    
    7. :(){:|:&};:
    have you got those super cool friends too, which try to fuck with your system using a fork bomb?
    you can easily secure this by limiting the number of processes per user:
      root@c0re:/# vi /etc/security/limits.conf
      #we hate forkbombs
      @users      soft   nproc      100
      @users      hard   nproc      150
    
    8. try to remove all users from "/etc/passwd" who you don't need. for example exim, saned, sendmail leave their users there, even if you uninstalled them.
      root@c0re:/# cat /etc/passwd
      root@c0re:/# userdel 
    
    9. you should disable root login via "su" and enable root privileges using "sudo". this allows the user to execute defined commands under another user's identity, even as root.
    you must use visudo to make changes in "/etc/sudoers":
      root@c0re:/# man sudoers
      root@c0re:/# visudo
      # /etc/sudoers
      # This file MUST be edited with the 'visudo' command as root.
      # See the man page for details on how to write a sudoers file.
      #
      Defaults   rootpw
      # Host alias specification
      # User alias specification
      # Cmnd alias specification
      # User privilege specification
      root   ALL=(ALL) ALL
      # Allow user c0re to gain root
      c0re   ALL=(ALL) ALL
    
    here I changed the default method to "rootpw" which would require the user to enter the root password instead of his own to gain the privileges.
    after you have verified that you made no errors just disable all attempts to log in via "su" by removing the "SUID bits". then just exit and try to log in again:
      root@c0re:/# chmod 0511 /bin/su
      root@c0re:/# exit
      c0re@c0re:/# sudo -s
      [sudo] password for root:
    
    10. last but not least: read your logs, watch your running processes and set up logrotate to rotate your logs once in a while.
      root@c0re:/# less /var/log/messages
      root@c0re:/# ps aux
    
    
    
    --[0x02 - Hardening SSH]--
    I think I don't need to tell you that you shouldn't use anything like telnet or vnc to connect to your box, because the traffic will not be encrypted and you are sending plain text passwords.
    so we are going to configure ssh and its daemon sshd. if you haven't done yet install the required packages:
      root@c0re:/# apt-get install ssh openssh-server
    
    after that there should be a file which configures the daemon in "/etc/ssh/" which is called "sshd_config"
    there are some things you need to change:
      root@c0re:/# vi /etc/ssh/sshd_config
      +) change the default port :22 to something different, e.g.: :8089 or :1337
      +) only allow protocol version 2
      +) uncomment 'ListAddress 0.0.0.0' or ::1 of you need ipv6
      +) set 'LoginGraceTime' to 60
      +) set 'PermitRootLogin' to 'no'
      +) make sure 'PermitEmptyPasswords' is set to 'no'
    
    you got a config file for each single user too, there is also some stuff you should enable:
      root@c0re:/# vi /etc/ssh/ssh_config
      +) ForwardAgent no   
      +) ForwardX11 no
      +) ForwardX11Trusted yes
      +) RhostsRSAAuthentication no
      +) RSAAuthentication yes
      +) PasswordAuthentication yes
      +) CheckHostIP yes
      +) ConnectTimeout 0
      +) StrictHostKeyChecking yes
      +) Protocol 2
      +) Cipher blowfish
      +) EscapeChar ~
    
    after you're done just restart sshd and all changes should take affect:
      root@c0re:/# /etc/init.d/ssh restart
      Restarting OpenBSD Secure Shell server: sshd.
    
    so this is all working fine from your LAN, but I think you also want to connect to your box from outside of your LAN.
    in this case we need to set up a port forwarding for the port where sshd is listening on.
    to test if your port forwarding works get a device which is not in your LAN, maybe use your iPhone over 3G/EDGE, and try to connect via ssh to your WAN IP and forwarded port.
    
    if you want to log & ban all people who try to bruteforce your ssh login automatically you can set up "fail2ban"
    "fail2ban's main function is to block selected IP addresses that may belong to hosts that are trying to breach the system's security.
    it determines the hosts to be blocked by monitoring log files (e.g. "/var/log/pwdfail", "/var/log/auth.log", etc.) and bans any host IP that makes too many login attempts or
    performs any other unwanted action within a time frame defined by the administrator." so lets install it:
      root@c0re:/# apt-get install fail2ban
    
    you can leave the settings in "/etc/fail2ban/fail2ban.conf" the way they are. the real config file is "jail.conf". just read through it, the basic settings should fit most of you by default.
    turn on other stuff like "[ssh-ddos]" and "[apache]" if you want too and restart fail2ban after you are done.
      root@c0re:/# vi /etc/fail2ban/jail.conf
      root@c0re:/# /etc/init.d/fail2ban restart
      Restarting authentication failure monitor: fail2ban.
    
    
    
    --[0x03 - Simple Firewall]--
    every system needs a firewall, so I'm going to show you how to set up a straight firewall.
    this part is split into two subparts, the first part is about setting up a firewall using iptables. the second sub part is about configuring a advanced policy firewall (APF).
    make sure that you have a look at the man pages of those two first, otherwise it could be very confusing.
    you will also need to decide what you would like to have as a firewall, iptables or APF, but for a non-server a simple iptables firewall like the one we are going to configure in subpart one, is good enough.
    so lets start:
    
    1. IPTables Firewall:
    -----------------------------
    it should be already installed on your system, you can check this by running:
      root@c0re:/# dpkg --list | grep iptables
      ii  iptables                                 1.4.8-3      administration tools for packet filtering and NAT
    
    fine, lets take a look at our current configuration:
      root@c0re:/# iptables -L
      Chain INPUT (policy ACCEPT)
      target     prot opt source               destination
    
      Chain FORWARD (policy ACCEPT)
      target     prot opt source               destination
    
      Chain OUTPUT (policy ACCEPT)
      target     prot opt source               destination
    
    not much there right? well we are going to change this soon, first you need to understand what all this means.
    I will just give you a basic overview, please read iptables man page for further information. 
    ok, you can see that we have 3 main things to configure:
      INPUT       (stuff that wants to connect to your computer)
      FORWARD     (routing packets)
      OUTPUT      (stuff you send to other computers/servers)
    
    we start by dropping all OUTPUT & FORWARD packets. don't do this for INPUT yet, otherwise it may lock you out if you are currently connected via ssh to your box.
      root@c0re:/# iptables -P OUTPUT DROP
      root@c0re:/# iptables -P FORWARD DROP
    
    the next thing you want to do is add a rule to INPUT to keep all connections established which are currently connected:
      root@c0re:/# iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
    
    this will keep your current established sessions alive, then its safe to DROP all other INPUT stuff:
      root@c0re:/# iptables -P INPUT DROP
    
    so your current table should look like this:
      root@c0re:/# iptables -vL
      Chain INPUT (policy DROP 110 packets, 18280 bytes)
       pkts bytes target      prot opt in     out     source              destination        
       11279   11M ACCEPT     all  --  any    any     anywhere            anywhere            state RELATED,ESTABLISHED
    
      Chain FORWARD (policy DROP 0 packets, 0 bytes)
       pkts bytes target    prot opt in     out     source               destination        
    
      Chain OUTPUT (policy DROP 10114 packets, 976K bytes)
       pkts bytes target     prot opt in     out     source               destination
    
    after we've done this we should allow any incoming packets which come from our loopback interface, you want to see your local web-server right?:
      root@c0re:/# iptables -A INPUT -i lo -j ACCEPT
    
    you want to ssh into that box in the future too, so we set up an INPUT rule to allow this:
    NOTE: if you changed the port sshd listens on please adapt it in the example below.
      root@c0re:/# iptables -A INPUT -p tcp --dport 1337 -j ACCEPT
    
    we should also allow some OUTPUT connections to ports which are widely used, e.g for sending/receiving emails or connecting to irc servers.
    I don't like the --multiport options because its hard to see which port receives data and how much, so we are just doing a few more lines instead of a single one.
      root@c0re:/# iptables -A OUTPUT -p tcp --dport 21 -j ACCEPT
      root@c0re:/# iptables -A OUTPUT -p tcp --dport 25 -j ACCEPT
      root@c0re:/# iptables -A OUTPUT -p udp --dport 43 -j ACCEPT
      root@c0re:/# iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
      root@c0re:/# iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT
      root@c0re:/# iptables -A OUTPUT -p tcp --dport 143 -j ACCEPT
      root@c0re:/# iptables -A OUTPUT -p tcp --dport 993 -j ACCEPT
      root@c0re:/# iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT
      root@c0re:/# iptables -A OUTPUT -p tcp --dport 465 -j ACCEPT
      root@c0re:/# iptables -A OUTPUT -p tcp --dport 6667 -j ACCEPT
      root@c0re:/# iptables -A OUTPUT -p tcp --dport 6697 -j ACCEPT
      root@c0re:/# iptables -A OUTPUT -p tcp --dport 8080 -j ACCEPT
    
    you will at least need the above config if you want to use a DNS server,a webbrowser(http,https),proxies,email,ftp,whois lookups or irc.
    I made a list to show you which port is used for what:
      21	 ftp
      25     default smtp
      43	 whois
      53     dns
      80     http
      143    default imap
      443    https
      465    google mail smtp
      993    google mail imap
      6667   irc
      6697   ssl-irc
      8080   proxies
    
    so you thought we would forget our friend icmp right?, well not at all, we let him in, but we prevent a flood of echo requests (ping)
    and we also permit all icmp in OUTPUT, so you can ping others on the network, etc:
      root@c0re:/# iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 10/second -j ACCEPT
      root@c0re:/# iptables -A OUTPUT -p icmp -j ACCEPT
    
    lets check our current iptable to see if all our rules are set properly:
      root@c0re:/#  iptables -vL
      Chain INPUT (policy DROP 1063 packets, 230K bytes)
       pkts bytes target     prot opt in     out     source               destination
      12911 8543K ACCEPT     all  --  any    any     anywhere             anywhere            state RELATED,ESTABLISHED      
          0     0 ACCEPT     icmp --  any    any     anywhere             anywhere            icmp echo-request limit: avg 10/sec burst 5
          2   100 ACCEPT     all  --  lo     any     anywhere             anywhere            
          0     0 ACCEPT     tcp  --  any    any     anywhere             anywhere            tcp dpt:1337
    
      Chain FORWARD (policy DROP 0 packets, 0 bytes)
       pkts bytes target     prot opt in     out     source               destination        
    
      Chain OUTPUT (policy DROP 2 packets, 124 bytes)
       pkts bytes target     prot opt in     out     source               destination
          0     0 ACCEPT     tcp  --  any    any     anywhere             anywhere            tcp dpt:ftp         
          7   389 ACCEPT     tcp  --  any    any     anywhere             anywhere            tcp dpt:whois
        538 34446 ACCEPT     udp  --  any    any     anywhere             anywhere            udp dpt:domain
       1227  160K ACCEPT     tcp  --  any    any     anywhere             anywhere            tcp dpt:www
        193 24808 ACCEPT     tcp  --  any    any     anywhere             anywhere            tcp dpt:https
       6624   14M ACCEPT     all  --  any    any     anywhere             anywhere            state RELATED,ESTABLISHED
          9   540 ACCEPT     tcp  --  any    any     anywhere             anywhere            tcp dpt:imap2
          1    60 ACCEPT     tcp  --  any    any     anywhere             anywhere            tcp dpt:submission
          5   300 ACCEPT     tcp  --  any    any     anywhere             anywhere            tcp dpt:imaps
          0     0 ACCEPT     tcp  --  any    any     anywhere             anywhere            tcp dpt:ssmtp
          1    60 ACCEPT     tcp  --  any    any     anywhere             anywhere            tcp dpt:6667
          1    60 ACCEPT     tcp  --  any    any     anywhere             anywhere            tcp dpt:6697
          1    84 ACCEPT     icmp --  any    any     anywhere             anywhere
    
    nice one, you set up a tiny firewall using iptables. but what happens if you reboot?!
    ..then all of our hard work is gone, since debian doesn't save the iptables and also doesn't load them during boot.
    but there is a work-around:
    
    lets save our current table in a file, I call it "firewall.conf" which I place in "/etc/iptables/":
      root@c0re:/# touch /etc/iptables/firewall.conf && iptables-save > /etc/iptables/firewall.conf
    
    afterwards you need to create a little shell script in /etc/network/if-pre-up.d/ which should execute what you want before the network is initialized.
    this may look like this:
      root@c0re:/# cat /etc/network/if-pre-up.d/iptables
      #!/bin/sh
      RESTORE=/sbin/iptables-restore
      STAT=/usr/bin/stat
      IPSTATE=/etc/iptables/firewall.conf #change the path to your table here
      test -x $RESTORE || exit 0
      test -x $STAT || exit 0
      if test `$STAT --format="%a" $IPSTATE` -ne "600"; then
        echo "Permissions for $IPSTATE must be 600 (rw-------)"
        exit 0
      fi
      if test `$STAT --format="%u" $IPSTATE` -ne "0"; then
        echo "The superuser must have ownership for $IPSTATE (uid 0)"
        exit 0
      fi
      $RESTORE < $IPSTATE
    
    lastly chmod this shell script and your "firewall.conf" and set its owner to root:
      root@c0re:/# chmod +x /etc/network/if-pre-up.d/iptables && chmod 0600 /etc/iptables/firewall.conf
      root@c0re:/# chown root:root /etc/network/if-pre-up.d/iptables 
    
    
    2. Advanced Policy Firewall:
    -----------------------------
    now that we know how iptables work and how to define some rules with it, its time to make our life a little bit easier.
    Advanced Policy Firewall, APF, is an iptables(netfilter) based firewall system, known for its easy general configuration.
    we are going to set up APF with DDOS deflate script.
    so at this point you need to make a decision: are you happy with your hand-made iptables firewall?, then don't install apf-firewall.
    but if you need a firewall for a server you should consider flushing all your previous iptables rules and install apf.
    I will assume here that you either want to install a firewall for a server or you are not happy with the somewhat difficult config of iptables.
      root@c0re:/# apt-get install apf-firewall && man apf
    
    the config file for APF is located in "/etc/apf-firewall/conf.apf"
    you can set inbound and outbound rules in there. we are going to implement the same rules used in the iptables example above.
    this is what the variables in "conf.apf" represent:
      'IG_TCP_CPORTS'  ==  inbound tcp ports
      'IG_UDP_CPORTS'  ==  inbound udp ports
      'IG_ICMP_TYPES'  ==  inbound icmp types
      'EG_TCP_CPORTS'  ==  outbound tcp ports
      'EG_UDP_CPORTS'  ==  outbound udp ports
      'EG_ICMP_TYPES'  ==  outbound icmp types
    
    so to implement all the rules we used in our iptables example we can set the variables like this:
      IG_TCP_CPORTS="1337"
      IG_UDP_CPORTS=""
      IG_ICMP_TYPES="0,3,5,8,11,30"
      EGF="1"
      EG_TCP_CPORTS="25,80,143,443,1337,993,465,6697,6667,8080"
      EG_UDP_CPORTS="53"
      EG_ICMP_TYPES="all"
    
    the variable "EGF" turns on the firewall for outbound ports. by this point you should already notice that it requires much less typing work than setting rules in iptables.
    now that we did the main config stuff we can restart APF for the first time (the failed is ok at the moment):
      root@c0re:/# /etc/init.d/apf-firewall restart
      apf-firewall disabled, please adjust the configuration to your needs ... failed!
      and then set RUN to 'yes' in /etc/default/apf-firewall to enable it. ... failed!
    
    recheck your config in "/etc/apf-firewall/conf.apf" if everything is set properly, and then change "RUN" to "yes" in "/etc/default/apf-firewall" and restart it once more.
      root@c0re:/# cat /etc/apf-firewall/conf.apf
      # Defaults for apf-firewall initscript
      # sourced by /etc/init.d/apf-firewall
      # installed at /etc/default/apf-firewall by the maintainer scripts
      # Configure APF editing /etc/apf-firewall files (conf.apf is the principal config files)
      # Modify to RUN="yes" when you are ready
      RUN="yes"
      
      root@c0re:/# /etc/init.d/apf-firewall restart
    
    ok now test if everything works as expected. 
    if you get locked out for some odd reason just wait 5 minutes, unless you didn't set "DEVEL_MODE='0'" in "/etc/apf-firewall/conf.apf", all config settings get
    discarded after 5 minutes. also watch your logfile of APF to detect misbehavior.
    
    when APF is working as expected, then you may also add DOS-Defalte to it.
    (D)DoS Deflate is a shell script to assist in combating denial of service attacks.
    please note that DOS-Deflate uses APF to ban IPs so you must have it installed for DOS-Deflate to work properly.
    the installation of it is pretty simple:
      root@masta:/# wget http://www.inetbase.com/scripts/ddos/install.sh
      --2011-03-26 14:02:47--  http://www.inetbase.com/scripts/ddos/install.sh
      Resolving www.inetbase.com... 205.234.99.83
      Connecting to www.inetbase.com|205.234.99.83|:80... connected.
      HTTP request sent, awaiting response... 200 OK
      Length: 1067 (1.0K) [application/x-sh]
      Saving to: “install.sh”
      100%[======================================>] 1,067       --.-K/s   in 0.001s  
      2011-03-26 14:02:47 (1.75 MB/s) - “install.sh” saved [1067/1067]
       
      root@masta:/# chmod 0777 install.sh && ./install.sh
      Installing DOS-Deflate 0.6
      Downloading source files...
      .....done
      Creating cron to run script every minute.....(Default setting)
      .....done
      Installation has completed.
      Config file is at /usr/local/ddos/ddos.conf
    
    also if you wish to uninstall it someday for any reason you can do this nearly the same as you installed (D)DoS-Defalte:
      root@masta:/# wget http://www.inetbase.com/scripts/ddos/uninstall.sh
      --2011-03-26 14:09:38--  http://www.inetbase.com/scripts/ddos/uninstall.sh
      Resolving www.inetbase.com... 205.234.99.83
      Connecting to www.inetbase.com|205.234.99.83|:80... connected.
      HTTP request sent, awaiting response... 200 OK
      Length: 443 [application/x-sh]
      Saving to: “uninstall.sh”
      100%[======================================>] 443         --.-K/s   in 0s      
      2011-03-26 14:09:38 (59.9 MB/s) - “uninstall.sh” saved [443/443]
    
      root@masta:/# chmod 0777 uninstall.sh && ./uninstall.sh
    
    after you have installed (D)DoS-Deflate its main config files reside in "/usr/local/ddos/ddos.conf".
    the settings in there are very well explained so I will not go over them. restart apf once more and you are done:
      root@masta:/# /etc/init.d/apf-firewall restart
    
    
    
    --[0x04 - Port Knocking]--
    so whats portknocking? well wikipedia can't explain it any better:
    "in computer networking, port knocking is a method of externally opening ports on a firewall by generating a connection attempt on a set of pre-specified closed ports.
    once a correct sequence of connection attempts is received, the firewall rules are dynamically modified to allow the host which sent the connection attempts to connect over specific port(s)
    the primary purpose of port knocking is to prevent an attacker from scanning a system for potentially exploitable services by doing a port scan,
    because unless the attacker sends the correct knock sequence, the protected ports will appear closed."
    
    here I will show you how to set up port knocking for ssh. you can however define it for ftp,telnet,etc. too if you like.
    let's assume you have already done some hardening on your ssh and choosed to set your sshd to listen on port 1337.
    let us also assume that you decided to set up a 'hand made' iptables firewall like in we discussed before and are not using APF or something similar.
    so we are going to install knockd, a daemon which will wait and listen for our secret knocking sequence.
    please do yourself a favor and read the man page of knockd to fully understand all config options of it:
      root@c0re:/# apt-get install knockd && man knockd
    
    after that we are going to define the knocking sequence, the iptables rule and the logfile to monitor whats going on.
    we are going to set the port to be open for 90 seconds, which should be enough for you to establish a connection to the ssh port.
    and after 90 seconds the port will be auto-closed and a new connection is not possible. lets have a look at my config:
      root@c0re:/# cat /etc/knockd.conf
      [options]
        logfile = /var/log/knockd.log
      [opencloseSSH]
        sequence    = 31337,73313,31337
        seq_timeout = 5
        start_command     = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 1337 -j ACCEPT
        cmd_timeout     = 90
        stop_command    = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 1337 -j ACCEPT
        tcpflags    = syn
    
    NOTE: if you have set an iptables rule to allow INPUT on your ssh port, you need to remove it now before enabling knockd, because otherwise port knocking wouldn't make much sense, would it?
    you can do this simply issuing the following command, or remove the line from your "/etc/iptables/firewall.conf" by hand.
      root@c0re:/# iptables -D INPUT -p tcp --dport 1337 -j ACCEPT
    
    I have set a different log file than syslog, simply because syslog gets filled with a lot of logs from other applications.
    my config also looks different than the default one, but that's just because I don't want to send a 'STOP' signal to close the port again when I'm done.
    so next thing would be to enable knockd by changing "START_KNOCKD=0" to "START_KNOCKD=1" and then restart the daemon:
      root@c0re:/# cat /etc/default/knockd
      ################################################
      # knockd's default file, for generic sys config
      ################################################
      # control if we start knockd at init or not
      # 1 = start
      # anything else = don't start
      #
      # PLEASE EDIT /etc/knockd.conf BEFORE ENABLING
      START_KNOCKD=1
      # command line options
      #KNOCKD_OPTS="-i eth1"
    
      root@c0re:/# /etc/init.d/knockd restart
      Stopping Port-knock daemon: knockd.
      Starting Port-knock daemon: knockd.
    
    to send the knocks from the connecting computer/device you have many tools available. you may use telnet, knock, netcat, hping, sendip or packit:
     telnet: c0re@OtherPC:/# telnet 192.168.0.1 31337
     	 c0re@OtherPC:/# telnet 192.168.0.1 73313
       	 c0re@OtherPC:/# telnet 192.168.0.1 31337
       	 c0re@OtherPC:/# ssh -p 1337 c0re@192.168.0.1
    
     knock:  c0re@OtherPC: knock 192.168.0.1 31337 73313 31337
       	 c0re@OtherPC:/# ssh -p 1337 c0re@192.168.0.1
    
     hping:  c0re@OtherPC:/# hping -i eth0 -c 1 -S 192.168.0.1 -p 31337
       	 c0re@OtherPC:/# hping -i eth0 -c 1 -S 192.168.0.1 -p 73313
       	 c0re@OtherPC:/# hping -i eth0 -c 1 -S 192.168.0.1 -p 31337
       	 c0re@OtherPC:/# ssh -p 1337 c0re@192.168.0.1
    
    NOTE: some telnet implementations (e.g. in windows) retry each connection 3 times, so you may not send the correct knocking sequence.
    you may end up sending sequences like "port1 port1 port1 port2 port2 port2 port3 port3 port3"
    so after we have sent a valid sequence from the other computer wanting to connect to our box our iptable INPUT chain should looks something like this:
      root@c0re:/# iptables -L
      Chain INPUT (policy DROP)
      target     prot opt source               destination        
      ACCEPT     icmp --  anywhere             anywhere            icmp echo-request limit: avg 10/sec burst 5
      ACCEPT     all  --  anywhere             anywhere            
      ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED
      ACCEPT     tcp  --  192.168.0.5          0.0.0.0/0           tcp dpt:1337
    
    you see the added IP address in there? this is the connection knockd opened for you.
    now that we already established a connection we don't care if our port is being closed again by the firewall after 90 seconds, because we earlier defined
    that all existing connections should stay established using this line:
      root@c0re:/# iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
    
    
    
    --[0x05 - ARPalert]--
    I hope you know what ARP (Address Resolution Protocol) is, if not then please consider learning TCP/IP.
    we will assume that you already know at least the basics of TCP/IP and its protocols and layers, so we jump right into it:
    
    "arpalert - this software is used for monitoring ethernet networks. it listens on a network interface (without using 'promiscuous' mode) and catches all conversations of MAC address to IP request.
    it then compares the MAC addresses it detected with a pre-configured list of authorized MAC addresses.
    if the MAC is not in list, arpalert launches a pre-defined user script with the MAC address and IP address as parameters.
    this software can run in daemon mode; it's very fast (low CPU and memory consumption).
    it responds at signal SIGHUP (configuration reload) and at signals SIGTERM, SIGINT, SIGQUIT and SIGABRT (arpalert stops itself)"
    
    in other words this means: you can detect MITM (Man In The Middle) attacks, MAC spoofing, etc. in your LAN.
    great that arpalert is also available in the default debian repository so we can install it quite simple.
    please read the man page for arpalert after you installed it:
      root@c0re:/# apt-get install arpalert && man arpalert
    
    the main config files of arpalert reside in "/etc/arpalert/"
      root@c0re:/# ls -lah /etc/arpalert/
      total 1.6M
      drwxr-xr-x   2 root root 4.0K Mar 20 20:55 .
      drwxr-xr-x 139 root root  12K Mar 21 15:00 ..
      -rw-r--r--   1 root root 4.7K Mar 17 18:48 arpalert.conf
      -rw-r--r--   1 root root    2 Mar 20 20:55 maclist.allow
      -rw-r--r--   1 root root    0 Mar  9  2010 maclist.deny
      -rw-r--r--   1 root root 1.6M Mar  9  2010 oui.txt
    
    there are just a few things you need to change in the config file:
      +) uncomment the log file, and change its path to "/var/log/arpalert/arpalert.log"
      +) set daemon to 'yes'
      +) uncomment the interface (e.g.: eth0)
      +) set a 'action to detect' command (best thing would be to code a quick alert-email script or something similar)
    
    well now that you got the main config restart arpalert and it should start logging all MACs and IPs in a ".leases file".
    just leave it like this for a couple of days until all IPs and MACs appear in this file.
      root@c0re:/# /etc/init.d/arpalert restart
      Stopping Ethernet station monitor daemon: arpalert.
      Starting Ethernet station monitor daemon: arpalert: Selected device: eth0
       
      root@c0re:/# cat /var/lib/arpalert/arpalert.leases
      dc:c5:3c:bb:8b:2d 192.168.0.2 eth0 1300689040 385784
      b4:07:f6:b5:27:22 192.168.0.5 eth0 1300653081 822336
      22:cf:30:78:f3:b2 192.168.0.1 eth0 1300690390 897939
      00:26:bb:0f:6b:10 192.168.0.6 eth0 1300655358 730242
      00:26:b5:cf:10:97 192.168.0.10 eth0 1300652579 545369
      00:26:bc:02:8a:f1 192.168.0.4 eth0 1300656049 209712
      00:1f:69:64:26:51 192.168.0.254 eth0 1300690390 898555
    
    so after you got all those addresses we need to fill them in the "maclist.allow file", so all changes to those IPs and MACs will be logged.
      root@c0re:/# cat /etc/arpalert/maclist.allow
      22:cf:30:78:f3:b2 192.168.0.1 eth0
      dc:c5:3c:bb:8b:2d 192.168.0.2 eth0
      00:26:bc:02:8a:f1 192.168.0.4 eth0
      b4:07:f6:b5:27:22 192.168.0.5 eth0
      00:26:bb:0f:6b:10 192.168.0.6 eth0
      00:26:b5:cf:10:97 192.168.0.10 eth0
      00:1f:69:64:26:51 192.168.0.254 eth0
    
    once you filled something in "maclist.allow" arpalert threads all others as potential intruders.
    now that's it. if you configured it properly it should at least log all changes at the path you gave it in the .conf file
      root@c0re:/# less /var/log/arpalert/arpalert.log
    
    if you set up an "action on detect" script in the config file it should launch once an intruder is detected.
    
    NOTE: if you have "network-manager" installed you will most likely have this line in your logs:
    "arpalert: [./capture.c 232] pcap_open_live error: eth0: That device is not up"
    this is caused because network-manager is too damn slow to fully bring your card online before arpalert tries to listen on it.
    if so, please consider removing it and set a static IP (you already should have done this in the basics..), after that the error is gone.
    
    
    
    --[0x06 - Tunneling Traffic]--
    a ssh tunnel is a connection that takes traffic from an arbitrary port on one machine and sends it through an intermediate machine to a remote machine.
    because it uses ssh to create the tunnel, all your data is encrypted. this part is also split in two subparts, the first containing information
    on how to tunnel using your favorite terminal, and the second shows a program called gstm to do the work for you.
    
    1. Console Tunneling
    -----------------------------
    the first thing you should do is to check if you can connect to your remote host:
      c0re@c0re:/# ssh c0re@92.201.34.172
      c0re@92.201.34.172's password: 
      c0re@tunnelbox:~$
    
    if you can login successfully, then the next step would be to specify a local dynamic port forwarding. see the man page of ssh to fully understand this:
      c0re@c0re:/# ssh -D 1337 c0re@92.201.34.172
      c0re@92.201.34.172's password:
      c0re@tunnelbox:~$
    
    you can also define an alias for this, so you don't have to type your username and the remote IP address all the time.
      c0re@c0re:~$ cat .bash_aliases
      alias sshtunnel='ssh -D 1337 c0re@92.201.34.172'
    
    there is also the possibility to connect to your tunnel without typing your password all the time, the solution is "sshpass".
    sshpass is an utility designed for running ssh using the mode referred to as "keyboard-interactive" password authentication, but in non-interactive mode.
    NOTE: these examples considered the least secure as simple ps command can expose your password to all users on the same host.
    I highly recommend using ssh's public key authentication or keychain software to set up secure passwordless ssh access, but anyway
    since I got asked quite often, I'll prove the info on this paper.
    start by installing the required package and read the man page:
      root@c0re:/# apt-get install sshpass && man sshpass
    
    the syntax is quite easy to understand, you just need to write your password in plaintext before the actual ssh command:
      root@c0re:/# sshpass -p 'your-password-here' ssh -D 1337 c0re@92.201.34.172
      c0re@tunnelbox:~$
    
    to make this a minimal typing work you can also define an alias for the whole command:
      c0re@c0re:~$ cat .bash_aliases
      alias sshtunnel='sshpass -p 'your-password-here' ssh -D 1337 c0re@92.201.34.172'
    
    NOTE: keep in mind that this method is very very insecure! just use it for testing purpose!!
    
    
    2. GUI Tunneling using gSTM
    -----------------------------
    gstm is a front-end for managing ssh-tunneled port redirects. it stores tunnel configurations in a simple xml format.
    the tunnels (local, remote and dynamic) can be managed and individually started/stopped through one simple interface.
    start by installing the required package and read the man page
      root@c0re:/# apt-get install gstm && man gstm
    
    click "add" and give your new tunnel a name, for example "privatetunnel". fill out the fields for IP, login, host&port and add a port redirection
    to complete the setup, e.g: type:dynamic port:1337 to-host:n/a to-port:n/a. now after you started the tunnel and entered the password all your traffic
    will be encrypted. you can also skip the password entering part by adding your private key (privkey) to the setup.
    
    
    now you can tunnel your traffic in programs like irc,pidgin,iceweasel,etc. it doesn't matter if you prefer manual tunneling or using a GUI.
    all you need to do is open the preferences of the desired program and select a proxy server. choose socks5 and enter "localhost" or "127.0.0.1" and select
    the port you specified during the setup of your tunnel, in my example it was "port:1337". restart the desired app and now all your traffic should be encrypted.
    you can check this for example in irc by connection to your favorite server and run a simple "/whois" command on yourself.
    
    if you are looking for a good place to buy yourself an ssh tunnel you may want to check out privatetunnels .
    they are offering tunnels in the ukraine for a quite cheap price and they also refuse to keep logs, which is a pretty good thing.
    check the "guarantee" page on privatetunnels for further informations .
    
    
    
    --[0x07 - Final words]--
    yeah that's about it, you're done.
    your box is now much better configured/secured.
    please keep in mind that this paper is not the "non plus ultra" in security, as I already said, it should just provide you a leading path to secure your box.
    if you think an important step/part is missing, feel free to write it down and send it over to me, if it fits the subject I will add it to this tutorial.
    ..and for all those wondering: no, those are not my real MACs/IPs/UUIDs/etc. - sorry to disappoint you guys!
    
    
    
    --[0x08 - Further reading]--
     +) Securing Debian Manual  
     +) Keeping Your Documents Safe In a Digital Age  
     +) Staying Anonymous in a Heavily Monitored World  
     +) Wikipedia on Port knocking 
     +) Recent Debian Security Advisories 
     +) Wikipedia on Network Security 
     +) IPTables Tutorial by Oskar Andreasson 
     +) Advanced Policy Firewall Readme 
     +) Wikipedia on SSH tunneling