How to install Postfix, Amavisd-new, SpamAssassin, Pyzor, Razor, DCC, and ClamAV on Fedora Core 4 - v2.1.8

By RoNNY Nussbaum

 

 

Greetings!

 

This document describes how to install Postfix, Amavisd-new, SpamAssassin, Pyzor, Razor, and DCC on one box running Fedora Core 4. The installation assumes that Postfix will not be the final destination of incoming mail. Also, no e-mail is sent through it to the outside world. It is a simple MTA that receives e-mail, scans it, and moves it to another MTA for processing.

 

For those of you still working on a v2.1.7 setup, the older document is here.

 

You need to know some Linux to use this guide. At the minimum you need to know how to work with vi (see Appendix B). Also, I’m not a Linux expert, so some of you gurus out there may find some better ways to do things. That’s fine. Feel free to give me feedback. It’s important to keep this document updated, your input is invaluable, and will help make this document better. For all questions or comments, please e-mail me at ronnynussbaum [at] gmail [dot] com.

 

Use this document at your own risk. I take absolutely no responsibility for any losses or damages incurred as a result of using this installation, but it does work…really!

 

This document was inspired by the original document written by Scott L. Henderson, however, it’s a document that I wrote on my own, and has some more settings, tweaks, and tricks that I learned about from my own experience, and from the good people in the mailing lists. I tried to be very clear, and explain each setting. If you find something to be confusing, please let me know.

 

I’d like to also mention the great document by mr88talent. His document describes a similar installation, but on a Debian rather than Fedora. You can find his document here: http://www200.pair.com/mecham/spam/, and I have found it to contain some valuable resources that are good for Fedora as well, and were used in this document.

 

I will start by installing Postfix, which will be our mail server in this case. Postfix uses amavisd-new to communicate with content filters, such as SpamAssassin, and ClamAV. SpamAssassin is using its own anti-spam techniques, as well as communicating with third-party services, such as Razor, Pyzor, and DCC, to detect if a message is spam or not. In this document, I will refer to amavis-new as Amavisd, and sometimes amavisd. In any case, I’m talking about amavisd-new, which can be found here: http://www.ijs.si/software/amavisd/.

 

You will also see situation where I claim that something will happen if we set a specific variable to a specific value.

Please keep in mind that this doesn’t necessarily means that in all cases, and all configurations, you will get the same results.

The setting may be true for this configuration only.

 

This document works best if you view it at a resolution of 1024x768. If you have a lower resolution browser window, make sure to pay careful attention to the commands that you type. Spaces tend to disappear when your browser wraps the lines. Also, some people reported printing the document, and that some underscores disappeared in the process. Please double-check every command that you type against the web version of the document.

 

One final note: this installation is for Fedora Core 4, but this document started its life as the installation manual for Fedora Core 3. With proper adjustment, it can be easily used on FC3. In fact, I think that the only thing that’s a little different is the installation part. If you chose to install FC3 instead of FC4, I suggest that you’ll simply ignore the differences that you see during install. It should work fine.

 

Another final note: please please please check the forum. There’s answers to a lot of your questions there.

 

Enjoy building the server.

 

-RoNNY

 

Table of Contents

How to install Postfix, Amavisd-new, SpamAssassin, Pyzor, Razor, DCC, and ClamAV on Fedora Core 4 - v2.1.6  1

Table of Contents. 2

Conventions Used In This Manual 4

Installing Fedora Core 4. 6

Errors During Boot 8

After the Initial Reboot 8

Login to the System for the First Time. 8

Firewall Protection. 9

PuTTY.. 9

WinSCP. 9

Disabling Some Unneeded Daemons (Services) 10

Updating the System.. 10

Changing the Language Preferences. 11

Make vi Show Files in Color (use vim) 11

Optional: Configuring ls. 11

Downloading the Required Software. 12

Set the System to Boot into Text Mode. 12

Creating Some Required Users. 12

Installing Postfix. 13

Configuring Postfix. 14

A Word About DNS and MX Records. 14

The master.cf File. 16

The main.cf File. 16

Postfix’s Own Anti-Spam Filters. 19

The virtual File. 22

The transport File. 23

The client_access File. 23

The helo_access File. 24

The sender_access File. 25

The recipient_access File. 25

Asynchronous Logging. 26

Testing Postfix. 26

Searching the Log. 27

Testing Incoming Mail 28

Setting Postfix to Start Automatically at System Boot 29

Saving Postfix’s Configuration. 29

Address Verification. 30

Installing SpamAssassin. 31

The Trusted Path Problem.. 33

Installing Amavisd-New.. 34

An Overview of Amavis’ Quarantine, Notifications, and Actions. 34

Configuring Amavisd-New.. 37

A Few Words About Tags. 37

Creating Some Directories for Amavisd. 42

Installing Some Prerequisites for Amavisd. 42

About Sender Policy Framework (SPF) 43

Creating White-List and Black-List files. 44

Testing Amavisd. 44

Setting Postfix to Use Amavisd. 45

Setting Amavisd to Start Automatically at System Boot 46

Amavis’ Little Children. 46

Installing Razor 47

Configuring Razor 48

Installing Pyzor 49

Installing DCC.. 50

More SpamAssassin Configuration. 52

Testing the Server 54

Reminder Regarding Configuration Changes. 56

Installing ClamAV.. 57

Configuring ClamAV.. 58

Testing ClamAV.. 59

Issuing Commands to clamd. 60

Alternative clamd Configuration. 61

Setting ClamAV (clamd) to Start Automatically at System Boot 62

Setting ClamAV to Auto-Update hourly. 63

Logwatch. 63

Logrotate. 64

Backing-up the Server’s Configuration. 64

Working with sa-learn. 67

Tweaking SpamAssassin’s Tests Scores. 68

Generating Mail Reports. 69

Appendix A: Setting up the IP address manually. 70

Setting up DNS resolution. 71

Modifying the hosts file. 71

Changing the host name. 71

Setting Up Multiple IPs for the Server 71

Appendix B: Very short vi manual 73

Appendix C: Postfix startup script 73

Appendix D: mime_mail script 75

Appendix E: Upgrading the Server’s Software. 80

Postfix. 80

SpamAssassin. 81

Amavis. 81

Razor 81

Pyzor 81

DCC.. 82

ClamAV.. 82

Revisions to this Document 84

To Do: 85

Thanks. 85

 

Conventions Used In This Manual

Throughout the manual, commands that should be typed in by you in the shell prompt, or in vi, will look like this. Several commands that need to be typed one after the other, are separated from each other with a white line:
command 1
command 2

When a command is too long to fit in one line its second, third, fourth, etc, lines will be indented:

this command is so long, so I had to type it in several lines

 and then indent it

 over and over again!

Note that the above conventions also may be used even when you type something in vi, and not necessarily the shell prompt.

 

Please read the very short vi manual in Appendix B. From now on, I will assume that you know how to use vi, so that when I write “edit the file”, “or “save close the file”; you’ll know what I mean. Also, unless otherwise stated, each command should be issued by pressing Enter after the command is typed in.


Installing Fedora Core 4

  1. Boot from the DVD or CD, and press <Enter> when you see the boot: prompt.
  2. You will then be asked if you want to check the media before installing. <Tab> to the Skip option, and press <Enter>.
  3. After a few seconds, you should see the GUI screen of Fedora's installation. Click Next. Choose your language and click Next. Choose your keyboard configuration and click Next again.
  4. Choose Custom Installation and click Next.
  5. On the next screen you'll have to define how you want your drive partitioned. I found that letting Disk Druid do the work is good for me, but you can choose to partition your system differently. It's your call. Just remember that you may have some large log files that you need to store.

    Choose Automatically Partition and hit Next. If this is a brand new drive, you may be getting a warning about erasing all the data on it, blah blah...
    You don't really care, since it's a new install, so let Disk Druid continue.

    You should then see a screen that asks you how you want automatic partitioning to happen. I always choose option two: Remove all partitions on this system. This will give you the most space in my experience.

    Click Next. You'll get a warning, so click Yes to get rid of it.
  6. You will then see your proposed disk partitioning configuration.
    Normally, Disk Druid will allocate around 100MB to /boot, about double your memory size to /swap, and the rest to / (slash. The root drive of your system, and where all other sub-directories, such as var, bin, etc, and tmp will be created).
    I know that this may be a bit confusing to a newbie, but explaining the directory structure in Linux is really beyond the scope of this document, so if you want to understand more about it, I suggest you get a good book :)
    Click Next.
  7. On the next screen you'll have the option to choose a boot loader password. By default, we will use the GRUB boot loader, and you can choose to put a password here so that only someone who knows the password could boot the machine. In my opinion, if your box is secured in your computer room, this is useless.
    Do you have boot passwords on your Windows machines? (do you?)
    Also, if you lose power, and your machine reboots, I think that it’s better for it to come up on its own, instead of waiting for you to enter the password. This is just my opinion. depending on your environment, you may decide to define a password here.
    Click Next.
  8. On the next screen you can define the IP address of the machine. If you know all the details now, go ahead and put them in: Click the Edit button, and uncheck the Configure using DHCP. Put the IP and subnet, press <Enter>, and fill the rest of the details in the main page.
    If you don’t have the details now, choose DHCP and see the end of this document for manual configuration later. I suggest that you update your machine’s IP address, hostname, and other networking preferences before you start installing Postfix.
    Click Next.
    Note: in one case, while configuring the network manually, my server was configured without a default gateway. If this happens to you, make sure to read Appendix A, and add the GATEWAY line to the NIC’s configuration file.
  9. On this screen you configure the firewall. You need to enable the firewall, allow SSH and SMTP, and disable SELinux.
    SELinux is some NSA security stuff that I'm still new to. It always breaks my SSH connections, so that's why I kill it. If you know a workaround which will enable SELinux and SSH at the same time, use it.
    Click Next.
  10. Select your time zone, and click Next.
  11. On the next window, you'll have to choose a password for the almighty root user. Make sure it's a secure password. Whoever has root has ownership of your machine, and this means that they can do whatever they want. Plain and simple.
    Click Next.
  12. On this window we'll select what to install. Note that this is not set in stone. If you feel comfortable removing some packages, be my guest and do it.

    Here’s the list by sections:


Desktops
:      

Choose either GNOME or KDE. I like GNOME.

Click on Details and uncheck all of the optional GNOME components.


Applications

Check Editors, go into the Details, and uncheck Emacs.

            Check everything under Text-Based Internet, except slrn and epic
            Uncheck Office/Productivity, Sound and Video, and Graphics.

 

Servers:         

Check Server Configuration Tools and all of its sub-components.

 

Development:

Check Development tools.

 

System:

Check Administration Tools.
            Uncheck Printing Support.

Uncheck Language Support.

 

Click Next twice to start the installation!

 

When the installation is done, the CD/DVD will be ejected, and you’ll have to click Reboot.


Errors During Boot

As of the writing of these lines, there’s an error that you’ll see right when the boot process begins. The following lines appear:

mknod failed to create /dev/console

mknod failed to create /dev/null

mknod failed to create /dev/zero

 

Please see this Bugzilla report to see if it was fixed: https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=157129

Update (07/17/2005): Bugzilla indicates that an update to the Kernel fixes this error. See the “updating the system” section below, and update your CD/DVD-installed Kernel!

After the Initial Reboot

After rebooting, you will have to set up a few more things:

 

  1. Click Next on the welcome screen.
  2. Accept the license agreement and click Next.
  3. On the next screen, make sure the date and time are correct, click on the Network Time Protocol tab, and set up an NTP server if you want. It can help a lot to have all your mail servers configured with NTP, so that all your logs have synced time-stamps.
    Click Next when done.
  4. You’ll find that we’ll not be using the graphical interface that much, but if you want to use it, you’ll probably want it at 1024x768 (the installation defaults to 800x600). Check that the Resolution button allows 1024x768, and select it. If it doesn’t, do this:
    Click the Configure button, and select Generic [CRT or LCD] Display, and press OK. The Resolution button will then include 1024x768, so select it, and click Next.
  5. On this screen you will have to create another user, since you don’t really want to work under the context of root. Just choose a good username with a strong password and hit Next.
  6. The next screen is for configuring the sound card. Click Next, since we won’t need it anyway.
  7. You don’t need to install anything from additional CDs, so click Next.
  8. Finish this part of the setup by clicking Next again.

 

Login to the System for the First Time

Login as root, and open a terminal window by using the main menu (like the “Start” menu in Windows), and then: Applications, System Tools, Terminal.

 

Issue the command ifconfig:

ifconfig

And press <Enter>.

 

See if you have an IP associated with the eth0 interface. If you don’t have an IP, check your cables and NIC.

 

Firewall Protection

I will not cover how to install a firewall on your server in this document. This server will be used as a mail-relay, spam filtering, and possible AV filtering server, nothing more. I think that making it a Firewall as well is a waste of valuable resources. Please make sure to create the necessary rules in your corporate firewall, to allow port 25 to this server, as well as any other necessary ports for Razor, etc, as you’ll see below.


PuTTY

PuTTY is a free SSH client. SSH is essentially a secured way of doing Telnet. At this point you can choose to continue working on the server directly, or to install PuTTY on your Windows-based PC, and SSH into your server instead!

 

Get PuTTY from here: http://www.chiark.greenend.org.uk/~sgtatham/putty/, then run it.

Select the SSH radio button when you see the main menu, enter your server’s IP in the “Host Name (or IP Address)” box, then put a name under the “Saved Sessions” box, and hit save.

 

From now on, every time you’ll start PuTTY, you can just choose the session name that you chose, and it’ll connect you to your server.

 

When connecting for the first time, you’ll see a security alert. Simply choose Yes, and you’ll be connected.

 

You can exit PuTTY by typing exit in the shell prompt. Don’t ever close PuTTY by hitting its window’s “X” button, at least not while you’re editing a file.

 

WinSCP

WinSCP is a very cool SCP (file-transfer) program that can greatly help you when you transfer files between your Windows-based PC, and your server. You can get it here: http://winscp.net/eng/index.php, and configuration of it is very easy. Just follow the defaults. You’ll have to give it your server’s IP address, as well as the user name and password for login. If you chose the “Norton Commander” look, it’ll give you two panes, one for your local PC, and the other for the remote server. You can then easily transfer files between the two.

Disabling Some Unneeded Daemons (Services)

Issue the command:

chkconfig <service name> off

Replacing <service name> with each of the following:
sendmail, apmd, cups, isdn, kudzu, netfs, nfslock, pcmcia, portmap, cups-config-daemon, and bluetooth.If your hard drives don’t support S.M.A.R.T., repeat the above for the smartd service as well.

Updating the System

Do you see that red ball with an exclamation point in it? It tells you that your system is not fully patched. So the first thing we’ll do is patch the system. I like to use the tool that came with Fedora, yum, to do the patching. Before we use yum, we need to import Fedora’s public key into our key ring. This is done to ensure that the packages that we’ll download are authentic, and came from trusted sources.

 

Type everything as shown. Remember that Linux is cASe sEnsItiVe.
In places that you see “- -“, remember that the two minuses should be typed without the space between them. It’s just that sometimes when I type -- in Word, it looks like one long minus.

 

Issue the following commands:

gpg --import /usr/share/rhn/RPM-GPG-KEY-fedora

rpm --import /usr/share/rhn/RPM-GPG-KEY-fedora


Now that you have Red Hat’s key in your key ring, you can download updated packages of Fedora.

 

Issue the command:

yum -y update

 

This will start downloading and installing new packages, and probably a brand new kernel. Take a coffee break.

 

After drinking many cups of coffee, issue the yum command shown above again, just to be sure that no update was missed. When you see a blue ball with a checkmark on it, your system is updated. You can repeat the process any time you want to update your system.

 

You can always issue the yum check-update command, to see what updates are available for update.

 

Changing the Language Preferences

We need to change the language settings of the system for SpamAssassin:

vi /etc/sysconfig/i18n

In the line that starts with LANG, change the “en_US.UTF-8”:

Put your cursor on the dot that’s in “en_US.UTF-8”, and press x 6 times, so that you’re left with “en_US”.

Save and exit the file.

Make vi Show Files in Color (use vim)

Argh! So annoying. The developers of FC4 changed something to make vi be the default editor instead of vim (VI iMproved).

We’re about to fix it below, but before we do, know that this change may cause you not to be able to run vi if your system ever crashes, and you need to run in emergency/single-user mode, and the /usr directory was not mounted for whatever reason. vim resides on /usr/bin/vim, so you can run it after mounting /usr in case of an emergency situation. If this is way to much information for you, don’t worry, and do the next steps anyway.

 

Edit the following file:

vi /etc/profile.d/vim.sh

 

It should look like this:

 

if [ -n "$BASH_VERSION" -o -n "$KSH_VERSION" -o -n "$ZSH_VERSION" ]; then

  [ -x /usr/bin/id ] || return

  [ `/usr/bin/id -u` -le 100 ] && return

  # for bash and zsh, only if no alias is already set

  alias vi >/dev/null 2>&1 || alias vi=vim

fi

 

Add a # sign in front of lines 2 and 3, so that it looks like this:

if [ -n "$BASH_VERSION" -o -n "$KSH_VERSION" -o -n "$ZSH_VERSION" ]; then

#  [ -x /usr/bin/id ] || return

#  [ `/usr/bin/id -u` -le 100 ] && return

  # for bash and zsh, only if no alias is already set

  alias vi >/dev/null 2>&1 || alias vi=vim

fi

 

And yes, in case you wonder, I know this can be done with Aliasing as well J

Optional: Configuring ls

I like the ls command to always show all files in a long listing, and in color.

Edit the /etc/bashrc file, and add:

alias ls='ls -al --color=tty' to the end of the file if you want it as well.

 

Downloading the Required Software

While we’re in the GUI, let’s download the installation sources that we’ll need.

Put them all under /usr/local/src. Note that you can also download the files to your Windows PC, and then transfer them to your server using WinSCP. Even though we can install some of this software using yum, installing from source is better in my opinion.

 

