Setting up a Cisco Switch from Scratch

This blog is probably going to be really “no-duh” for most people. But I’ve had questions over the years on how to setup a switch from scratch and how to enable management from it remotely. So, I wiped my switch config and started over. After reloading the switch I was brought to the “Initial Configuration Dialog”. You can either choose to go through that or not. The initial config is basically just getting an IP address setup for management, setting up a username and setting up the “enable” password. You can see below what the init dialog looks like.

init-config

From there, you’ll have just a few more things to do in order to have a base config up and running, and enable remote access. We need to create a certificate, specify the domain name, secure SSH, and then setup the VTY lines. Let’s get that done here:

Erdmanor3750G#  conf t
Erdmanor3750G(config)#  
Erdmanor3750G(config)#  ip domain-name erdmanor.com
Erdmanor3750G(config)#  
Erdmanor3750G(config)#  crypto key generate rsa general-keys modulus 2048
The name for the keys will be: Erdmanor3750G.erdmanor.com

% The key modulus size is 2048 bits
% Generating 2048 bit RSA keys... [OK]
00:15:32 %SSH-5-ENABLED: SSH 1.99 has been enabled

Erdmanor3750G(config)#  
Erdmanor3750G(config)#  ip ssh version 2
Erdmanor3750G(config)#  
Erdmanor3750G(config)#  line vty 0 15
Erdmanor3750G(config-line)#  
Erdmanor3750G(config-line)#  transport input ssh
Erdmanor3750G(config-line)#  login local
Erdmanor3750G(config-line)#  exit
Erdmanor3750G(config)#  
Erdmanor3750G(config)#  username steve privilege 15 password MyP@ssW0rd
Erdmanor3750G(config)#  
Erdmanor3750G(config)#  service password-encryption
Erdmanor3750G(config)#


Now we can go back to our Linux box and log in from the command line.

steve @ debianvm ~ :) ##   ssh 3
The authenticity of host '192.168.86.3 (192.168.86.3)' can't be established.
RSA key fingerprint is 11:4e:b6:34:72:23:9a:0f:03:28:f0:e2:c9:b7:cc:20.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.86.3' (RSA) to the list of known hosts.
steve@192.168.86.3's password:
Erdmanor3750G#
Erdmanor3750G#exit
Connection to 192.168.86.3 closed.
steve @ debianvm ~ :) ##


Hope this was helpful!



http://www.cisco.com/c/en/us/td/docs/switches/lan/catalyst2960/software/release/12-2_53_se/configuration/guide/2960scg/swauthen.html

VN:F [1.9.22_1171]
Rating: 0.0/5 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Debian Backups, the Command Line Way…

I’ve been wanting to write a blog on this for a long time since I’ve actually had this backup method running in my environment for years. It’s super easy to setup and, while thank god I’ve never had to recover from a backup, I have been able to go back and recover individual files from my backups. What you’ll need from an environment setup is at least one Linux box that you need backed up, and at least one NAS or other file storage server that has an SSH server. I perform all my backups to online disk storage that is based on FreeNAS. There are plenty of NAS environment, and I’m not saying FreeNAS is the best or the worst, but I like it and it works for me. It works extremely well with Linux, Windows and Mac OS X.

