@author: c0re <http://enigmagroup.org>
@copyright: CreativeCommons <http://creativecommons.org/licenses/by-nc-sa/3.0/>
@version: 1.3 | 09.13.2013


[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 other 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 <username>

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 <http://privatetunnels.com/>.
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 <http://privatetunnels.com/guarantee/>.



--[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  <http://www.debian.org/doc/manuals/securing-debian-howto/>
 +) Keeping Your Documents Safe In a Digital Age  <http://www.enigmagroup.org/articles/view/Cryptography/98-Keeping-Your-Documents-Safe-In-a-Digital-Age>
 +) Staying Anonymous in a Heavily Monitored World  <http://www.enigmagroup.org/articles/view/Briefings/97-Staying-Anonymous-in-a-Heavily-Monitored-World>
 +) Wikipedia on Port knocking <http://en.wikipedia.org/wiki/Port_knocking>
 +) Recent Debian Security Advisories <http://www.debian.org/security/>
 +) Wikipedia on Network Security <http://en.wikipedia.org/wiki/Network_security>
 +) IPTables Tutorial by Oskar Andreasson <http://www.csie.ntu.edu.tw/~r93134/iptable/iptables-tutorial.html>
 +) Advanced Policy Firewall Readme <http://www.rfxn.com/appdocs/README.apf>
 +) Wikipedia on SSH tunneling <http://en.wikipedia.org/wiki/Tunneling_protocol#Secure_Shell_tunneling>