Amavisd-new: http://www.ijs.si/software/amavisd/#download

Postfix: http://www.postfix.org/download.html

SpamAssassin: http://spamassassin.apache.org/downloads.cgi

ClamAV: http://www.clamav.net/

Razor: http://razor.sourceforge.net/ - Download the agents, and the agents-sdk files.

Pyzor: http://pyzor.sourceforge.net/

DCC: http://www.dcc-servers.net/dcc/ (click on the top, where it says “DCC Version x.xx)

Set the System to Boot into Text Mode

Linux works much faster without the GUI, so we’ll make a change to make Fedora boot into text mode from now on. We’ll still be able to change into the GUI when we want to.

 

Issue the command:

vi /etc/inittab

 

And look for the line with “id:5:initdefault”.

Point your cursor to the “5” in the string shown above, and then press r and 3.

Save and exit the file.

 

Type reboot and press <Enter>.

 

Fedora should start without the GUI.

 

Login as root.

Tip: To change into GUI mode, login and then issue the startx or init 5 commands.

Creating Some Required Users

We need to create some users for Postfix to work with, as well as some groups.

Issue the following commands:

 

Make a backup of your user and group list files:

cp /etc/passwd /etc/passwd-original

cp /etc/group /etc/group-original

 

Add a group for Postfix:

groupadd -g 54321 postdrop

 

Add a user for Postfix:

Double-check before pressing <Enter>. Make sure that you get the CaSe right:

echo "postfix:*:12345:12345:Postfix:/no/where:/no/shell" >>/etc/passwd

 

Add a user for Amavisd:

useradd -d /var/amavis -c "amavisd-new daemon" -u 999 amavis

This creates the user amavis and the directory where all of our amavis stuff will happen!

 

You will soon read about the LINUX2 file. Remember that if you ever change the passwd file, you’ll have to make sure that a copy of it is in /var/spool/postfix/etc/. Please see the note in Appendix A for more details. For now, don’t worry about it J

 

Installing Postfix

First, we’ll change to the directory where Postfix was downloaded to:

cd /usr/local/src

 

Now we need to untar it:

tar xzvf postfix-#.#.#.tar.gz

(#.#.# should be replaced with your version number. This is what I’ll use from now on)

 

Then change to the directory where Postfix was extracted to:

cd postfix-#.#.#

 

Then build the program:

make

 

You’ll see many lines on the screen as the source is compiled.

Now we’ll install Postfix:

make install

 

Press <Enter> to accept all the defaults when asked.

At the end of the installation, Postfix will write this to the console:

 

    Warning: you still need to edit myorigin/mydestination/mynetworks

    parameter settings in /etc/postfix/main.cf.

 

    See also http://www.postfix.org/faq.html for information about dialup

    sites or about sites inside a firewalled network.

 

    BTW: Check your /etc/aliases file and be sure to set up aliases

    that send mail for root and postmaster to a real person, then run

    /usr/bin/newaliases.

 

That’s it. Postfix is now installed.

Got errors? Check that you did all the steps above correctly.

 

At this point you can do a very preliminary test, and start/stop postfix:

 

postfix start

You should see: postfix/postfix-script: starting the Postfix mail system

postfix stop

You should see: postfix/postfix-script: stopping the Postfix mail system

 

You shouldn’t get any errors. If you do, make sure that you did all the steps above correctly ;)

 

Configuring Postfix

We’ll start by configuring Postfix to work as an MTA, and when it fully works, we’ll move to adding Amavisd, SpamAssassin, and the rest to it. This will allow us to make sure that each step works before moving on.

 

Postfix was designed to work in a chrooted environment. “chroot” is short for “changed root”, and means that the application will be run from within a directory that it will see as the root of the drive, hence enhancing security.

Postfix’s author Wietse Venema created a script that we can use to make Postfix run in a chrooted environment. The script is under /usr/local/src/postfix-#.#.#/examples/chroot-setup and it’s named LINUX2.

 

Postfix must be running before we begin:

postfix start

 

Let’s copy the LINUX2 script into our path, so that we could call it any time without specifying the full path:

cp /usr/local/src/postfix-#.#.#/examples/chroot-setup/LINUX2 /usr/local/sbin/

 

Now, let’s issue the rest of the commands:

chmod +x /usr/local/sbin/LINUX2

LINUX2

postfix stop

 

A Word About DNS and MX Records

When I tested my system, I wanted a way to test live, while not interrupting my organization’s e-mail delivery. Since I had access to my company’s firewall, and our DNS, a good trick that I found was to manipulate both in such a way that only e-mail from Gmail will come through my server. I chose Gmail because I knew that it’s mainly used by other employees. Our customers will not e-mail us from Gmail. If your situation is different, use any other free e-mail service.

 

I added my new server as a secondary MX record in our DNS:

MX priority 10:          my company’s first mail server

MX priority 20:          my test server

MX priority 30:          other mail server

Etc…

 

I e-mailed myself from Gmail, and saw that the e-mail comes from wproxy.gmail.com (update: it also comes from zproxy.gmail.com and xproxy.gmail.com) I then went to www.dnsstuff.com and found all the “A” records for wproxy.gmail.com: 64.233.184.192 to 64.233.184.207. So I added them to a group, and created some rules in my firewall:

 

Source

Destination

Service

Action

Gmail mail servers

All of my company’s

mail servers except

the test server

SMTP

Reject

Gmail mail servers

My test server

SMTP

Accept

Rest of the world’s mail servers

My test server

SMTP

Reject

Rest of the world’s mail servers

All of my company’s

mail servers except

the test server

SMTP

Accept

 

I found that I need to use REJECT and not DROP for it to work properly. DROP actually made some of the sending servers think that everything worked fine, so they didn’t even attempt to deliver to my secondary MX: my test box.

 

Let’s talk a little about two very important files in Postfix: master.cf and main.cf.

master.cf is used to configure some site-wide settings for Postfix, as well as some definitions for Postfix’s many services. Postfix is made out of a bunch of separate components that together act as a mail server (MTA). I really suggest that you spend some time at the Postfix site (www.postfix.org) to learn how it really works.

 

Another interesting thing that you may want to do if you have access to change your DNS records, is see if you can add several IP addresses to your server, and list all of them under your domain’s zone. This can help fool some spammers. A lot of them are ignoring the primary MX record, assuming (rightfully in most cases) that the secondary MX is less protected, and they e-mail it directly. You can try and fool them by arranging your DNS MX records like this:

 

MX priority 10:            Your Postfix server

MX priority 20:            Your Postfix server (2nd IP)

MX priority 30:            backup mail server

MX priority 40:            Your Postfix server (3rd IP)

 

This makes your Postfix server appear on the MX list 3 times, with different IPs. When spammers go to the secondary MX, they still get to your server. Make sure to read Appendix A, if you want to setup multiple IPs on your server.

The master.cf File

This file specifies the settings to Postfix’s services. We’ll have to tell Postfix that its services should work in a chrooted environment, as we already set above.

This file, and many other files in Postfix, is located under the /etc/postfix directory.

Let’s go into that directory:

cd /etc/postfix/

 

…make a copy of master.cf to be on the safe side:

cp master.cf master.cf.original

 

…and then edit master.cf:

vi master.cf

 

The file is actually a table with the list of services that Postfix uses.

Position the cursor on the “n” that is under the chroot column in every line except lines that end with pipe, virtual, local, and proxymap, and then press r, and y (to replace the n with y). Note that lines that begin with “#” are comments, so you don’t have to change them. When you’re done, save and close the file.

 

Find the line that begins with pickup, and add these two lines right under it:

Note the white space (you can use a tab instead) at the beginning of each line, and the lack of one at the end of the line.

 -o content_filter=

 -o receive_override_options=no_header_body_checks

 

This will make sure that local messages (such as ones originating from the server itself by Cron, and are sent to root) are not subjected to content filtering, or any header checks.

 

We will come back to this file later, since it’s in here (as well as main.cf) that we’ll tell Postfix to use Amavisd, however, for now we’ll make sure that Postfix works as a mail server only. Save and close the file.

 

The main.cf File

The main.cf file is where all the cool stuff happens. It’s actually the file that controls how Postfix will treat mail. Some of the settings in this file can be considered preliminary spam filters, since they allow you to detect when a connecting mail server is not “talking” the right way--a method often used by spammers. I have seen cases where a real and perfectly legal mail server failed to connect, but thanks to Postfix’s robust settings, I was able to fix it by creating an exception for this specific domain/IP. I will show you how to do all of that below.

 

The structure of the file is actually quite simple, and the commands’ explanation can be found on Postfix’s web site. You’ll see a link there to all of main.cf’s commands. This is a great resource, and I suggest that you’ll use it. The main.cf file that’s supplied with Postfix includes some settings and their explanation. We’ll renamed it to something else, and create a new main.cf.

 

To insert the directives into the main.cf file, we’ll use the postconf command with the -e switch, which means edit. It will automatically enter the directives for us, and we won’t have to use vi.

 

Please note that for some of the postconf commands below, you can simply take the arguments, and put them yourself into main.cf, using vi.

For example, this will work for the first postconf command that you see below. You can simply take the “myhostname = spamserver.example.com”, without the quotes, and put it into main.cf.

However, this will not work with the third postconf command below. Taking “myorigin = \$mydomain” and putting it into main.cf will generate an error.

The reason is the “\” that is used when you type the postconf command to “escape” the “$” character, and prevent the shell from thinking that what follows the “$” is a variable. Long story short, if you want to type these in manually, remove any “\” in front of a “$”, and then put it into main.cf.

 

Let’s rename the original file, and then edit a brand new one:

cd /etc/postfix

mv main.cf main.cf.original

 

Now we’ll create a new main.cf:

touch main.cf

 

Here are the arguments that I use in main.cf:

 

postconf -e “myhostname = spamserver.example.com”

This defines the full hostname for your server. Replace spamserver.example.com with your host name. For example: spamserver.hooters.com (you lucky bastard)

 

postconf -e “mydomain = example.com”

Your server’s domain name. Replace example.com with your host name. For example: hooters.com

 

postconf -e “myorigin = \$mydomain”

The domain name that mail coming from this machine will appear to come from. You want this set to your domain name.

 

postconf -e “mydestination =”

We set this to nothing, since we’re not delivering mail locally.

 

postconf -e “local_recipient_maps =”

This tells Postfix that none of your final mail recipients are on this server (i.e. we’re going to relay the mail to another server.)

 

postconf -e “mynetworks = 10.20.30.40”

This tells Postfix which IPs can send mail through it. It’s very important to specify at least one IP, so that you won’t become an open relay.

Normally, you will also use this parameter if your server sends mail out. In my configuration I’m only using the server to receive mail, so I set it to my PC’s IP.

You can separate several values with commas, and you can use CIDR notation (i.e. 10.20.0.0/16)

 

postconf -e “relay_domains = \$mydomain, example2.com”

Here we can specify which domains (and their sub-domains, i.e. sub.domain.com) this server will relay mail for. I actually receive mail for two domains: my main one (“mydestination”), and another one (“example2.com”). Be careful to specify only the domains that you accept mail for!

 

postconf -e “message_size_limit = 10485760”

This sets the maximum message size to 10MB (10 * 1024 * 1024)

 

postconf -e “transport_maps = hash:/etc/postfix/transport”

This is an important one. First, notice the notation of “hash:”. Hash files are actually database files. You will see that we have some other files that we’ll specify with the “hash:” notation. We create them as normal text files, but for Postfix to use them we need to change them into their “hashed” form. Every time you create a file that is referenced by hash:, you need to run the postmap command on it (postmap <file name>). This will compile the text file into a Postfix-readable hash format. Running this command will create an identical file name, but with the suffix of “.db”. For example:

 

postmap transport

Will create a file named transport.db.

 

transport_maps defines where e-mail to specific domains or users should be relayed to. It is where we define the next “hop” for our incoming mail. Usually, this hop is the next mail server in the organization. For example: I receive mail from the Internet through the spam server (the one I’m building with you right now), I then relay it to a Trend Micro server for content filtering, and from there it goes to another e-mail server!

Using the transport_maps definition, I can tell Postfix that the next hop should be the Trend Micro server. I can also tell Postfix that if mail arrives for ronny@example.com, to skip the Trend Micro server and go directly to the last e-mail server in my configuration.

 

I will soon show you the contents of all of the files that I discuss here, and are Hash files. Their description is following the main.cf configuration section we’re in right now.

 

postconf -e “smtpd_helo_required = yes”

This states that connecting clients should issue a “HELO/EHLO” command first. Note that this is related to smtpd_helo_restrictions that we’ll see soon below.

 

postconf -e “disable_vrfy_command = yes”

The SMTP VRFY command can be used to harvest e-mail addresses, so we disable it.

 

postconf -e “virtual_alias_maps = hash:/etc/postfix/virtual”

This specifies where the virtual mapping file is, which is like an alias file that we’ll use. I found that when a log was sent out from within the server, the recipient was root, and since there’s no root@example.com (although I could add an alias in my proprietary e-mail system to it, under my name record), e-mails were bouncing. The virtual file can help us by mapping a local recipient to a real e-mail. We also need to accept mail to postmaster@exmaple.com, and possibly something like abuse@example.com. By setting these e-mail addresses in the virtual file, mail to these addresses will be delivered to a mailbox in your proprietary e-mail system.

 

postconf -e "alias_maps = hash:/etc/aliases"

This tells Postfix where the aliases file is located. We will not be using any aliases, since they are used when Postfix is not used as a mail-relay. However, the location of the file is important to Postfix, and the default setting for alias_maps includes a reference to an NIS server (which we don’t have), so we run the above command to get rid of the NIS references.

 

newaliases

This creates the aliases.db file from the aliases file. Postfix expects this whether we use the aliases file or not.

 

You’ll have to set postfix to accept delimiters (such as ronny+postfix@example.com), if your final mail server is using them. Do one of the following three lines:

postconf -e "recipient_delimiter = "

postconf -e "recipient_delimiter = -"

postconf -e "recipient_delimiter = +"

 

Postfix’s Own Anti-Spam Filters

Postfix has some powerful, built-in features that allow it to filter for some unwanted e-mail.

As mail comes in, a remote client connects; it then sends its name (helo), then the user that the mail is from, then the recipients of the message, and then the data itself.

To understand better what happens during an SMTP transaction, check out this link: http://helpdesk.islandnet.com/pep/smtp.php.

 

Postfix allows us to deny or grant access to a message, based on the specific client, hostname it HELO with, sender, recipient, or the data that’s in the message.

These restrictions are known as smtpd_*_restrictions, since the * can be replaced by client, helo, sender, recipient, and data.

 

Although the client, helo, sender, and recipient can be combined under one restriction stage (recipient), I like to separate them since it makes my main.cf file more readable.

 

It’s important to understand what happens when a match is made, and we’ll start with some terminology:

A restriction stage is one of the five smtpd_*_restrictions stages that are mentioned above.

Each restriction stage has a set of tests under it.

Each test can evaluate to OK, REJECT, or DUNNO.

 

Here’s how it all works:

-When a specific test within a restriction stage evaluates as OK, Postfix will skip the current restriction stage, and go to the next restriction stage.

-When a specific test within a restriction stage evaluates as REJECT, Postfix will reject the e-mail. Nothing else happens.

-When a specific test within a restriction stage evaluates as DUNNO, Postfix will skip to the next test within the current restriction stage.

-When all five restriction stages were evaluated, the default action is to permit the message.

 

Each of the first four restriction stages that we’ll use will have Hash files that allow you to OK or REJECT a message.

We will see these files later.

 

postconf -e "smtpd_client_restrictions = check_client_access hash:/etc/postfix/client_access,

 reject_rbl_client sbl.spamhaus.org, reject_rbl_client relays.ordb.org, reject_rbl_client

 opm.blitzed.org, reject_rbl_client list.dsbl.org,reject_rbl_client cbl.abuseat.org,

 reject_rbl_client dul.dnsbl.sorbs.net, reject_rbl_client dun.dnsrbl.net"

 

The smtpd_client_restrictions section defines which clients will be allowed or denied access to your mail server.

 

The first line that you see reads a file named client_access to check if there’s any clients that we know of, and should be rejected or not.

 

The other lines, ones that begin with reject_rbl_client, define sites that hold lists of black-listed domains, IPs, senders, etc.

 

postconf -e "smtpd_helo_restrictions =  check_helo_access hash:/etc/postfix/helo_access,

 reject_invalid_hostname, reject_non_fqdn_hostname"

 

This defines the restrictions that we want to have after a client connected, and is issuing a “HELO”. As you can see, we use an access file here as well, and then we do two more check: we reject invalid hostnames, and when the connecting client is not sending its FQDN in the HELO command.

Please note that rejecting by non FQDN may give you some hard time. There are many hosts out there that HELO as “mail” instead of “mail.company.com”. If you find that you have a lot of false-positives, remove the “reject_non_fqdn_hostname” from main.cf, and restart Postfix.

 

postconf -e "smtpd_sender_restrictions = check_sender_access hash:/etc/postfix/sender_access,

 reject_non_fqdn_sender, reject_unknown_sender_domain, reject_rhsbl_sender relays.ordb.org,

 reject_rhsbl_sender opm.blitzed.org, reject_rhsbl_sender dun.dnsrbl.net"

 

The restrictions on the sender should be pretty straight forward to you by now. As you can see, I use a file to check for allowed senders, and then I do some rejections on non FQDN senders, and senders with unknown domain. In addition, black-listed senders are denied.

 

postconf -e "smtpd_recipient_restrictions = reject_non_fqdn_recipient,reject_unknown_recipient_domain,

 permit_mynetworks, reject_unauth_destination, check_recipient_access

 hash:/etc/postfix/recipient_access"

 

Once again we check a file to see who our accepted or rejected recipients are. This access file will be one of our most important files. You’ll soon see how you’ll be able to set it up so that only some users’ e-mail is being filtered through SpamAssassin! I found it to be a great way to beta-test my server with some users, before deploying it company-wide.

 