There are two parts to this:

  • 1. manual backups
  • 2. automated backups

  • Let’s start with the manual backups, because once we have the manual backups performed, then we can easily turn that into a script and run it in CRON.


    First, we need to specify the directories we don’t want to backup in a file that is accessible to root. Let’s list the directories in “/” first.

    steve @ steve-G75VX ~ :) ##   ll /
    total 18M
    drwxr-xr-x  25 root   root 4.0K Oct 22 14:54 ./
    drwxr-xr-x  25 root   root 4.0K Oct 22 14:54 ../
    drwxr-xr-x   2 root   root 4.0K Aug 14 02:03 bin/
    drwxr-xr-x   4 root   root 3.0K Oct  3 11:39 boot/
    drwxrwxr-x   2 root   root 4.0K May 21 11:52 cdrom/
    -rw-------   1 root   root  18M Oct  3 11:40 core
    drwxr-xr-x  24 root   root 4.8K Oct 31 12:38 dev/
    drwxr-xr-x 148 root   root  12K Oct 27 20:37 etc/
    drwxr-xr-x   3 root   root 4.0K May 21 11:53 home/
    lrwxrwxrwx   1 root   root   33 Aug 14 02:06 initrd.img -> boot/initrd.img-3.19.0-25-generic
    lrwxrwxrwx   1 root   root   33 Jul 10 08:56 initrd.img.old -> boot/initrd.img-3.19.0-22-generic
    drwxr-xr-x  26 root   root 4.0K Oct 13 13:41 lib/
    drwxr-xr-x   2 root   root 4.0K May 21 12:41 lib32/
    drwxr-xr-x   2 root   root 4.0K Apr 22  2015 lib64/
    drwx------   2 root   root  16K May 21 11:47 lost+found/
    drwxr-xr-x   3 root   root 4.0K May 21 12:01 media/
    drwxr-xr-x   2 root   root 4.0K Apr 17  2015 mnt/
    drwxr-xr-x   6 root   root 4.0K Oct 20 11:28 opt/
    dr-xr-xr-x 283 root   root    0 Oct 21 20:30 proc/
    drwx------   4 root   root 4.0K Oct 27 16:57 root/
    drwxr-xr-x  30 root   root 1.1K Oct 27 20:50 run/
    drwxr-xr-x   2 root   root  12K Aug 14 02:03 sbin/
    drwxr-xr-x   2 root   root 4.0K Apr 22  2015 srv/
    dr-xr-xr-x  13 root   root    0 Oct 22 14:55 sys/
    drwxrwxrwx   2 nobody root 4.0K Oct 22 17:55 tftp/
    drwxrwxrwt  18 root   root 4.0K Nov  1 15:17 tmp/
    drwxr-xr-x  11 root   root 4.0K May 21 12:41 usr/
    drwxr-xr-x  13 root   root 4.0K Apr 22  2015 var/
    lrwxrwxrwx   1 root   root   30 Aug 14 02:06 vmlinuz -> boot/vmlinuz-3.19.0-25-generic
    lrwxrwxrwx   1 root   root   30 Jul 10 08:56 vmlinuz.old -> boot/vmlinuz-3.19.0-22-generic


    So, based on this, we’ll exclude like this:

    steve @ steve-G75VX ~ :) ##   sudo mkdir /backups
    [sudo] password for steve:
    steve @ steve-G75VX ~ :) ##   sudo touch /backups/exclude.list
    steve @ steve-G75VX ~ :) ##   sudo nano /backups/exclude.list
    steve @ steve-G75VX ~ :) ##  

    /cdrom
    /dev
    /lost+found
    /proc
    /run
    /sys
    /tmp

    (Ctrl+x to quit, then y to save)


    Now that we have our directory and exclude list setup, now we need to make sure RSYNC is installed on our system.

    steve @ steve-G75VX ~ :) ##   sudo apt-get update
    ...
    ...
    Fetched 1,743 kB in 21s (79.7 kB/s)
    Reading package lists... Done
    steve @ steve-G75VX ~ :) ##   sudo apt-get install rsync
    Reading package lists... Done
    Building dependency tree      
    Reading state information... Done
    rsync is already the newest version.
    0 upgraded, 0 newly installed, 0 to remove and 38 not upgraded.
    steve @ steve-G75VX ~ :) ##


    Now that we have RSYNC installed and our backup exclusions defined, lets get our backups started.

    First, edit your .bashrc file in your home directory and add this line:

    alias backupall='sudo rsync -athvz --delete / steve@1.1.1.1:/mnt/Backups/laptop/


    “What does all this do?” you might ask… well, it’s quite simple really.

    First, we create an alias for your shell named, “backupall”, because we’ll be performing full system backups from here.

    Next, we call “rsync” to run as root, and ask it to run with the switches -a, -t, -h, -v and -z.

  • -a = run in archive mode, which equals -rlptgoD (no -H,-A,-X)
  • -t = makes sure to preserve modification times on your files
  • -h = ensures that output numbers in a human-readable format
  • -v = trun verbosely.
  • -z = makes sure that file data is compressed during the transfer
  • And lastly, the “–delete” means, “This tells rsync to delete extraneous files from the receiving side (ones that aren’t on the sending side), but only for the directories that are being synchronized. You must have asked rsync to send the whole directory (e.g. lqdirrq or lqdir/rq) without using a wildcard for the directory’s contents (e.g. lqdir/*rq) since the wildcard is expanded by the shell and rsync thus gets a request to transfer individual files, not the files’ parent directory. Files that are excluded from the transfer are also excluded from being deleted unless you use the –delete-excluded option or mark the rules as only matching on the sending side (see the include/exclude modifiers in the FILTER RULES section).” — http://linux.die.net/man/1/rsync

    Next is the “/”, which means we’re backing up everything in “/”, which is everything.

    Lastly, we’re specifying the destination. In this case, we’re doing RSYNC over SSH, so we’ll be specifying a location in the way that you would specify a destination in SCP.


    Now test running your backup. I’ve run mine before, so my update is pretty quick. But this is going to backup your whole system for, so expect it to take a while.

    steve @ steve-G75VX ~ :( ᛤ>   backupallnas
    steve@1.1.1.1's password:
    sending incremental file list
    ./
    var/lib/mysql/blog/wp_AnalyticStats.MYD
    var/lib/mysql/blog/wp_AnalyticStats.MYI
    var/lib/mysql/blog/wp_options.MYD
    var/lib/mysql/blog/wp_options.MYI
    var/lib/mysql/blog/wp_postmeta.MYD
    var/lib/mysql/blog/wp_postmeta.MYI
    var/lib/sudo/steve/0
    var/log/auth.log
    var/log/apache2/access.log
    var/log/apache2/error.log

    sent 1.09M bytes  received 50.77K bytes  58.56K bytes/sec
    total size is 1.91G  speedup is 1673.17
    rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1070) [sender=3.0.9]
    steve @ steve-G75VX ~ :( ᛤ>



    Now we need to create our script, and make it executable.

    root @ steve-G75VX ~ :) ##   nano /backups/backupall
    root @ steve-G75VX ~ :) ##   chmod +x /backups/backupall
    root @ steve-G75VX ~ :) ##   ll /backups/backupall
    -rwxr-xr-x 1 root root 96 Nov  1 17:02 /backups/backupall*
    root @ steve-G75VX ~ :) ##


    I added this one line to the backup file:

    sudo rsync -athvz --delete / steve@1.1.1.1:/mnt/Backups/laptop/



    This looks pretty good! Now that we have a full backup of our machine, lets get this setup in CRON.

    steve @ steve-G75VX ~ :) ##   sudo su
    root @ steve-G75VX ~ :) ##   crontab -l
    no crontab for root
    root @ steve-G75VX ~ :( ##   crontab -e
    no crontab for root - using an empty one

    Select an editor.  To change later, run 'select-editor'.
      1. /bin/ed
      2. /bin/nano        <---- easiest
      3. /usr/bin/vim.tiny

    Choose 1-3 [2]: 2
    crontab: installing new crontab
    root @ steve-G75VX ~ :) ##


    The line that I added to CRON was this:

    0 3 * * * /backups/backupall >/dev/null 2&>1


    This basically states that every day at 3am, this script will be run.


    From here we need to make sure our local system can perform password-less logon to the SSH server. To do that we’ll be working off of a prior blog I wrote on SSH Keys, here: Using SSH Keys to simplify logins to remote systems.

    You’ll want to test that your system can SSH to your remote system without entering a password. As long as that works, we’re good to go!

    That’s it! It’s that simple!



    I have run into issues on some machines where SSH keys don’t work. I haven’t had the time to troubleshoot why, so I got a different way to figure out how to make backups work, without using SSH keys. The down side is that this is MUCH less secure, and I really don’t recommend running this in a production setting. But for home or non-business use, you’re probably just fine.

    So to do this, we’re going to use “SSHPASS” package. It’s out there for Debian and Ubuntu, so I’m sure it’s out there for other Linux/Unix systems as well.

    root @ steve-G75VX ~ :) ##   sudo apt-get install sshpass
    Reading package lists... Done
    Building dependency tree      
    Reading state information... Done
    The following NEW packages will be installed:
      sshpass
    0 upgraded, 1 newly installed, 0 to remove and 38 not upgraded.
    Need to get 10.5 kB of archives.
    After this operation, 56.3 kB of additional disk space will be used.
    Get:1 http://us.archive.ubuntu.com/ubuntu/ vivid/universe sshpass amd64 1.05-1 [10.5 kB]
    Fetched 10.5 kB in 0s (65.3 kB/s)  
    Selecting previously unselected package sshpass.
    (Reading database ... 258807 files and directories currently installed.)
    Preparing to unpack .../sshpass_1.05-1_amd64.deb ...
    Unpacking sshpass (1.05-1) ...
    Processing triggers for man-db (2.7.0.2-5) ...
    Setting up sshpass (1.05-1) ...
    root @ steve-G75VX ~ :) ##


    Go ahead and test logging into your NAS box, or any box really, with this. The idea is that, when you’re scripting you need to logon to remote systems without a password. If you can’t use SSH keys, then this is your next best bet. Create a file in “root’s” home dir and name it whatever you want. I named mine, “backup.dat”. It must contain only the password you use to log into your remote machine, on one line, all by itself.

    root @ steve-G75VX ~ :) ##   nano ~/backup.dat
    root @ steve-G75VX ~ :) ##   chmod 600 backup.dat


    You’ll call “sshpass”, -f for the file with the password, the location of your “ssh” program, -p and the port number (default port for ssh is 22), followed by the username you login with (make sure it’s in the format of, “user@machine-ip”).

    root @ steve-G75VX ~ :) ##   sshpass -f /root/backup.dat /usr/bin/ssh -p 22 steve@1.1.1.1
    Last login: Sun Nov  1 17:22:08 2015 from 1.1.1.2
    FreeBSD 9.2-RELEASE (FREENAS.amd64) #0 r+2315ea3: Fri Dec 20 12:48:50 PST 2013

        FreeNAS (c) 2009-2013, The FreeNAS Development Team
        All rights reserved.
        FreeNAS is released under the modified BSD license.

        For more information, documentation, help or support, go here:
        http://freenas.org
    Welcome to FreeNAS
    [steve@freenas ~]$ exit
    logout
    Connection to 1.1.1.1 closed.
    root @ steve-G75VX ~ :) ##


    Okay, now that we’ve tested this and know it’s working, lets modify our script here and get this working with “sshpass”.

    root @ steve-G75VX ~ :) ##   /usr/bin/rsync -athvz --delete --rsh="/usr/bin/sshpass -f /root/backup.dat ssh -o StrictHostKeyChecking=no -l YourUserN@me" /home/steve steve@1.1.1.1:/mnt/Backups/laptop/


    Now test to make sure the script is working (as soon as you see the incremental file list being sent, you know it’s working properly):

    root @ steve-G75VX ~ :) ##   /usr/bin/rsync -athvz --delete --rsh="/usr/bin/sshpass -f /root/backup.dat ssh -o StrictHostKeyChecking=no -l steve" /home/steve steve@1.1.1.1:/mnt/Backups/laptop
    sending incremental file list
    ^Crsync error: received SIGINT, SIGTERM, or SIGHUP (code 20) at rsync.c(632) [sender=3.1.1]
    root @ steve-G75VX ~ :) ##
    root @ steve-G75VX ~ :) ##
    root @ steve-G75VX ~ :) ##   /backups/backupall
    sending incremental file list
    steve/.cache/google-chrome/Default/Cache/
    ^Crsync error: received SIGINT, SIGTERM, or SIGHUP (code 20) at rsync.c(632) [sender=3.1.1]
    root @ steve-G75VX ~ :( ##

    Success!







    http://linux.die.net/man/1/rsync
    https://www.debian-administration.org/article/56/Command_scheduling_with_cron

    VN:F [1.9.22_1171]
    Rating: 0.0/5 (0 votes cast)
    VN:F [1.9.22_1171]
    Rating: 0 (from 0 votes)

    How-to: SCP files from ASA

    This is a quick and simple blog. Just notes really on how to use SCP/SSH to download files off of an ASA. It comes in handy for scripting purposes, but I thought I would at least share for everyone to see.

    First things first, we need to enable SSH and SCopy on our ASA. We can accomplish this by entering config mode, and then issuing 2 different “ssh” commands:

    steve @ phiberoptiklmde ~ :) ##  ssh steve@1.1.1.1
    pomeroy@1.1.1.1's password:
    Type help or '?' for a list of available commands.
    MyASA5510> en
    Password: ***********
    MyASA5510# conf t
    MyASA5510(config)#ssh 0.0.0.0 0.0.0.0 Inside
    MyASA5510(config)#ssh scopy enable
    MyASA5510(config)#wr
    Cryptochecksum: 0d46cc75 79177ae7 9069c9a8 94153d78

    8184 bytes copied in 0.690 secs
    [OK]
    MyASA5510(config)#exit
    MyASA5510#exit

    The first “ssh” command allows anyone to connect to this from the “Inside” interface of our ASA. This is NOT secure. In a real production environment, we should lock this down to a specific IP address, a handful of IP addresses, or a management network.

    The second “ssh” command tells the ASA to enable “scopy”. Which basically means that you can connect to the ASA with a SCP client and download files.

    From here we can just use our Linux machine to download the file to whatever folder you want to save your files to. See below on how to do that.
    Start with “scp”, then your user account at the IP of the machine: “scp steve@1.1.1.1”.
    From here, it needs to call an actual file that exists on the ASA. If you log into the ASA and issue the “dir” command from enable mode, you can get a listing of all files on the local flash drive on the machine.
    Lastly, you just need to specify the path that you want to save the file to.

    It’s that easy!

    steve @ phiberoptiklmde ~ :) ##   scp steve@1.1.1.1:anyconnect-win-3.1.05152-k9.pkg /home/steve/Desktop/anyconnect-win-3.1.05152-k9.pkg
    serdman@1.1.1.1's password:
    anyconnect-win-3.1.05152-k9.pkg                                                                                                                                                                           100%   34MB 212.0KB/s   02:42    
    Connection to 1.1.1.1 closed by remote host.
    steve @ phiberoptiklmde ~ :) ##   scp steve@1.1.1.1:anyconnect-macosx-i386-3.1.02040-k9.pkg /home/steve/Desktop/penvpn01-anyconnect/anyconnect-macosx-i386-3.1.02040-k9.pkg
    serdman@1.1.1.1's password:
    anyconnect-macosx-i386-3.1.02040-k9.pkg                                                                                                                                                                   100%   11MB 226.7KB/s   00:48    
    Connection to 1.1.1.1 closed by remote host.
    steve @ phiberoptiklmde ~ :) ##   scp steve@1.1.1.1:anyconnect-linux-3.1.02040-k9.pkg /home/steve/Desktop/anyconnect-linux-3.1.02040-k9.pkg
    serdman@1.1.1.1's password:
    anyconnect-linux-3.1.02040-k9.pkg                                                                                                                                                                         100%   11MB 317.9KB/s   00:34    
    Connection to 1.1.1.1 closed by remote host.
    steve @ phiberoptiklmde ~ :) ##   scp steve@1.1.1.1:anyconnect-linux-64-3.1.02040-k9.pkg /home/steve/Desktop/anyconnect-linux-64-3.1.02040-k9.pkg
    serdman@1.1.1.1's password:
    anyconnect-linux-64-3.1.02040-k9.pkg                                                                                                                                                                      100% 9735KB 314.0KB/s   00:31    
    Connection to 1.1.1.1 closed by remote host.
    steve @ phiberoptiklmde ~ :) ##   scp steve@1.1.1.1:anyconnect-macosx-i386-3.1.05152-k9.pkg /home/steve/Desktop/anyconnect-macosx-i386-3.1.05152-k9.pkg
    serdman@1.1.1.1's password:
    anyconnect-macosx-i386-3.1.05152-k9.pkg                                                                                                                                                                   100%   11MB 334.6KB/s   00:34  
    Connection to 1.1.1.1 closed by remote host.  
    steve @ phiberoptiklmde ~ :) ##   scp steve@1.1.1.1:anyconnect-linux-64-3.1.05152-k9.pkg /home/steve/Desktop/anyconnect-linux-64-3.1.05152-k9.pkg
    serdman@1.1.1.1's password:
    anyconnect-linux-64-3.1.05152-k9.pkg                                                                                                                                                                      100%   10MB 343.9KB/s   00:31  
    Connection to 1.1.1.1 closed by remote host.
    steve @ phiberoptiklmde ~ :) ##   scp steve@1.1.1.1:anyconnect-linux-3.1.05152-k9.pkg /home/steve/Desktop/anyconnect-linux-3.1.05152-k9.pkg
    serdman@1.1.1.1's password:
    anyconnect-linux-3.1.05152-k9.pkg                                                                                                                                                                         100%   10MB 341.5KB/s   00:31    
    Connection to 1.1.1.1 closed by remote host.
    steve @ phiberoptiklmde ~ :) ##

    VN:F [1.9.22_1171]
    Rating: 0.0/5 (0 votes cast)
    VN:F [1.9.22_1171]
    Rating: 0 (from 0 votes)

    Backing up Cisco Configurations for Routers, Switches and Firewalls

    I will add more about this when I have time. Until then, you should be able to just install python, paramiko and pexpect and run this script as-is (obviously changing the variables).

    This should give you all the software you need:

    sudo apt-get update
    sudo apt-get install python python-pexpect python-paramiko

    I plan on GREATLY increasing the ability of this script, adding additional functionality, as well as setting up a bash script that will be able to parse the configs, and perform much deeper backup abilities for ASAs.

    I have not tested this on Routers and Switches. I can tell you that the production 5520 HA Pair that I ran this script against was running “Cisco Adaptive Security Appliance Software Version 8.4(2)160”. Theoretically, I would believe that this would work with all 8.4 code and up, including the 9.x versions that are out as of the writing of this blog.

    Here you go! Full Scripted interrogation of Cisco ASA 5520 that can be setup to run on a CRON job.

    #!/usr/bin/python
    import paramiko, pexpect, hashlib, StringIO, re, getpass, os, time, ConfigParser, sys, datetime, cmd, argparse



    ### DEFINE VARIABLES

    currentdate="10-16-2014"
    hostnamesfile='vpnhosts'
    asahost="192.168.222.1"
    tacacsuser='testuser'
    userpass='Password1'
    enpass='Password2'
    currentipaddress="192.168.222.1"
    currenthostname="TESTASA"


    #dummy=sys.argv[0]
    #currentdate=sys.argv[1]
    #currentipaddress=sys.argv[2]
    #tacacsuser=sys.argv[3]
    #userpass=sys.argv[4]
    #enpass=sys.argv[5]
    #currenthostname=sys.argv[6]

    parser = argparse.ArgumentParser(description='Get "show version" from a Cisco ASA.')
    parser.add_argument('-u', '--user',     default='cisco', help='user name to login with (default=cisco)')
    parser.add_argument('-p', '--password', default='cisco', help='password to login with (default=cisco)')
    parser.add_argument('-e', '--enable',   default='cisco', help='password for enable (default=cisco)')
    parser.add_argument('-d', '--device',   default=asahost, help='device to login to (default=192.168.120.160)')
    args = parser.parse_args()

       


    #python vpnbackup.py $currentdate $currentipaddress $tacacsuser $userpass $enpass $currenthostname



    def asaLogin():
       
        #start ssh")
        child = pexpect.spawn ('ssh '+tacacsuser+'@'+asahost)
       
        #testing to see if I can increase the buffer
        child.maxread=9999999
       
        #expect password prompt")
        child.expect ('.*assword:.*')
        #send password")
        child.sendline (userpass)
        #expect user mode prompt")
        child.expect ('.*>.*')
        #send enable command")
        child.sendline ('enable')
        #expect password prompt")
        child.expect ('.*assword:.*')
        #send enable password")
        child.sendline (enpass)
        #expect enable mode prompt = timeout 5")
        child.expect ('#.*', timeout=10)
        #set term pager to 0")
        child.sendline ('terminal pager 0')
        #expect enable mode prompt = timeout 5")
        child.expect ('#.*', timeout=10)
        #run create dir function")
        createDir()
        #run create show version")
        showVersion(child)
        #run create show run")
        showRun(child)
        # run showCryptoIsakmp(child)
        showCryptoIsakmp(child)
        # run dirDisk0(child)
        dirDisk0(child)
        # run showInterfaces(child)
        showInterfaces(child)
        #run  showRoute")
        showRoute(child)
        #run showVpnSessionDetail")
        showVpnSessionDetail(child)
        # run showVpnActiveSessions(child)
        showWebVpnSessions(child)
        # run showVpnActiveSessions(child)
        showAnyConnectSessions(child)
        #send exit")
        child.sendline('exit')
        #close the ssh session")
        child.close()
       
       
    def createDir():
        if not os.path.exists(currentdate):
            os.makedirs(currentdate)
        if not os.path.exists(currentdate+"/"+currenthostname):
            os.makedirs(currentdate+"/"+currenthostname)
       
       
       
    def showVersion(child):
        #setting a new file for output")
        fout = file(currentdate+"/"+currenthostname+"/"+currenthostname+datetime.datetime.now().strftime("%m-%d-%Y")+"sh-ver.txt",'w')
        #capturing the command output to the file")
        child.logfile_read = fout
        #sending show version")
        child.sendline('show version')
        #expect enable mode prompt = timeout 400")
        child.expect(".*# ", timeout=50)
        #closing the log file")
        fout.close()
       
       
    def showRun(child):
        #setting a new file for output")
        fout = file(currentdate+"/"+currenthostname+"/"+currenthostname+datetime.datetime.now().strftime("%m-%d-%Y")+"sh-run.txt",'w')
        #capturing the command output to the file")
        child.logfile_read = fout
        #sending more system running-config")
        child.sendline('more system:running-config')
        #expect enable mode prompt = timeout 400
        child.expect(".*# ", timeout=999)
        #closing the log file
        fout.close()   
       

    def showCryptoIsakmp(child):
        #setting a new file for output")
        fout = file(currentdate+"/"+currenthostname+"/"+currenthostname+datetime.datetime.now().strftime("%m-%d-%Y")+"cryptoisakmp.txt",'w')
        #capturing the command output to the file")
        child.logfile_read = fout
        #sending show crypto isakmp sa")
        child.sendline('show crypto isakmp sa')
        #expect enable mode prompt = timeout 400
        child.expect(".*# ", timeout=50)
        #closing the log file
        fout.close()   


    def dirDisk0(child):
        #setting a new file for output")
        fout = file(currentdate+"/"+currenthostname+"/"+currenthostname+datetime.datetime.now().strftime("%m-%d-%Y")+"dirdisk0.txt",'w')
        #capturing the command output to the file")
        child.logfile_read = fout
        #sending dir disk0:")
        child.sendline('dir disk0:')
        #expect enable mode prompt = timeout 400
        child.expect(".*# ", timeout=75)
        #closing the log file
        fout.close()


    def showInterfaces(child):
        #setting a new file for output")
        fout = file(currentdate+"/"+currenthostname+"/"+currenthostname+datetime.datetime.now().strftime("%m-%d-%Y")+"interfaces.txt",'w')
        #capturing the command output to the file")
        child.logfile_read = fout
        #sending show interface")
        child.sendline('show interface')
        #expect enable mode prompt = timeout 400
        child.expect(".*# ", timeout=100)
        #closing the log file
        fout.close()


    def showRoute(child):
        #setting a new file for output")
        fout = file(currentdate+"/"+currenthostname+"/"+currenthostname+datetime.datetime.now().strftime("%m-%d-%Y")+"show-route.txt",'w')
        #capturing the command output to the file")
        child.logfile_read = fout
        #sending show route")
        child.sendline('show route')
        #expect enable mode prompt = timeout 400
        child.expect(".*# ", timeout=300)
        #closing the log file
        fout.close()


    def showVpnSessionDetail(child):
        #setting a new file for output")
        fout = file(currentdate+"/"+currenthostname+"/"+currenthostname+datetime.datetime.now().strftime("%m-%d-%Y")+"vpnsession.txt",'w')
        #capturing the command output to the file")
        child.logfile_read = fout
        #sending show vpn-sessiondb detail")
        child.sendline('show vpn-sessiondb detail')
        #expect enable mode prompt = timeout 400
        child.expect(".*# ", timeout=50)
        #closing the log file
        fout.close()


    def showWebVpnSessions(child):
        #setting a new file for output")
        fout = file(currentdate+"/"+currenthostname+"/"+currenthostname+datetime.datetime.now().strftime("%m-%d-%Y")+"webvpns.txt",'w')
        #capturing the command output to the file")
        child.logfile_read = fout
        #sending show vpn-sessiondb webvpn")
        child.sendline('show vpn-sessiondb webvpn')
        #expect enable mode prompt = timeout 400
        child.expect(".*# ", timeout=200)
        #closing the log file
        fout.close()


    def showAnyConnectSessions(child):
        #setting a new file for output")
        fout = file(currentdate+"/"+currenthostname+"/"+currenthostname+datetime.datetime.now().strftime("%m-%d-%Y")+"anyconnectvpns.txt",'w')
        #capturing the command output to the file")
        child.logfile_read = fout
        #sending show vpn-sessiondb anyconnect")
        child.sendline('show vpn-sessiondb anyconnect')
        #expect enable mode prompt = timeout 400
        child.expect(".*# ", timeout=999)
        #closing the log file
        fout.close()




    def main():
        #Nothing has been executed yet
        #executing asaLogin function
        asaLogin()
        #Finished running parTest\n\n Now exiting
       

    main()

    Here are all the websites that have provided help to me writing these scripts:
    http://www.802101.com/2014/06/automated-asa-ios-and-nx-os-backups.html
    http://yourlinuxguy.com/?p=300
    http://content.hccfl.edu/pollock/Unix/FindCmd.htm
    http://paulgporter.net/2012/12/08/30/
    http://paklids.blogspot.com/2012/01/securely-backup-cisco-firewall-asa-fwsm.html
    http://ubuntuforums.org/archive/index.php/t-106287.html
    http://stackoverflow.com/questions/12604468/find-and-delete-txt-files-in-bash
    http://stackoverflow.com/questions/9806944/grep-only-text-files
    http://unix.stackexchange.com/questions/132417/prompt-user-to-login-as-root-when-running-a-shell-script
    http://stackoverflow.com/questions/6961389/exception-handling-in-shell-scripting
    http://stackoverflow.com/questions/7140817/python-ssh-into-cisco-device-and-run-show-commands
    http://pastebin.com/qGRdQwpa
    http://blog.pythonicneteng.com/2012/11/pexpect-module.html
    https://pynet.twb-tech.com/blog/python/paramiko-ssh-part1.html
    http://twistedmatrix.com/pipermail/twisted-python/2007-July/015793.html
    http://www.lag.net/paramiko/
    http://www.lag.net/paramiko/docs/
    http://stackoverflow.com/questions/25127406/paramiko-2-tier-cisco-ssh
    http://rtomaszewski.blogspot.com/2012/08/problem-runing-ssh-or-scp-from-python.html
    http://www.copyandwaste.com/posts/view/pexpect-python-and-managing-devices-tratto/
    http://askubuntu.com/questions/344407/how-to-read-complete-line-in-for-loop-with-spaces
    http://stackoverflow.com/questions/10463216/python-pexpect-timeout-falls-into-traceback-and-exists
    http://stackoverflow.com/questions/21055943/pxssh-connecting-to-an-ssh-proxy-timeout-exceeded-in-read-nonblocking
    http://www.pennington.net/tutorial/pexpect_001/pexpect_tutorial.pdf
    https://github.com/npug/asa-capture/blob/master/asa-capture.py
    http://stackoverflow.com/questions/26227791/ssh-with-subprocess-popen

    VN:F [1.9.22_1171]
    Rating: 0.0/5 (0 votes cast)
    VN:F [1.9.22_1171]
    Rating: 0 (from 0 votes)

    Linux Stuff: How to setup SSH certificates to simplify logins to remote systems

    SSH and Server Certificates

    If you haven’t done this yet, we’re going to make life easy and get the SSH Certificates setup to make it super easy to SSH from our Linux Desktop.

     

    You’ll want to make sure to install SSH Server and client on both the machines you’re planning on configuring. Most of the time this is done already.

    Debian Based machines:

    apt-get install ssh openssh-server openssh-client

     

    Red Hat Based machines:

    yum install ssh openssh-server openssh-client

     

    When that’s done test out connecting from your local machine to your remote host using:

    ssh steve@208.28.163.39
    The authenticity of host '208.28.163.39 (208.28.163.39)' can't be established.
    RSA key fingerprint is 69:23:4c:49:35:41:ca:ae:23:3f:69:63:b2:ba:12:3c.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added '208.28.163.39' (RSA) to the list of known hosts.
    user03@208.28.163.39's password:
    user03 @ newstudent ~ :) ᛤ>   pwd
    /home/user03
    user03 @ newstudent ~ :) ᛤ>   exit
    logout
    Connection to 208.28.163.39 closed.
    steve @ mintdebianvm ~ :) ᛤ>

    Now we can setup SSH keys on this system so that you can easily log in from your main Linux Desktop machine.

     

    So go to your home directory on your local machine (NOT THE REMOTE SYSTEM!) and your navigate to your home folder. From here CD into your .ssh directory and we’ll create your SSH Certificates. If your “.ssh” directory doesn’t exist, just make one! Same goes for your REMOTE system too! Make sure that exists or this won’t work!

    cd ~/.ssh/
    ssh-keygen -t rsa -b 2048
    {save as default file, press enter}        
    {enter your own password and hit enter}     <-- this can be blank
    {confirm your password}                     <-- this can be blank

     

    Once this is done we’ll setup your host with keys to stay authenticated

    cat ~/.ssh/id_rsa.pub | ssh user03@208.28.163.39 "cat - >> ~/.ssh/authorized_keys"

     

    Now edit your LOCAL “.ssh/config” file and add in your new server. If you don’t have one, again, just create one!

    Host 208              <-- make that whatever you want. Keep it simple and easy to remember!
    HostName 208.28.163.39      <-- IP of remote host
    User user03                 <-- Your username on the remote machine.

     

    And now you can test your new ssh keys by doing this:

    ssh 208

     

    You may need to adjust your permissions properly. To do so, simply run this command on your local system:

    chmod 700 ~/.ssh && chmod 600 ~/.ssh/*

     

    And this command on your remote system that you’re trying to connect to:

    chmod 600 ~/.ssh/authorized_keys && chmod 700 ~/.ssh/

     

    Now you should be able to just log in without a password to any Remote system you set this up on!! 🙂

    ssh 208

     

    Enjoy!

    VN:F [1.9.22_1171]
    Rating: 0.0/5 (0 votes cast)
    VN:F [1.9.22_1171]
    Rating: 0 (from 0 votes)

    Linux How-To: Debian Server, Bind9 DNS and Postfix Mail Relay SPAM Filter


    So, MS Exchange has been attacked so many times over the years that it would be stupid to let it just sit out on the internet. Same goes for Microsoft DNS server. I would try as hard as I could to never put a Microsoft Server out on the Internet, or even allow a Microsoft to directly service the Internet. It’s just too risky, and I don’t play dice in certain situations such as these. I would, however, make an exception for hosting an Internet Information Services (IIS) Web Server. There are easy ways to lock down IIS and the OS, perform secure code reviews on the website itself, put reverse proxies in front of the web server (Apache Mod_Security or DotDefender)… the list goes on.

    But this isn’t a blog about web services. This blog is about setting up a secure Debian Server to host out a Bind9 DNS server and a Postfix reverse email Proxy. And this really could be split up into two different blogs, but I really think that they belong together because of how intertwined Email services are with DNS. Without DNS, mail would be significantly more difficult. But, DNS is also the problem with a LOT of SPAM. DNS configured improperly causes much of the SPAM that gets through to be seen by end users. Also, with DNS and Postfix running on the same box, the services are speedier and more responsive. We’ll do our best, but I really hope I can just refer people to this setup, because I truly believe that if more people would secure their mail servers and setup DNS properly, we could easily stop MOST SPAM that is out on the Internet from making it to Inbox’s around the world.

    And this will be a nice, really long, blog… strap in, people, we’re in for a ride! 🙂

     

    First things first, we need to start with a fresh install of Debian server. The main reason why I choose to go with Debian server is that:

    • First, it’s exceedingly stable and secure right out of the box. Very little configuration is needed…
    • Second, the creators of Debian don’t make tons of changes and they aren’t on the bleeding edge of new technologies.
    • Third, Debian is super easy to use and the software we need is also super easy to install
    • Lastly, especially for virtualized environments, a full install, using my method, takes a minimum of 512MB RAM and 1.5GB HDD space.

     

     

    I want to let everyone know here, that whatever I post on my site is things that I truly believe in. The main reason why I believe this process to work so well is that I’ve seen it in action at past employers, I’ve seen the MASSIVE cost savings past on to our customers, and because of all that I’ve implemented this exact same process at home. So basically, I eat my own dog food. I’m not going to tell you all to do something that is in secure or full of shit. My email server is already receiving emails through this Postfix Proxy, my domains are hosted off of this BIND9 server, and, if I may say, it’s ALL working beautifully.

    A good friend of mine, Nick (I’ll leave out his last name until he says it’s okay to mention him here), was the one who inspired me to get much of this stuff going. I worked with him at a past employer and showed me much of this stuff. Regardless, what I’m trying to get to here is, just the way that we have things setup now is pretty damn good. I have one domain passing all of my mail to a DMZ which has zero restrictions, and that domain forwards all the email it gets to my home server, which is the Proxy we’re about to setup. The reason I do this is to make sure that my SPAM filtering isn’t killing emails I WANT to see. SO, every so often I’ll check both accounts, side by side, and make sure that I’m filtering properly. And if I’m not, I’ll tweak the proxy accordingly. Eventually, maybe even in this blog, I’ll get a mail quarantine up and running so that I can just do away with the DMZ server and pass all my mail through this Proxy…

    Lastly, I’ve gone out of my way to make this as absolutely clear as I can. I’ve referenced all the sites and pages at the bottom of this blog, as I always do, and made this as close to perfect as I can. If you want an “installer” for this process, then you’re in the wrong spot. I will never build an automated installer for this without charging a butt load of money. If that’s what you’re looking for, go buy some Windows based software. Here, we’re working with Debian server on the Bash Shell.

     

     

    Anyways… So let’s get a base image up and running.

    Debian Minimal Install: The base for all operations

    When you’re done with that come back here and we’ll keep going… In the mean time let’s talk about the software we’re dealing with here…

     

    Postfix

    While Postfix can do a lot, just by itself, in filtering SPAM, it’s not the end all, be all, software. It’s literally just a Mail Transfer Agent (MTA), and it’s only purpose is to send and receive mail. So what we need to do here is arm Postfix with some weaponry, by the likes of Amavis-New, SpamAssassin, Anomy Sanitizer, and ClamAV. Now, I know your thinking, “ClamAV, huh?” But it’s better than nothing, it’s open source and it’s got over a million signatures. If you’re reading this thinking “WTF? My company wont be able to run this!”, then you’re in luck, because Postfix can forward mail for AV inspection to many of the top names in Anti Virus (Kaspersky, Symantec and McAfee). But for this article we’re going to work with ClamAV and some other tools, so deal with it. It’s free, and so is this blog…

     

     

    Amavis-New

    Amavis-New is a really good SPAM filtering engine, as well as SpamAssassin. What we’ll have to do is create two directories for Amavis and SpamAssassin to work in. They both receive mail from Postfix, unpack the email and attachments, inspect everything, then package everything back up the way they should be, and send it back to Postfix. This happens in two forks. Amavis gets the email first, then sends it back to Postfix, then it’s sent to SpamAssassin, then sent back to Postfix.

    When Amavis first starts at system boot, it just sits there and waits until it gets work to do, as any good little daemon should do. But when an email comes in, Amavis instantly forks a child process to do the work that needs to be done. This child process will create a sub directory in, in the Amavis working directory, and to it’s unpacking, inspection and repacking in. In the Amavis conf file you can specify how many children can be spawned, but you’ll want to test this out. Our config will have 5 children, and on a box with 1GB of ram, we should have PLENTY of room to work with. Now, if you’re running a Enterprise level SPAM filtering service, you may want to setup multiples of these servers that sit on a few or more MX records so that you can spread out the work load. Then beef up how much RAM and CPU cores you allocate to the VM and then allow Amavis to spawn more children. Pending the amount of hardware you have to work with, you could filter a TON of email with this configuration.

    Really though, at the end of the day, I strongly recommend that you investigate the Amavis-New website. Their FAQ’s are great and super informative. It’s truly amazing what this product can do.

     

     

    SpamAssassin

    As for SpamAssassin let’s talk about this for a minute. At the writing of this blog, Spam Assassin is at release 3.3.1. I’ll tell you the same thing I said a minute ago about Amavis: You should really look at the Spam Assassin website for more details about running, installing, configuring, testing and the operations of Spam Assassin. But I’ll briefly go over this stuff now. SpamAssassin works like many other filtering engines, “grading” the email on a multitude of different areas, including content, encoding, MIME settings, HTML markup and blacklists provided from different carriers like Spamhaus (which we’ll talk about later in this blog). Configured and monitored properly, Spam Assassin, just by itself, can filter over 97% of all SPAM, it’s false positive ratio is easily 1% or less, and the best part is that it has the ability to “learn” about new SPAM. The scoring engine is like a game of golf. The lower the score, the better. Other factors are looked at as well, such as Blacklisted IP’s, Reverse DNS lookups, list of banned words, list of banned file attachments (exe, vbs, etc…) sender and receiver addresses, valid date and time, etc…

    SpamAssassin isn’t all by itself though. While SpamAssassin is able to do a LOT on it’s own, it also “calls” other programs in to help it, such as razor, pyzor, and dcc-client. Each of these programs have specialized duties that perform additional SPAM checking. Razor is a distributed network devoted to spam detection. Razor uses statistical and randomized signatures that effectively identify many different types of SPAM. Pyzor, not surprisingly, is built on Python and also is based on a network dedicated to identifying SPAM. Like Razor, it too is signature based. Lastly, DCC (Distributed Checksum Clearinghouses) is also an anti-spam content filter. According to the DCC website, “The idea of DCC is that if mail recipients could compare the mail they receive, they could recognize unsolicited bulk mail. A DCC server totals reports of checksums of messages from clients and answers queries about the total counts for checksums of mail messages. A DCC client reports the checksums for a mail message to a server and is told the total number of recipients of mail with each checksum. If one of the totals is higher than a threshold set by the client and according to local whitelists the message is unsolicited, the DCC client can log, discard, or reject the message.”

    Back to SpamAssassin… The thing that really makes SpamAssassin great is the way that it handles SPAM. It’s completely configurable to the way YOU want SPAM handled. You can have it tag email as potential SPAM by just changing the email headers. There’s also ways that Spam Assassin will modify the Subject line of an email to include text like “***Potential SPAM***” or whatever you want it to say to your end users. This option truly is great, because there will always be false positives (email marked as SPAM that really isnt), and there will always be false negatives (SPAM that gets through to the end user that shouldn’t). With Subject line modification, we can alert the user to use their best judgement in looking at an email. If a message has a high enough score we can have the message quarantined until the user releases the message for review, or in extreme cases the email can just be dropped without notification.

    On the contrary, not all email should be blocked either. And Spam Assassin can look into messages to see if they have good karma. This sounds strange, but while there are services like Spamhaus, there are services that do the exact opposite of them. For instance, there are services like ISIPP Email Accreditation and Deliverability, Return Path who actually owns Bonded Sender which used to be Iron Port‘s product (which now Cisco owns), and more.

     

     

    Anomy

    Just because I’m too lazy to keep going on with this, I’ll just forward you to the Anomy website and you can look at their information if you want to know more. The main reason why I’ve decided to incorporate Anomy is because of the fact that, while the other SPAM and Virus checkers need to perform inspection on the disk, which can get very intense (and in extremely large environments can cause performance issues), Anomy does everything in system memory. The other reason why is that Anomy comes with it’s own custom built MIME parser which performs more checks than some of the other options. The thing that we’re looking at here is security in layers. You’ll hear that concept driven into your head over and over until the end of time. Security in layers. The day that you can buy 1 product to perform ALL of your security needs is the day I’m out of a job. Until then, you’re going to have to use multiple scan engines, multiple security technologies and continue to drive a culture of knowledge for your employees.

     

     

     

    Awesome, you got your VM up and running!!!

     

    SSH and Server Certificates

    In that tutorial I had you setup the IP address on your new Debian server to 192.168.0.100. We’ll reference that IP address for the rest of the time, but you can substitute it for whatever you made it on your network.

    If you haven’t done this yet, we’re going to make life easy and get the SSH Server installed so we can get some remote access to this server from our Linux Desktop.

    apt-get install ssh openssh-server openssh-client

     

    When that’s done test out connecting from your local machine to this virtual host using:

    ssh steve@192.168.0.100

    Now we can setup SSH keys on this system so that you can easily log in from your main Linux Desktop machine.

     

    So go to your home directory on your local machine (NOT THE SERVER!) and your navigate to your home folder. From here CD into your .ssh directory and we’ll create your SSH Certificates.

    cd ~/.ssh/
    ssh-keygen -t rsa
    {save as default file, press enter}        
    {enter your own password and hit enter}     <-- this can be blank
    {confirm your password}                     <-- this can be blank

     

    Once this is done we’ll setup your host with keys to stay authenticated

    cat ~/.ssh/id_rsa.pub | ssh steve@192.168.0.100 "cat - >> ~/.ssh/authorized_keys"

     

    Now edit your “.ssh/config” file and add in your new server. If you dont have one just create one!

    Host 100
    HostName 192.168.0.100
    User steve

     

    And now you can test your new ssh keys by doing this:

    ssh 100

     

    You may need to adjust your permissions properly. To do so, simply run this command on your local system:

    chmod 700 ~/.ssh && chmod 600 ~/.ssh/*

     

    And this command on your remote system that you’re trying to connect to:

    chmod 600 ~/.ssh/authorized_keys && chmod 700 ~/.ssh/

     

    Disable IPv6

    For our install, we need to disable IPv6. I’ve seen issues with Postfix and Bind when there is IPv6 running on the same box. I always bitch about lazy admins, and here I am being lazy and turning off IPv6 instead of fixing the underlying issue. 🙁

     

                               SO! Let’s get IPv6 disabled! haha 🙂

     

    I promise I’ll look into the issue over time, because I’ll need to make this solution work with IPv6 eventually. I can’t run from it forever. In the mean time, lets get going with editing your grub file:

    sudo vim /etc/default/grub

     

    While you’re in your Grub file, find the line that looks like this:

    GRUB_CMDLINE_LINUX="

     

    What you need to do here is make it look like this:

    GRUB_CMDLINE_LINUX="ipv6.disable=1"

     

    Then you need to update the loader by doing this:

    steve @ debian ~ :) ?>   sudo update-grub2
    Generating grub.cfg ...
    Found linux image: /boot/vmlinuz-2.6.32-5-amd64
    Found initrd image: /boot/initrd.img-2.6.32-5-amd64
    done
    steve @ debian ~ :) ?>   sudo update-grub
    Generating grub.cfg ...
    Found linux image: /boot/vmlinuz-2.6.32-5-amd64
    Found initrd image: /boot/initrd.img-2.6.32-5-amd64
    done

     

     

    Bind9 Domain Name System (DNS)

    Perfect! Now, let’s get Bind9 installed and configured properly. What I’ve done in my network is allowed my Internal Name Servers keep a copy of the External DNS zones. It makes life easier than setting up all your internal servers to also look at your External Servers. We’ll run through that as well during the setup. You’ll also want to get a copy of the Bind 9 Administrator Reference Manual. It’s not critical, but there’s some pretty damn good information in that document. www.bind9.net has both the online website and the downloadable PDF document.

    sudo apt-get install bind9

     

    Now that Bind is installed, lets configure the service to do what we want. We’ll start by editing our “named.conf” file where all the good stuff is.

    cd /etc/bind/
    sudo vim named.conf

    ### Named.conf File ###
    // This is the primary configuration file for the BIND DNS server named.
    //
    // Please read /usr/share/doc/bind9/README.Debian.gz for information on the
    // structure of BIND configuration files in Debian, *BEFORE* you customize
    // this configuration file.
    //
    // If you are just adding zones, please do that in /etc/bind/named.conf.local

    include "/etc/bind/named.conf.options";
    include "/etc/bind/named.conf.local";
    include "/etc/bind/named.conf.default-zones";

     

    This file is really tiny; it’s really just the spawn point for all the other configurations. And there’s two ways you can do this.

    • 1. You can remove all the other files and just do all your configurations in here
    • 2. You can continue to use the file structure the way it is

    Either way will work. If you’re a small company with only a few domain names, you can easily get away with lumping everything into this file and still keep separate zone files. If you’re a large company you may want to stay with many separate, smaller, configuration files. Especially when you’re dealing with companies that own hundreds, if not thousands, of domain names… even more so if you’re dealing with companies dispersed over several continents… or globally!

     

    In this scenario, we’re going to tighten things up just to make the initial config easy to see, but by no means am I telling you that you have to do it this way. DO it however you feel makes the most sense to you!

     

    So here we have the named.conf file; go ahead and make a backup of all your config files into a backup folder here and then modify your named.conf to look like mine below.

    cd /etc/bind/
    sudo mkdir installer-backup
    sudo cp * installer-backup/
    rm named.*

     

    And here is the code you can copy and paste into your “named.conf” file:

    sudo vim named.conf

    #####################################################################################
    #  This is not part of the default configuration that is included as part of the    #
    #  Bind 9 package. This section is commented out because it isnt needed.            #
    #  Also, for all of the files that were installed by default,                       #
    #  look in the "/etc/bind/installer-backup" directory                               #
    #####################################################################################
      #                                                                               #
      #                CONFIGURED BY STEVE ERDMAN, updated 12/27/12                   #
      #                                                                               #
      #################################################################################

    // The following section is the called the options section.
    // Configures the working directory for this BIND9 installation
    // Sets up BIND to allow query's from the Internet
    // recursion only from the Internal network (Change to your Internal Network!)
    // Forwarders set to Level 3, Google and OpenDNS public servers (if these guys dont work, the Internet is probably broken!
    // Listening on all interfaces (make sure to update this address to your real IP on this server!)
    // IPv6 turned off
    // running "named" version
    // auth-nxdomain states that this server will answer authoritatively for all domains configured on it

    options {
            directory "/etc/bind";
            notify-source * port 53;
            allow-query { any; };
            allow-recursion { 127.0.0.1; 192.168.0.0/24; };
            forwarders { 209.244.0.3; 209.244.0.3; 8.8.8.8; 8.8.4.4; 208.67.222.222; 208.67.220.220; };
            listen-on { 127.0.0.1; 192.168.0.100; };
            listen-on-v6 { none; };
            version "named";
            auth-nxdomain yes;    # conform to RFC1035
    };
    // end of options

    #---------------------------------------------------------------------------------------#
    #     Below are all of the zone files for all the forward and lookup zones that your    #
    #     company is responsible for.                                                       #
    #---------------------------------------------------------------------------------------#

    // zone name
    // 'type' only allows master, slave, stub, forward, hint... We own our zone, we're the master.
    // specify the file that our zone sits in
    // allow anyone to query our server
    // allow our internal name servers to cache this zone as a slave server
    // specify that if the zone data may have changed, that all servers with this zone data need to contact the SOA
    // THE ERDMANOR
    zone "example.com" IN {
                    type master;
                    file "/etc/bind/db.example.com";
                    allow-query { any; };
                    allow-transfer {192.168.0.7; 192.168.0.13; 192.168.0.18; 192.168.0.47; };
                    notify yes;
    };
    //same options apply as the above zone
    // 111.222.333.44 Reverse DNS
    zone "333.222.111.in-addr.arpa" {
                    type master;
                    file "/etc/bind/333.222.111.in-addr.arpa";
                    allow-query { any; };
                    allow-transfer {192.168.0.7; 192.168.0.13; 192.168.0.18; 192.168.0.47; };
                    notify yes;
    };

    #---------------------------------------------------------------------------------------#
    #   Consider adding the 1918 zones here, if they are not used in your organization  #
    #                  to use these just uncomment the following line:                      #
    #   include "/etc/bind/zones.rfc1918";                          #
    #---------------------------------------------------------------------------------------#
         #   Below are some zones that your server should cache                        #
         #   The for more info on this visit: http://www.zytrax.com/books/dns/ch7/     #
         #-----------------------------------------------------------------------------#

    // prime the server with knowledge of the root servers
    zone "." {
            type hint;
            file "/etc/bind/db.root";
    };
    // be authoritative for the localhost forward and reverse zones, and for
    // broadcast zones as per RFC 1912
    zone "localhost" {
            type master;
            file "/etc/bind/db.local";
    };
    zone "127.in-addr.arpa" {
            type master;
            file "/etc/bind/db.127";
    };
    zone "0.in-addr.arpa" {
            type master;
            file "/etc/bind/db.0";
    };
    zone "255.in-addr.arpa" {
            type master;
            file "/etc/bind/db.255";
    };

     

     

    Now we need to create some zone files. “What is a zone file?” you may be asking… Well, zone files are where all of your host information is stored, so that when a Internet customer queries “www.yourdomain.com” your DNS server looks up in it’s zone file the “www” host A record, and returns the response. There are all kinds of records, and here is a site that can explain all of this for you: List of DNS record types at Wikipedia.

     

    Now that you’re understanding records, lets get your zone file going. Working off of the example “named.conf” file above, let’s create our “db.example.com” and “333.222.111.in-addr.arpa” zone files. If you want to cheat a little bit, go ahead and use a zone file generator such as this one, but you really should understand how they work as well. So let’s look at one…

    sudo vim db.example.com


    ; BIND data file for example.com
    ;
    $TTL 3600
    @       IN      SOA     ns1.example.com.      ns2.example.com. (
                            201212263453789   ; serial number YYMMDDNN + some numbers
                            28800           ; Refresh
                            7200            ; Retry
                            3600          ; Expire
                            3600           ; Min TTL
                            )

           
        IN  NS  ns1.example.com.
            IN  NS  ns2.example.com.

            IN  MX  10  mail.example.com.
            IN  MX  20  smtp.example.com.

    $ORIGIN example.com.
        IN  A   111.222.333.41
    ns1     IN      A       111.222.333.42
    ns2     IN      A       111.222.333.43
    mail    IN      A       111.222.333.44
    smtp    IN      A       111.222.333.45
    autodiscover    IN      A       111.222.333.46
    vpn     IN      A       111.222.333.47
    www     IN      A       111.222.333.48

     

    Now let’s look at our Reverse Lookup zone so you can get an idea of what yours should look like:

    sudo vim 333.222.111.in-addr.arpa


    ; BIND data file for local loopback interface
    ;
    $TTL 3600
    @       IN      SOA     ns1.example.com.      dns.example.com. (
                            201212263453789   ; serial number YYMMDDNN
                            28800           ; Refresh
                            7200            ; Retry
                            3600          ; Expire
                            3600           ; Min TTL
                            )

    42     IN      NS       ns1.example.com.
    43     IN      PTR      smtp.example.com.
    44     IN      PTR      mail.example.com.
    45     IN      PTR      smtp.example.com.
    47     IN      PTR      vpn.example.com.
    48     IN      PTR      www.example.com.

     

    Awesome, now, one last thing that has helped me is if the “/etc/bind/” directory was owned by the “bind” user that was created upon install. Let’s do that real quick!

    sudo chown -R bind:root /etc/bind/

     

    Give your Bind server a quick restart, but you restart the service, open another bash shell tab (or session) and do a “sudo tail -f /var/log/syslog” and watch the output to make sure everything loads properly. It all should load up right, but if not, it’s better to find out now if there’s a problem than to wait until the end and troubleshoot tons of errors you *MAY* be having.

     

    sudo /etc/init.d/bind9 restart
    Stopping domain name service...: bind9 waiting for pid 2655 to die.
    Starting domain name service...: bind9.

     

    And dont forget your “tail”!

    steve @ debian ~ :( ?>sudo tail -f /var/log/syslog
    [sudo] password for steve:
    Dec 26 22:17:01 debian /USR/SBIN/CRON[3353]: (root) CMD (   cd / && run-parts --report /etc/cron.hourly)
    Dec 26 22:48:05 debian named[2655]: received control channel command 'stop -p'
    Dec 26 22:48:05 debian named[2655]: shutting down: flushing changes
    Dec 26 22:48:05 debian named[2655]: stopping command channel on 127.0.0.1#953
    Dec 26 22:48:05 debian named[2655]: stopping command channel on ::1#953
    Dec 26 22:48:05 debian named[2655]: no longer listening on ::#53
    Dec 26 22:48:05 debian named[2655]: no longer listening on 127.0.0.1#53
    Dec 26 22:48:05 debian named[2655]: no longer listening on 192.168.0.100#53
    Dec 26 22:48:05 debian named[2655]: exiting
    Dec 26 22:48:06 debian named[3491]: starting BIND 9.7.3 -u bind
    Dec 26 22:48:06 debian named[3491]: built with '--prefix=/usr' '--mandir=/usr/share/man' '--infodir=/usr/share/info'
    Dec 26 22:48:06 debian named[3491]: adjusted limit on open files from 1024 to 1048576
    Dec 26 22:48:06 debian named[3491]: found 2 CPUs, using 2 worker threads
    Dec 26 22:48:06 debian named[3491]: using up to 4096 sockets
    Dec 26 22:48:06 debian named[3491]: loading configuration from '/etc/bind/named.conf'
    Dec 26 22:48:06 debian named[3491]: reading built-in trusted keys from file '/etc/bind/bind.keys'
    Dec 26 22:48:06 debian named[3491]: using default UDP/IPv4 port range: [1024, 65535]
    Dec 26 22:48:06 debian named[3491]: using default UDP/IPv6 port range: [1024, 65535]
    Dec 26 22:48:06 debian named[3491]: listening on IPv4 interface lo, 127.0.0.1#53
    Dec 26 22:48:06 debian named[3491]: listening on IPv4 interface eth0, 192.168.0.100#53
    Dec 26 22:48:06 debian named[3491]: generating session key for dynamic DNS
    Dec 26 22:48:06 debian named[3491]: set up managed keys zone for view _default, file 'managed-keys.bind'
    Dec 26 22:48:06 debian named[3491]: automatic empty zone: 254.169.IN-ADDR.ARPA
    Dec 26 22:48:06 debian named[3491]: automatic empty zone: 2.0.192.IN-ADDR.ARPA
    Dec 26 22:48:06 debian named[3491]: automatic empty zone: 100.51.198.IN-ADDR.ARPA
    Dec 26 22:48:06 debian named[3491]: automatic empty zone: 113.0.203.IN-ADDR.ARPA
    Dec 26 22:48:06 debian named[3491]: automatic empty zone: 255.255.255.255.IN-ADDR.ARPA
    Dec 26 22:48:06 debian named[3491]: automatic empty zone: 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA
    Dec 26 22:48:06 debian named[3491]: automatic empty zone: 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA
    Dec 26 22:48:06 debian named[3491]: automatic empty zone: D.F.IP6.ARPA
    Dec 26 22:48:06 debian named[3491]: automatic empty zone: 8.E.F.IP6.ARPA
    Dec 26 22:48:06 debian named[3491]: automatic empty zone: 9.E.F.IP6.ARPA
    Dec 26 22:48:06 debian named[3491]: automatic empty zone: A.E.F.IP6.ARPA
    Dec 26 22:48:06 debian named[3491]: automatic empty zone: B.E.F.IP6.ARPA
    Dec 26 22:48:06 debian named[3491]: automatic empty zone: 8.B.D.0.1.0.0.2.IP6.ARPA
    Dec 26 22:48:06 debian named[3491]: command channel listening on 127.0.0.1#953
    Dec 26 22:48:06 debian named[3491]: command channel listening on ::1#953
    Dec 26 22:48:06 debian named[3491]: the working directory is not writable
    Dec 26 22:48:06 debian named[3491]: zone 0.in-addr.arpa/IN: loaded serial 1
    Dec 26 22:48:06 debian named[3491]: zone 333.222.111.in-addr.arpa/IN: ending notifies (serial 3289701)
    Dec 26 22:48:06 debian named[3491]: zone 127.in-addr.arpa/IN: loaded serial 1
    Dec 26 22:48:06 debian named[3491]: zone 255.in-addr.arpa/IN: loaded serial 1
    Dec 26 22:48:06 debian named[3491]: zone example.com/IN: loaded serial 16381
    Dec 26 22:48:06 debian named[3491]: zone localhost/IN: loaded serial 2
    Dec 26 22:48:06 debian named[3491]: managed-keys-zone ./IN: loading from master file managed-keys.bind failed: file not found
    Dec 26 22:48:06 debian named[3491]: managed-keys-zone ./IN: loaded serial 0
    Dec 26 22:48:06 debian named[3491]: running
    Dec 26 22:48:06 debian named[3491]: zone example.com/IN: sending notifies (serial 598703)

     

     

    Success! Your DNS server started and all your zones are loaded! Let’s test a couple queries and just make sure 🙂

    steve @ debian ~ :) ?>   dig @192.168.0.100 erdmanor.com mx

    ; <<>> DiG 9.8.1-P1 <<>> @192.168.0.100 erdmanor.com mx
    ; (1 server found)
    ;; global options: +cmd
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 55227
    ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 2, ADDITIONAL: 4

    ;; QUESTION SECTION:
    ;erdmanor.com.          IN  MX

    ;; ANSWER SECTION:
    erdmanor.com.       3600    IN  MX  20 smtp.erdmanor.com.
    erdmanor.com.       3600    IN  MX  10 mail.erdmanor.com.

    ;; AUTHORITY SECTION:
    erdmanor.com.       3600    IN  NS  ns1.erdmanor.com.
    erdmanor.com.       3600    IN  NS  ns2.erdmanor.com.

    ;; ADDITIONAL SECTION:
    mail.erdmanor.com.  3600    IN  A   65.55.37.62
    smtp.erdmanor.com.  3600    IN  A   64.4.59.173
    ns1.erdmanor.com.   3600    IN  A   74.125.228.105
    ns2.erdmanor.com.   3600    IN  A   74.125.228.96

    ;; Query time: 1 msec
    ;; SERVER: 192.168.0.100#53(192.168.0.100)
    ;; WHEN: Wed Dec 26 22:52:11 2012
    ;; MSG SIZE  rcvd: 172

     

    Fantastic, we’re looking good so far!

     

     

    Now that you’re mostly updated, you’ll need to visit the registrar for your domain name and update the information for where your domain is hosted. These records are called glue records and normally they take a while to update. They could take up to 12 or 24 hours to update so dont get worried if you have and DNS issues in the next few hours. Really, the best time to update that information for production domains (domains that cant suffer down time) is early on a Saturday night. Many people are watching TV, busy with the family or out on the town after 8pm on a Saturday (unless you’re me, haha). By the time the propagation spreads across the Internet, it’s Sunday morning and no one really noticed. Also, you’ll want to get on the phone with your ISP to have them forward all reverse lookup queries to your name servers. This is critical if you want YOUR out going email not to be tagged as SPAM!

    According to WikiPedia, “Name servers in delegations are identified by name, rather than by IP address. This means that a resolving name server must issue another DNS request to find out the IP address of the server to which it has been referred. If the name given in the delegation is a subdomain of the domain for which the delegation is being provided, there is a circular dependency. In this case the nameserver providing the delegation must also provide one or more IP addresses for the authoritative nameserver mentioned in the delegation. This information is called glue. The delegating name server provides this glue in the form of records in the additional section of the DNS response, and provides the delegation in the answer section of the response.

    For example, if the authoritative name server for example.org is ns1.example.org, a computer trying to resolve www.example.org first resolves ns1.example.org. Since ns1 is contained in example.org, this requires resolving example.org first, which presents a circular dependency. To break the dependency, the nameserver for the org top level domain includes glue along with the delegation for example.org. The glue records are address records that provide IP addresses for ns1.example.org. The resolver uses one or more of these IP addresses to query one of the domain’s authoritative servers, which allows it to complete the DNS query.”

     

    While your registrar information is updating let’s move forward and get some email action going!

     


    If all you were looking for here was a DNS tutorial for a single DNS server, you’re done. If you’re looking to go any further into SPAM filtering, continue on!

    I will be posting a blog as soon as I can on how to setup a distributed DNS server cluster. Stay tuned for that!

     

     

    Postfix and SPAM Filtering

    Alright, we need some software here, so… lets get Postfix installed!

    sudo apt-get update && sudo apt-get dist-upgrade
    sudo apt-get install -y postfix

     

    Now, when the software is installing, you’ll want to setup Postfix in a certain way. You NEED to make sure you pick “Internet Site” at the first prompt, and enter your EXTERNAL MX A-record. Many times this MX A Record is either “mail.example.com” or smtp.example.com”, but you’ll want to verify from your DNS zone that we created back in the BIND9 section.. See my screenshots below:

    Internet Site

    smtp.erdmanor.com

     

    Now that we have Postfix installed, we can setup a temporary mail relay to our Microsoft Exchange server. THIS SHOULD NOT BE IN PRODUCTION RIGHT NOW!

    GO ahead and edit your “main.cf” file. There is a line we need to change that I’ll show you below:

    sudo vim /etc/postfix/main.cf

    # Uncomment the next line to generate "delayed mail" warnings
    delay_warning_time = 4h


    # Add the IP address of your Exchange server's Receive Connector responsible for your Domain. (See below Screenshot)
    relayhost =192.168.0.125

    # And lastly, find "myorigin", and right below that add in "relay_domains = mydomain.com, example.com, (other, domains, comma, separated)"
    myorigin = /etc/mailname
    relay_domains = erdman.cc, erdmanor.com, someone.net, assholes.org

    # If you're hosting multiple domains, you'll want to setup a transport config file.
    transport_maps = hash:/etc/postfix/transport

    WE will talk about the /etc/postfix/transport file, and others, later, but this DOES need to be there!

    Exchange Server Receive Connector

     

    Now that we have that complete, we’ll restart the service:

    sudo /etc/init.d/postfix restart

     

    SPAM Filtering Engines

    Alright, cool… Let’s get some more software installed!

    sudo apt-get install -y amavisd-new spamassassin clamav-daemon

     

    As soon as that’s complete you’ll want to update the ClamAV virus definitions. They’re readily available, and even easier, you can run a simple command to do this:

    sudo freshclam
    [sudo] password for steve:
    ClamAV update process started at Thu Dec 27 00:16:40 2012
    main.cvd is up to date (version: 54, sigs: 1044387, f-level: 60, builder: sven)
    daily.cvd is up to date (version: 16130, sigs: 427971, f-level: 63, builder: neo)
    bytecode.cvd is up to date (version: 209, sigs: 40, f-level: 63, builder: neo)

    If you’re really looking to have fun with this, just create a quick shell script and then make a cron job out of it to run daily 🙂

     

    Alright, more software to install. Mainly more dependencies and stuff you’ll need that may not have been installed yet.

    sudo apt-get install -y libnet-dns-perl pyzor razor libarchive-tar-perl libio-socket-ssl-perl libio-socket-inet6-perl libnet-ident-perl liburi-perl libwww-perl libmailtools-perl tnef arj bzip2 cabextract cpio file gzip nomarch pax unzip zip zoo ripole cabextract p7zip lzop rpm2cpio unrar-free arc

     

    Perl Script Installs

    Following some package installs, we’ll be needing some perl scripts. So to install those, follow these instructions:

    steve @ debian ~ :) ?>   sudo perl -MCPAN -e shell


    CPAN is the world-wide archive of perl resources. It consists of about
    300 sites that all replicate the same contents around the globe. Many
    countries have at least one CPAN site already. The resources found on
    CPAN are easily accessible with the CPAN.pm module. If you want to use
    CPAN.pm, lots of things have to be configured. Fortunately, most of
    them can be determined automatically. If you prefer the automatic
    configuration, answer 'yes' below.

    If you prefer to enter a dialog instead, you can answer 'no' to this
    question and I'll let you configure in small steps one thing after the
    other. (Note: you can revisit this dialog anytime later by typing 'o
    conf init' at the cpan prompt.)
    Would you like me to configure as much as possible automatically? [yes]

     

    You’ll see a ton of information fly by as many values are automatically generated for you.
    Feel free to look at that stuff if you want. When you’re ready install the perl modules we need:

    (as you’re installing these Perl modules, you’ll see a lot of scrollback)

    o conf prerequisites_policy ask
    o conf commit
    install IP::Country::Fast
    install MIME::Base64
    install MIME::QuotedPrint
    install Net::DNS
    install DB_File
    quit

     

    Now for the DCC install. I haven’t found a package for DCC in the Debian repo’s unfortunately, and while that is a drawback to this software, it’s not the end of the world. We’ll just need to do some quick building of the software. But first we need to acquire the software from the DCC download page. The newest version that is out was released on January 12, 2013.

    From your Debian VM, run this command:

    wget http://www.dcc-servers.net/src/dcc/old/dcc-1.3.144.tar.Z

    Then you can extract and build the software like this:

    tar -xzvf dcc-1.3.144.tar.Z
    cd dcc-1.3.144/
    ./configure
    make
    sudo make install clean

    And you’re ready to move forward! (we’ll configure DCC later, for now we just need to have the software installed)

    NOTE

    Perfect, we’re moving right along here. One other thing to note here is that with all this going on, you’re going to want a highly tuned box. What I mean by that is, think of it this way: Every time a message comes in, we’re sending that message through 4 scanning engines, each one of which invokes it’s own shell or child process, some using a Perl interpreter, and unpacking/repacking each message in a temporary folder, inspecting the message and then sending it back out to your internal Exchange server. There’s A LOT going on here. This may add a bit of latency to the delivery of your messages. Remember, I’m running a VM on an SSD, with a Core i7 960, and the VM has 2 cores and 1GB of RAM. The latency I’m seeing here, as opposed to my other email service, is less than 1 minute, which is more than reasonable. We’ll go over some tuning at the end of this and tweak this whole system to work as efficiently as possible.

     

    Okay, now we need some user accounts created so that we can tighten up security a bit.

    Start by cat’ing your /etc/passwd file. Pending if your following my tutorial on a Red Hat, CentOS, Ubuntu or other OS, I want to make sure that our “amavis”, “spamd”, “anomy” and “clamav” users are created.

    steve @ debian ~ :) ?>   cat /etc/passwd
    ...
    ...
    steve:x:1000:1000:Steve Erdman,,,:/home/steve:/bin/bash
    postfix:x:104:107::/var/spool/postfix:/bin/false
    bind:x:105:109::/var/cache/bind:/bin/false
    clamav:x:106:110::/var/lib/clamav:/bin/false
    amavis:x:107:111:AMaViS system user,,,:/var/lib/amavis:/bin/sh

     

    SpamAssassin Configure

    Based on this information, we’re good on most user accounts, but we need to create a “spamd” account and an “anomy” account. We also need to setup working directories for both of these services and lock down access to them.

    sudo mkdir /var/run/spamassassin
    sudo mkdir /usr/local/anomy
    sudo groupadd -g 112 spamd
    sudo useradd -u 112 -g 112 -s /sbin/nologin -d /var/run/spamassassin spamd
    sudo chown spamd:spamd /var/run/spamassassin
    sudo chmod 750 /var/run/spamassassin
    sudo groupadd -g 113 anomy
    sudo useradd -u 113 -g 113 -s /sbin/nologin -d /usr/local/anomy anomy
    sudo chown root:anomy /usr/local/anomy
    sudo chmod 750 /usr/local/anomy
    sudo usermod -a -G clamav amavis
    sudo usermod -a -G amavis clamav

     

    Now let’s modify the SpamAssassin conf file:

    sudo vim /etc/default/spamassassin

     

    And modify these parameters: ( by default, SpamAssassin is disabled, we need to give it options to start)

    ENABLED=1
    OPTIONS="--username=spamd --create-prefs --max-children 5 --helper-home-dir"
    PIDFILE="/var/run/spamassassin/spamd.pid"
    CRON=1

     

    Now lets try to start SpamAssassin:

    sudo /etc/init.d/spamassassin restart

     

    And update the databases for SpamAssassin:

    sudo sa-update

     

     

    Amavis-New Configure

    Now, let’s get Amavis running. Technically, it is already running, but we need to enable Virus and SPAM filtering. Start by editing this file:

    sudo vim /etc/amavis/conf.d/15-content_filter_mode

     

    There are 4 lines in the file that you need to “uncomment”. See below:

    use strict;

    # You can modify this file to re-enable SPAM checking through spamassassin
    # and to re-enable antivirus checking.
    #
    # Default antivirus checking mode
    # Please note, that anti-virus checking is DISABLED by
    # default.
    # If You wish to enable it, please uncomment the following lines:

    @bypass_virus_checks_maps = (
       \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);

    #
    # Default SPAM checking mode
    # Please note, that anti-spam checking is DISABLED by
    # default.
    # If You wish to enable it, please uncomment the following lines:

    @bypass_spam_checks_maps = (
       \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);

    1;  # ensure a defined return

     

    Now restart Amavis to take effect:

    sudo /etc/init.d/amavis restart

     

     

     

    Anomy Configure

    ###I WANT TO STRESS THAT THIS PORTION (ANOMY) IS STILL UNDER INVESTIGATION AND YOU CAN SKIP THIS PART###

    Now lets get Anomy installed and running. First we’ll have to download it from their website.

    steve @ debian ~ :) ?>   cd ~
    /home/steve
    steve @ debian ~ :) ?>   wget http://bre.klaki.net/cgi-bin/qc?mailtools.anomy.net/dist/anomy-sanitizer-1.76.tar.gz
    HTTP request sent, awaiting response... 200 OK
    Length: 172722 (169K) [application/x-gzip]
    Saving to: “qc?mailtools.anomy.net%2Fdist%2Fanomy-sanitizer-1.76.tar.gz”

    100%[================================================================================>] 172,722      168K/s   in 1.0s    

    2012-12-27 15:26:38 (168 KB/s) - “qc?mailtools.anomy.net%2Fdist%2Fanomy-sanitizer-1.76.tar.gz” saved [172722/172722]

     

    Now to move it to it’s new home and unpack it. (for some reason the file name wasnt right so we need to rename it)

    sudo mv qc\?mailtools.anomy.net%2Fdist%2Fanomy-sanitizer-1.76.tar.gz /usr/local/anomy-sanitizer-1.76.tar.gz
    cd /usr/local/
    sudo su
    tar -zxvf anomy-sanitizer-1.76.tar.gz
    cd anomy
    ls -alh

     

    For starters on configuration, I found a site that provides a baseline config that we’ll work off of. Thanks to “advosys.ca” for this one! We’ll use this conf file to start with. If that link doesn’t work, here it is on my site: anomy.conf.

    Download that file and place it in your /usr/local/anomy/ folder.

    END OF ANOMY SECTION

     

     

    Allow Mail to be Scanned: Postfix Configuration

     

    Now what we need to do is setup Postfix to actually send the mail to the Spam Filtering engines. In order to make this happen we’re going to have to modify some postfix files. We’re also going to setup the “client_access”, “helo_access”, “sender_access” and “transport” files. We’ll talk more about that when after we modify the “main” and “master” files for Postfix. Basically, these files further enhance how Postfix is able to start the filtering process before mail even gets to the SPAM Filtering Engines. It is here that we start invoking services such as dsbl.org, spamhaus.org, abuseat.org, and dnsbl.sorbs.net that work by notifying servers like our that a domain is either blacklisted or black-holed. PLEASE Visit their sites for more information. Let’s start by looking at the “main.cf” file. To look at the “main.cf” file in all it’s glory, check this out. All of the descriptions below are accredited to this that page.

    **NOTE**: I’m setting up my configuration with the ability to verify user accounts through Active Directory. The reason for this is to allow Postfix to verify that the email address is valid before processing the mail. This is yet another safeguard against SPAM. Why accept mail for an account that doesn’t exist in your domain? Just block it! I’ll also show you how to secure the communications between Postfix and the domain. We’ll talk about this later. I haven’t added this content yet, but I will in the future!**END NOTE**

    What I’m going to do is just post my “main.cf” file in here and then comment the hell out of it so you understand the reasons for what is in the file. Please take out ALL of my comments before pasting this config into your “main.cf” file! If you don’t, you will most definitely have errors at run time!

    #EDITED BY STEVE ERDMAN
    # This is the banner that will be seen by all systems connecting to our Postfix server.
    smtpd_banner = The Erd-Manor-dot-com ESMTP Relay

    #Biff is an old legacy thing that isnt needed anymore and can cause performance issue if left on.
    biff = no

    #We dont want to help anyone out. If you're hosting more than 1 domain, you better leave this off (no).
    append_dot_mydomain = no

    #This is how much time Postfix will wait before sending a message back to the originating server
    #that there is an issue.
    delay_warning_time = 4h

    #This tells Postfix where to send mail on the next hop. You need this if you have more than 1 domain.
    transport_maps = hash:/etc/postfix/transport

    #The Internet hostname of this mail system. The default is to use the fully-qualified domain name (FQDN)
    #of your MX record.
    myhostname = smtp.erdmanor.com

    #The alias databases that are used for local mail delivery. We'll be modifying this later.
    alias_maps = hash:/etc/aliases

    #This is just where the aliases exist at.
    alias_database = hash:/etc/aliases

    #For most cases, your /etc/mailname file should contain the "myhostname" value. In this case, smtp.erdmanor.com
    myorigin = /etc/mailname

    #What destination domains (and subdomains thereof) this system will relay mail to.
    #This can be a file or a list of domains, that, are, comma, separated
    relay_domains = erdman.cc, erdmanor.com

    #The list of domains that are delivered via the $local_transport mail delivery transport. By default
    #this is the Postfix local delivery agent which looks up all recipients in /etc/passwd and /etc/aliases.
    #The SMTP server validates recipient addresses with $local_recipient_maps and rejects non-existent
    #recipients.This can be a file or a list of domains
    mydestination = debian.example.com, localhost

    #This is usually the primary IP address of your Internal Exchange Server. This value is trumped by "transport_maps"
    # so if you have multiple relay servers, you can comment this out like I have.
    #relayhost = 192.168.0.125

    # This is just a list of your internal networks. The list of "trusted" remote SMTP clients that have more
    #privileges than "strangers". You can also specify "/file/name" or "type:table" patterns.
    mynetworks = 127.0.0.0/8, 192.168.0.0/24

    #The maximal size of any local individual mailbox or maildir file, or zero (no limit). In fact, this limits
    #the size of any file that is written to upon local delivery, including files written by external commands
    #that are executed by the local delivery agent. This limit must not be smaller than the message size limit.
    mailbox_size_limit = 0

    #The separator between user names and address extensions (user+foo). Basically, the software tries user+foo
    #and .forward+foo before trying user and .forward. Just leave it the way it is.
    recipient_delimiter = +

    #The network interface addresses that this mail system receives mail on. Specify "all" to receive mail on all
    #network interfaces (default) and "loopback-only" to receive mail on loopback network interfaces only.
    inet_interfaces = all

    #After the message is queued, send the entire message to the specified transport:destination. The transport
    #name specifies the first field of a mail delivery agent definition in master.cf; the syntax of the next-hop
    #destination is described in the manual page of the corresponding delivery agent. More information about
    #external content filters is in the Postfix FILTER_README file.
    content_filter = smtp-amavis:[127.0.0.1]:10024

    #Enable or disable recipient validation, built-in content filtering, or address mapping. Typically, these
    # are specified in master.cf as command-line arguments... Specify zero or more of the following options.
    #The options override main.cf settings and are either implemented by smtpd(8), qmqpd(8), or pickup(8)
    #themselves, or they are forwarded to the cleanup server.
    #no_address_mappings means that we will disable canonical address mapping, virtual alias map expansion,
    #address masquerading, and automatic BCC (blind carbon-copy) recipients. This is typically specified
    #BEFORE an external content filter.
    receive_override_options = no_address_mappings

    #Require that addresses received in SMTP MAIL FROM and RCPT TO commands are enclosed with <>, and that
    #those addresses do not contain RFC 822 style comments or phrases. This stops mail from poorly written
    #software. By default, the Postfix SMTP server accepts RFC 822 syntax in MAIL FROM and RCPT TO addresses.
    strict_rfc821_envelopes = yes

    #Reject the request when the HELO or EHLO hostname has no DNS A or MX record. The
    #unknown_hostname_reject_code parameter specifies the numerical response code for rejected requests
    #(default: 450). This is a strong way to stop many spammers.
    unknown_hostname_reject_code = 450

    #The numerical Postfix SMTP server response code when a client without valid address <=> name mapping
    # is rejected by the reject_unknown_client_hostname restriction. The SMTP server always replies with
    #450 when the mapping failed due to a temporary error condition. Do not change this unless you have a
    # complete understanding of RFC 5321. Turning this on can cause a lot of false positives, test this out.
    ### unknown_client_reject_code = 450

    #Disable the SMTP VRFY command. This stops some techniques used to harvest email addresses.
    disable_vrfy_command = yes

    #Wait until the RCPT TO command before evaluating $smtpd_client_restrictions, $smtpd_helo_restrictions
    #and $smtpd_sender_restrictions, or wait until the ETRN command before evaluating
    #$smtpd_client_restrictions and $smtpd_helo_restrictions. This feature is turned on by default because
    #some clients apparently mis-behave when the Postfix SMTP server rejects commands before RCPT TO.The
    #default setting has one major benefit: it allows Postfix to log recipient address information when
    #rejecting a client name/address or sender address, so that it is possible to find out whose mail is
    #being rejected.
    smtpd_delay_reject = yes

    #Require that a remote SMTP client introduces itself with the HELO or EHLO command before sending the
    #MAIL command or other commands that require EHLO negotiation.
    smtpd_helo_required = yes

    #You need to read this --> http://www.postfix.org/postconf.5.html#smtpd_client_restrictions
    smtpd_client_restrictions =
            permit_mynetworks,
            check_client_access hash:/etc/postfix/client_access,
            reject_unknown_client_hostname,
    #Below are all of the DNS Blacklists that Spam originates from.
            reject_rbl_client sbl-xbl.spamhaus.org,
            reject_rbl_client cbl.abuseat.org,
            reject_rbl_client dul.dnsbl.sorbs.net,
            reject_rbl_client sbl.spamhaus.org,
            permit

    # You need to read this --> http://www.postfix.org/postconf.5.html#smtpd_helo_restrictions
    smtpd_helo_restrictions =
            permit_mynetworks,
            check_helo_access hash:/etc/postfix/helo_access,
            reject_non_fqdn_helo_hostname,
            reject_invalid_helo_hostname,
    #        reject_unknown_helo_hostname, #This can cause false positives, test before production!
            permit

    smtpd_sender_restrictions =
            permit_mynetworks,
            check_sender_access hash:/etc/postfix/sender_access,
            reject_non_fqdn_sender,
            reject_unknown_sender_domain, #This can cause false positives, test before production!
            permit

    smtpd_recipient_restrictions =
            permit_mynetworks,
            permit_sasl_authenticated,
            reject_unauth_destination,
            reject_invalid_hostname,
            reject_non_fqdn_hostname, #This can cause false positives, test before production!
            reject_non_fqdn_recipient,
            reject_unknown_recipient_domain,
            permit

    smtpd_error_sleep_time = 1s
    smtpd_soft_error_limit = 10
    smtpd_hard_error_limit = 20


    # Basic SPAM prevention...Require that a remote SMTP client introduces itself with the HELO or
    #EHLO command before sending the MAIL command or other commands that require EHLO negotiation.
    smtpd_helo_required = yes

     

     

    Wow, that took forever…

     

     

    Now we need to jump into the “master.cf” file. This one is a bit more tricky than the “main.cf” in that it has a lot more little tweaks. For more info on “master.cf”, there is an excellent “FAQ” on Postfix’s website: HERE. Here we go, I’ll do this the same as I did for the “main.cf” file, attempting to explain as much as I can so that you understand what everything is doing. 🙂 Remember to take out ALL of my comments before pasting this config into your “master.cf” file! If you don’t, you will most definitely have errors at run time!

     

    Here we go, here’s my “master.cf” file:

    # ==========================================================================
    # service type  private unpriv  chroot  wakeup  maxproc command + args
    #               (yes)   (yes)   (yes)   (never) (100)
    # ==========================================================================
    smtp      inet  n       -       -       -       -       smtpd
    #submission inet n       -       -       -       -       smtpd
    #  -o milter_macro_daemon_name=ORIGINATING
    #628       inet  n       -       -       -       -       qmqpd
    pickup    fifo  n       -       -       60      1       pickup
             -o content_filter=
             -o receive_override_options=no_header_body_checks
    cleanup   unix  n       -       -       -       0       cleanup
    qmgr      fifo  n       -       n       300     1       qmgr
    #qmgr     fifo  n       -       -       300     1       oqmgr
    tlsmgr    unix  -       -       -       1000?   1       tlsmgr
    rewrite   unix  -       -       -       -       -       trivial-rewrite
    bounce    unix  -       -       -       -       0       bounce
    defer     unix  -       -       -       -       0       bounce
    trace     unix  -       -       -       -       0       bounce
    verify    unix  -       -       -       -       1       verify
    flush     unix  n       -       -       1000?   0       flush
    proxymap  unix  -       -       n       -       -       proxymap
    proxywrite unix -       -       n       -       1       proxymap
    smtp      unix  -       -       -       -       -       smtp
    relay     unix  -       -       -       -       -       smtp
        -o smtp_fallback_relay=
    showq     unix  n       -       -       -       -       showq
    error     unix  -       -       -       -       -       error
    retry     unix  -       -       -       -       -       error
    discard   unix  -       -       -       -       -       discard
    local     unix  -       n       n       -       -       local
    virtual   unix  -       n       n       -       -       virtual
    lmtp      unix  -       -       -       -       -       lmtp
    anvil     unix  -       -       -       -       1       anvil
    scache    unix  -       -       -       -       1       scache
    maildrop  unix  -       n       n       -       -       pipe
      flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
    uucp      unix  -       n       n       -       -       pipe
      flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)

    smtp-amavis     unix    -       -       -       -       2       smtp
            -o smtp_data_done_timeout=1200
            -o smtp_send_xforward_command=yes
            -o disable_dns_lookups=yes
            -o max_use=20

    127.0.0.1:10025 inet    n       -       -       -       -       smtpd
            -o content_filter=
            -o local_recipient_maps=
            -o relay_recipient_maps=
            -o smtpd_restriction_classes=
            -o smtpd_delay_reject=no
            -o smtpd_client_restrictions=permit_mynetworks,reject
            -o smtpd_helo_restrictions=
            -o smtpd_sender_restrictions=
            -o smtpd_recipient_restrictions=permit_mynetworks,reject
            -o smtpd_data_restrictions=reject_unauth_pipelining
            -o smtpd_end_of_data_restrictions=
            -o mynetworks=127.0.0.0/8
            -o smtpd_error_sleep_time=0
            -o smtpd_soft_error_limit=1001
            -o smtpd_hard_error_limit=1000
            -o smtpd_client_connection_count_limit=0
            -o smtpd_client_connection_rate_limit=0
            -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks

     

    Now we need to take care of our “client_access”, “helo_access”, “sender_access” and “transport” files as we spoke of earlier. There are many types of these files that can be referenced by the “main.cf” file, but these are really the only ones we need. Theoretically, we could have created a bunch more of these, and in a large enterprise that owns hundreds or thousands of domains, it’s almost a necessity to do so. For all the info you need about these files look at the database webpage and the man 5 access page.

    Back in the “main.cf” file, we added a line item in there that looks like this, “check_client_access hash:/etc/postfix/client_access“. The purpose of the Client Access file is to “search the specified access database for the client hostname, parent domains, client IP address, or networks obtained by stripping least significant octets.” So what does that mean? Basically it means that this file is like access control list for remote SMTP servers. It checks client information: host names, network addresses, and envelope sender or recipient addresses.

    As a safeguard, we should NEVER be accepting email from our own domain, from a remote source. Our Exchange server is inside our organization already and will process our internal mail for us. This proxy will deny anyone out on the internet trying to spoof mail into our domain. You want to make sure to have every domain you own in this list. And you can also do some “whitelisting” in here as well. Let’s get our “client_access” file going:

    erdmanor.com        REJECT
    erdman.cc       REJECT
    74.114.46.150       OK
    directv.com     OK
    linuxmint.com       OK
    forums.linuxmint.com    OK

     

    Now for our “helo_access” file. This file is much the same, it’s another ACL that we are setting up. Postfix states that this command will tell the Postfix server to “Search the specified access database for the MX hosts for the HELO or EHLO hostname, and execute the corresponding action . Note 1: a result of “OK” is not allowed for safety reasons. Instead, use DUNNO in order to exclude specific hosts from blacklists. Note 2: specify “smtpd_helo_required = yes” to fully enforce this restriction (without “smtpd_helo_required = yes”, a client can simply skip check_helo_mx_access by not sending HELO or EHLO).

    erdmanor.com            REJECT
    erdman.cc           REJECT
    /^smtp\.erdman\.cc$/        550 Dont use my own hostname
    /^smtp\.erdmanor\.com$/     550 Dont use my own hostname
    /^mail\.erdman\.cc$/        550 Dont use my own hostname
    /^mail\.erdmanor\.com$/     550 Dont use my own hostname
    /^ns1\.erdman\.cc$/     550 Dont use my own hostname
    /^ns1\.erdmanor\.com$/      550 Dont use my own hostname
    /^ns2\.erdman\.cc$/     550 Dont use my own hostname
    /^ns2\.erdmanor\.com$/      550 Dont use my own hostname
    /^\[108\.227\.33\.121\]$/   550 Dont use my own IP address
    /^\[108\.227\.33\.122\]$/   550 Dont use my own IP address
    /^\[108\.227\.33\.123\]$/   550 Dont use my own IP address
    /^\[108\.227\.33\.124\]$/   550 Dont use my own IP address
    /^\[108\.227\.33\.125\]$/   550 Dont use my own IP address
    /^[0-9.]+$/         550 Your software is not RFC 2821 compliant
    /^[0-9]+(\.[0-9]+){3}$/     550 Your software is not RFC 2821 compliant

     

    Moving right along here, lets look at the “Sender_Access” file here. Again, this is another ACL that is supposed to search the specified access database for the MAIL FROM address, domain, parent domains, or localpart@, and execute the corresponding action. We want all of our domains in here as well, and for the same reason as the “client_access” file.

    erdmanor.com            REJECT
    erdman.cc               REJECT
    forums.linuxmint.com    OK
    linuxmint.com       OK

     

    And lastly, our transport file. This file is really important. Without this working properly we wont get any mail at all from this proxy.

    erdmanor.com        smtp:[192.168.0.126]
    erdman.cc       smtp:[192.168.0.127]

     
     

    Now that we have our access and transport files completed, we need to make them usable to Postfix. The only way that’s possible is to run the “Postmap” command on them.

    sudo postmap client_access
    sudo postmap helo_access
    sudo postmap sender_access
    sudo postmap transport

     

    ANYTIME YOU MODIFY THESE 4 FILES YOU MUST RUN THE POSTMAP COMMAND AGAINST THEM AND THEN RESTART POSTFIX! NO EXCEPTIONS!

     

    Now that Postfix is setup and ready to go, lets get that restarted and watch our log files at the same time. You should still have a second terminal open, so start your “tail” and then you can restart Postfix.

    steve @ debian ~ :) ?>sudo tail -f /var/log/syslog
    steve @ debian ~ :) ᛤ>   sudo /etc/init.d/postfix restart
    Stopping Postfix Mail Transport Agent: postfix.
    Starting Postfix Mail Transport Agent: postfix.

     

    Here is the output from the tail:

    Dec 28 11:34:12 debian postfix/master[1481]: terminating on signal 15
    Dec 28 11:34:12 debian postfix/master[3266]: daemon started -- version 2.7.1, configuration /etc/postfix

     

     

    At a bare minimum here, assuming your DNS records are setup properly, your MX records have propagated throughout the Internet, your Firewall is setup properly, your Exchange box is setup properly, and the other million variables are good, you should be able to drop this in between your firewall and your Exchange server. I would suggest putting this in a DMZ that is forward facing to the internet as I explained in one of my previous blogs “Serious network architecture that works for everyone“.

     

     

    SPAM Filter: SpamAssassin Configuration

    Now that our Postfix Proxy is moving mail properly, lets get some SPAM engines configured. 🙂 We’ll start with SpamAssassin. A brief background on SpamAssassin: This product is an open source code set that is actually used in a TON of other SPAM filtering products behind the scenes.

    Let’s get a quick idea of where SpamAssassin stores it’s files:

    /etc/spamassassin
    /etc/cron.daily/spamassassin
    /etc/default/spamassassin
    /etc/init.d/spamassassin
    /etc/mail/spamassassin
    /etc/spamassassin/
    /usr/bin/spamassassin
    /usr/share/spamassassin
    /usr/share/doc/spamassassin/
    /usr/share/man/man1/spamassassin*
    /usr/share/perl5/spamassassin-run.pod
    /usr/share/spamassassin/
    /var/lib/spamassassin
    /var/lib/amavis/.spamassassin
    /var/lib/dpkg/info/spamassassin.*
    /var/lib/spamassassin/

     

     

    Here is what my “/etc/spamassassin/local.cf” file looks like. I’ll comment on the file as I did earlier in this blog. Dont forget to remove ALL “#comments” before using this in your configuration. If you don’t, you will most definitely have errors at run time! Also, according to SpamAssassin, “There are now multiple files read to enable plugins in the /etc/mail/spamassassin directory; previously only one, “init.pre” was read. Now both “init.pre”, “v310.pre”, and any other files ending in “.pre” will be read. As future releases are made, new plugins will be added to new files, named according to the release they’re added in.” So we’re going to have to go through that stuff as well. Again, if you would like any further information regarding this, I urge you to visit the SpamAssassin page for the local.cf configuration settings.

    # I recommend not using this for this implementation. Our Postfix Server is acting as a Proxy to our
    # Exchange server. If you have internal servers that need to get mail to your users, then the best
    # place to handle that workload is at the Exchange Server Receive connectors. Send you internal mail there.
    # trusted_networks 192.168.0.0/24

    #Here is where we do our subject line rewrite for mail that is marked as SPAM.
    rewrite_header Subject  [***** SPAM _SCORE_ *****]

    #Score that a message needs to get to in order to be classified as SPAM.
    # this number is actually pretty high, but after tweaking it, you can lower it to 4.5 or 5.0.
    required_score      7.0

    #If the mail message meets the two above requirements the message is then packed up into an attachment and
    # forwarded to the recipient in plain text. It is up to the user to inspect and go from there.
    report_safe     2

    # Turn on DCC
    # dcc
    use_dcc 1
    dcc_path            /usr/bin/dccproc
    dcc_add_header          1
    dcc_dccifd_path         /usr/sbin/dccifd

    # Turning on the skip_rbl_checks setting will disable the DNSEval plugin, which implements Real-time Block
    # List (or: Blackhole List) (RBL) lookups. We WANT Those checks to happen so leave this at ZERO (0).
    skip_rbl_checks     0

    #razor
    use_razor2          1
    razor_config            /etc/razor/razor-agent.conf

    #pyzor
    pyzor_options           --homedir /etc/mail/spamassassin discover
    use_pyzor           1
    pyzor_path          /usr/bin/pyzor
    pyzor_add_header        1


    # Language and Location options. I have mine set to only allow English. If you work at a large international
    # business you'll want to setup all the languages your company communicates in or just say allow all:
    #  ok_locales all         (allow all locales)
    #  ok_locales en          (only allow English)
    #  ok_locales en ja zh    (allow English, Japanese, and Chinese)
    ok_locales              en


    # The next three deal with the Bayes system and how SpamAssassin actually can "learn" spam.
    use_bayes       1
    use_bayes_rules     1
    bayes_auto_learn    1
    use_learner 1

    # If you receive mail filtered by upstream mail systems, like a spam-filtering ISP or mailing list, and that
    # service adds new headers (as most of them do), these headers may provide inappropriate cues to the Bayesian
    # classifier, allowing it to take a "short cut". To avoid this, list the headers using this setting. Example:
    # bayes_ignore_header X-Upstream-Spamfilter
    # bayes_ignore_header X-Upstream-SomethingElse
    bayes_ignore_header X-Bogosity
    bayes_ignore_header X-Spam-Flag
    bayes_ignore_header X-Spam-Status

    # To be accurate, the Bayes system does not activate until a certain number of ham (non-spam) and
    # spam have been learned. The default is 200 of each ham and spam, but you can tune these up or
    # down with these two settings.
    bayes_min_ham_num        20 #default is 200
    bayes_min_spam_num       20 #default is 200

    # The Bayes system will, by default, learn any reported messages (spamassassin -r) as spam.
    # If you do not want this to happen, set this option to 0.
    bayes_learn_during_report      1


    # SpamAssassin will opportunistically sync the journal and the database. It will do so once a day,
    # but will sync more often if the journal file size goes above this setting, in bytes. If set to
    # 0, opportunistic syncing will not occur.
    bayes_journal_max_size        102400

    # What should be the maximum size of the Bayes tokens database? When expiry occurs, the Bayes
    # system will keep either 75% of the maximum value, or 100,000 tokens, whichever has a larger
    # value. 150,000 tokens is roughly equivalent to a 8Mb database file.
    bayes_expiry_max_db_size      200000

    # If enabled, the Bayes system will try to automatically expire old tokens from the database.
    # Auto-expiry occurs when the number of tokens in the database surpasses the
    # bayes_expiry_max_db_size value.
    bayes_auto_expire      1


    # If this option is set, whenever SpamAssassin does Bayes learning, it will put the information
    # into the journal instead of directly into the database. This lowers contention for locking the
    # database to execute an update, but will also cause more access to the journal and cause a delay
    # before the updates are actually committed to the Bayes database.
    bayes_learn_to_journal (default: 0)



    #   Some shortcircuiting, if the plugin is enabled
    #
    ifplugin Mail::SpamAssassin::Plugin::Shortcircuit

    #   default: strongly-whitelisted mails are *really* whitelisted now, if the
    #   shortcircuiting plugin is active, causing early exit to save CPU load.
    #   Uncomment to turn this on
    shortcircuit USER_IN_WHITELIST       on
    shortcircuit USER_IN_DEF_WHITELIST   on
    shortcircuit USER_IN_ALL_SPAM_TO     on
    shortcircuit SUBJECT_IN_WHITELIST    on

    #   the opposite; blacklisted mails can also save CPU
    shortcircuit USER_IN_BLACKLIST       on
    shortcircuit USER_IN_BLACKLIST_TO    on
    shortcircuit SUBJECT_IN_BLACKLIST    on

    #   and a well-trained bayes DB can save running rules, too
    #
    shortcircuit BAYES_99                spam
    shortcircuit BAYES_00                ham

    endif # Mail::SpamAssassin::Plugin::Shortcircuit

     

     

    Here’s that Exact same file without all the comments:

    rewrite_header Subject  [***** SPAM _SCORE_ *****]
    required_score          7.0
    report_safe         2
    use_dcc 1
    dcc_path                /usr/bin/dccproc
    dcc_add_header          1
    dcc_dccifd_path         /usr/sbin/dccifd
    skip_rbl_checks     0
    use_razor2          1
    razor_config            /etc/razor/razor-agent.conf
    pyzor_options           --homedir /etc/mail/spamassassin discover
    use_pyzor               1
    pyzor_path          /usr/bin/pyzor
    pyzor_add_header        1
    ok_locales              en
    use_bayes       1
    use_bayes_rules     1
    bayes_auto_learn    1
    use_learner 1
    bayes_ignore_header X-Bogosity
    bayes_ignore_header X-Spam-Flag
    bayes_ignore_header X-Spam-Status
    bayes_min_ham_num        20 #default is 200
    bayes_min_spam_num       20 #default is 200
    bayes_learn_during_report      1
    bayes_journal_max_size        102400
    bayes_expiry_max_db_size      200000
    bayes_auto_expire      1
    bayes_learn_to_journal (default: 0)


    ifplugin Mail::SpamAssassin::Plugin::Shortcircuit

    shortcircuit USER_IN_WHITELIST       on
    shortcircuit USER_IN_DEF_WHITELIST   on
    shortcircuit USER_IN_ALL_SPAM_TO     on
    shortcircuit SUBJECT_IN_WHITELIST    on

    shortcircuit USER_IN_BLACKLIST       on
    shortcircuit USER_IN_BLACKLIST_TO    on
    shortcircuit SUBJECT_IN_BLACKLIST    on

    shortcircuit BAYES_99                spam
    shortcircuit BAYES_00                ham

    endif # Mail::SpamAssassin::Plugin::Shortcircuit

     

    Now we need to restart SpamAssassin and test out our changes.

    sudo sa-update -D --updatedir /tmp/updates
    sudo /etc/init.d/spamassassin restart
    echo "test" | sudo spamassassin -D pyzor 2>&1 | less

     

    Alright, enough SpamAssassin stuff. Let’s get Amavis up and running.

     

     

    SPAM Filter: Amavis-New Configuration

    Now that our Postfix Proxy is moving mail properly, and SpamAssassin is filtering mail, lets get some Amavis-New configured. Remember what we said before: Amavis sends mail to SpamAssassin by default. That is the reason why we setup SpamAssassin first. In order to have Amavis properly scanning mail we’ll be configuring files in your /etc/amavis/ directory. Before we jump into that, lets get an Idea of where Amavis is located in your Server. Below is where Amavis has files by a default install:

    /etc/amavis/
    /etc/amavis/conf.d/
    /etc/cron.d/amavisd-new
    /etc/cron.daily/amavisd-new
    /etc/cron.hourly/amavisd-new
    /etc/init.d/amavis
    /etc/init.d/amavisd-new-milter
    /etc/ldap/schema/amavis.schema
    /etc/logcheck/ignore.d.server/amavisd-new
    /etc/logcheck/violations.ignore.d/amavisd-new
    /usr/sbin/amavis
    /usr/sbin/amavis-milter
    /usr/sbin/amavisd-agent
    /usr/sbin/amavisd-nanny
    /usr/sbin/amavisd-new
    /usr/sbin/amavisd-new-cronjob
    /usr/sbin/amavisd-release
    /usr/share/amavis/
    /usr/share/amavis/conf.d/
    /usr/share/doc/amavisd-new/
    /usr/share/lintian/overrides/amavisd-new
    /var/lib/amavis/
    /var/lib/dpkg/info/amavisd-ne*
    /var/lib/update-rc.d/amavis
    /var/lib/update-rc.d/amavisd-new-milter

     

    I know that seems like a lot, but we’ll try cover it all. Amavis is really a different beast than SpamAssassin. But since SpamAssassin is already doing the brunt force of the work, we can take our time in this one a bit.

     

     

     

     

     

    SPF Records

    The last thing I wanted to cover in this blog, since we’re hosting our own DNS and Mail servers, it would only be right for us to cover DNS SPF records. This is just another layer of security that we *should be* using to help strengthen, not only our email, but our whole external domain.

     

     

    STILL A WORK IN PROGRESS!

    I updated this again on 2/3/13. But I’m lazy, so… there’s no change log. 🙂

     

     

    References for this blog go out to:
    http://pcsupport.about.com/od/tipstricks/a/free-public-dns-servers.htm
    http://www.bind9.net/manuals
    http://www.zytrax.com/books/dns/ch7/queries.html
    http://www.itechlounge.net/2011/12/bind-unexpected-rcode-refused-resolving-xx-xx-xx-xx-in-addr-arpaptrin/
    http://www.webupd8.org/2009/11/how-to-disable-ipv6-in-ubuntu-910.html
    http://pgl.yoyo.org/as/bind-zone-file-creator.php
    http://postfix.1071664.n5.nabble.com/Unknown-Recipient-Domain-td44755.html
    http://www.cyberciti.biz/tips/howto-postfix-flush-mail-queue.html
    http://www.zytrax.com/books/dns/
    http://www.fencepost.net/2010/03/fix-postfix-recipient-address-rejected-domain-not-found/
    http://www.zytrax.com/books/dns/ch7/xfer.html#notify
    http://www.zytrax.com/books/dns/ch8/soa.html
    http://www.cyberciti.biz/tips/howto-postfix-flush-mail-queue.html
    http://www.postfix.org/addon.html
    http://wiki.apache.org/spamassassin/UsingRazor
    http://wiki.apache.org/spamassassin/UsingPyzor
    http://wiki.apache.org/spamassassin/UsingDcc
    http://www.dcc-servers.net/dcc/
    http://www.kaspersky.com/linux-mail-security
    http://www.postfix.org/FILTER_README.html
    http://www.giac.org/paper/gsec/2824/smtp-gateway-virus-filtering-amavis-postfix/104787
    http://advosys.ca/papers/email/53-postfix-filtering.html
    http://mailtools.anomy.net/
    http://www.dcc-servers.net/dcc/INSTALL.html
    http://www.amavis.org/
    http://spamassassin.apache.org/
    http://www.postfix.org/
    http://onetforum.com/fourm/viewtopic.php?p=27
    http://wiki.apache.org/spamassassin/WritingRules
    http://codesorcery.net/old/docs/spamtricks.html
    http://svn.apache.org/repos/asf/spamassassin/branches/3.3/spamd/README
    http://spamassassin.apache.org/full/3.3.x/doc/Mail_SpamAssassin_Conf.html
    http://wiki.apache.org/spamassassin/FrequentlyAskedQuestions

    VN:F [1.9.22_1171]
    Rating: 5.0/5 (1 vote cast)
    VN:F [1.9.22_1171]
    Rating: 0 (from 0 votes)