As for the other settings:

 

reject_non_fqdn_recipient: from the Postfix web site:

Reject the request when the RCPT TO address is not in fully-qualified domain form, as required by the RFC.

 

reject_unknown_recipient_domain: from the Postfix web site:

Reject the request when the RCPT TO address has no DNS A or MX record and Postfix is not final destination for the recipient address.

 

permit_mynetworks: from the Postfix web site:

Permit the request when the client IP address matches any network or network address listed in $mynetworks.

 

I remind you that my $mynetworks value is set to my own PC’s IP address. In the context of this section, this means that e-mails from my IP address will be allowed to be sent through the server. This is not a mandatory setting, however, since we are changing the default setting for smtpd_recipient_restrictions, the Postfix web page states that we must use at least one of 4 other options or Postfix will refuse to receive mail (read about them here: http://www.postfix.org/postconf.5.html#smtpd_recipient_restrictions). One of these settings is reject_unauth_destination, which is shown below.

 

reject_unauth_destination: from the Postfix web site:
Reject the request unless one of the following is true:

-Postfix is mail forwarder: the resolved RCPT TO address matches $relay_domains or a subdomain thereof, and contains no sender-specified routing (user@elsewhere@domain),

-Postfix is the final destination: the resolved RCPT TO address matches $mydestination, $inet_interfaces, $proxy_interfaces, $virtual_alias_domains, or $virtual_mailbox_domains, and contains no sender-specified routing (user@elsewhere@domain).

 

postconf -e "smtpd_data_restrictions =  reject_unauth_pipelining"

This prevents the connecting client from pipelining SMTP commands. Pipelining is sending commands ahead of time, rapidly, and without waiting for a reply. This tactic is commonly used by spammers.

 

There are other settings in main.cf that make Postfix a very powerful MTA. For example, every time a message is denied for whatever reason (client/helo/sender/recipient restrictions); a message is sent back to the sender. You can customize this message to say whatever you want. Another example includes the ability to do header checks, and body checks of a message. Postfix can be configured to deny messages that have a specific string in their headers or body. Check the Postfix website for these options (header_checks and body_checks). I won’t use them here. For a complete and better understanding, go to Postfix’s web page and read a little about these commands. Some of them are really cool.

 

The virtual File

Our virtual file is what maps certain required e-mail addresses, which may not exist, into real addresses that do exist. For example: by matching root to my e-mail address, I was able to get reports from the server; which are sent to root locally. Also, if someone is e-mailing abuse@example.com, it resolves to my address. Note that e-mails to “virus” , and “spam” will go to special mailboxes that I created on the final mail server.

 

Edit the virtual file:

vi /etc/postfix/virtual

 

Add the following lines to it, replacing “example.com” with your domain name:

 

root       ronny@example.com

postmaster ronny@example.com

abuse      ronny@example.com

virus      virus@example.com

spam       spam@exmaple.com

 

As we’ll see later, you can tell Amavis whether you want spam/virus messages forwarded to your users, or go into a mailbox.

 

Close the virtual file, and remember that is should be compiled with postmap:

postmap /etc/postfix/virtual

The transport File

The transport file specifies the next hop for each one of the domains that we’re going to relay mail for. Let’s edit the file and add some lines:

vi /etc/postfix/transport

Add the following lines, for each of the domains that you have:

 

example.com     smtp:[50.60.70.80]

example2.com    smtp:[50.60.70.80]

 

This tells Postfix that mail for example.com, and example2.com should be relayed to the server at IP 50.60.70.80. Of course, you should use your next hop e-mail server’s IP instead of 50.60.70.80.

 

Note that you can also add a line like this:

ronny@example.com smtp:[123.123.123.123]

 

This will configure Postfix to relay mails to ronny@example.com into a different mail server than that of example.com! It’s pretty powerful, but normally you won’t need it.

 

Save and close the file. Now run:

postmap /etc/postfix/transport

 

The client_access File

The client_access file is checked by the smtpd_client_restrictions directive.

 

The client_access file is not something that comes with Postfix. It’s a file that I decided to create, but it has the same structure and format as the access file that came with Postfix. The access file that came with Postfix has some cool instructions in it on how to allow or deny access (look at it!), and although you can just create the client_access file from scratch, I like to make a copy of the access file, name it client_access, and then edit it:

 

cp /etc/postfix/access /etc/postfix/client_access

 

We will now look inside the client_access file:

vi /etc/postfix/client_access

 

Mine is set up like this at the end of the file (you’ll see that most of it, if not all, is commented out with #):

 

62.90.17.131 OK

That’s pretty much it. I found that this IP address is of someone we know, and that the mail server was black-listed. By putting it in my client_access file, we were able to get mail from that IP.

 

Another keyword that you can use here is REJECT. If you know about a specific IP that e-mails you crap, just reject them. You can even specify a message with your reject. Read the Postfix web site, or the access file that came with Postfix.

 

Now, remember that this is a file that’s referenced by “hash:”, and therefore we need to postmap it:

 

postmap /etc/postfix/client_access

 

Check the directory /etc/postfix/. You should see a file named client_access.db. This is the client_access file after it was “postmapped”, and this is the file the Postfix actually reads.

 

The helo_access File

Again, I made a copy of my access file, and named it helo_accesss:

cp /etc/postfix/access /etc/postfix/helo_access

 

My helo_access file looks like this:

 

example.com              REJECT

example2.com            REJECT

1.2.3.4                                                  REJECT

localhost                     REJECT

wincp10005                 OK

 

In the above file I reject anyone that tries to HELO as coming from my own domain. A host connecting from the Internet should obviously have a different domain name, since I am the host for example.com. I also reject anyone that’s sending a HELO as coming from my server’s own IP-which in this example is 1.2.3.4. I reject anyone that’s sending a HELO as localhost, but I accept the host named wincp10005, because it’s valid, and I know that it can’t send its Fully Qualified Domain Name (FQDN) for a good reason.

 

Remember that this file should be complied with postmap:

postmap /etc/postfix/helo_access

 

The sender_access File

My sender_access file is actually blank, but I thought that it’ll be a good idea to introduce this feature here. Its structure is similar to the recipient_access file discussed below. The sender_access file will be where you put a black-listed sender’s e-mail address, and OK it for delivery (for example, if the sender’s e-mail address is on one of the RBLs). You can also specify some senders to be rejected here, such as john@baddomain.com, but note that if the entire domain is a bad one, you can simply block it in the access file that’s under the smtpd_client_restrictions.

 

cp /etc/postfix/access /etc/postfix/sender_access

postmap /etc/postfix/sender_access


The recipient_access File

As stated above, you can use this file during beta-testing, so that only e-mail that arrives to some users is being filtered through SpamAssassin. Normally, as you probably understand, this won’t be the case, as you would probably want to filter e-mail to your entire organization/users.

To create the file, you can copy the access file into a brand new recipient_access, like so:

cp /etc/postfix/access /etc/postfix/recipient_access

 

Let’s see first what this file should contain if your server is not in beta, i.e. your server is ready to be deployed for filtering all e-mail addresses:

 

example.com              OK

 

That’s it. One line in the file that states that all mail to the domain example.com (change it to yours, of course) is “OK”. “OK” here means: “Send it through SpamAssassin”.

You already saw how to edit files with vi, so simply edit your recipient_access file, and put this line in it. Remember to postmap it.

 

Now let’s see what this file should contain if you plan to send only some of the e-mail addresses through filtering:

 

Larry@example.com    OK

Moe@example.com      OK

Curly@example.com    OK

example.com FILTER smtp:[IP.ADD.RE.SS]

 

What I did here was tell Postfix to send only Larry’s, Moe’s, and Curly’s e-mail through SpamAssassin. Everything else was filtered to an SMTP server at IP.ADD.RE.SS. Simply put the IP address of your organization’s next hop server inside the square parenthesis. In my situation, we had an SMTP server (we’ll call it “1”) that received all of our e-mail from the Internet. It then scanned it, and forwarded all non-virus/non-malware e-mail to the second server (we’ll call it “2”). “2” then delivered the messages to our employees’ mailboxes. When I added the new Postfix/SA/Amavisd server to the mix, it became the first server that gets e-mail from the Internet, so the IP address that I put the “FILTER” line was the IP of the server known as “1”. This created a situation where employees that did not participate in my spam filtering experiment, continued to get their e-mail normally, as if Postfix wasn’t even there (but of course, it was!).

 

If you have another domain that you filter through SA, simple add it to this file like this:

example.com     OK
example2.com    OK


Asynchronous Logging

We’re done setting up Postfix for now, but before we move on, let’s make sure that we have better logging. We’ll make a change to make logging asynchronous. Edit the file /etc/syslog.conf, and find the line that starts with mail, and ends with /var/log/maillog.

Add a single dash before the /var/log/maillog, so that it looks like this:

 

mail.*                             -/var/log/maillog

 

Save and close the file.

 

Issue this command to restart syslog:

service syslog restart

Testing Postfix

Let’s start Postfix:

postfix start

 

Then, open a command prompt on another machine, and type the following:

telnet <your server’s IP> 25

 

You should get a prompt from Postfix, telling you that it’s ready:

220 spamserver.example.com ESMTP Postfix

 

Now, let’s HELO with our IP:

helo 10.10.10.10            Put your IP instead

Postfix will reply with its full name:

250 spamserver.example.com

 

Issue the mail from: command:

mail from:test@gmail.com      You can use your Hotmail/Gmail address here

 

Postfix should reply with this:

250 Ok

 

Note: If postfix replies with an error, it will tell you what failed. For example, in my tests Postfix replied with a “helo command rejected” message. Well? This means that I failed during the smtpd_helo_restrictions checks. A quick change to the helo_access file fixed the problem. The IP that I connected from wasn’t in the file. I added it with an OK, restarted Postfix, and it worked! Chances are that if you fail, it’s because of one of those restrictions. Don’t be afraid to try to fix things, it’s still a test server, eh?

 

Now issue the rcpt to: command:

rcpt to: you@yourdomain.com

Postfix will reply with:

250 Ok

 

Now we’ll send the actual data:

data

 

Postfix will reply with:

354 End data with <CR><LF>.<CR><LF>

 

Enter the following lines:

subject: This is a test

Test

                        This is an empty line. Simply press <Enter>.

.                     Yep. It’s just a period!

 

Postfix will reply with:

250 Ok: queued as <random number goes here>

 

Now quit:

quit

 

And postfix will reply with:

221 Bye

Connection to host lost.

 

That’s it. Check your mailbox and see if you got anything. You can also look at the log, and see the entire transaction as seen from Postfix’s end.

Searching the Log

I usually issue this command at the prompt:

less /var/log/maillog

 

When you see the log, press the End key to go to the end of it, and use the up, down, page up, and page down keys to navigate through it.

 

You can use forward-slash, and then a term to look for something:

/example.com

 

This will look for any line with “example.com” in it.

Using the question mark you can search backwards (i.e. ?example.com)

 

To quit press q, and you’ll be back in the command prompt.

 

The log rotates daily at 4:00 am (configurable of course), and the old logs get names such as maillog.1.gz, maillog.2.gz, etc. These represent the logs of the day before, two days before, etc. You can still view them in the same manner:

less /var/log/maillog.1.gz

 

Testing Incoming Mail

To test incoming e-mail from the outside world, I suggest that you’ll do the Firewall changes that I discussed above. Hopefully you changed DNS already…it takes time to update, and without it we won’t be able to do a real test. After the changes are done, you should be able to send yourself a test message from Gmail (or any other service you chose), and receive it with no problems.

 

An alternative way will be to use a mail client such as Outlook Express, to send messages to your e-mail box. This is easily done by setting up OE like this:

 

1)      Click on Tools, the Accounts.

2)      Click on Add, then Mail.

3)      Put any name you want as the display name. The e-mail that you’ll get will be from this name, and will look like name<em@il.com>. Hit Next.

4)      Put the e-mail address that is sending the message to the box. For example: you@hotmail.com, or you@gmail.com. Hit Next.

5)      Leave the combo box on POP3. Put your server’s IP address in the Incoming mail, and Outgoing mail fields. Hit Next.

6)      Give the account a name. Leave the password blank. Hit Next.

7)      Hit Finish.

8)      Click on Tools, then Options.

9)      In the General tab, uncheck Send and receive messages at startup, and Check for new messages every. Hit OK.

 

Try to compose a message to your e-mail address, and then hit Send.

Sending will most likely fail. The reason for that is that reject_non_fqdn_hostname is set in main.cf, under the smtpd_helo_restrictions.

OE will most likely issue a HELO with your computer name, and not in FQDN form.

For the purpose of testing, remove the reject_non_fqdn_hostname from main.cf, and test again.

Setting Postfix to Start Automatically at System Boot

The postfix startup script is in: http://www.freespamfilter.org/Scripts/postfixstartupscript.txt.

Download and save it the file with the name postfix under /etc/init.d/:

cd /etc/init.d/

wget http://www.freespamfilter.org/Scripts/postfixstartupscript.txt
mv postfixstartupscript.txt postfix

This script is also available in appendix C.

 

Follow these instructions to make Postfix auto-start as a daemon when you boot the server:

chmod +x /etc/init.d/postfix

chkconfig --add postfix

 

I’ve had some issues making this run on FC4. I typed:

./postfix

Right after the steps above and got a message about a bad interpreter.

If you get the same thing, type this:

dos2unix postfix

 

This concludes the Postfix installation part. You may choose to run the server with only Postfix for a day or two, just to see that everything is working fine before we continue.

 

Saving Postfix’s Configuration

Using the postconf command you can send the entire configuration changes that you just did into a file. Later, I’ll go over the files that need to be backed up in order to restore the server to full functionality in case of a disaster, however, if you’re interested in saving the entire configuration to a file, issue the following command:

postconf -n >>postconf.txt

 

The file that will be created (postconf.txt) contains the current configuration of Postfix.

 

Address Verification

This section is optional.

When I installed Postfix, I wanted to have a way of filtering non-existent recipient addresses before Postfix starts scanning the message.

Think about it, if someone e-mails Fake123@yourdomain.com, and this address doesn’t exist, why take it through Amavisd, SpamAssassin and ClamAV? It’s a waste of resources.

 

Fortunately, Postfix has something called “Address Verification”, and you can read about it here: http://www.postfix.org/ADDRESS_VERIFICATION_README.html.

The idea is very simple: Postfix will send a probe message, as postmaster@yourdomain.com, to the nearest MTA. The probe message is simply sent to see how this MTA responds. If it accepts the message, the user exists. If not, it’ll come back with a 550 error, and then Postfix will reject the message, and send a non-delivery to the sender. By “nearest MTA” I mean that Postfix will send the probe message in the same way it sends normal messages that arrive. This is the idea, simplified.

 

At this point I’d like to mention something that Dave (www.freespamfilter.org moderator/owner) brought to my attention. He wrote in one of the forum’s messages:

 

“I noticed something with setting up the address verification over time.

 

When relaying mail to an Exchange server, it 250's everything, because Exchange 2000 doesn't have the ability to reject invalid recipients without installing some 3rd party software that costs money of course.

 

With the latest version of Exchange, this will work because the reject mail ability is finally built in.”

 

So…bear that in mind.

 

Things get a little more complex when the nearest (next) MTA--the one Postfix sends normal e-mails to, after it’s done scanning them--doesn’t have the list of e-mail addresses in your domain. Consider this example of a site that receives mail:

 

Mail coming from the Internet is received by your server running Postfix/Amavisd/etc.

Scanning is done on the message, and from there it’s transferred (as specified in the transport file) to the next MTA.

The next MTA is simply doing another Anti-Virus check, and then forwards it to the third and last MTA.

This last MTA is the one holding the list of users, and is actually responsible for delivering the message.

 

In this configuration, Postfix’s probe message will be sent to the second MTA, the one that has no idea about the existence or inexistence of e-mail addresses in the domain. It can either reply with: “Sure! I’ll get the mail for this user”, or it may reply with “I have no user by that name”. In any case, you don’t get a definite answer whether the e-mail exists or not.

 

If your situation is such that the next MTA is also your final one, and it’s the one holding the list of valid e-mails/users, then you’re all set. Your incoming messages and Postfix’s probe messages will be sent to that final MTA.

 

However, if you have a situation as the one described above, you’ll have to add a parameter to tell Postfix to override the transport file when it’s doing probe messages.

 

There are only a handful of settings that you’ll have to change to make it work with the configuration described in this document.

 

If your next MTA is also your final MTA, edit main.cf, and add:

reject_unverified_recipient

Before your “permit_mynetworks”, under the “smtpd_recipient_restrictions” restriction.

 

If you have the situation described above, and you need the probe messages sent to an MTA other than your next MTA, make a copy of the transport file:

cp transport probe_transport

 

Then edit probe_transport, and change the SMTP line that you added when you created the transport file, to reflect the IP address of the MTA that holds your e-mail/users list.

 

Save and close the file, and then postmap it.

 

Now edit main.cf again, and add this line:

address_verify_transport_maps = hash:/etc/postfix/probe_transport

In other words: use the probe_transport file when doing address probes.

 

By default, Postfix will reply to MTAs that e-mail to non-existing addresses with the error code “450”. The 4xx error messages are soft error messages, and as a result, a lot of MTAs will continue to send the message over and over again to your Postfix server. They may eventually fail to deliver, but it’ll take time. This happened to me when I tested the server by e-mailing to Ronnnny@mydomain.com. Gmail’s mail server saw that the reply message was a “450”, so it thought: “Ah! It’s a soft error. I’ll send the message again in a few minutes”. And it did that for a while.

 

After you have done all the changes above, and you can see in the log that Postfix is indeed working and rejecting messages to unknown recipient addresses, you can change the “450” error to a “550” error: A “hard” error.

 

Add this to your main.cf file:

unverified_recipient_reject_code = 550

Then save and close the file.

 

Remember to reload Postfix after all the changes to main.cf.

 

And with this, we’re done!

Installing SpamAssassin

Start by reading this: http://svn.apache.org/repos/asf/spamassassin/branches/3.0/README

It’s the README file that comes with SpamAssassin, and it’ll give you a better understanding of how SpamAssassin works.

 

Note that you can always install SpamAssassin using yum. I prefer to install from source. It gives me a sense of control, knowing that I installed it myself. You can choose either way, but whatever you choose, remember to stay consistent, and upgrade in the same manner. If you choose to use yum, you can simply issue the following command, and then skip straight into the “The Trusted Path Problem” section below:

yum install spamassassin

 

Otherwise, do this:

Change to the directory where SpamAssassin’s install is in:

cd /usr/local/src/

 

Untar SpamAssassin:

tar xzvf Mail-SpamAssassin-#.#.#.tar.gz

 

After a few seconds, SpamAssassin will be extracted.

Change to the directory where SpamAssassin was extracted:

cd Mail-SpamAssassin-#.#.#

 

There is a Perl module that needs to be installed for SpamAssassin to work properly.

We’ll use Perl to download the module:

 

perl -MCPAN -e shell

 

Since this is the first time that you’re running CPAN, you’ll be prompted with this:

 

CPAN is the world-wide archive of perl resources. It consists of about

100 sites that all replicate the same contents all 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, you have to configure it properly.

 

If you do not want to enter a dialog now, you can answer 'no' to this

question and I'll try to autoconfigure. (Note: you can revisit this

dialog anytime later by typing 'o conf init' at the cpan prompt.)

 

Are you ready for manual configuration? [yes]

 

Hit <Enter> to accept the default, and you’ll get Perl’s command prompt.

If Perl complains that some modules it needs are not there, just hit <Enter> again, or <space>, and then <Enter>.

We will now proceed to the installation of the module. If you’re asked whether you want to upgrade an existing module, answer yes. You may also get some messages about the server being busy. Just keep trying.

 

Type the following commands:

install Digest::SHA1

 

When the installation is done, type quit to and then <Enter> get back to the shell prompt.

 

Run the following commands to compile and install SpamAssassin:

perl Makefile.PL

 

When asked:

What email address or URL should be used in the suspected-spam report

text for users who want more information on your filter installation?

(In particular, ISPs should change this to a local Postmaster contact)

default text: [the administrator of that system]

 

Answer: postmaster@example.com. Replace example.com with your domain name.

Choose the default (no) to the “Check network rules during 'make test'” question.

 

Note that SpamAssassin may complain here that the Net::DNS module is not found, or that it is of a lower version. Ignore this. We’ll install Net::DNS later, with Amavisd.

Now issue these commands:

make

make install

The Trusted Path Problem

In certain environments, where your server is behind a NAT address, SpamAssassin can identify some spam as coming from a trusted server, when in fact, it’s not. You can read about this problem here: http://wiki.apache.org/spamassassin/TrustPath?highlight=%28all_trusted%29

 

What happens is that your server, having an internal IP address, sees its own NAT IP address and may think that it’s not trusted.

 

If you see a lot of spam messages that have the “ALL_TRUSTED” text appearing inside the X-Spam-Status tag (see “A Few Words About Tags” below). This means that SpamAssassin considered a spam message to come from what it thinks is a trusted server.

 

In our configuration, SpamAssassin will always get mail from the Internet, so we’ll add its Internet IP address to SpamAssassin’s configuration.

 

Edit SpamAssassin configuration file:

 

vi /etc/mail/spamassassin/local.cf

 

Add the trusted_networks line for every Internet IP address that your spam e-mail server is known as, and may receive mail through. I have 3 IP addresses associated with my spam server, and all of them appear in DNS as MXs (all actually point to the same server!):

 

trusted_networks 201.202.203.204

trusted_networks 205.206.207.208

trusted_networks 209.210.211.212

 

Obviously, you should use your server’s IP addresses.

 

You’ll also need to specify the same IP addresses as internal_networks:

internal_networks 201.202.203.204

internal_networks 205.206.207.208

internal_networks 209.210.211.212

 

Save and close the file.

 

Note: We haven’t installed Amavisd yet, but remember that you need to reload amavisd (amavisd reload) every time you change SpamAssassin’s local.cf file.

Installing Amavisd-New

The installation of Amavisd is done by copying two files from the extracted archive into two directories. We’ll start by extracting Amavisd:

 

cd /usr/local/src/

tar xzvf amavisd-new-#.#.#.tar.gz

cd amavisd-new-#.#.#

 

Now let’s copy those two files:

cp amavisd /usr/local/sbin/

cp amavisd.conf /etc/

 

Amavisd is now installed.

 

An Overview of Amavis’ Quarantine, Notifications, and Actions

When Amavis find a virus, spam, banned files, or banned headers, it can do several things:

 

Pass the message-The recipient will get the message.

Discard the message-The recipient will not get the message. The sender is not notified about the failure to deliver, and the message will be quarantined, if we decided to enable quarantine.

Bounce the message-The recipient will not get the message. The sender gets a bounce notification. No notification is sent, though, if the message was a virus that is known to fake the sender’s name.

Reject the message-The recipient will not get the message. The sender should get a reject or a non-delivery notification, but Amavis trusts the mail server (MTA) that it’s using it to actually issue those. This setting should not be used with Postfix.

 

The main difference between Bounce and Reject is who prepares the DSN (Delivery Status Notification).

Reject means that the MTA prepares and sends the DSN.

Bounce means that Amavis will prepare and send the DSN (which is also more informative).

 

You can see that since we’re using Postfix, our only options are Pass, Discard, and Bounce. In Amavis, these options are named D_PASS, D_DISCARD, and D_BOUNCE, and you can use them with the $final_spam_destiny, $final_virus_destiny, $final_banned_destiny, and $final_bad_header_destiny variables. If you’ll read Amavisd’s documentation, you’ll see them referred to as $final_*_destiny. In our setup, we set spam, virus, and banned to discard, and since we are not disabling the quarantine, they will be quarantined. If we disable the quarantine altogether, mail that is discarded is actually lost.

 

Next, let’s discuss the quarantine:

Amavis can quarantine a message that is found with spam/virus/etc to a specific directory that we tell it, or it can e-mail it to another e-mail box.

So essentially, you can have all your spam sent to spam@yourdomain.com, all your viruses to virus@yourdomain.com, etc, or you can have your virus e-mails stored in a directory on the server.

 

When using a directory on the server itself, Amavis allows you to specify one quarantine directory with the $QUARANTINEDIR variable, however, you can choose to put spam messages into a sub-directory under this main directory, virus messages to another sub-directory, and so on. You can also choose to dump all the spam/virus/etc messages into the quarantine directory, without putting them in sub-directories.

 

The sample amavisd.conf file has a good example of how to put bad messages into directories under the quarantine directory, based on their status (spam/virus/etc). You can read this file here:

vi /usr/local/src/amavisd-new-#.#.#/amavisd.conf-sample

 

In my setup, I chose not to use the quarantine directory at all. Instead, I e-mailed the message to a specific mailbox based on what that message was.

If it was spam, I sent it to spam@mydomain.com, viruses went to virus@mydomain.com, etc.

 

This is easily accomplished by setting the values of $spam_quarantine_to, $virus_quarantine_to, and $banned_quarantine_to to specific e-mail addresses.

 

The important thing to remember is that setting these to something like an e-mail address will disable the quarantining into the quarantine directory on the server.

By setting this on my server:

$spam_quarantine_to = "spam\@$mydomain";

I effectively sent all spam from this moment on to this mailbox, instead of the quarantine directory on the server.

 

Next, we’ll cover notifications:

Amavis lets you send a notification every time a spam, virus, banned files, or bad headers are caught. It’s not really something that you’ll necessarily want to implement, but here’s how to do it, using viruses as an example:

 

If $virus_admin is defined, then messages about viruses will be sent.

So… this is a required step for notifications:

$virus_admin               = "postmaster\@$mydomain";

 

The e-mail address can be whatever you want it to be. You don’t have to use postmaster, but it does specifies who will be the person receiving messages about viruses.

 

The next thing we need to set is $mailfrom_notify_admin. I’ve had some hard time understanding this one, but this is how to read the variable’s meaning: “What will be the envelope sender e-mail address when e-mailing the admin?”

 

This variable is set to postmaster in my setup:

$mailfrom_notify_admin     = "postmaster\@$mydomain";

 

We’ll also set up two more variables: $mailfrom_notify_recip, and $mailfrom_notify_spamadmin. As it turns out, Amavis allows you to set a different envelope sender depending on who gets the message. We didn’t really have to set up these last two, since we’re not notifying the recipients about viruses that they (almost) got. In addition, the last variable pertains to notifications to the spamadmin, which is also something that we won’t do, but in this document I set them to postmaster@example.com just in case you’ll ever enable them.

 

The last setting is $hdrfrom_notify_admin, and it sets the Header-From.

In my system it’s set up like this:

$hdrfrom_notify_admin = "Content Filter <postmaster\@$mydomain>";

 

When this variable is set, it’ll override the $mailfrom_notify_admin, and your e-mail client will show its contents instead of $mailfrom_notify_admin.

If this variable is not set, then whatever is in $mailfrom_notify_admin will be used for the Header-From address.

 

To disable notifications for viruses altogether, all you have to do is comment out the $virus_admin variable. No $virus_admin means no virus notifications.

 

Everything said above about virus notifications is valid towards spam, banned files, and bad headers notifications.

The only exception is that when it comes to spam you have the ability to also change the subject line of the message, and add spam tags to the e-mail’s header.

Read the sample file for more details.

Configuring Amavisd-New

Configuration of Amavisd is done by modifying the amavisd.conf file, located under the /etc directory. Remember that the original can always be extracted from the archive, or the directory it was extracted to, if you made a mistake.

 

Amavis can do some content filtering on its own, such as banning certain file extensions, or what it sees as bad headers. I never really checked what “bad headers” is all about, but the banning of some file types is interesting, and I will refer to these settings below. You don’t have to implement file banning if you don’t want to.

 

There are only a few modifications that we’ll do to the file. Simply search the file for the settings that I’ll show you, and modify them accordingly. An explanation is following each setting:

 

 

$daemon_user  = 'vscan';

This sets the system user that Amavisd will use. Remember that we created a user and a group for amavisd to use.

You need to set yours to:

$daemon_user  = 'amavis';

 

$daemon_group = 'vscan';

This sets the system group that Amavisd will use.

You need to set yours to:

$daemon_group  = 'amavis';

 

$mydomain = 'example.com';

Change example.com to your own domain. If you have more than one domain, put the most common one here. It won’t matter, and the others will be scanned as well. We’ll soon see another place where we can put the rest of our domains.

$mydomain = 'example.com';


A Few Words About Tags

Messages that pass through SpamAssassin are assigned a score based on a variety of tests that are performed on them. When Amavisd gets the score, it can attach it to the message header, or not. Along with the score tag (X-Spam-Status), there are other tags, such as X-Spam-Flag, and X-Spam-Level. X-Spam-Status is the most useful tag, since it actually gives you an explanation of the spam score, and what tests were made to give the message this specific score.

 

Here’s an example from a spam message that I got:

 

X-Spam-Status: Yes, hits=27.552 required=5 tests=BAYES_99,

 DATE_IN_FUTURE_12_24, DRUGS_ERECTILE, DRUGS_ERECTILE_OBFU, DRUGS_SLEEP,

 DRUGS_SLEEP_EREC, HTML_BACKHAIR_4, HTML_MESSAGE, HTML_OBFUSCATE_10_20,

 MIME_HTML_ONLY, MSGID_DOLLARS, RAZOR2_CF_RANGE_51_100, RAZOR2_CHECK,

 RCVD_IN_SORBS_WEB, SUBJ_HAS_SPACES, SUBJ_HAS_UNIQ_ID, URIBL_AB_SURBL,

 URIBL_OB_SURBL, URIBL_SBL, URIBL_SC_SURBL, URIBL_WS_SURBL

X-Spam-Level: ***************************

X-Spam-Flag: YES

 

This message had a score of 27.552-a very high score.

 

With Amavisd, we can choose when we want these tags added to our messages, as well as what to do when a message hits a pre-defined “spamminess” level, as shown below.

 

$sa_tag_level_deflt  = 2.0;

This setting defines at what spam level we want to add two of the spam tags: X-Spam-Status, and X-Spam-Level. I found it best to set this value to “undef”, so that these spam tags are always added:

$sa_tag_level_deflt  = undef;

 

$sa_tag2_level_deflt = 6.31;

This value defines what score is our threshold for spam. Everything at or above this score will be considered spam, and will allow us to do things such as add a prefix to the subject line of the message. I found that 6.31 is too high, and set it to 5.0:

$sa_tag2_level_deflt = 5.0;

 

$sa_kill_level_deflt = 6.31;

This value defines at what spam level the mail will be considered as needed to be quarantined (or sent to an e-mail box) by Amavis. It also defines the “spamminess” level of the message, above which the sender will receive a Delivery Status Notification (DSN), which is basically a: “your message was not delivered” e-mail. 

No DSN will be sent, though, if the $sa_dsn_cutoff_level value is set below the current spam level (see below).

 

I don’t want to send messages back to spammers, and I don’t want the message copied to a special mailbox at this time, so I set this value at 10000:

$sa_kill_level_deflt = 10000;

 

This means that all of my spam messages get delivered to my users, with a modified subject line, as long as the spam level of the message is not over 10000-a very good number.

 

If you want your spam to go into an e-mail box instead of being sent to your users, set this number to be the same as the $sa_tag2_level_deflt.

Now, the above sentence is only true for our setup. We’ll soon set the “$spam_quarantine_to” variable to a specific e-mail address, so in effect, every e-mail that will be considered spam (and therefore have all of the 4 spam headers, plus its subject changed), will also be considered as “needs to be quarantined/sent to a special box”).

If you don’t set the “$spam_quarantine_to” variable, the message will go to a quarantine on your server.

 

$sa_dsn_cutoff_level = 9;

This value defines the spam level at which we’re no longer interested in sending a DSN message to the sender. You can leave it as it is, since we’ll not do any bouncing (see below the change from D_BOUNCE to D_DISCARD).

 

# @bypass_virus_checks_maps = (1);

Find this line, and remove the #, so that Anti-Virus checks will be disabled. We’ll enable this later.

@bypass_virus_checks_maps = (1);

 

$sa_spam_subject_tag = '***SPAM*** ';

This is where you define how you want the subject line modified when Amavisd thinks that a message is spam. I changed mine to this:

$sa_spam_subject_tag = '[Possible Spam] ';

Notice the space after the last square parenthesis.

 

@local_domains_maps = ( [".$mydomain"] );

This is where we define the domains that Amavis will scan e-mail for.

Change it to:

@local_domains_maps = ( [".$mydomain", "example2.com", "example3.com"] );

 

# $final_virus_destiny      = D_DISCARD;

Find this line, and remove the #, to make Amavis send messages with viruses in them to the quarantine, which will be an e-mail box in our case, as you’ll see below:

$final_virus_destiny      = D_DISCARD;

 

Setting any of the $final_*_destiny variables to D_DISCARD will make sure that we’re not sending a message (DSN) about the blocked virus message back to the sender.

 

# $final_banned_destiny     = D_BOUNCE;

This tells Amavis what to do with banned files it finds in messages.

You can leave it as it is if you don’t plan to implement banning files, or uncomment the line and change it to D_DISCARD to make it forward the message to a specific mailbox, which is what we’ll do:

$final_banned_destiny     = D_DISCARD;

Note: even if you leave this setting as is, i.e. commented out, double-extension files will still be blocked. This is an Amavis default.

 

# $final_spam_destiny       = D_BOUNCE;

Find this line, remove the #, and change D_BOUNCE to D_DISCARD:

$final_spam_destiny       = D_DISCARD;

This will put the mail in our quarantine, which we will define as an e-mail address (such as spam@example.com.)

 

$virus_admin               = "virusalert\@$mydomain";

This defines who gets messages about found viruses. Change it to postmaster:

$virus_admin               = "postmaster\@$mydomain";

 

Right under the last setting, you’ll see these three lines:

$mailfrom_notify_admin     = "virusalert\@$mydomain";

$mailfrom_notify_recip     = "virusalert\@$mydomain"; 

$mailfrom_notify_spamadmin = "spam.police\@$mydomain";

 

Change them to:

$mailfrom_notify_admin     = "postmaster\@$mydomain";

$mailfrom_notify_recip     = "postmaster\@$mydomain";

$mailfrom_notify_spamadmin = "postmaster\@$mydomain";

This means that the mail message’s FROM field will show:

FROM: postmaster@example.com

When the message is sent to an Admin, or when it’s sent to the recipient, or when it’s sent to the spamadmin.

 

Note that there’s also a setting for $spam_admin, but we’re not interested in sending notifications to anyone when spam is found.

 

The following commands will have to be typed, since they don’t appear in the amavisd.conf file by default:

 

@bypass_banned_checks_maps = (1);

Amavis bans e-mails with certain extensions by default. For example, all double-extension files are blocked.

If you don’t want to implement banning, add the line above.

Not adding this line will make Amavis block banned files-its default behavior.

 

If you are interested in banning certain file type, look for the section starting with $banned_filename_re = new_RE. You’ll see that Amavis blocks certain double-extension files, as well as some regular files, such as EXE, COM, SCR, etc. The block of text there is very detailed, and looks somewhat like this:

 

$banned_filename_re = new_RE(

# qr'^UNDECIPHERABLE$',  # is or contains any undecipherable components

 

  # block certain double extensions anywhere in the base name

  qr'\.[^./]*[A-Za-z][^./]*\.(exe|vbs|pif|scr|bat|cmd|com|cpl|dll)\.?$'i,

 

# qr'\{[0-9a-z]{4,}(-[0-9a-z]{4,}){0,7}\}?'i,  # Class ID extensions - CLSID

 

  qr'^application/x-msdownload$'i,                  # block these MIME types

  qr'^application/x-msdos-program$'i,

  qr'^application/hta$'i,

 

# qr'^message/partial$'i,         # rfc2046 MIME type

# qr'^message/external-body$'i,   # rfc2046 MIME type

 

# [ qr'^\.(Z|gz|bz2)$'           => 0 ],  # allow any in Unix-compressed

  [ qr'^\.(rpm|cpio|tar)$'       => 0 ],  # allow any in Unix-type archives

# [ qr'^\.(zip|rar|arc|arj|zoo)$'=> 0 ],  # allow any within such archives

 

  qr'.\.(exe|vbs|pif|scr|bat|cmd|com|cpl)$'i, # banned extension - basic

# qr'.\.(ade|adp|app|bas|bat|chm|cmd|com|cpl|crt|emf|exe|fxp|grp|hlp|hta|

#        inf|ins|isp|js|jse|lnk|mda|mdb|mde|mdw|mdt|mdz|msc|msi|msp|mst|

#        ops|pcd|pif|prg|reg|scr|sct|shb|shs|vb|vbe|vbs|

#        wmf|wsc|wsf|wsh)$'ix,  # banned ext - long

 

# qr'.\.(mim|b64|bhx|hqx|xxe|uu|uue)$'i,  # banned extension - WinZip vulnerab.

 

  qr'^\.(exe-ms)$',                       # banned file(1) types

# qr'^\.(exe|lha|tnef|cab|dll)$',         # banned file(1) types

);

 

So, if you want to disable a statement you need to add # in the beginning of its line.

 

@whitelist_sender_maps = read_hash("$MYHOME/white.lst");

This defines where our white-list file is. $MYHOME is set by default to /var/amavis.

 

@blacklist_sender_maps = read_hash("$MYHOME/black.lst");

This defines where our black-list file is. $MYHOME is set by default to /var/amavis.

 

$spam_quarantine_to = "spam\@$mydomain";

Based on how you set $sa_kill_level_deflt above, this allows you to send the spam message to a specific e-mail address. The above example will send it to spam@<your domain name>. This is optional. You can ignore this setting if you simply want to forward all spam to your users. However, if you set your tag settings above so that $sa_kill_level_deflt is equal to $sa_tag2_level_deflt, then you do need this.

 

$virus_quarantine_to = "virus\@$mydomain";

This will send all viruses to a special mailbox on your final mail server, named virus@example.com (we set this up in Postfix’s virtual file)

 

$banned_quarantine_to = "spam\@$mydomain";

If you chose to implement the banning of certain file types (see above the $bypass_banned_checks_maps), the add this line.

 

$recipient_delimiter = '+';

or

$recipient_delimiter = '-';

Set either one of the two if and only if you defined e-mail address delimiters in Postfix.

 

$hdrfrom_notify_admin = "Content Filter <postmaster\@$mydomain>";

This makes the header-from e-mail be from the address specified.

 

These are all the settings that we need to define in amavisd.conf.

Save and close the file.

 

Creating Some Directories for Amavisd

Follow these commands to create the necessary directories for Amavisd:

 

mkdir /var/amavis/db/

mkdir /var/amavis/tmp/

mkdir /var/amavis/.pyzor/

mkdir /var/virusmails

The last directory we created is where Amavisd stores banned and virus-infected e-mails that it finds. As you know, we’re not using either checks, but instead of messing with Amavisd’s configuration, I decided to simply create this directory. If you did everything as I wrote, there will never be a single e-mail in this directory.

 

Now we’ll change the owner of these directories to the Amavisd user and group:

chown -R amavis:amavis /var/amavis

chown -R amavis:amavis /var/virusmails

chmod -R 750 /var/amavis

 

Installing Some Prerequisites for Amavisd

There are some Perl modules that need to be installed for Amavisd to work properly.

We’ll use Perl to download the modules. When asked to download prerequisites, answer yes:

 

perl -MCPAN -e shell

 

Type the following commands:

 

install MD5

You’ll see lots of lines on the screen, as Perl is downloading the module you requested and installs it. Eventually, you should see an “OK”. When you do, move on with these installs:

 

install Compress::Zlib Net::DNS Archive::Tar Archive::Zip Archive::Rar

As you can see, you can specify several modules for installation in one line!

Answer yes to all questions.

 

install IO::Stringy Mail::Internet Net::Server

install Convert::UUlib MIME::Base64 MIME::Parser

install Convert::TNEF Digest::MD5 Time::HiRes Unix::Syslog

You may need to press <Enter> here.

 

install Mail::SPF::Query      (Optional. See SPF section below. You may choose not to install SPF)

install Net::SMTP BerkeleyDB

 

When the installation is done, exit by typing:

 

quit

<Enter>

About Sender Policy Framework (SPF)

SPF is yet another way to verify that senders are who they say they are. Gmail already implements SPF, and if you want to do it, you can too! Read more about it here: http://spf.pobox.com/

 

After installing the Perl module Mail::SPF::Query, SPF will be installed and enabled for SpamAssassin’s use.

 

If you find that there are too many false-positives, or any other SPF errors, you can disable SPF in two ways:

 

By editing /etc/mail/spamassassin/init.pre, and commenting out loadplugin Mail::SpamAssassin::Plugin::SPF, or by adding these lines to the SpamAssassin configuration file, in /etc/mail/spamassassin/local.cf:

 

vi local.cf

 

Add the following lines:

score SPF_PASS 0 0 0 0

score SPF_FAIL 0 0 0 0

score SPF_SOFTFAIL 0 0 0 0

score SPF_HELO_PASS 0 0 0 0

score SPF_HELO_FAIL 0 0 0 0

score SPF_HELO_SOFTFAIL 0 0 0 0

 

Then save and close the file.

 

Restart Amavisd:

amavisd reload (skip this if Amavisd is not running yet)

Creating White-List and Black-List files

We defined two files: white.lst and black.lst, in amavisd.conf.

For amavisd to work properly, we need to create them whether they contain anything in them, or not:

 

touch /var/amavis/white.lst

touch /var/amavis/black.lst

 

The format of these files is quite simple: one e-mail per line. Black-listed e-mails will always be blocked, and white-listed e-mails will always be allowed in. When an e-mail is found on the white-list, its X-Spam-Status tag shows: "No, hits=x required=5 WHITELISTED".

Please remember that every time that you create or “play” with the white/black list files, you may inadvertently change the permissions on them from amavis to something else. It’s always good to run chown -R amavis:amavis /var/amavis/ after such changes.

 

Testing Amavisd

To test Amavisd, do the following:

 

amavisd stop

It shouldn’t be running, but we’ll stop it anyway to avoid all doubt. If it wasn’t running, you should get an error.

 

amavisd debug

This starts amavisd in debug mode. You should see lots of lines on the screen. You’ll see which modules were loaded, and which were not. Remember that not all modules should be loaded, since we’re using Amavisd to do just one thing of the gazillion things that it can do. Look at the bottom of the debug report. You should see:

 

Net::Server: Parent ready for children.

 

This is your indication that Amavisd loaded properly. Amavisd will also report any errors that it encountered, such as missing modules. If that’s the case, make sure you didn’t forget to load any of the modules.

 

To exit from debug mode, press ctrl+c. You may also need to press <Enter> to get to the command prompt.

Setting Postfix to Use Amavisd

Up until now we set up Amavisd and Postfix as two separate applications. If you followed all of the instructions, you should now have both working with no issues.

We “tell” Postfix to use Amavisd by editing Postfix’s master.cf and main.cf files.

 

First, let’s edit master.cf:

 

vi /etc/postfix/master.cf

 

Now scroll down to the bottom of the file, and in a new line (after pressing i, of course), insert the following:

 

 

smtp-amavis  unix    -    -    y    -    2    smtp

 -o smtp_data_done_timeout=1200

 -o smtp_send_xforward_command=yes

 -o disable_dns_lookups=yes

 

127.0.0.1:10025 inet    n    -    y    -    -    smtpd

 -o content_filter=

 -o local_recipient_maps=

 -o relay_recipient_maps=

 -o smtpd_restriction_classes=

 -o smtpd_helo_restrictions=

 -o smtpd_sender_restrictions=

 -o smtpd_recipient_restrictions=permit_mynetworks,reject

 -o mynetworks=127.0.0.0/8

 -o strict_rfc821_envelopes=yes

 -o smtpd_error_sleep_time=0

 -o smtpd_soft_error_limit=1001

 -o smtpd_hard_error_limit=1000

 -o receive_override_options=no_header_body_checks

 

This tells postfix that we’ll use Amavisd as an external program to check our mail. It also sets up port 10025 as the port that Amavisd will communicate back the results to Postfix.

Read about all the other settings here: http://www.postfix.org/postconf.5.html.

Close and save the file

 

Now, let’s edit main.cf:

 

vi /etc/postfix/main.cf

 

Add this line anywhere in the file:

content_filter = smtp-amavis:[localhost]:10024

 

This tells Postfix to communicate with Amavisd on our local machine, on port 10024.

 

Save and close the file.

Setting Amavisd to Start Automatically at System Boot

Amavisd comes with a shell script that allows us to set it to start automatically every time the system boots. The script is located in the source directory that we extracted Amavisd to: /usr/local/src/amavisd-new-#.#.#/, so we’ll copy it from there to the /etc/init.d/ directory, and call it amavisd:

cp /usr/local/src/amavisd-new-#.#.#/amavisd_init.sh /etc/init.d/amavisd

 

We now need to make the script executable:

chmod +x /etc/init.d/amavisd

 

…and add it to the list of startup services:

chkconfig --add amavisd

 

However, the script refers to Amavisd as being in “/usr/sbin/amavisd”, while earlier we moved it to “/usr/local/sbin/amavisd”, so let’s reflect this change in the script:

 

vi /etc/init.d/amavisd

 

Find the line with:

prog="/usr/sbin/amavisd"

 

And change it to:

prog="/usr/local/sbin/amavisd"

 

Amavis’ Little Children

Amavis creates 2 child processes by default when it starts. The amount of child processes defines how much mail will be scanned at any given time, and the more child processes, the more e-mail scanning is done per a given amount of time. You can change the default of two processes into a larger number, provided you have a good machine, with enough RAM. This is more of a trial and error kind of thing. I think that a pretty high limit will be 10-12 child processes, but 4 is a good number. To change the number of child processes, you need to edit amavisd.conf, and master.cf:

vi /etc/amavisd.conf

 

Find the line:

$max_servers = 2;

 

And change it to:

$max_servers = 4;

Save and close the file.

 

Now edit master.cf:

vi /etc/postfix/master.cf

 

Find this line, which you added earlier:

smtp-amavis  unix    -    -    y    -    2    smtp

 

Change the 2 to a 4:

smtp-amavis  unix    -    -    y    -    4    smtp

 

Save and close the file.

Installing Razor

Razor helps SpamAssassin detect spam messages. This is from its web site:

 

What is Vipul's Razor?

Vipul's Razor is a distributed, collaborative, spam detection and filtering network. Through user contribution, Razor establishes a distributed and constantly updating catalogue of spam in propagation that is consulted by email clients to filter out known spam. Detection is done with statistical and randomized signatures that efficiently spot mutating spam content. User input is validated through reputation assignments based on consensus on report and revoke assertions which in turn is used for computing confidence values associated with individual signatures.

 

We start by installing the SDK, which loads some required Perl modules that Razor will use.

 

Change to the directory where Razor’s install is in:

cd /usr/local/src/

 

Untar Razor’s SDK:

tar xjvf razor-agents-sdk-#.##.tar.gz

After a few seconds, Razor’s SDK will be extracted.

 

Change to the directory it was extracted to:

cd razor-agents-sdk-#.##

 

Now, let’s compile and install the SDK:

perl Makefile.PL

make

make test

make install

 

After a minute or two the SDK will be installed.

 

Now let’s install Razor itself. The procedure is similar to the installation of the SDK:

We go one directory level up:

cd ..

 

Untar Razor:

tar xjvf razor-agents-#.##.tar.gz

After a few seconds, Razor will be extracted.

 

Change to the directory it was extracted to:

cd razor-agents-#.##

 

Now, let’s compile and install Razor:

perl Makefile.PL

make

make test

make install

 

Configuring Razor

First, make sure that you allow TCP port 2703 outgoing from your server to the Internet:

 

razor-admin -d -create

 

If the command completed successfully, you should see:

razor-admin finished successfully.

This connected you to the Razor servers, and configured your server to use them.

 

Next, run this command:

 

razor-admin -register

 

This command creates a razor identity on your server. You should see:

Register successful.

or

razor-admin finished successfully.

If it gives you an error, run it again. Note that you may need to open some ports on your firewall for this command to complete successfully (TCP 2703).

 

We will now change some settings in the Razor configuration file:

vi /root/.razor/razor-agent.conf

 

Find the line that says:

debuglevel             = 3

 

And change the 3 to a 0.

In addition, add this line:

 

razorhome = /var/amavis/.razor

 

This tells Razor that its files are now going to be under /var/amavis/.

Since the amavis user is going to need to have access to Razor’s files, we tell Razor in its configuration file that its new home is under the /var/amavis/.razor/ directory. We will then move all of Razor’s files into their new home.

 

First, save and close the file you were editing above..

Now let’s move Razor to the /var/amavis/ directory:

cp -r /root/.razor/ /var/amavis/

Answer “y” to any overwrite question if you see one.

 

We now tell Razor to reconfigure itself to the new location:

razor-admin -d -create -home=/var/amavis/.razor/

If the command completed successfully, you should see:

razor-admin finished successfully.

 

Due to a change in the license agreement for Razor and DCC, SpamAssassin v3.1.x will not use both applications by default.

If the situation described in the license agreement allows you to run Razor, do the following to re-enable it:

 

Edit the file v310.pre:

vi /etc/mail/spamassassin/v310.pre

 

Find the line that looks like this:

#loadplugin Mail::SpamAssassin::Plugin::Razor2

 

And remove the #:

loadplugin Mail::SpamAssassin::Plugin::Razor2

 

Save and close the file.

 

That’s it!

Installing Pyzor

Pyzor is a system of distributed servers that is very similar to Razor. We use it here in order to fine tune our server’s spam-fighting abilities. It uses UDP Port 24441 to communicate with its server(s). Pyzor requires Python v2.2.1 and above. You can issue the following command to see if you have it installed:

yum list python

 

If you don’t have it installed, install it with yum:

yum install python

 

Start the installation by extracting the archive:

cd /usr/local/src/

tar xjvf pyzor-#.#.#.tar.bz2

cd pyzor-#.#.#

 

Once in the directory, issue the commands:

python setup.py build

python setup.py install

 

The install may mess up some of the permissions. We can fix it by issuing this command:

chmod -R a+rX /usr/share/doc/pyzor /usr/lib/python#.#/site-packages/pyzor /usr/bin/pyzor /usr/bin/pyzord

 

The gdbm module is required for Pyzor’s operation as well. gdbm is a GNU implementation of the standard Unix dbm library. You can check if it’s installed by running:

python -c 'import gdbm' && echo 'gdbm found'

If you get a “gdbm found”, you’re all set.

If not, run:

yum install gdbm

 

We’ll now tell Pyzor to find the Pyzor server(s):

pyzor discover

 

(If you get some errors running it for the first time, run it again)

This creates a file named servers in the /root/.pyzor/ directory. The directory will be created if not already there. However, since Amavis will have to have access to this file as well, we’ll copy it to the .pyzor directory that we created under our amavis user directory tree:

 

cp /root/.pyzor/servers /var/amavis/.pyzor/

 

To be absolutely sure that the /var/amavis/ directory is really owned by the amavis user and group, it’s always good to issue this command:

chown -R amavis:amavis /var/amavis/

 

By running this command, you switch temporarily to the amavis user, and then ping the Pyzor server:

su amavis -c 'pyzor ping'

 

You should see the server’s IP and port, followed by (200, 'OK').

If you don’t get this, make sure that port 24441 UDP is open from your server to the world.

 

Installing DCC

Much like Razor and Pyzor, DCC is a collaborative network of spam signatures. It can greatly enhance our server’s detection rate. DCC requires that port 6277 UDP will be open out. We start by switching to the source directory:

cd /usr/local/src/

 

Then we untar the package that we downloaded earlier, and change to the extracted directory:

tar xzvf dcc.tar.Z

cd dcc-#.#.#/

 

Now we’ll configure and install it:

./configure --with-uid=amavis

make

make install

 

This gets DCC installed. Now we need to tell it not to search any local DCC server, since we’re not going to run any servers on our machine. We will use the public DCC servers available on the Internet. If you have a huge site, and receive more than 100,000 messages per day, consider having a local DCC server. For now, run these commands:

cdcc "delete 127.0.0.1"
cdcc "delete 127.0.0.1 Greylist"

Note that you can add more DCC servers to your list. Visit DCC’s webpage for a current list.

 

There’s one last thing that we need to do. DCC comes with a script that prunes some of DCC’s log file. The installation instructions for DCC tell us to make run this script daily, or even more frequently. You will soon see that we’re going to have several scripts that are running at specific times. In Linux, you use the cron daemon to schedule jobs to run at a specific time. We will first create a symbolic link from /usr/bin/cron-dccd to the real script, located at /var/dcc/libexec/cron-dccd:

ln -s /var/dcc/libexec/cron-dccd /usr/bin/cron-dccd

 

Now, we’ll tell cron to run it every morning, at 5:00 am:

crontab -e

 

Add this line:

0 5 * * * /usr/bin/cron-dccd

 

Save and close the file. You should see:

crontab: installing new crontab

 

Don’t worry about the meaning of the numbers and asterisks. We’ll go over all of this later, when we set-up some more cron jobs.

 

This concludes the configuration of DCC as a stand-alone client. SpamAssassin will run DCC every time a message arrives, and this can be pretty time-consuming. If you have a server with a lot of RAM (512MB+), a better way will be to run DCC as a daemon. This way it’ll be constantly running, and the interaction between it and SpamAssassin will be more efficient. Understand that this is not a required step. SpamAssassin will run just fine without a “daemonized” DCC. The daemon version of DCC is named dccifd.

We start by editing the dcc_conf file:

vi /var/dcc/dcc_conf

 

Find the line that reads:

DCCIFD_ENABLE=off

(note: not the DCCD_ENABLE=OFF line)

 

and change it to:

DCCIFD_ENABLE=on

 

Save and close the file.

 

We’ll now make this daemon run every time the system starts:

cp /var/dcc/libexec/rcDCC /etc/init.d/DCC

chkconfig --add DCC

 

Let’s make sure that the amavis user and group have full access to the DCC directory:

chown -R amavis:amavis /var/dcc

 

And finally, we’ll edit SpamAssassin’s configuration file, and tell it where to find the path to DCC:

vi /etc/mail/spamassassin/local.cf

 

Add this to the end of the file:

dcc_home /var/dcc

 

Save and close the file.

Due to a change in the license agreement for Razor and DCC, SpamAssassin v3.1.x will not use both applications by default.

If the situation described in the license agreement allows you to run DCC, do the following to re-enable it:

 

Edit the file v310.pre:

vi /etc/mail/spamassassin/v310.pre

 

Find the line that looks like this:

#loadplugin Mail::SpamAssassin::Plugin::DCC

 

And remove the #:

loadplugin Mail::SpamAssassin::Plugin::DCC

 

Save and close the file.


More SpamAssassin Configuration

Next, we’ll copy some files from /root/.spamassassin/ to /var/amavis/.spamassassin/.

What we’re trying to accomplish is to make the amavis and root users “see” that SpamAssassin’s configuration is under /var/amavis/.spamassassin/ (root will assume by default that it’s under /root/.spamassassin/).

 

Run:

spamassassin --lint -D

This will show you some debug information, and since you’re running it as root, it’ll create the .spamassassin directory under /root/ (it creates such a directory for every user running spamassassin). The --lint command checks the rule base for errors. We’ll now copy the settings that were created for root, into the home directory of amavis:

 

When running the next command, please answer “n” to the possible “overwrite?” question:

 

cp -ir /root/.spamassassin /var/amavis

 

We’ll now make the root and amavis users read from the same preferences file, by creating a symbolic link:

 

cd /root/.spamassassin/

rm -f user_prefs

ln -s /var/amavis/.spamassassin/user_prefs user_prefs

 

What we did in the above steps was basically creating a link, so that every time root is looking for the user_prefs file under /root/.spamassassin, it’ll actually be the file /var/amavis/.spamassassin/user_prefs. This creates an interesting situation: if you find yourself working as root, and you run commands such as spamassassin --lint -D, or others, such as sa-learn, root may reclaim ownership of them. You may find yourself with a file named user_prefs that’s under the /var/amavis/.spamassassin/ directory, but Amavis won’t be able to access it (it’s owned by root).

To solve this, get used to this command (you don’t have to run it now, we’ll run it soon, below):

chown -R amavis:amavis /var/amavis

In English: give the amavis user and group full access to the directory and sub directories under /var/amavis. Feel free to run this whenever!

 

Next, we’ll edit SpamAssassin’s configuration file, and modify some files’ locations:

vi /etc/mail/spamassassin/local.cf

 

Add the following lines to the file:

razor_config /var/amavis/.razor/razor-agent.conf
bayes_path /var/amavis/.spamassassin/bayes
auto_whitelist_path /var/amavis/.spamassassin/auto-whitelist

lock_method flock

 

Lines 1 and 3 above refer to already-existing files that are in these directories from previous steps that we did. Line 4 tells SpamAssassin that the Bayes database files are located here, on this machine’s hard drive, and not somewhere else (such as an NFS server).

 

If you want to get a better report in the mail header, about the tests that SpamAssassin did along with the actual scores that they each contribute to the total score, ad this line:

add_header all Status _YESNO_, score=_SCORE_ required=_REQD_ tests=_TESTSSCORES(,)_ _DCCR_ _PYZOR_ _RBL_ autolearn=_AUTOLEARN_ version=_VERSION_

Save and exit the file.

 

We now need to create the Bayes database, referenced in the second line that we added to local.cf:

sa-learn --sync

 

This will initialize the Bayes database.

 

The last step that we have to do is give Amavisd full ownership of all the files under /var/amavis/. Issue this command:

 

chown -R amavis:amavis /var/amavis/

Testing the Server

This is a good time to stop and test Postfix, Amavis, SpamAssassin, Pyzor, Razor, and DCC. We’re about to start the installation of our Anti Virus software, so before we do, let’s test that everything is OK thus far!

 

Reboot your new server:

reboot

 

After rebooting, Postfix and Amavisd should be starting automatically. If they’re not, you probably made some mistakes above. Go to the appropriate sections and fix the problems.

You can check the process list (ps aux) to see that Postfix and Amavisd are running, but you can also do the following:

amavisd reload

 

If amavisd is not running, you’ll get an error:

No PID file /var/amavis/amavisd.pid, can't reload the process

 

Make sure that you correctly did the steps for making it load automatically at boot-up.

 

If it was running, it will kill itself, and then reload itself:

daemon terminated, waiting for the dust to settle...

becoming a new daemon...

 

To start Amavisd, issue this command:

amavisd start

 

Note that Amavisd only reports errors. If everything is well, it’ll simply show you the command prompt after it loads.

 

With Postfix the situation is similar. First, issue a reload:

postfix reload

 

If Postfix is not running, you’ll get this error:

postfix/postfix-script: fatal: the Postfix mail system is not running

Make sure that you correctly did the steps for making it load automatically at boot-up.

 

If Postfix was running, it’ll reload itself really fast:

postfix/postfix-script: refreshing the Postfix mail system

 

To start Postfix, issue the following command:

postfix start

 

You should see:

postfix/postfix-script: starting the Postfix mail system

 

You may see the following when starting Postfix:

postfix/postfix-script: warning: /var/spool/postfix/etc/passwd and /etc/passwd differ

 

If you do, issue this command:

LINUX2

 

Stopping Postfix is done by issuing postfix stop. Stopping Amavisd is done by issuing amavisd stop. Amavisd should always be started before Postfix, since Postfix depends on Amavisd.

 

Now we’ll actually test Amavisd with SpamAssassin, and see that everything is OK. Type these commands:

amavisd stop

amavisd debug-sa

 

This will throw tons of text to the screen, but it should then stop, and give no errors.

(By the way: if you see nothing on the screen, you may have some permissions issues. Run chown -R amavis:amavis /var/amavis/)

Scroll up and down (if you use an ssh client), and look for lines like:

debug: using "/var/amavis/.spamassassin/user_prefs" for user prefs file

 

This line tells you that the user_prefs file was read from /var/amavis/.spamassassin/-exactly what we wanted!

 

Also look for this:

dbg: bayes: xxxxx tie-ing to DB file R/O /var/amavis/.spamassassin/bayes_toks

dbg: bayes: xxxxx tie-ing to DB file R/O /var/amavis/.spamassassin/bayes_seen

 

This tells us that the Bayes database is exactly where we wanted it.

 

A good Razor configuration should show you this:

dbg: razor2: razor2 is available, version 2.77

 

A good Pyzor configuration should show you:

dbg: plugin: loading Mail::SpamAssassin::Plugin::Pyzor from @INC

dbg: pyzor: network tests on, attempting Pyzor

 

And finally, a good DCC configuration should show you:

dbg: plugin: loading Mail::SpamAssassin::Plugin::DCC from @INC

dbg: dcc: network tests on, registering DCC

 

You can end the debug session with CTRL+C.

 

Lets start Amavisd again:

amavisd start

 

Once both Postfix and Amavis are up, the easiest way to test is to do the firewall changes that I suggested, and test from Gmail. You can also use Outlook Express as discussed before. To simulate a spam message, you can send the GTUBE message (Generic Test for Unsolicited Bulk Email). Spam scanners such as SpamAssassin are designed to see this message as spam, and report it as such.

 

Simply e-mail yourself the following in the body of the message from Gmail:

XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X

 

You can read more about it, and get a text file with GTUBE in it here:

http://spamassassin.apache.org/gtube/

 

Your message should be delivered to the e-mail address that you sent it to.

It should have the spam tags (you will need to view the message source to see them), and it should say “[Possible Spam] “ (unless you chose something else) in the subject line, before your original subject.

 

If it didn’t work, then you know that the problem is probably with Amavisd, since we know that Postfix works. Look in the log (less /var/log/maillog), and try to determine where the problem is. Also check that you did all the steps in the configuration and setup of Amavisd.

 

Another problem that you may have is that Amavisd doesn’t have access rights to all the files and directories under /var/amavis. Issue the following commands to fix it:

chown -R amavis:amavis /var/amavis/
chmod -R 750 /var/amavis/

 

Reminder Regarding Configuration Changes

One important thing to remember is that every time you make a change to main.cf, or the master.cf configuration files in Postfix, you must reload Postfix it by issuing:

postfix reload

 

If you modified any of the other configuration files, the ones that we referred to with the hash:/, you also need to run postmap <file name> after the change. For example, if you modified the recipient_access file, you need to do the following:

postmap /etc/postfix/recipient_access

postfix reload

 

Also remember that Amavisd can be very sensitive to directories and files that it should own. You may need to run chown on specific directories or files, to change the ownership back to Amavisd, if they somehow get messed-up.


Installing ClamAV

This section is completely optional, and you can skip it if you don’t want to integrate virus scanning into your server.

Download the latest version from www.clamav.net to /usr/local/src/.

Remember that you can use WinSCP to transfer the download from your Windows machine to the server very easily.

 

Extract the file:

cd /usr/local/src/

tar xzvf clamav-#.##.#.tar.gz

 

My installed zlib was too old (older than 1.2.2), so I had to update it.

You can skip this section, and return to it later only if you get an error about and old Zlib.

cd /usr/local/src/

wget http://www.zlib.net/zlib-1.2.2.tar.gz

tar xzvf zlib-1.2.2.tar.gz

cd zlib-1.2.2

make test

make install

 

Create a group (clamav), and new user (clamav):

groupadd clamav

useradd -g clamav -s /bin/false -c "Clam AntiVirus" clamav

 

We just changed the /etc/passwd file, since we added a user. This will make Postfix report that its passwd file is different than the /etc/passwd file. To fix this, issue:

LINUX2

 

Answer yes to overwrite.

 

Add the clamav user to the amavis group:

gpasswd -a clamav amavis

 

Change to the ClamAV source directory (where it was extracted to):

cd /usr/local/src/clamav-#.##.#

 

Configure ClamAV:

./configure --sysconfdir=/etc

 

If the configure program exits with no errors, ClamAV was configured correctly.

 

Now, we’ll compile and install it:

make

make install

 

Configuring ClamAV

We’ll now configure the clamd.conf file:

vi /etc/clamd.conf

 

Find the line that has Example on it, and comment it out, or delete it altogether.

clamd won’t run when this line is there.

 

Look for a line that starts with LocalSocket, and write down the value that appears after the word LocalSocket. Mine shows:

LocalSocket /tmp/clamd

 

This is the socket that clamd uses. In this case, the socket is a file named clamd under /tmp/. Think of a socket as a gateway that Amavisd will use to send an e-mail for scanning to clamd. Amavisd will pipe the e-mail to clamd through the file /tmp/clamd. To many, this looks a little weird. Most of us are used to having a server with a specific IP and a port so that we can simply telnet the server on that port and issue commands. clamd can work in that way (TCPSocket), but from reading that I did I learned that there’s a decrease in performance when the IP/Port method is used. Nevertheless, if you want to make clamd work like that, with a specific IP (it’ll actually be your server’s IP, or 127.0.0.1, or localhost-all three are the same) and a specific port, look below for the Alternative clamd Configuration section.

 

Find the line #AllowSupplementaryGroups, and uncomment it by removing the #.

‌‌‌By default, only the same user id/group id as the clam user can query the clamd

socket. ‌‌‌‌‌‌‌With supplementary groups, anyone who shares a group id with the clam user can query the socket.

 

Also note the line that specifies the log file location. I don’t implement any logging, but if you choose to, please read more about it in the documentation.

 

Save and exit the file.

 

We can update ClamAV by running freshclam, but we need to configure it first:

vi /etc/freshclam.conf

 

Find the line that has Example on it, and comment it out, or delete it altogether. freshclam won’t run when this line is there.

 

Save and exit the file.

 

We also need to tell Amavisd to use ClamAV.

Edit amavisd.conf:

vi /etc/amavisd.conf

 

Comment the line starting with @bypass_virus_checks_maps = (1); by adding a # to its beginning:

# @bypass_virus_checks_maps = (1);

 

Find the ClamAV section (type /Clam, and <Enter> to search for it), then uncomment it so that it looks like this:

['ClamAV-clamd',

   \&ask_daemon, ["CONTSCAN {}\n", "/var/run/clamav/clamd"],

   qr/\bOK$/, qr/\bFOUND$/,

   qr/^.*?: (?!Infected Archive)(.*) FOUND$/ ],

 

Change the /var/run/clamav/clamd to /tmp/clamd.

The /tmp/clamd is taken from the clamd.conf setting that you wrote down earlier.

 

This should already be set-up for you, if you did it under the Amavis configuration section, but in case it’s not, uncomment the line:

# $final_virus_destiny      = D_DISCARD;

 

Find the line starting with $virus_admin, and make sure that it’s not commented.

This line defines who gets the virus alerts every time a virus is detected. By default, this line is configured to e-mail virusalert@example.com, but you can change it of course.

If you don’t wish to receive notifications about captured viruses, comment-out this line. They will then be either stored on your server, or forwarded to a mailbox, depending on what you selected that you want done under Amavisd’s configuration.

 

The following was also covered under Amavisd’s configuration. In case you didn’t do it, here it is again:

 

Find the three lines starting with:

$mailfrom_notify_admin     = "virusadmin\@$mydomain";

$mailfrom_notify_recip = "postmaster\@$mydomain";
$mailfrom_notify_spamadmin = "postmaster\@$mydomain";

And change them to:

$mailfrom_notify_admin     = "postmaster\@$mydomain";

$mailfrom_notify_recip = "postmaster\@$mydomain";
$mailfrom_notify_spamadmin = "postmaster\@$mydomain";

 

Add this line:

$hdrfrom_notify_admin = "Content Filter <postmaster\@$mydomain>";

 

This makes the header-envelope from be from the address specified.

Save and close the file.

 

Testing ClamAV

First, let’s check that Amavisd recognizes ClamAV at all.

Start ClamAV:

clamd

 

Now start Amavisd in debug mode:

amavisd stop

amavisd debug

 

Look for lines like these:

Using internal av scanner code for (primary) ClamAV-clamd

Found secondary av scanner ClamAV-clamscan at /usr/local/bin/clamscan

 

Issue a CTRL+C to stop Amavis.

 

You can now run Amavis normally:

amavisd start

 

And then restart/start postfix:

postfix reload

-or-

postfix start

 

Run the command freshclam to update the virus database.

 

Do the firewall changes as mentioned, and send yourself an e-mail from Gmail.

You should receive it with no problems.

 

Next, e-mail yourself another e-mail with this string in it:

X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*

 

Make sure the e-mail contains this string in the body, and that it’s the only thing there.

This is known as the EICAR test string. All Anti-Virus software should detect this as a virus (but of course, it’s not. It’s used for testing only.)

 

You should have an e-mail dropped as a text file in /var/virusmails, or to the e-mail address that you specified above, with the contents of the message!

 

If you don’t, go over the configuration changes again, and see if you missed something.

 

Now will be a good time to reboot the server, and see that clamd loads automatically.

You can do so by issuing a PING command to it, as shown below.


Issuing Commands to clamd

Using LocalSocket

If you chose the LocalSocket method of communicating with clamd, you’ll have to use a very cool piece of software called socat to send commands to clamd. You can read about it here: http://www.dest-unreach.org/socat/, and get it by issuing this command:

cd /usr/local/src/

wget http://www.dest-unreach.org/socat/download/socat-1.4.2.0.tar.gz

 

Note that there may be a new version, so go to the web page first, and then issue the wget command with the right file name.

 

Now, let’s extract and install it:

tar xzvf socat-#.#.#.#.tar.gz

cd socat-1.4                     (you may have a different directory name)

./configure

make

make install


You can now run socat - /tmp/clamd and then issue one of the following commands:

PING - should reply with a PONG. It tells you that clamd is alive.

RELOAD - reloads the database

SHUTDOWN - shuts down clamd

VERSION - shows you clamd’s version.

 

Please read the man page for clamd for all other commands (man clamd)

Using TCPSocket

Using the TCPSocket way is easy. You simply issue the following:

telnet <IP-Address-Of-Your-Server> Command to clamd.

 

For example:

telnet 127.0.0.1 PING

 

…should send you a PONG back.

 

Alternative clamd Configuration

As mentioned above, you can run clamd as a server on a specific port. This is known as TCPSocket mode. To do this, you’ll first have to stop clamd if it’s running.

 

Using socat (if clamd is currently running in LocalSocket mode):

socat - /tmp/clamd

SHUTDOWN

 

Using the kill command:

Find the process number by issuing:

ps aux|grep [c]lamd

 

The process number is the second to the left. It’s 9398 in the example below:

root      9398  0.0  1.4 28896 14712 ?       Ss   14:28   0:01 clamd

 

Kill the process:

kill <process-number-goes-here>

Now open clamd.conf:

vi /etc/clamd.conf

 

Find the line that starts with LocalSocket and comment it out.

Find the commented line #TCPSocket 3310 and uncomment it.

Find the commented line #TCPAddr 127.0.0.1 and uncomment it.

 

You can change the port (3310) to something else if you want to, but remember what it is. The same goes for the IP, but since it’s set to 127.0.0.1, I suggest you won’t change either one.

 

Save and close the file.

 

Open amavisd.conf:

vi /etc/amavisd.conf

Under the ClamAV section, find this line:

 \&ask_daemon, ["CONTSCAN {}\n", "/var/run/clamav/clamd"],

 

Note: if you already used clamd in LocalSocket mode, this line will be:

\&ask_daemon, ["CONTSCAN {}\n", "/tmp/clamd"],

 

Change the line so that it looks like this:

\&ask_daemon, ["CONTSCAN {}\n", "127.0.0.1:3310"],

 

Note: if you changed the IP/Port, make sure you type your new IP/Port here.

Save and close the file.

 

Restart clamd:

clamd

 

You can now telnet to it, and issue the PING command to see if it’s alive:

telnet 127.0.0.1 3310

PING

 

You should get the reply: PONG.

Setting ClamAV (clamd) to Start Automatically at System Boot

The ClamAV distribution includes a script to allow us to start clamd every time the system boots. The script is under the contrib/init/RedHat/ directory, after the distribution’s tar file is extracted. We need to copy this file to the /etc/init.d/ directory.

 

cp /usr/local/src/clamav-#.##.#/contrib/init/RedHat/clamd /etc/init.d/

Note that you may have a different version than 0.85.1. Change the copy command above accordingly.

 

Now we’ll make the script executable, and add it to the list of start-up services:

chmod 0755 /etc/init.d/clamd

chkconfig --add clamd

Setting ClamAV to Auto-Update hourly

Update your crontab file:

crontab -e

 

Add the following line to the end of your crontab file:

MM * * * * /usr/local/bin/freshclam --quiet

Replace MM with anything between 0 and 59. This will make freshclam run at this specific minute every hour.

 

Save and close the file.

You can verify that freshclam is/was running, by examining the cron log file:

less /var/log/cron

 

Logwatch

During the configuration of Postfix, we set up a file named virtual. In it, there was a line that aliased the name “root” to your name. We did that so that all e-mails to root will be actually sent to you.

 

Fedora will send a log to root daily by default to root, and as a result, you will now get this log.

The log contains some useful information, and some not so useful information…

You can see how many SSH sessions were made to your server, and from which IPs. You can also see the disk space remaining.

 

Cron (Linux’s/Unix’s task scheduler if you will) is configured by default to run daily jobs at 04:02 every day, so this is when the log will be sent to you. You can change that by editing /etc/crontab.

 

Jobs that should run daily are located under /etc/cron.daily, and if you look inside that directory, you should see something like this:

 

drwxr-xr-x   2 root root  4096 Jun  2 11:58 .

drwxr-xr-x  73 root root 12288 Jun  2 12:03 ..

lrwxrwxrwx   1 root root    28 Apr 27 18:53 00-logwatch -> ../log.d/scripts/logwatch.pl

-rwxr-xr-x   1 root root   418 Nov 19  2004 00-makewhatis.cron

-rwxr-xr-x   1 root root   276 Sep 28  2004 0anacron

-rwxr-xr-x   1 root root   180 Oct 19  2004 logrotate

-rwxr-xr-x   1 root root  2133 Nov 23  2004 prelink

-rwxr-xr-x   1 root root   104 Nov  1  2004 rpm

-rwxr-xr-x   1 root root    82 Oct 20  2004 slocate.cron

-rwxr-xr-x   1 root root   286 Aug 13  2004 tmpwatch

-rwxr-xr-x   1 root root   136 Feb 21 10:38 yum.cron

 

These are all the jobs that are running daily, at 04:02 in the morning.

Note that the file representing Logwatch is actually a symbolic link (like a shortcut in Windows) to the real file, which is a Perl script located under /etc/log.d/scripts/logwatch.pl.

You can disable any log reporting that you don’t want. To do this, edit the configuration file for Logwatch:

vi /etc/log.d/conf/logwatch.conf

 

Then look for the line that says:

Service = All

 

And if you want to disable any logging for Sendmail, add the following under it:

Service = -sendmail

 

You can do that with any service that is reported in the log. Sendmail was just an example.

Logrotate

Another file that you saw in the /etc/cron.daily/ directory was logrotate, and as the name suggests, it’s a script for rotating log files. By default, the logrotate script will rotate the log every week, and keep 4 weeks of backlogs, uncompressed. Since Postfix’s logs can get really big, I like to change logrotate so that logs are being compressed after they’re rotated. If you like it too, edit the logrotate configuration file:

vi /etc/logrotate.conf

 

Find the line that says:

#compress

 

Put your cursor on the # sign, and press x to delete the # sign. Then save and exit the file.

 

Backing-up the Server’s Configuration

Backing-up your system is very important. This document can help you build an alternate server fairly easily should you need to, however, it’ll be really cool if you could just have all the configuration files handy, won’t it?

 

Appendix D contains a script written by William Julien, which can help us send e-mail with attachments through Postfix. I found this script on a Red Hat forum (https://www.redhat.com/archives/fedora-list/2004-May/msg02178.html).

The best way to get it to your box is to select and copy the script to the clipboard, then paste it into a plain text file called mime_mail.pl, and then use WinSCP to transfer it to /usr/local/sbin.

 

Once you have the file, issue the following command to make it executable:

cd /usr/local/sbin/

chmod +x mime_mail.pl

 

Let’s test the script. Run this command:

./mime_mail.pl -s "Test" -u root -f /etc/postfix/LICENSE

 

This should send root@yourdomain.com the file LICENSE from Postfix’s directory, with the subject line “Test”.

 

It’s important to mention that in my setup, root resolves to ronny, so every e-mail to root is sent to me. If you didn’t do that, simply replace root with your e-mail.

 

If you didn’t get any e-mail with the file, check your log file for errors with:

less /var/log/maillog

 

Now that we can send e-mails from the server to ourselves, let’s create a script that takes all the files that we want to backup, puts them in one directory, archives them, and sends the archive to us. We’ll call the file “backup-files”, and I assume that you’re still in the /usr/local/sbin directory:

vi backup-files

 

In the file, type the following lines:

#!/bin/sh

rm -drf /tmp/backup

mkdir /tmp/backup

cp /etc/postfix/aliases /tmp/backup/

cp /etc/postfix/client_access /tmp/backup/

cp /etc/postfix/helo_access /tmp/backup/

cp /etc/postfix/recipient_access /tmp/backup/

cp /etc/postfix/sender_access /tmp/backup/

cp /etc/postfix/transport /tmp/backup/

cp /etc/postfix/virtual /tmp/backup/

cp /etc/postfix/main.cf /tmp/backup/

cp /etc/postfix/master.cf /tmp/backup/

cp /var/amavis/white.lst /tmp/backup/

cp /var/amavis/black.lst /tmp/backup/

cp /etc/amavisd.conf /tmp/backup/

cp /etc/log.d/logwatch.conf /tmp/backup/

cp /etc/logrotate.conf /tmp/backup/

cp /etc/mail/spamassassin/*.cf /tmp/backup/

cp /etc/mail/spamassassin/init.pre /tmp/backup/

cp /var/amavis/.razor/razor-agent.conf /tmp/backup/

cp /etc/clamd.conf /tmp/backup/

cp /etc/freshclam.conf /tmp/backup/

cp /etc/sysconfig/network-scripts/ifcfg-eth0 /tmp/backup/

cp /etc/sysconfig/network-scripts/ifcfg-eth0:1 /tmp/backup/

cp /etc/sysconfig/network-scripts/ifcfg-eth0:2 /tmp/backup/

cp /etc/resolv.conf /tmp/backup/

cp /etc/hosts /tmp/backup/

cp /etc/sysconfig/network /tmp/backup/

cp /usr/local/sbin/backup-files /tmp/backup

cp /usr/local/sbin/mime_mail.pl /tmp/backup

cp /usr/local/sbin/rules_du_jour /tmp/backup

cp /var/dcc/dcc_conf /tmp/backup

crontab -l >/tmp/crontabcontents

cp /tmp/crontabcontents /tmp/backup

rm /tmp/crontabcontents

DM=`date +%b"_"%d"_"%G`

tar -Pzcf /tmp/backup_$DM.tar.gz /tmp/backup/

/usr/local/sbin/mime_mail.pl -s "Spam Server Configuration Backup" -u root -f "/tmp/backup_$DM.tar.gz"

rm -f /tmp/backup_$DM.tar.gz

Save and close the file.

 

Note: This script assumes that you did install ClamAV. If you did not, remove the configuration files of Clam and Freshclam from the script.

 

Note: The same goes for a multiple IP server. Remove the lines for backing up eth0:1, and eth0:2 if you have only one IP associated with your machine.

 

Now, make it executable:

chmod +x backup-files

 

And then make a test run:

./backup-files

 

You should get an e-mail with a file named “backup_MMM_DD_YYYY.tar.gz”, where MMM is representing the month, DD the day, and YYYY the year.

 

We can now make this script run daily or weekly. Run the following command to add it to root’s cron job:

crontab -e

 

You then edit the file just like in vi. Add this line:

0 19 * * * /usr/local/sbin/backup-files

 

This will send you the configuration file every night at 7:00 PM (19:00).

You probably figured it out already: The first number represents the minutes, and the second number represents the hour 24-hour format.

The third number represents the day of month (1-31).

The fourth number represents the month (1-12, or a name)

The fifth number is the day of week (0-7. 0 or 7 is Sunday, 1 is Monday, etc.)

 

So, to make receive a backup of your configuration every Sunday at 19:00, instead of every day at 19:00, you will need to modify the last number to be a 0 (or a 7), instead of “*”:

0 19 * * 0 /usr/local/sbin/backup-files

 

This is quite simple, huh?

You can now exit the file

 

You can type man 5 crontab to read more about the structure of the crontab file.


Working with sa-learn

sa-learn is provided with SpamAssassin, to help you teach SpamAssassin which messages are spam, and which are ham. The Bayesian filter in SpamAssassin must be fed both ham and spam to be effective.

 

The format of the command is:

sa-learn [--spam|--ham] message

 

Given a spam text message spam_message, you can train SpamAssassin’s heuristics database by issuing:

sa-learn --spam spam_message

 

Given a ham text message ham_message, you can train SpamAssassin’s heuristics database by issuing:

sa-learn --ham spam_message

 

I found it to be very useful in the first few days of my server’s activity.

I asked my users to forward me the message source, and then I copied-pasted it into a text file that I fed into SpamAssassin.

 

You can do so yourself, by taking e-mails that are in your spam mail box, and feed them to SpamAssassin. What I usually do is convert them to their raw original format, then drop them on my server, and run the sa-learn command with either the ham or spam options.

 

Note that running sa-learn as root may change the Bayes files permissions to root.

To prevent that from happening, you can run sa-learn as the amavis user:

su amavis –‘sa-learn –-spam spam_message’

or

su amavis –‘sa-learn –-spam ham_message’


Tweaking SpamAssassin’s Tests Scores

Each of the tests that SpamAssassin runs has its own score. When an e-mail matches a specific test, that score is added to the total. Then, using Amavisd, we define the score that will make an e-mail be considered as spam. To see SpamAssassin’s current tests and their scores, go here: http://spamassassin.apache.org/tests_3_0_x.html. Note that every test has the ability to provide four different scores, depending on how SpamAssassin is used. When SpamAssassin is set to do local tests only (score set 1), only local rules are consulted. These rules are under /usr/share/spamassassin/, and you see their scores in the first column. When SpamAssassin is doing net tests (score set 2), it consults services like Pyzor, Razor, DCC, etc, and the scores that will be given are shown in the second column. When SpamAssassin is using the Bayes database to score a message (score set 3), it simply uses the database that it creates over time. Score set 4 is used when SpamAssassin is set to consult Bayes, network tests (Razor, Pyzor, DCC), and local tests. Score set 4 is what we use in our server. Amavis’ configuration file has a line in it: $sa_local_tests_only = 0; which means that SpamAssassin will be used with Score set 4.

 

You can always tweak a test’s score by adding it to local.cf with a new score value. We did this above when we discussed disabling SPF, where you saw that a score of 0 disables a test. Here’s an example:

score SPF_PASS 0 0 0 0

This disables the test SPF_PASS altogether.

 

Read more about it here (‌‌‌‌‌‌‌‌‌Adjusting Rule Scores): http://wiki.apache.org/spamassassin/AdjustRuleScore?highlight=%28scores%29%7C%28default%29

 

By monitoring the spam that you get, you may notice that a specific test keeps appearing.

You can then modify its score so that it’ll add more points to the final score. Tweaking Razor’s tests is probably the most common thing that I’ve seen people do. If you see that a lot of your spam is correctly tagged by Razor, modify its two rules to give a higher score.

 

Another interesting thing that you can do is create your own scores, or use rules that others already wrote. A very good starting point will be the SARE website at: http://www.rulesemporium.com/index.html, where you can download custom rules and simply put them in the /etc/mail/spamassassin/ directory. The files need to end with .cf to work properly. Always run spamassassin -–lint -D before implementing new rules on your site. Running this command will “lint” the rules for any errors. SARE also has links to other sites on the subject.

 

You can use Rule Du Jour to automatically update some of the SARE rules: http://www.exit0.us/index.php?pagename=RulesDuJour.

 

To write custom rules for SpamAssassin, check out these websites:

http://wiki.apache.org/spamassassin/CustomRulesets,
http://mywebpages.comcast.net/mkettler/sa/SA-rules-howto.txt
http://wiki.apache.org/spamassassin/WritingRules?highlight=%28scores%29

Note that every time you change local.cf, or add new rule sets to /etc/mail/spamassassin/ you need to restart amavisd by issuing: amavisd reload.

 

Generating Mail Reports

Jim Sun created a nice Perl script that goes over Postfix’s log and sends you a nice summary. I found it to be very useful for the first few days of running the server. After a while, I didn’t even look at it any more. Nevertheless, you may need to show some stats to management, so follow the instructions in this section to install the script.

 

Start by downloading the script:

cd /usr/local/src/
wget http://jimsun.linxnet.com/downloads/pflogsumm-1.1.0.tar.gz

 

Notice that we’re downloading v1.1.0. You may want to check Jim’s site for a new version if it fails (http://jimsun.linxnet.com/postfix_contrib.html). There are other cool Postfix-related documents there. Check it out.

 

You should now how the compressed script downloaded. Let’s extract it:

tar xzvf pflogsumm-1.1.0.tar.gz


This will create the directory pflogsumm-1.1.0, and put all the files there.

 

We’ll now copy some of the required files from the extracted directory, and put them under /usr/local/sbin/:

cp /usr/local/src/pflogsumm-1.1.0/pflogsumm.pl /usr/local/sbin/

cp /usr/local/src/pflogsumm-1.1.0/rem_smtpd_stats_supp.pl /usr/local/sbin/

cp /usr/local/src/pflogsumm-1.1.0/pflogsumm.1 /usr/local/sbin/


Let’s make the script executable:

chmod +x /usr/local/sbin/pflogsumm.pl


Let’s add it to our crontab file. Edit the file:

crontab -e


Add this line:

0 3 * * * /usr/local/sbin/pflogsumm.pl -d yesterday /var/log/maillog 2>&1 |/bin/mail –s

 "Daily Spam Server Activity Summary" root

 

Save and close the crontab file.

 

We need to install the Date::Calc Perl module for the script to work properly.

Let’s get into MCPAN and get them:

perl -MCPAN -e shell

 

When you get the prompt, type:

install Date::Calc

 

If you’re asked to install other modules that are required, say yes (you’ll probably be asked for Bit::Vector and Carp::Clan)

When it’s done installing, type quit to get back to the shell prompt.

 

Appendix A: Setting up the IP address manually

Reminder: Note that the LINUX2 script that is discussed in the document (the one that’s switching Postfix to a chrooted environment) copies the hosts and resolv.conf files that I’ll discuss below (it also copies other files, such as passwd). If you’re manually setting your network configuration, you’ll have to copy these two files into /var/spool/postfix/etc/ or run the LINUX2 file again when you’re done.

 

Edit the file /etc/sysconfig/network-scripts/ifcfg-eth0 (assuming eth0 is your network card. Usually it is):

 

vi /etc/sysconfig/network-scripts/ifcfg-eth0

 

In this example, I setup the IP to be 10.10.0.123 in a class B network. Don’t worry if your file already contains things that are not here (such as HWADDR). You can simply add the lines that I have below. Note that the file is very simple, and follow the format of VARIABLE=something (note the UPPER case). If you see a variable below that is already in your file, use mine instead. For example, your file may have “BOOTPROTO=DHCP”, but below you can see that I chose to use “BOOTPROTO=static”. In this case, use my line.

Press i (lower case “I” or the Insert key, and make sure the following lines are in the file, excluding the comments that I put in parenthesis:

DEVICE=eth0

BOOTPROTO=static

BROADCAST=10.10.255.255        (note that this is a class B. Yours may differ)

IPADDR=10.10.0.123

NETMASK=255.255.0.0                 (note that this is a class B. Yours may differ)

NETWORK=10.10.0.0                     (note that this is a class B. Yours may differ)

ONBOOT=yes

TYPE=Ethernet                              (note that yours may not be Ethernet. Usually it is)

GATEWAY=10.10.0.100                 (yours may be different)

 

Save and close the file.

Setting up DNS resolution

Edit the file /etc/resolv.conf:

vi /etc/resolv.conf

 

Make sure the following lines are in the file:

search localdomain                   replace it with your domain name

nameserver 1.2.3.4                   replace it with your first name server

nameserver 5.6.7.8                   replace it with your second name server

nameserver 9.10.11.12            replace it with your third name server

Save and close the file.

Modifying the hosts file

Edit the file /etc/hosts:

vi /etc/hosts

 

You should see:

127.0.0.1               localhost.localdomain localhost

 

Modify the file, so that your server’s FQDN and host name appear right after the 127.0.0.1:

127.0.0.1               spamserver.example.com spamserver localhost.localdomain localhost

 

Save and close the file.

Changing the host name

Edit the file /etc/sysconfig/network:

 

vi /etc/sysconfig/network

 

Enter the fully qualified host name after the HOSTNAME= line, then save and close the file.

 

Fedora will send an e-mail to root automatically every day with log information. It’s actually a job run by cron called Logwatch. Changing the host name will make this e-mail subject say: “Logwatch for yourhostname here

 

Setting Up Multiple IPs for the Server

You may want to have more than one IP addresses associated with your server. This can help fight spam, by making spammers think that your backup MX is actually a different server, when it fact, it’s not. This is very easily accomplished in Linux.

Start by copying your ifcfg-eth0 file to ifcfg-eth0:1, ifcfg-eth0:2, ifcfg-eth0:3, etc, for as many other IPs that you want to set up:

cd /etc/sysconfig/network-scripts/

cp ifcfg-eth0 ifcfg-eth0:1

cp ifcfg-eth0 ifcfg-eth0:2

.

.

Then edit each of the files that you created, and change the DEVICE= line, and the IPADDR= line to be the new device name (eth0:1, eth0:2, etc), and the new IP Address.

Here’s an example file:

 

DEVICE=eth0:1

BOOTPROTO=static

HWADDR=00:30:8C:AF:F8:DF

BROADCAST=10.10.255.255

IPADDR=1.2.3.4

NETMASK=255.255.0.0

NETWORK=10.10.0.0

ONBOOT=yes

TYPE=Ethernet

GATEWAY=10.10.0.1

 

Save and close each file.

 

Usually, you would set up internal IPs that are NATed to external, Internet-routable IPs. If that is the case, remember to add the new IPs that your server is known as on the Internet into SpamAssassin’s local.cf file. See the section about SpamAssassin’s Trusted Path for details.

 

You should now reboot your server. You can then ping each of the IP addresses to see if it responds.


Appendix B: Very short vi manual

vi is a very useful and common editor in Linux.

There are two modes that it operates in. One allows you to enter commands, and the other allows you to enter text.

 

You start vi by typing vi and then <Enter>.

You can also type vi filename to edit filename. If filename is a new file, it will be created. If it’s not new, it’ll be simply opened.

 

When you edit a file, vi will open in non-edit mode. You won’t be able to start typing text. To actually type something, you’ll have to press i (note the lower case!), or the Insert key to get into insert mode. Then, you can move around and change text. To switch back to command (non-edit) mode, press <ESC>.

 

There are some cool things you can do in command mode:

 

Pressing x while on a character will erase that character. So if you have the word Ronnny, and you put the cursor on one of the n characters, and press x, it will delete that n and give you Ronny. Of course, you could also press i to get into insert mode, and then Del to delete the n.

 

Pressing r while on a character will allow you to replace that character. If you have the word Rongy, and you’ll place the cursor over the g, and then type rn (that’s replace, and then the character n), you’ll get Ronny.

 

These are very useful, and work while you’re not in insert mode. To be sure you’re not in insert mode, press ESC:

 

dd deletes a whole line and puts it in the “clipboard”.

yy copies a whole line and puts it in the “clipboard”.

p pastes whatever is in the clipboard.

G takes you to the end of the document.

:w writes the changes you made to the file.

:wq writes the changes you made to the file, and exits to the shell prompt.

:q! exits immediately, without saving

:q quits, assuming you made no changes to the file.

 

Appendix C: Postfix startup script

This script is by Scott L. Henderson.

 

#!/bin/sh

#

# postfix      This shell script takes care of starting and stopping

#               postfix.

#

# chkconfig: 2345 80 30

# description: Postfix is a Mail Transport Agent, which is the program \

#              that moves mail from one machine to another.

# processname: postfix

# config: /etc/postfix/

# pidfile: /var/run/postfix.pid

 

# Source function library.

. /etc/rc.d/init.d/functions

 

# Source networking configuration.

. /etc/sysconfig/network

 

# Check that networking is up.

[ ${NETWORKING} = "no" ] && exit 0

 

[ -f /usr/sbin/postfix ] || exit 0

[ -d /etc/postfix ] || exit 0

[ -d /var/spool/postfix ] || exit 0

 

RETVAL=0

 

# See how we were called:

 

case "$1" in

  start)

        # Start daemons.

        echo -n "Starting postfix: "

        /usr/sbin/postfix start

        RETVAL=$?

        [ $RETVAL -eq 0 ] && touch /var/lock/subsys/postfix

        ;;

  stop)

        # Stop daemons.

        echo -n "Shutting down postfix: "

        /usr/sbin/postfix stop

        RETVAL=$?

        [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/postfix

        echo

        ;;

  restart)

        $0 stop

        $0 start

        ;;

  reload)

        /usr/sbin/postfix reload

        exit $?

        ;;

  abort)

        /usr/sbin/postfix abort

        exit $?

        ;;

  flush)

        /usr/sbin/postfix flush

        exit $?

        ;;

  check)

        /usr/sbin/postfix check

        exit $?

        ;;

  *)

        echo "Usage: postfix

{start|stop|restart|reload|abort|flush|check}"

        exit 1

esac

 

exit $RETVAL


Appendix D: mime_mail script

This script is by William Julien. Save it as mime_mail.pl.

 

#!/usr/bin/perl -w

#

# simple program to send a text message with an attachment

#

# William Julien

###

 

use strict;             # turn on the strict pragma

use Getopt::Std;        # use standard getopt to parse options

 

$/ = undef;             # turn on slurp mode

 

#

# scope local variables

#

my ($date,              # the current date

   $sendmail,          # the sendmail command

   $document,          # the document text

   %options,           # program options

   $filename,          # a file to send

   $file,              # the content of a file

   @filelist,          # list files to send

   $tolist,            # list of comma separated email addresses

   $today,             # today's date

   $usage,             # program usage

   $man,               # program man page

   $subject,           # email subject

   $extent,            # file extension

   %mime_type,         # list of supported application context mime types

   $mime_type,         # current mime application content type

   );

 

#

# variable initializations

#

$man = <<MAN;

NAME

   mime_mail

 

DISCRIPTION

   This program is a command line mailer that sends a text file

   description and one or more files in mime attachments. On success,

   mime_mail will work silently.

 

SYNOPSIS

   mime_mail -h | -d document.txt -s "mail subject"

             -u "user1 [,user2 ...]" -f "file1 [,file2 ...]"

 

OPTIONS

   -h

       Displays a man page.

 

   -d document.txt

        Sends "document.txt" in the mail message body. The file must

       be a normal text file. If a "-" is provided as an argument,

       the input will be taken from stdin. If no "-d" argument is

       supplied, the attachment will be sent with the message

       "Please see the attached.".

 

   -s "mail subject"

       Sets the mail subject. The mail subject must be quoted if the

        subject contains any spaces.

 

    -u user1,user2 ...

       A comma separated list of email addresses or aliases. Quotes

       are required if the list contains any spaces.

 

    -f file1,file2 ...

       A comma separated list of files to attach. Quotes are required

       if the list contains any spaces. The files can be of any type.

       The recognized application content types are ".doc", ".html",

       ,"htm",".xls", ".csv", ".pdf", ".rtf", and ".mdb".

 

William Julien

425-865-5511

MAN

$usage = <<USAGE;

 

Usage:

mime_mail -h | -d document.txt -s "mail subject"

         -u "user1 [,user2 ...]" -f "file1 [,file2 ...]"

USAGE

$sendmail = "/usr/sbin/sendmail";

if ( ! -f $sendmail ) {

   die "Sorry -- cannot locate sendmail at $sendmail.\nYou must edit $0\n";

}

$today = scalar(localtime());

%mime_type = ("doc"   => "application/msword",

             "txt"   => "text/plain",

             "htm"   => "text/html",

             "html"  => "text/html",

             "xls"   => "application/vnd.ms-excel",

             "csv"   => "application/octet-stream",

             "pdf"   => "application/acrobat",

             "rtf"   => "application/rtf",

             "mdb"   => "application/vnd.ms-access",

            );

 

#

# process program options

#

getopts('d:s:u:f:h', \%options) or die "$usage\n";

if ( defined $options{"h"} ) {

   print "$man\n";

   exit;

}

if ( defined $options{"f"} ) {

   @filelist = split /\,/,$options{"f"};

   foreach $file (@filelist) {

       if (! -f $file) {

           die "$0: cannot open $file\n";

       }

   }

} else {

   die "$usage\n";

}

if ( defined $options{"d"} ) {

   $document = $options{"d"};

   if ( $document eq "-" ) {

       $document = <STDIN>;

   } else {

       if ( -f $document ) {

           open F, "$document";

           $document = <F>;

           close F;

       } else {

           die "$0 error: cannot open $document\n";

       }

   }

} else {

   $document = "Please see the attached.\n";

}

if ( defined $options{"s"} ) {

   $subject = $options{"s"};

} else {

   die "$usage\nError: No Subject\n";

}

if ( defined $options{"u"} ) {

   $tolist = $options{"u"};

} else {

   die "$usage\n$0 error: no subject specified\n";

}

open MAIL, "|$sendmail -t";

print MAIL <<HEADER;

To: $tolist

Subject: $subject

Date: $today

Mime-Version: 1.0

Content-Type: multipart/mixed;

        boundary="ThisRandomString"

 

This mail was formatted with mime_mail (wmj)

 

--ThisRandomString

Content-Type: text/plain; charset=us-ascii

Content-Transfer-Encoding: 7bit

 

$document

HEADER

foreach $filename (@filelist) {

   $extent = $filename =~ /\.(\w+)$/ ? "\L$1" : undef;

   $mime_type = "application/octet-stream";

   if ( defined $extent ) {

       if ( defined $mime_type{"$extent"} ) {

           $mime_type = $mime_type{"$extent"};

       } else {

           $mime_type = "application/octet-stream";

       }

   }

    open F,"$filename";

   $file = <F>;

   close F;

   $file = encode_base64($file);

   print MAIL <<FILE;

--ThisRandomString

Content-Type: $mime_type; name="$filename"

Content-Transfer-Encoding: base64

Content-Disposition: attachment; filename="$filename"

 

$file

FILE

}

print MAIL "--ThisRandomString--\n";

#

# send the mail

#

close MAIL;

 

#

# fin

###

 

sub encode_base64

{

   use integer;

   my $res = "";

   my $eol = $_[1];

   $eol = "\n" unless defined $eol;

   pos($_[0]) = 0;                          # ensure start at the beginning

   while ($_[0] =~ /(.{1,45})/gs) {

       $res .= substr(pack('u', $1), 1);

       chop($res);

   }

   $res =~ tr|` -_|AA-Za-z0-9+/|;            # `# help emacs

   # fix padding at the end

   my $padding = (3 - length($_[0]) % 3) % 3;

   $res =~ s/.{$padding}$/'=' x $padding/e if $padding;

   # break encoded string into lines of no more than 76 characters each

   if (length $eol) {

       $res =~ s/(.{1,76})/$1$eol/g;

   }

   return $res;

}

 

 

Appendix E: Upgrading the Server’s Software

Upgrading the server’s installed software should be done carefully. You should always read the release notes of the updated application, and see if you even need to upgrade:

Is it solving a problem that you currently have?

 

You should also ask yourself another question: Did the configuration files change?

This usually happens with new major releases. You don’t want to upgrade without reading about all the changes first.

 

You may also want to create a duplicate server first, and test the upgrade procedures on it. I usually use virtual machines to do just that.

 

If you came to the conclusion that you want to upgrade the server, run the backup-files script first, see that you got the current configuration to your e-mail, and then follow these procedures to upgrade each of our installed applications:

 

Postfix

Download the most recent version, and put it under /usr/local/src/:

cd /usr/local/src/

wget ftp://ftp.midvalleyhosting.com/pub/postfix/official/postfix-#.#.#.tar.gz

 

Now extract the source:

tar xzvf postfix-#.#.#.tar.gz

 

Change to the extracted directory:

cd postfix-#.#.#

 

And then issue these commands:

postfix stop

make

make upgrade

postfix start

 

SpamAssassin

Start by backing up the local.cf, and init.pre files under /etc/mail/spamassassin/.

It’s probably best to run the backup-files script, since it’ll grab all of the *.cf files under the above folder.

You can then issue the yum install spamassassin command, or simply follow the instructions in the SpamAssassin section above, to compile from source. Both worked for me, and whatever method you choose: stick with it throughout the life time of your server.

Amavis

Start by stopping Amavis. Then, follow the instructions outlined above on how to install Amavis. Note that you should skip the step that copies amavisd.conf to /etc/. You already have an amavisd.conf file there!

 

Make sure to read the release notes carefully. In most cases, your current amavisd.conf file will be just fine, and all you’ll have to do is upgrade the amavisd executable. Again, the key is to read the release notes. During the creation of this document, I successfully upgraded from v2.3.0 to v2.3.2 without any problems.

 

Razor

To upgrade Razor, simply download the new version and the SDK from Razor’s website, and then follow the instructions for installing Razor as they are outlined above. During the creation of this document, I successfully upgraded from v2.72 to v2.74 without any problems. Note that when a new major release comes out, such as 3.0, you will need to read the installation instructions carefully, since some file may have changed. Remember to restart amavisd when you’re done: amavisd reload.

 

Pyzor

Coming Soon

 

DCC

The following procedure was used to upgrade from v1.3.5 to v1.3.12. Since it wasn’t a major version change, there were no changes to the config file, however, you should always read the release notes and see what has changed.

 

I started by backing up my configuration.

I downloaded the latest DCC install and extracted it under /usr/local/src.

Then, I ran cdcc -V to see the version number. CTRL+C got me out of the cdcc prompt.

I issued amavisd stop, and then service cdcc stop.

I changed into the directory where DCC was extracted to, and ran the configure, make, and make install commands as specified in the DCC installation section above.

 

Just for the heck of it, I ran cdcc info, to see if the local servers that were removed when I installed the previous version, are still removed.

They were not showing, but I decided to run the cdcc "delete 127.0.0.1" command anyway, and got an error: entry not found. I now knew for sure that the two local servers are not there.

 

I checked the config file, but it didn’t change, as expected.

 

The dccifd daemon changed, so I ran the copy command to overwrite the old version with the new one:

cp /var/dcc/libexec/rcDCC /etc/init.d/DCC

 

Then, I made sure that the amavis user and group have full access to the DCC directory:

chown -R amavis:amavis /var/dcc

 

I issued the amavisd debug-sa command, and saw: DCC: got response.

 

I then restarted the dccifd daemon and amavisd:

service DCC start

amavisd start

ClamAV

I have done the following to upgrade successfully from v0.86.1 to v0.86.2. Please note that with major version changes, you may need to do more things.

It’s always a good thing to read the release notes, and in this case there were no changes to any of the config files, but if there are, you should learn about them.

 

I started by backing up my configuration.

I grabbed the new install, and extracted it, just like the ClamAV installation section above states.

After stopping amavisd (amavisd stop), I killed clamd (socat - /tmp/clamd, and then QUIT).

I ran the configure, make, and make install commands as stated above, in the ClamAV installation section.

I restarted clamd.

After running amavisd debug, I saw that my installation was successful.

Running socat - /tmp/clamd, and then issuing VERSION, confirmed that I’m on v0.86.2.

Running freshclam -V confirmed that I’m on v0.86.2 as well.

I then quit debug mode, and ran amavisd again (amavisd start)

 

Please also read the following page: http://wiki.clamav.net/index.php/UpgradeInstructions.

Although the recommended instructions at the bottom were not fully followed by me, I found them to be a very good guideline.


Revisions to this Document

Date

Version

Details

June 29, 2005

2.0

Initial release (based on FC3 v1.4)

July 5, 2005

2.1

Lots of changes and additions. Some rewrites and corrections.

Thanks for all your comments.

July 10, 2005

2.1.1

Minor spelling and punctuation errors fixed.

July 17, 2005

2.1.2

Minor typos and corrections.

 

Changed the backup script so that DCC’s configuration is backed up too.

 

Add a change to local.cf so that scores and their values are shown in the mail header. Very good for debuggin score values.

 

Fixed an error copying LINUX2 to /usr/local/sbin/

 

Fixed an error under the definition of “relay_domains” of main.cf: “mydestination” replaced with “mydomain”

 

Fixed an Error where “chown” was followed by “-r” instead of “-R”

 

Fixed explanation of ‌“‌@bypass_banned_checks_maps = (1);”

 

Fixed a “chown” line that was supposed to be “chown -R”

July 18, 2005

2.1.3

Fixed some grammar

 

Fixed missing tar line under the zlib installation phase

July 19, 2005

2.1.4

Fixed the line that copies clamd to /etc/init.d/

 

Added a statement regarding possible false-positives when using reject_non_fqdn_hostname

 

Added a better explanation as to how to copy the script from Appendix D to the server

 

Added a new section for testing the mail server using Firewall changes, as well as Outlook Express

August 1, 2005

2.1.5

Added a section about upgrading ClamAV

 

Added a section about upgrading DCC

 

Added a warning about the “\” in front of the “$” in some postconf lines.

 

Added a warning about underscores that are sometimes not printed

August 4, 2005

2.1.6

Various corrections and fixes as I was going through the document and installing a new server from scratch.

 

Added installation of SHA1 during SpamAssassin’s install

 

Added a whole new Address Verification section

 

Updated Gmail’s mail servers

October 13,2005

2.1.7

Changed the section that talks about making Postfix run automatically at boot time, where the script didn’t work well. This is easily fixed with the dos2unix command.

 

Razor is now extracted with “tar xjvf”.

 

Added a new section to both Razor’s and DCC’s installation sections, showing how to re-enable them after the change in the license agreement forced the SpamAssassin team to disable them by default on v3.1.x.

 

Changed the backup script to backup crontab, mime_mail.pl, and the rules_du_jour executable.

 

Minor changes and corrections.

December 13, 2005

2.18

Added a warning about the inaccessibility of vi in case of a system crash, to the area of the document that discusses making vi show in color.

 

Added a comment about Exchange 2000 to the address verification section.

 

 

To Do:

1.      Upgrade procedure for Pyzor.

 

Thanks

Thanks to Mr88talent for debugging the document for me, and finding so many of the errors!

Thanks also to DaveD, www.freespamfilter.com’s moderator and owner for hosting this doc.

And last but not least, to all of you out there who use this document, and give your nice (mostly) comments.

 

-RoNNY