Tutorial Debian Etch

Post on 26-Oct-2014

39 views 0 download

Tags:

Transcript of Tutorial Debian Etch

Index Page 1 Page 2

Create Debian Installer CDDebian InstallationPuTTY, additional programs and aptCreate Firewall RulesInstall MySQLInstall programs that use SSL certificatesCreate and install SSL CertificatesEnable php in apache-sslInstall and configure phpMyAdminPerform some preliminary Postfix configurationInstall SquirrelMail softwareInstall and configure PostfixAdmin and maildropConfigure SASL and TLSInstall and configure amavisd-new

Create Bayes and AWL tables in MySQLConfigure and customize SquirrelMailConfigure RazorInstall pflogsummInstall BINDAdditional Postfix configurationSet up PostfixAdmin VacationInstall postfixadmin SquirrelMail pluginInstall MailZuQuotaInstall Mailgraph - OptionalInstall mysql-zrmThe alias issueActing as a relay server

You don't want to loose mail due to a failed hard drive. I suggest using software or hardware RAID1 (I provide aseparate software RAID1 howto). I am not going to install a GUI when I install Debian, so during installation "Standardsystem" will be the only package group I select. In other words, I will not select "Desktop environment". This is a copyand paste document. You need to save all three pages of this document to your computer then edit this page anddo a search and replace of certain items in order to customize it for your server. Open this saved document inWordPad, a plain text HTML editor or other similar text editor that will not modify the HTML code and read theinstructions at the top of the document. The instructions will point you to some items that should be changed. Note thatonce this document is edited to match your preferences, there will be passwords in this document. Please take steps tosecure your copy of this document. Once edited, make backup copies of all three pages to a CD or floppies or at least toa different directory. Don't make the same mistake I have made a couple times by editing this page and thendownloading another fresh copy and overwriting it. I personally find that when selecting a block of text it is easier to startat the bottom and work up rather than starting at the top and working down.

Without going into much detail about hardware requirements I can tell you that the biggest problem you will face is howlong it takes to scan a message for spam and viruses. On a powerful computer on a wide Internet pipe it typically takesaround 5 seconds. On a lower powered machine (like an older P4 2.0Ghz single processor) on a narrower pipe (like a T1), it can take 20 or 30 seconds. However, you control the number of concurrent spam scanning processes. Theoreticallyyou add more processes for greater throughput. The problem is, each process takes a considerable amount of CPUpower and RAM. If you incrementally add processes, at some point your server will grind to a halt - most likely due toswap thrashing. That said, your server should have a minimum of 1GB RAM. Mark Martinec wrote a paper that illustratesthe capacity of a single moderately powerful dual processor machine http://www.ijs.si/software/amavisd/amavisd-new-magdeburg-20050519.pdf. Mailscanner is a product similar to amavisd-new. Here are some samples of servers used withMailscanner: http://wiki.mailscanner.info/doku.php?id=maq:index#setup_examples. Note that these examples are usingolder (less CPU intensive) versions of SpamAssassin. Also note that on this server you will have the significant additionaloverhead of Apache, MySQL and Courier. If you want to install intrusion detection (I use an older version of AIDE) youwill need a floppy drive. I have to warn you, the company I work for only has about 50 mail users, so this has not beentested on a large scale. This setup has only been tested using the en_US locale.

Create Debian Installer CD:Index Top Bottom

Make a new directory on your Windows computer and call it 'debian' or something. Then download the latest versionof the Debian installer for 'etch' and save it there. Go to: http://www.debian.org/releases/etch/debian-installer/. Readthe errata while you are on that page. One interesting errata is http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=401435.

Note that there are etch 4.0r3 i386 or etch 4.0r3 ia64 or etch 4.0r3 amd64 CDs available from this location butunfortunately I have only tested this setup using the i386 CD (32bit). By default it installs the Linux kernel version2.6.18.

Debian Installation:Index Top Bottom

Information on the Debian Installer is located at http://d-i.alioth.debian.org/manual/en.i386/apa.html

If using RAID1, you should have both drives installed. We are going to erase the hard drive so make sure you don'thave any data on it you might need. You may have to change the order of boot devices in your BIOS before we begin.Boot up the computer using the Installer CD or the Installer floppy #1. If you use the floppy to boot up, it willprompt you for remaining floppies. I recommend the CD-ROM. The instructions below pertain to the CD-ROM methodin the default "ask as few questions as possible" mode. Set the correct date and (local) time in the BIOS before youstart. When the system boots up to the Debian screen, simply press [Enter] at the boot: prompt.

[ !! Choose Language]This determines the language of the installer and picks a keyboard.This installation has only been tested with English - English[Choose country, territory or area]Choose what is appropriate

Unplug the ethernet cable.

[! Select a keyboard layout]American English selects a standard qwerty keyboard.

There will be a few screens of activity, then this will come up:[Configuring the network with DHCP]Hit [Cancel] because we want DHCP configuration to fail.

Plug the ethernet cable back in.

[!! Configure the network]Network autoconfiguration failed

We wanted that to happen, simply press:[Continue]

On the next screen, choose the default of:[Configure network manually]

[!! Configure the network]Make sure Num Lock is on![IP address:]111.111.111.111[Netmask:]255.255.255.x[Gateway:]333.333.333.333[Name server addresses:]444.444.444.444 555.555.555.555[Hostname:]msa[Domain name:]example.com

For partitioning hard drives, I am going to use software RAID1. I suggest using a pair of 320GB or larger hard drives.Another possibility is using four drives and allocating an entire pair of drives to the mail store: /var/vmail. See: http://www200.pair.com/mecham/raid/raid1.html

[! Configure time zone][Select your time zone:]Simply choose what is appropriate.

[!! Set up users and passwords]This will ask for root's password and allow you to create a "normal" user and a password for that user. Watch your[Num Lock] status. Use really good passwords and don't forget them. Please add one, and just one, normal userhere. If you plan on storing mail locally on this machine (not documented here), or even if you don't, create a userwho's main purpose in life might be to hold root's mail. I suggest calling the user myroot or something similar.

Keep in mind that all the best hacker tools run on Linux. If a hacker gains root access to this box, your entire network ishistory.

[Installing the base system]Wait....

[! Configure the package manager][Use a network mirror?]Choose [Yes][Debian archive mirror country:]Choose your country[Debian archive mirror:]Choose a mirror near you (mirrors.kernel.org works very well in the US)[HTTP proxy information](configure if needed, otherwise leave unconfigured)

Scanning the mirror...

[! Configuring popularity contest]You decide if you would like participate.

[Debian software selection][Choose software to install:]You only want to select 'Standard system' here (nothing else). Use the space bar to deselect 'Desktop environment'then simply [Tab] over and select [Continue].

Software will download now. I hope you have a fast Internet connection. What software we don't have now, we can easilyget later. We are trying to keep this system somewhat clean. We will use apt-get to install most software after the fact.Some software may also be upgraded, and as a result, you may be asked some questions. When asked a question,usually the default answer will be the correct answer.

This section should not show up, but just in case it ever does:

[Configuring console data]IMPORTANT! choose "Don't touch keymap"

This should not come up either, but in case it does:

[Configuring Exim v4 (exim4-config)]

[General type of mail configuration:]choose [no configuration at this time][Really leave the mail system unconfigured?] [Yes]

[Root and postmaster mail recipient:]The "normal" user we added earlier will display here. This is fine, so simply accept this. All of root's mail will beredirected to this "normal" user's mailbox. This is necessary because you typically cannot access root's mailboxremotely.

[! Install the GRUB boot loader on a hard disk][Install the GRUB boot loader to the master boot record?]If you would like the install the (recommended) GRUB boot loader choose [Yes]If you would like the install the LILO boot loader [Tab] over and select [Go Back]Then select the 'Install the LILO boot loader...'[Finish the installation]Remove the CD or floppy when prompted, then hit [Continue] This will reboot.

Once the system is installed, login as root and issue the following command:apt-get install ntpdate ssh vim

It may ask you to insert the installation CD; do so, then please remove it afterwards.

PuTTY, additional programs and apt:Index Top Bottom

I will now turn off the monitor and head on over to my trusty old Windows computer. I am going to configure everything else from there.

You should have this document open in a window on your Windows computer because we are going to use the WindowsSSH client PuTTY to operate our server remotely. We are going to save a lot of typing because you are going to selecttext with the mouse, copy it to the clipboard with [Ctrl]+c and then paste it into the PuTTY window with a right-click of themouse. Also, simply highlighting text in the PuTTY window copies that text to the clipboard.

Place putty.exe on your desktop, open it up, select SSH, input the IP address of the server then enter a name for yoursession in the Saved Sessions box. In the Category window, expand Terminal and click on Features. Check the box"Disable application keypad mode". Just below this in the Category window, click on Window, and increase "Lines ofscrollback" from 200 to 800. click on Session (at the top), then Save. The "Disable application keypad mode" enables usto use the numeric keypad when using vi.

When you use PuTTY again, simply double click on the saved session. Make sure you are at a command (shell) promptbefore exiting PuTTY. You can log out of the bash shell (and hence close the the PuTTY window) by issuing thecommand 'logout' or 'exit' or [Ctrl]+d.

Note.Your [Home] and [End] keys will work when editing a file using vi, but will not work at the command prompt (you can use[Ctrl]+a and [Ctrl]+e for this).

Open up a PuTTY session now and log in as root.

This would be a good time to also download and install WinSCP. WinSCP is a great GUI file browser that lets youtransfer files between your Windows machine and your new Debian box. You can also edit files on your Debian box fromyour Windows machine using WinSCP's editor. I suggest when you save sessions you leave the password blank so youare prompted for it each time you log in.

We are going to use vi (vim actually) to do most of our editing. Fortunately we only need to learn a few commands to beable to accomplish our tasks. There are 3 operating modes in vi. There is the "Command" mode, the "Write" mode andthe "Command line" mode. When you first open a file for editing, you are in Command mode. You change to Write modeby entering the letter "i", (short for "insert"). You can edit text pretty much as you would expect in Write mode. You exitout of Write mode and return to Command mode by hitting the [Esc] key. There are many commands that can be learnedin Command mode but we only need to learn two more in addition to "i". Those commands are ":" (a colon) and "/" (aforward slash). The colon is used to enter the third mode, the Command line mode and the slash enables the Searchcommand. When you are in Command line mode, you will see a colon at the bottom of the screen. Here is a list ofcommands we will use while in Command line mode:

:q quit (provided you have not made any changes) By the way, the lower case q is used often in *nix as a way to exit ascreen.:q! exits vi and discards changes (great when you trashed the file and just want to start over!):wq saves the changes and exits vi (write and quit)

:w saves the current changes but does not exit vi (write)And in command mode:G The capital "G" Goes to the bottom of the page (very handy)

And here is how the Search command works:/text_to_search_for moves the cursor to the first occurrence of text_to_search_for

Once the first occurrence of the text we searched for is found, use a lower case 'n' to find the next occurrence.

That's all we need to know for now! The biggest mistake you will make at first is you will forget to hit "i" (to enter insertmode) before you paste stuff into a document.If you would like a cheat sheet for additional commands: http://www.fprintf.net/vimCheatSheet.html and http://amath.colorado.edu/computing/unix/vi/

Set the system clock:

ntpdate clock.fmt.he.netntpdate ntp1.tummy.com

Enter the following command:dpkg-reconfigure locales

[Configuring locales]You use [PgUp] [PgDn] [up-arrow] [down-arrow] [tab] and [spacebar] to navigate and select.The etch installer software installed en_US.UTF-8 UTF-8 on my system. I suggest you install the en_US ISO-8859-1locale (in addition to any other ISO-8859-x locales you may require). If you need to change the locale, or addadditional locales, use the [arrow] [spacebar] and [tab] keys. An UTF-8 locale should not be used as the defaultsystem LANG (set in /etc/environment or /etc/default/locale), SpamAssassin and amavisd-new may have problems ifyou do. However, you should keep the UTF-8 locale in addition to the ISO-8859-x file or Perl may complain.

[Which locale should be the default in the system environment?]I suggest you do NOT choose [None], I suggest you choose [en_US] or other non UTF-8 locale (an ISO-8859-xlocale).

Our default language is currently an UTF-8 locale. We want our system wide language to be an ISO-8859-x (non UTF-8) locale. You can set the language in /etc/environment (if it exists, otherwise it is set in /etc/default/locale). This file isread when we log in. We need to use a non UTF-8 locale so characters will appear as we expect them to and to avoidother problems. It is best to run amavisd-new in a non-UTF8 locale environment. The 'dpgk-reconfigure locales'program previously automatically updated /etc/environment, but it no longer does when using the etch version so weare going edit it manually (it now updates /etc/default/locale). Make sure you have installed a corresponding ISO-8859-x locale for the UTF-8 locale we are going to change:cat /etc/environment

If the above returns "No such file or directory", then the setting is in /etc/default/locale and you can skip editingthis file, otherwise please continue.vim /etc/environment

Change LANG from a UTF-8 setting:LANG="en_US.UTF-8"

to a non UTF-8 setting:LANG="en_US"

Save and exit the file: [Esc]:wq to 'write and quit' or [Esc]:q to quit without saving (so you can give it another try).Note: you can run the command locale to see the current settings. It is best to reboot after changing the /etc/environment file. Changes are not recognized until you at least log out, then back in.

There is an errata dealing with tcp_window_scaling on Linux kernel 2.6.17 (and newer).http://kerneltrap.org/node/6723 http://marc.info/?l=postfix-users&m=117457942431349 You may want to considerwhat may happen (large files fail to transfer between systems) when there is a buggy router between you and

someone else, and may wish to make this change to the system (you decide):echo "net.ipv4.tcp_wmem = 4096 65536 65536" >>/etc/sysctl.confecho "net.ipv4.tcp_rmem = 4096 65536 65536" >>/etc/sysctl.confsysctl -p

I am going to assume this may slow down communications between systems under certain circumstances.

Our default system editor will be nano, and not vim. I will change my default system editor to vim:

vim /root/.profile

and just below the line "fi" insert this entry:export EDITOR=/usr/bin/vim.basic

Save and exit the file: [ESC]:wq

vim /etc/apt/sources.list

At this point, the contents of the file may look something like this:

## deb cdrom:[Debian GNU/Linux testing _Etch_ - Official Snapshot i386 Binary-1 (20061111)]/ etch main

deb cdrom:[Debian GNU/Linux testing _Etch_ - Official Snapshot i386 Binary-1 (20061111)]/ etch main

deb http://mirrors.kernel.org/debian/ etch maindeb-src http://mirrors.kernel.org/debian/ etch main

deb http://security.debian.org/ etch/updates maindeb-src http://security.debian.org/ etch/updates main

We need to modify this file so the result will look something like this:(with only the http server unique to your particular system)

deb http://mirrors.kernel.org/debian/ etch main non-free contribdeb-src http://mirrors.kernel.org/debian/ etch main

deb http://security.debian.org/ etch/updates main non-free contribdeb-src http://security.debian.org/ etch/updates main

deb http://volatile.debian.org/debian-volatile etch/volatile main

Note what I have done here. Any lines that use the cdrom#deb cdrom:[Debian GNU/Linux testing _etch_

have been erased and the words "non-free" and "contrib" have been added. Debian Volatile has also been added.

You will have to add the current Volatile gpg key. Note that if you are unable to retrieve the key from subkeys.pgp.net itmight be an indication of some sort of firewall or proxy issue. I personally have a proxy that gives me problems so I workaround it by using another gateway (see /etc/network/interfaces). I have a feeling my proxy does not proxy this protocolproperly. If that is also the case with you, you may end up having problems with other programs such as the DCC client:

gpg --keyserver subkeys.pgp.net --recv-key BBE55AB3gpg --armor --export BBE55AB3 | apt-key add -

You must run apt-get update next.

apt-get update

You should also make sure the system is up to date.

apt-get upgrade

If the kernel is upgraded:

reboot

For security reasons I remove some programs. My server will not need the pident service or provide shared disk space.

apt-get remove nfs-common pidentd portmap

If you are using a multi-processor machine, then use a multi-processor kernel. To locate available smp kernels foretch, you could run:apt-cache search linux-image | grep smp | grep linux-image

If you are running a 2.6.18 (etch) kernel, and have a dual core Intel system, you could for example use the 'linux-image-2.6-686-smp' kernel. You would pick the kernel that most closely matches your system (and your current kernel). To install it, you would simply run (for example):apt-get install linux-image-2.6-686-smp

If you installed a new kernel, please reboot afterwards.

There is a problem I describe here. Here I attempt to fix it:apt-get install yaird

apt-get remove initramfs-tools

KERNEL=`uname -r`cp /boot/initrd.img-$KERNEL /boot/initrd.img-$KERNEL-backupmv /boot/initrd.img-$KERNEL /boot/initrd.img-$KERNEL-backup2yaird --output=/boot/initrd.img-$KERNEL $KERNELls -l /boot

Make sure it shows you have a good initrd.img that matches the other stuff:

-rw-r--r-- 1 root root 70781 2007-05-09 16:14 config-2.6.18-4-686drwxr-xr-x 2 root root 4096 2007-06-10 09:25 grub-rw------- 1 root root 1135592 2007-06-19 20:15 initrd.img-2.6.18-4-686-rw-r--r-- 1 root root 4490534 2007-06-19 20:14 initrd.img-2.6.18-4-686-backup-rw-r--r-- 1 root root 4490534 2007-06-10 09:25 initrd.img-2.6.18-4-686-backup2-rw-r--r-- 1 root root 722037 2007-05-09 22:14 System.map-2.6.18-4-686-rw-r--r-- 1 root root 1261213 2007-05-09 22:14 vmlinuz-2.6.18-4-686

Then reboot:rebootexit

Create Firewall Rules:Index Top Bottom

On my system I try to keep as much traffic as possible between this machine and my users encrypted, so I don't openport 80. I will configure my clients to use 443 (apache-ssl), 993 (courier-imap-ssl) and 995 (courier-pop-ssl) wheneverpossible. I also limit access to ssh to my local network.

DO NOT USE AS IS, CHANGE NETWORK ADDRESS FIRST IF YOU HAVE NOT ALREADY DONE SO:You can copy and paste this whole section to the shell prompt:

iptables -Fiptables -N FIREWALL

iptables -F FIREWALLiptables -A INPUT -j FIREWALLiptables -A FORWARD -j FIREWALLiptables -A FIREWALL -p tcp -m tcp --dport 25 --syn -j ACCEPTiptables -A FIREWALL -p tcp -m tcp --dport 110 --syn -j ACCEPTiptables -A FIREWALL -p tcp -m tcp --dport 143 --syn -j ACCEPTiptables -A FIREWALL -p tcp -m tcp --dport 443 --syn -j ACCEPTiptables -A FIREWALL -p tcp -m tcp --dport 465 --syn -j ACCEPTiptables -A FIREWALL -p tcp -m tcp --dport 587 --syn -j ACCEPTiptables -A FIREWALL -p tcp -m tcp --dport 993 --syn -j ACCEPTiptables -A FIREWALL -p tcp -m tcp --dport 995 --syn -j ACCEPTiptables -A FIREWALL -p tcp -m tcp --dport 4650 --syn -j ACCEPTiptables -A FIREWALL -p tcp -m tcp -s 222.222.222.222/24 --dport 22 --syn -j ACCEPTiptables -A FIREWALL -i lo -j ACCEPTiptables -A FIREWALL -p udp -m udp --sport 53 -j ACCEPTiptables -A FIREWALL -p tcp -m tcp --sport 53 -j ACCEPTiptables -A FIREWALL -p udp -m udp --dport 123 -j ACCEPTiptables -A FIREWALL -p udp -m udp --sport 6277 -j ACCEPTiptables -A FIREWALL -p udp -m udp --sport 24441 -j ACCEPTiptables -A FIREWALL -p tcp -m tcp --syn -j REJECTiptables -A FIREWALL -p udp -m udp -j REJECTiptables-save > /etc/firewall-rulesiptables-restore < /etc/firewall-rules

This will write the firewall rules to a file on this server, but iptables starts with an empty rule set each time the computerrestarts. The rule set I saved to /etc/firewall-rules must be "loaded" into iptables every time the system starts up.

I am going to insert the command to configure iptables into a file that starts up the network interfaces when the systemboots up:

vi /etc/network/interfaces

And insert the following text in the blank line just below "iface lo inet loopback":pre-up iptables-restore < /etc/firewall-rules

While you are at it, 2 lines down, change allow-hotplug eth0 to:auto eth0

Save and exit the file, then reboot:rebootexit

If you have problems accessing the system after it boots up, enter the command iptables -F from the console toclear out iptables. This will allow you another shot at it.

Install ntp, a c compiler, logcheck and some other stuff:

apt-get install ntp make gcc bison flex libc6-dev logcheck logcheck-database flip psmisc dpkg-dev

For more information about logcheck rules and patterns to include or ignore:vi -R /usr/share/doc/logcheck-database/README.logcheck-database.gz

and to debug logcheck:su -s /bin/bash -c "/usr/sbin/logcheck -otd" logcheck

Install MySQLIndex Top Bottom

apt-get install mysql-server

Out of the box MySQL is tuned for a system with very little memory. We need to allocate more memory for cachingitems. This will make a huge difference in performance. We are going to change all tables to InnoDB so we will adjustsome InnoDB settings. If you currently have data in MySQL or you have made changes to /etc/mysql/my.cnf youshould not perform these steps to replace your my.cnf file with mine! Also, I am assuming you have at the very

least 1GB of physical memory installed (2GB recommended - 3GB even better):cp /etc/mysql/my.cnf /etc/mysql/my.cnf-originalzcat /usr/share/doc/mysql-server-5.0/examples/my-medium.cnf.gz > /etc/mysql/my.cnfcd /etc/mysql/wget http://www200.pair.com/mecham/spam/my-medium.cnf.patch.txtpatch my.cnf < my-medium.cnf.patch.txt/etc/init.d/mysql restart

Add a password for user 'root' (make sure the hostname is correct):mysql -u root

From the mysql> prompt, create the two passwords required for root (bold text items need to be replaced with yourpersonal settings - you should have edited this document already):SET PASSWORD FOR 'root'@'localhost' = PASSWORD('roots_password');SET PASSWORD FOR 'root'@'msa' = PASSWORD('roots_password');FLUSH PRIVILEGES;SHOW VARIABLES LIKE 'innodb_fast_shutdown';

Make a mental note of the innodb_fast_shutdown setting. The default is "1". Quit mysql:QUIT

Since my patch changed the size of innodb_log_file_size, we will have to create new logs. If innodb_fast_shutdownwas something other than "1", edit /etc/mysql/my.cnf and add an entry "innodb_fast_shutdown = 1" and then restartmysql with "/etc/init.d/mysql restart". Once innodb_fast_shutdown = 1 then:/etc/init.d/mysql stop

Make sure that it shuts down without errors (to ensure that there is no information for outstanding transactions in thelogs). Then:mv /var/lib/mysql/ib_logfile0 /var/lib/mysql/iblogfile0-oldmv /var/lib/mysql/ib_logfile1 /var/lib/mysql/iblogfile1-old/etc/init.d/mysql startls -l /var/lib/mysql/ib_*

It should show our two log files are now 48MB in size (50331648). I have set "innodb_buffer_pool_size = 192M" whichwill give much better performance than the default of 8M, and "innodb_log_file_size = 48M" which is 25% of theinnodb_buffer_pool_size. If you have plenty of RAM, you can increase innodb_buffer_pool_size even more, butpersonally I would not set it to more than 25% of physical RAM. You may need the extra space for a polar bear ordung beetle.

Install programs that use SSL certificatesIndex Top Bottom

The next command goes on one line. Before you issue this command, read the paragraph following it.apt-get install apache-ssl libapache-mod-php4 php4 php4-common php4-mysql php4-gd php4-mcryptmcrypt ca-certificates openssl

You will be asked questions. Sample answers follow. Be sure to use the full name for your state or province name andthe host name must be the FQDN host name of this machine (however, the certificate created here will soon bereplaced):Country Name USState or Province Name UtahLocality Name Salt Lake CityOrganisation Name Widgits Inc.Organisational Unit Name WebMail ServerHost Name msa.example.comEmail Address postmaster@example.com

Actually, that was just practice. We are not going to use the certificate we just created. Do not browse to the webserver yet. At least, DO NOT install the certificate. Now install Postfix:apt-get install postfix postfix-pcre postfix-mysql libsasl2-modules-sql libsasl2-modules

Answer the questions:General type of configuration? Internet SiteMail name? example.com (edit this so only the domain name is used here)

apt-get install courier-imap-ssl courier-pop-ssl courier-authlib-mysql

Create directories for web-based administration ? [No]

Create and install SSL CertificatesIndex Top Bottom

Every client that connects to this server will need to be able to resolve the hostname of the server. Add an entry toyour hosts file or add an A record to your DNS server so we can properly interact with the server. We are going to beour own Certificate Authority and sign our own certificates. These commands are dependent on /etc/ssl/openssl.cnf assupplied by Debian. We start by making a small change to /etc/ssl/openssl.cnf. We make it so by default ourcertificates are good for 10 years instead of 1:sed -i 's/= 365\t/= 3653\t/' /etc/ssl/openssl.cnfgrep 365 /etc/ssl/openssl.cnf

We will set up a common place to put our certificates:cd /rootmkdir CAcd CAmkdir demoCAcd demoCAmkdir newcertsmkdir privateecho '01' > serialtouch index.txtcd ..

Create a Root Certificate:openssl req -new -x509 -extensions v3_ca -keyout demoCA/private/cakey.pem -out cacert.pem -days3653

Enter a passphrase when prompted. You will need this passphrase in the future. What I mean is: make it unique anddon't ever loose it. You will be asked questions. Sample answers follow. Be sure to use the full name for your state orprovince name and the Common Name should be something that describes you as an authority (like Widgits Inc.RootCA):Country Name USState or Province Name UtahLocality Name Salt Lake CityOrganisation Name Widgits Inc.Organisational Unit Name WebMail ServerCommon Name (eg, YOUR name) Widgits Inc. RootCAEmail Address postmaster@example.com

This process produces two files as output: a private key in demoCA/private/cakey.pem and a root CA certificate incacert.pem. Any and all key files we produce will need to be protected from unauthorized persons reading them, andmust not be lost for the next 10 years. Also realize that the CA you created can sign any number of certificates (until itexpires 10 years from now) so you only need to (or want to) create the CA once. We will copy our cert and our key tosomething more descriptive:cp -i demoCA/private/cakey.pem demoCA/private/cakey.example.com.pemchmod 600 demoCA/private/*cp -i cacert.pem cacert.example.com.pemcp -i cacert.pem cacert.example.com.crt

The cacert.example.com.pem and cacert.example.com.crt are copies of our certificate and are the files that can bedistributed and installed on the client's machines. Windows clients would use the .crt file. On my Windows 2000system, double clicking this file would install it in Internet Explorer (which is exactly what want). Simply browsing to ourserver will give us the opportunity to install the web server certificate we will create (this will be the Common Namemsa.example.com) but this is not the same as installing the CA certificate in the Trusted Root Certification Authoritiesstore (seen as the Common Name you entered above). Just in case you are not familiar, in IE6 it's Tools->InternetOptions->Content->Certificates->Trusted Root Certification Authorities. Outlook and Outlook Express use the samecertificate store as Internet Explorer. In Mozilla Thunderbird it's Tools->Options->Privacy->Security->View Certificates->Authorities. In Firefox it's Tools->Options->Advanced->Encryption->View Certificates->Authorities->Import. If you gothrough this process more than once while testing, don't install duplicate certificates. Delete any old 'test' certificate youpreviously installed before adding your new one that replaces it. In my old version of The Bat! I add a new contact inthe "Trusted Root CA" section of the address book and import the certificate from there. I suggest using WinSCP to

transfer the cacert.example.com.crt certificate to your machine. I think the worst part of getting this server set up isgetting the CA certificates installed on the clients. Sometimes it's worth it to buy a certificate from a well knowncommercial CA that is already in the Trusted Root Certification Authorities store.

We are now going to create a request for a certificate from the CA (which is us - but could be a commercial CA if youlike). Everyone that connects to us will connect to the hostname of this machine. The Secure Web server, SecureIMAP server, Secure POP server and Postfix Secure SMTP server will all be msa.example.com, so the CommonName MUST BE our FQDN hostname when we create the request. The Organization name needs to be the sameas the one in the CA cert. Do not enter your email address, challenge password or an optional company name whengenerating the CSR:openssl req -new -nodes -out req.pem

Country Name USState or Province Name UtahLocality Name Salt Lake CityOrganisation Name Widgits Inc.Organisational Unit Name WebMail ServerCommon Name (eg, YOUR name) msa.example.comEmail Address

This process produces two files as output, a private key in privkey.pem and a certificate signing request in req.pem.These files should be kept. The private key is of course necessary for SSL encryption. We will make backup copies ofthese files with more descriptive names:cp -i privkey.pem privkey.msa.example.com.pemchmod 600 privkey.*cp -i req.pem req.msa.example.com.pem

Sign the Certificate (you will be asked for the pass phrase):openssl ca -out cert.pem -cert cacert.pem -infiles req.pem

This process updates the CA database and produces two files as output, a certificate in cert.pem and a copy of thecertificate in demoCA/newcerts/ named xx.pem, where xx is the serial number. We will copy the cert to a moredescriptive name. The certificate has both the encoded version and a human-readable version in the same file. Wewant to strip off the human-readable portion as follows:mv -i cert.pem temp.cert.msa.example.com.pemopenssl x509 -in temp.cert.msa.example.com.pem -out cert.pemcp -i cert.pem cert.msa.example.com.pem

Postfix will want the cert and the key in two separate files, apache-ssl will want the two combined (but can use twoseparate files if configured to do so). Courier will want the two combined, with a Diffie-Hellman code block added.Sheesh, why can't we all just get along?cat privkey.msa.example.com.pem cert.msa.example.com.pem >key-cert.pemcp -i key-cert.pem key-cert.msa.example.com.pemcp -i key-cert.pem key-cert-dh.msa.example.com.pem

openssl gendh >> key-cert-dh.msa.example.com.pemchmod -R 600 /root/CA

After those steps, you have four installable components (and some more descriptive backup copies):A private key in privkey.pem (with a copy in privkey.msa.example.com.pem)A certificate in cert.pem (with a copy in cert.msa.example.com.pem)A combined private key and certificate in key-cert.pem (with a copy in key-cert.msa.example.com.pem)A combined private key, certificate and DH code in key-cert-dh.msa.example.com.pem

Now give a copy of the combined certificate to apache-ssl. Apache-ssl is currently using the /etc/apache-ssl/apache.pem certificate (the SSLCertificateFile setting in /etc/apache-ssl/httpd.conf). We will reconfigure it to use /etc/apache-ssl/key-cert.msa.example.com.pem:/etc/init.d/apache-ssl stop/etc/init.d/apache-ssl start

cd /root/CA/cp key-cert.msa.example.com.pem /etc/apache-ssl/chmod 600 /etc/apache-ssl/key-cert.msa.example.com.pemsed -i 's/apache.pem/key-cert.msa.example.com.pem/' /etc/apache-ssl/httpd.conf/etc/init.d/apache-ssl stop

/etc/init.d/apache-ssl start

Give Postfix the files it needs and tell it where they are (and set a couple other TLS parameters). We also make abackup of main.cf before we modify it for the first time:cp -i /etc/postfix/main.cf /etc/postfix/main.cf-24jul2007

mkdir -p /etc/postfix/sslcp privkey.msa.example.com.pem /etc/postfix/sslcp cert.msa.example.com.pem /etc/postfix/sslcp cacert.example.com.pem /etc/postfix/sslpostconf -e "smtpd_tls_key_file = /etc/postfix/ssl/privkey.msa.example.com.pem"postconf -e "smtpd_tls_cert_file = /etc/postfix/ssl/cert.msa.example.com.pem"postconf -e "smtpd_tls_CAfile = /etc/postfix/ssl/cacert.example.com.pem"postconf -e "smtpd_tls_received_header = yes"postconf -e "smtpd_use_tls = yes"chmod 600 /etc/postfix/ssl/*postfix reload

Install certificates in Courier IMAP and configure imapd-ssl to use them (this changes the TLS_CERTFILE setting):cp -i key-cert-dh.msa.example.com.pem /etc/courier/

chmod 600 /etc/courier/key-cert-dh.msa.example.com.pemchown daemon /etc/courier/key-cert-dh.msa.example.com.pemsed -i 's/imapd.pem/key-cert-dh.msa.example.com.pem/' /etc/courier/imapd-ssl/etc/init.d/courier-imap-ssl stop/etc/init.d/courier-imap-ssl start

And configure Courier POP3 to use the same certificates:sed -i 's/pop3d.pem/key-cert-dh.msa.example.com.pem/' /etc/courier/pop3d-ssl/etc/init.d/courier-pop-ssl stop/etc/init.d/courier-pop-ssl start

Running some of these commands again will result in overwriting keys and certificates. That may not be good. Somefiles will necessarily be overwritten if additional certificates are requested, signed and created. That is expected, and isthe reason we make host-specific copies of everything as we go along. Just be careful not to overwrite any host-specific files we have created. And remember, only one Root Certificate Authority needs creation. Make a backup ofthe session, both on and off the system (transfer the directory via WinSCP).cp -r /root/CA /root/CA-24jul2007

Note that if you create certificates for additional hosts and want to provide SSL for multiple hosts via the VirtualHostdirective, it is my understanding you will need a separate IP address for each host: http://httpd.apache.org/docs/trunk/ssl/ssl_faq.html#vhosts. For example, I created a request for a new cert for mailzu.domain.tld. Then I signed it usingour CA cert, stripped off the human readable portion, combined the key and certificate into a single file called key-cert.mailzu.domain.tld.pem and copied this certificate to the /etc/apache-ssl directory. Later we will install MailZu,which has a home directory of /var/www/mailzu. If you wanted to access /var/www/mailzu using a virtual host (usingSSL) via https://mailzu.domain.tld, you would have to add another IP address. Here I show adding one to an existinginterface that has the IP address 192.168.1.222 - (this is in /etc/network/interfaces):

auto eth0iface eth0 inet static address 192.168.1.222 netmask 255.255.255.0 network 192.168.1.0 broadcast 192.168.1.255 gateway 192.168.1.1

auto eth0:0iface eth0:0 inet static address 192.168.1.223 netmask 255.255.255.0 network 192.168.1.0 broadcast 192.168.1.255 gateway 192.168.1.1

Then I created a file called /etc/apache-ssl/vhosts.conf with the contents:

<VirtualHost 192.168.1.223:443>DocumentRoot /var/www/mailzuServerName mailzu.domain.tldSSLCertificateFile /etc/apache-ssl/key-cert.mailzu.domain.tld.pem</VirtualHost>

I personally do not go this route (who has IP addresses to spare?), so I do not do this. I choose to access MailZu viahttps://msa.example.com/mailzu. This means I only have to deal with one host certificate (and one IP address).BTW, I reboot after making changes to /etc/network/interfaces.

Enable php in apache-sslIndex Top Bottom

The next command is on one line. We will use sed to edit a file that will enable php in apache-ssl.sed -i 's|#AddType application/x-httpd-php .php|AddType application/x-httpd-php .php|' /etc/apache-ssl/httpd.conf

grep php4_module /etc/apache-ssl/modules.conf

If you do not get:LoadModule php4_module /usr/lib/apache/1.3/libphp4.so

Then you need perform the next step:apache-modconf apache-ssl enable mod_php4

Regardless, restart apache-ssl:/etc/init.d/apache-ssl restart

Download a home page. This page describes some of the features of the mail system to new users. Those featuresare not yet installed but we can install this page. One it is in place, edit it (you may prefer the WinSCP editor) and do asearch and replace on the items listed at the top of the page. No doubt once this entire system is installed you will doa lot more editing of this page:cd /var/wwwwget http://www200.pair.com/mecham/spam/virtual.index.htmlcp index.html index.html-apache-originalcp virtual.index.html index.htmlsed -i 's/Our Organization/Widgits Inc./' index.htmlsed -i 's/somehost.domain.tld/msa.example.com/' index.htmlsed -i 's/domain.tld/example.com/' index.htmlchown root:www-data index.html

Browse to the server (first add the address to DNS or your hosts file):https://msa.example.com

Install and configure phpMyAdminIndex Top Bottom

apt-get install phpmyadmin

At this point our https://msa.example.com/phpmyadmin program is open for abuse. We will secure it by making theURL obscure, by setting a user name and password and by optionally (but highly recommended) only allowing chosenIP addresses to access the URL. Obscure the URL by changing its name (which should have already been done byediting this page):mv /var/www/phpmyadmin /var/www/phpmyadmiNx

With the current settings in /etc/apache-ssl/httpd.conf, our files used for access control (files like .htpasswd) will not beused unless we tell apache-ssl to use them. We will modify the provided access control file, then change /etc/apache-ssl/httpd.conf so it uses it. The current user name is 'admin'. Let's begin by obscuring the user name:sed -i 's/admin/myadmin_username/' /etc/phpmyadmin/htpasswd.setup

Then, create a password for that user:

htpasswd -c /etc/phpmyadmin/htpasswd.setup myadmin_username

New password: myadmin_passwordRe-type new password: myadmin_password

Now we direct apache-ssl to use this access file by placing directives in a configuration file we create. Once this is inplace, attempts to browse to the /phpmyadmiNx directory will be met with a login dialog box. Note that our version of/etc/apache-ssl/http.conf contains the command "Include /etc/apache-ssl/conf.d" so that any config files we place inthis directory will be read. I am also going to illustrate limiting access to one single workstation (yours of course). Thisis optional, but recommended. If you need to allow access to a network of machines, see http://httpd.apache.org/docs/1.3/mod/mod_access.html:

vi /etc/apache-ssl/conf.d/phpmyadmin.conf

and insert the following, making sure the IP address is the IP address of your workstation (as the mailserver sees it).Also make sure any comments start at the leftmost column.

<Directory /var/www/phpmyadmiNx/>

order deny,allow deny from all allow from 666.666.666.666#allow from 666.666.666.666 allow from 192.168

AuthUserFile /etc/phpmyadmin/htpasswd.setup AuthGroupFile /dev/null AuthName "phpMyAdmin" AuthType Basic require valid-user </Directory>

Restart apache-ssl:/etc/init.d/apache-ssl restart

and browse to phpMyAdmin:https://msa.example.com/phpmyadmiNx

The first login is the phpMyAdmin user name and password: myadmin_username myadmin_passwordThe second login is your mysql login (probably root and roots_password). You can close the phpMyAdmin web page.

Perform some preliminary Postfix configurationIndex Top Bottom

We want to explicitly set our domain name and host name in Postfix so there is no possibility Postfix finds somethingelse:postconf -e "mydomain = example.com"postconf -e "myorigin = example.com"postconf -e "myhostname = msa.example.com"

At this point, if you issue this command:postconf -n

Postfix should show main.cf is configured something like this:

alias_database = hash:/etc/aliasesalias_maps = hash:/etc/aliasesappend_dot_mydomain = nobiff = noconfig_directory = /etc/postfixinet_interfaces = allmailbox_command = procmail -a "$EXTENSION"mailbox_size_limit = 0mydestination = example.com, msa.example.com, localhost.example.com, localhostmydomain = example.commyhostname = msa.example.com

mynetworks = 127.0.0.0/8myorigin = example.comrecipient_delimiter = +relayhost =smtp_tls_session_cache_database = btree:${queue_directory}/smtp_scachesmtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)smtpd_tls_CAfile = /etc/postfix/ssl/cacert.example.com.pemsmtpd_tls_cert_file = /etc/postfix/ssl/cert.msa.example.com.pemsmtpd_tls_key_file = /etc/postfix/ssl/privkey.msa.example.com.pemsmtpd_tls_received_header = yessmtpd_tls_session_cache_database = btree:${queue_directory}/smtpd_scachesmtpd_use_tls = yes

Please note that 'postconf -n' does not show every setting we have in main.cf. Postfix should accept mail for theaddresses listed in /etc/aliases and deliver it to a mailbox in /var/mail. You should test this. Configure a MUA to usethis mail server as its outgoing SMTP server. I like to designate a MUA I'm not using at the moment for testingpurposes. For test purposes I typically I have several different MUAs (Outlook, Outlook Express, Thunderbird, TheBat!) set up on the system I am sending mail from. Do not send mail from the command line (using sendmail orother means) when testing this system. In all tests we perform I expect you to send test messages from an externalclient (unless of course we are testing something like SquirrelMail). Now send a message to postmaster@example.com. See what /var/log/mail.log said about the transaction (look for errors). It should also show you the userthe message was delivered to:tail -50 /var/log/mail.log

ls -l /var/mail

In the /var/mail directory you should see the mbox of the user the message was delivered to. You can ' more /var/mail/user ' to read the contents of the mbox.

Grab the Postfix source code (we need a few samples from it):cd /usr/local/srcwget http://ftp.debian.org/debian/pool/main/p/postfix/postfix_2.3.8.orig.tar.gztar xzf postfix_2.3.8.orig.tar.gz

Make sure you answer "n" to "Overwrite?". Do the first command separately:cp -i /usr/local/src/postfix-2.3.8/conf/* /etc/postfix

cp -i /etc/postfix/header_checks /etc/postfix/body_checkscp -i /etc/postfix/access /etc/postfix/sender_accesscp -i /etc/postfix/access /etc/postfix/rbl_client_exceptionscp -i /etc/postfix/access /etc/postfix/rbl_sender_exceptionscp -i /etc/postfix/access /etc/postfix/rbl_recipient_exceptionscp -i /etc/postfix/access /etc/postfix/reject_over_quota

cp /usr/local/src/postfix-2.3.8/examples/chroot-setup/LINUX2 /usr/sbinchmod +x /usr/sbin/LINUX2LINUX2

On Debian, Postfix runs chrooted. The LINUX2 script is used to copy files to the chroot jail.

Install SquirrelMail softwareand a few other thingsIndex Top Bottom

We just need the software in place at this time.apt-get install squirrelmail squirrelmail-locales maildrop

apt-get install sudo php-pear php5-mysql php5-gd php5-cli php5-common php5-mcrypt

apt-get install php-db php-net-socket php-log php-net-smtp

Install and configure PostfixAdmin and maildropIndex Top Bottom

Add our virtual user and group:groupadd vmail -g 6060useradd vmail -u 6060 -g 6060

And create the directory where our mail will be stored:mkdir /var/vmailchown -R vmail:vmail /var/vmailchmod -R 700 /var/vmail

Install subversion:apt-get install subversion

Download revision 1 of the source code (from the SVN repository):cd /var/wwwsvn -r 1 co https://postfixadmin.svn.sourceforge.net/svnroot/postfixadmin/trunk postfixadmin

Just like phpMyAdmin, we obscure the postfixadmin URL. Run these commands in sections - but don't manuallychange to a different directory during the process. I hope you have saved this document to your computer and havedone a search and replace on the bold items. This document is for you to customize to your particular system. Readthe instructions at the top of the page once you have opened it in a plain text editor (like WordPad):mv postfixadmin postFixadminx

cd /var/www/postFixadminxcp -i DATABASE_MYSQL.TXT DATABASE_MYSQL.TXT~

sed -i "s/password('postfix')/password('pfix_password')/" DATABASE_MYSQL.TXTsed -i "s/password('postfixadmin')/password('pfixadm_password')/" DATABASE_MYSQL.TXTwget http://www200.pair.com/mecham/spam/database_mysql.patch.txtpatch DATABASE_MYSQL.TXT < database_mysql.patch.txtmysql -u root -p < DATABASE_MYSQL.TXT

(you will need to enter roots_password in order to complete the last command)chmod 600 DATABASE_MYSQL.TXTcp config.inc.php.sample config.inc.phpsed -i "s|admin_url'] = ''|admin_url'] = 'https://msa.example.com/postFixadminx'|" config.inc.phpsed -i "s|admin_path'] = ''|admin_path'] = '/var/www/postFixadminx'|" config.inc.phpsed -i "s/password'] = 'postfixadmin'/password'] = 'pfixadm_password'/" config.inc.phpsed -i 's/postmaster@change-this-to-your.domain.tld/postmaster@example.com/' config.inc.phpsed -i 's/abuse@change-this-to-your.domain.tld/abuse@example.com/' config.inc.phpsed -i 's/hostmaster@change-this-to-your.domain.tld/hostmaster@example.com/' config.inc.phpsed -i 's/postmaster@change-this-to-your.domain.tld/postmaster@example.com/' config.inc.phpsed -i 's/webmaster@change-this-to-your.domain.tld/webmaster@example.com/' config.inc.phpsed -i 's/autoreply.change-this-to-your.domain.tld/autoreply.example.com/' config.inc.phpsed -i 's|to change-this-to-your.domain.tld|to https://msa.example.com/postFixadminx|' config.inc.phpsed -i 's|http://change-this-to-your.domain.tld|https://msa.example.com/postFixadminx|' config.inc.phpsed -i "s/domain_path'] = 'NO/domain_path'] = 'YES/" config.inc.phpsed -i "s/domain_in_mailbox'] = 'YES/domain_in_mailbox'] = 'NO/" config.inc.phpsed -i "s/mailboxes'] = '10'/mailboxes'] = '300'/" config.inc.phpsed -i "s/maxquota'] = '10'/maxquota'] = '500'/" config.inc.phpsed -i "s/quota'] = 'NO/quota'] = 'YES/" config.inc.phpsed -i 's/EHLO/HELO/' functions.inc.php

You should vi config.inc.php and browse through it to familiarize yourself with all the possible settings and to makesure your domain name was properly updated. Create a .htaccess password for the admin url (user name will bepfadmin_username). Assign the password pfadmin_passwordcd /var/www/postFixadminx/adminhtpasswd -c .htpasswd pfadmin_username

Now tell apache-ssl to use the file. We also limit access to our own workstation, but you can add more IP addresses(or networks) if needed. Access to https://msa.example.com/postFixadminx/admin/ is controlled by the IP address(es) of the client and the .htaccess user name and password. The super user is the only one who should have accessto this URL.

vi /etc/apache-ssl/conf.d/postfixadmin.conf

and insert this phrase. Don't forget to edit the ip address if you have not already done so and remember thatcomments must left justified:

<Directory /var/www/postFixadminx/admin/>

order deny,allow deny from all allow from 666.666.666.666 #allow from 666.666.666.666 allow from 192.168

AuthUserFile /var/www/postFixadminx/admin/.htpasswd AuthGroupFile /dev/null AuthName "Postfix Admin" AuthType Basic require valid-user </Directory>

Restart apache-ssl:/etc/init.d/apache-ssl restart

When we add a user to postfixadmin it creates records in the MySQL database but it does not create a Maildir for thatuser. We can make that happen with a patch to postfixadmin and a couple bash scripts. We also apply a patch tocreate new MySQL data in lower case rather than mixed case. Another patch is a group of patches others havesubmitted to the project:cd /var/www/postFixadminx/wget http://www200.pair.com/mecham/spam/postfixadmin.autocreate.patch.txtwget http://www200.pair.com/mecham/spam/postfixadmin.lowercase.patch.txtwget http://www200.pair.com/mecham/spam/postfixadmin.multipatch.txtwget http://www200.pair.com/mecham/spam/admin-edit-mailbox.patch.txtwget http://www200.pair.com/mecham/spam/edit-mailbox.patch.txt

cp create-alias.php create-alias.php~cp create-mailbox.php create-mailbox.php~cp edit-mailbox.php edit-mailbox.php~cp admin/create-alias.php admin/create-alias.php~cp admin/create-admin.php admin/create-admin.php~cp admin/create-domain.php admin/create-domain.php~cp admin/create-mailbox.php admin/create-mailbox.php~cp admin/edit-mailbox.php admin/edit-mailbox.php~cp users/vacation.php users/vacation.php~cp stylesheet.css stylesheet.css~cp admin/list-virtual.php admin/list-virtual.php~cp templates/overview.tpl templates/overview.tpl~cp templates/admin_list-virtual.tpl templates/admin_list-virtual.tpl~cp templates/login.tpl templates/login.tpl~cp templates/header.tpl templates/header.tpl~cp templates/admin_list-domain.tpl templates/admin_list-domain.tpl~cp languages/de.lang languages/de.lang~cp search.php search.php~

patch -p0 < postfixadmin.lowercase.patch.txt

patch -p0 < postfixadmin.multipatch.txt

patch -p0 < postfixadmin.autocreate.patch.txt

patch -p0 < edit-mailbox.patch.txt

patch admin/edit-mailbox.php <admin-edit-mailbox.patch.txt

cd /usr/sbinwget http://www200.pair.com/mecham/spam/maildirmake.sh.txtmv maildirmake.sh.txt maildirmake.shchmod +x maildirmake.shwget http://www200.pair.com/mecham/spam/quotachange.sh.txt

mv quotachange.sh.txt quotachange.shchmod +x quotachange.sh

In order to allow the www-data user to run the scripts, you must run:visudo

and on the bottom of the page add this stuff (notice our hostname):www-data msa=NOPASSWD: /usr/sbin/maildirmake.shwww-data msa=NOPASSWD: /usr/sbin/quotachange.sh

Set permissions:cd /var/www/postFixadminxchown -R root:www-data ../postFixadminxchmod 640 *.php *.txt *~chmod 600 *.TXTchmod 640 admin/*.php admin/*~chmod 640 images/*.pngchmod 640 languages/*.lang languages/*~chmod 640 templates/*.tpl templates/*~chmod 640 users/*.php users/*~

Now you can browse to postfixadmin and run the setup script:https://msa.example.com/postFixadminx/setup.php

Assuming everything is OK, click on the link to the admin section and get past the apache security with pfadmin_username and pfadmin_password . You will need to log into the /admin page with a user name of admin@domain.tld and a password of admin (note: domain.tld is literally domain.tld). All 'Super admins' are directed to the /admin page. Click on "New Domain" and add the primary domain (example.com). Leave the optional "Add defaultmail aliases:" and "Mail server is backup MX:" boxes unchecked. All domains you add should have either an A recordor MX record in DNS in order for PostfixAdmin to consider them valid. Add any other domains you need. Only adddomains that will store mail locally (we will talk about relay domains later). Now click on "New Admin" and add youremail address and a strong password. You are not adding a mailbox here, you are adding yourself as anadministrator. Once you are added, you need to promote yourself to a Super admin. To do so, click "Admin List", edityour login and check the "Super admin" checkbox. You do not need to select any domains when you are a Superadmin. Only select a domain (or domains) when adding a normal admin. Now Logout and log back in using your username.

Please delete admin@domain.tld otherwise the whole world knows your Super admin login. Only Super admins haveaccess to the /admin page. You can add one or more 'normal' admins at this time if you like. You actually need to addan additional normal admin login for yourself that you will use on a day to day basis. Normal admins get a differentscreen. The https://msa.example.com/postFixadminx/ will be used by normal administrators and access to this URLwill be controlled by IP address of the client and the user name and password that is assigned to the administrator byus (using the tools at https://msa.example.com/postFixadminx/admin). Users can change their forwardinginformation and password at https://msa.example.com/postFixadminx/users; however, they will not need to once weadd a SquirrelMail plugin. That's all we'll do here for the moment, but leave the current page open. Return to thePuTTY screen and rename setup.php:cd /var/www/postFixadminxmv setup.php setup.php.txt

Back at the browser window you will notice a link to Return to https://msa.example.com/postFixadminx. Clicking onthis should bring you to the normal admin page where you (and possibly other domain admins) would log in to manageyour domain(s). The first thing you should do is Add Mailbox for yourself. The "Active:" and "Create mailbox:" checkboxes should of course be checked. Notice that Username: is only the local part; you choose the @domain from thedrop down box. Create the username in lower case. This is your IMAP account. It is imperative that ourmaildirmake.sh script runs correctly when a mailbox is created in postfixadmin, otherwise Postfix will accept themessage but will not be able to deliver it to a mailbox. Check that a mailbox exists, and a squirrelmail profile wascreated:ls -l /var/vmail/example.comls -l /var/lib/squirrelmail/data

Note that if you delete a mailbox from postfixadmin, as a safety precaution we will not automatically delete the user'smaildir (or mail). You will have to manually remove it. You should add another regular user "test@example.com" touse when you need to test sending and receiving messages as a normal user (not related to any administratoraccounts). At this point we still need to configure Postfix to send mail to our virtual mailboxes using the informationstored in the postfixadmin databases. Begin by downloading and modifying Postfix data access configuration files:

cd /etc/postfixwget http://www200.pair.com/mecham/spam/mysql_virtual_alias_maps.cfwget http://www200.pair.com/mecham/spam/mysql_virtual_domains_maps.cfwget http://www200.pair.com/mecham/spam/mysql_virtual_mailbox_maps.cfsed -i 's/password = postfix/password = pfix_password/' mysql_virtual_alias_maps.cfsed -i 's/password = postfix/password = pfix_password/' mysql_virtual_domains_maps.cfsed -i 's/password = postfix/password = pfix_password/' mysql_virtual_mailbox_maps.cfchmod 640 mysql_*chown root:postfix mysql_*

We need to remove our domain name from $mydestination because our domain will soon be listed as a virtual mailboxdomain - and you cannot have a domain in more than one address class:cp /etc/postfix/main.cf /etc/postfix/main.cf-domainpostconf -e "mydestination = msa.example.com, localhost.example.com, localhost"

Now tell Postfix to use our MySQL data files (and maildrop - which still needs configuration):touch /etc/postfix/virtualpostmap /etc/postfix/virtualpostconf -e "virtual_minimum_uid = 6060"postconf -e "virtual_gid_maps = static:6060"postconf -e "virtual_uid_maps = static:6060"postconf -e "virtual_alias_maps = proxy:mysql:/etc/postfix/mysql_virtual_alias_maps.cf, hash:/etc/postfix/virtual"postconf -e "virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql_virtual_domains_maps.cf"postconf -e "virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf"postconf -e "virtual_transport = maildrop"postconf -e "virtual_mailbox_base = /var/vmail/"postconf -e "maildrop_destination_concurrency_limit = 2"postconf -e "maildrop_destination_recipient_limit = 1"

Note that I use proxy:mysql: here (proxymap(8)). When proxymap(8) is used, changes to the MySQL tables may notbe recognized immediately. During testing you may want to remove proxy: because it may cause frustration andconfusion. Alternately, reload Postfix so changes are recognized sooner.

To configure maildrop, first get a new maildroprc file from me that contains instructions to deliver spam to the user'sSpam folder:cd /etcmv maildroprc maildroprc-oldwget http://www200.pair.com/mecham/spam/maildroprc.txtcp maildroprc.txt maildroprctouch /var/log/maildroprc.logchown vmail:vmail /var/log/maildroprc.logcd /etc/logrotate.d/wget http://www200.pair.com/mecham/spam/maildrop.logrotate.txtmv maildrop.logrotate.txt maildrop

Now we need to edit the maildrop entry in master.cf. We will also make a backup of the original master.cf:cp -i /etc/postfix/master.cf /etc/postfix/master.cf-24jul2007vi /etc/postfix/master.cf

Locate the current maildrop transport and comment it out (as shown) then insert the new maildrop transport as shown:

#maildrop unix - n n - - pipe# flags=ODRhu user=vmail argv=/usr/bin/maildrop -d ${recipient} maildrop unix - n n - - pipe flags=ODRhu user=vmail:daemon argv=/usr/bin/maildrop -w 90 -d ${user}@${nexthop} ${extension} ${recipient} ${user} ${nexthop}

Then reload Postfix:postfix stoppostfix start

You should get a message that files differ; run LINUX2 to correct that. At this point, since we are sending mail tomaildrop, maildrop also needs to read the MySQL data in order to determine the relationship between user@example.com and the maildir where mail is supposed to go for that user. Fortunately, both Courier and maildrop canuse the same configuration file to store the settings. This file is /etc/courier/authmysqlrc. We need to make quite a few

changes to this file to get it to work in our current environment, so rather than edit it, get a new one from me. Notethat tabs must be used to separate the variable and the value. Also, read through this file to get an idea of what itcontains:cd /etc/couriermv authmysqlrc authmysqlrc~wget http://www200.pair.com/mecham/spam/authmysqlrc.txtmv authmysqlrc.txt authmysqlrcsed -i "s/MYSQL_PASSWORD\tpostfix/MYSQL_PASSWORD\tpfix_password/" authmysqlrcchown daemon:daemon authmysqlrcchmod 660 authmysqlrc

You also need to tell authdaemond to use the authmysqlrc file we just modified. We will use data in our MySQL postfixdatabase to authenticate users for IMAP, POP and SASL. For remote clients to send mail we will use SASL with TLS.We can optionally use CRAM-MD5 for those clients (like my old version of The Bat!) that seem to have a broken TLSimplementation. At least the password will be encrypted during its trip across the wire:sed -i 's/authmodulelist="authpam"/authmodulelist="authmysql"/' authdaemonrc/etc/init.d/courier-authdaemon restart

We will enable CRAM-MD5 login mechanism for imapd (port 143):cp -ip /etc/courier/imapd /etc/courier/imapd~sed -i 's/SORT QUOTA IDLE/SORT QUOTA AUTH=CRAM-MD5 IDLE/' /etc/courier/imapd

Let's simply start off clean, we need to make certain stuff works after a reboot anyway:rebootexit

Once the system comes back up:tail -f /var/log/mail.log

Now we will send a message through the system to see if it lands in our maildir. You should already have a MUA setup to use this server as its outgoing server. You should also now be able to configure it to connect to the IMAP serverusing your username (full email address) and password. Assuming you have successfully created a maildir foryourself, send a message to yourself and see if you get it. Tail the mail.log file as the message goes through. Also:grep fatal /var/log/mail.logSuccess should look like:

Jun 10 11:21:06 msa postfix/pipe[11513]: 0FBC5240C2: to=<garyv@example.com>, relay=maildrop, delay=0.13,delays=0.07/0.02/0/0.04, dsn=2.0.0, status=sent (delivered via maildrop service)

If you have an error, you must fix it before you continue. We have made a lot of changes to a lot of files. It iscertainly possible something happened along the way that would prevent proper delivery of a message. You shouldhave an understanding of the files involved. You just have to find the incorrect setting(s). Some familiarity with Postfixwould really be handy. Basic stuff like familiarity with the mailq, postsuper, qshape and postqueue commands. Alsoremember that you have phpMyAdmin to browse the database (and possibly make manual changes). You shouldbrowse the postfix database to get familiar with the structure of the data. You will also want to set up the IMAPaccount for the test@example.com user and send a message to that address.ls -al /var/vmail/example.com/test/new

cat /var/log/maildroprc.log

If you can deliver mail to users, it would be a good idea to familiarize yourself with PostfixAdmin at this time. Addsome aliases, add some domains. Play with the software. Postfix will no longer use /etc/aliases for our virtual domainsso you will need to make aliases (or mailboxes) for root, abuse, postmaster, webmaster and logcheck @example.com. If you fail to make aliases or mailboxes for recipients of system generated mail, maildrop will bouncethe messages and complain with an 'Invalid user specified.' error. Set up your MUA to retrieve mail from the mailservervia IMAP SSL on port 993. If you must use POP3, use POP3 SSL on port 995. POP3 clients will only be able toretrieve mail from the /new folder which means they will never see their Spam folder unless they also use SquirrelMail.If you must use standard POP (110) or IMAP (143), configure the client to use TLS (if it's an option - some clients useit automatically). Some clients may wish to use CRAM-MD5 to authenticate to port 110 or 143. If so, you will have tofire up phpMyAdmin and place a cleartext password in the 'clear' field for those users. Hopefully you are using mydatabase schema with the 'clear' field added. If not, it's likely maildrop will think every user is invalid. Install the CAcertificate we created earlier on the test client if you have not already done so. Not having the root certificate properlyinstalled will cause all kinds of grief.

If you need to debug pop3d/imapd/pop3d-ssl/imapd-ssl, edit those files in the /etc/courier directory and add DEBUG_

LOGIN=2. Then of course restart any of those services as needed. This will give more details in mail.log. Also check /var/log/auth.log:/etc/init.d/courier-pop restart/etc/init.d/courier-pop-ssl restart/etc/init.d/courier-imap restart/etc/init.d/courier-imap-ssl restart

There are three (contributed) scripts that come with PostfixAdmin in the ADDITIONS directory that are used to deleteorphaned maildirs. These are mailboxes you deleted in PostfixAdmin but the files remain on the system. As mentionedearlier, I do not automatically delete maildirs when a user is removed. I would leave orphaned files alone for somelength of time. One of the provided scripts would delete all your mail if you let it. That can't be good. Of the other two,cleanupdirs.pl appears to be Ok but I'm still not going to allow it do delete maildirs; I'm only going to use it to reportorphaned ones. I'm also going to rename it maildircheck.cp -i /var/www/postFixadminx/ADDITIONS/cleanupdirs.pl /usr/sbin/maildircheck

touch /var/log/maildircheck.logsed -i "s|/home/vmail|/var/vmail|" /usr/sbin/maildirchecksed -i "s/removed_maildirs.log/maildircheck.log/" /usr/sbin/maildirchecksed -i "s/someuser/postfix/" /usr/sbin/maildirchecksed -i "s/somepass/pfix_password/" /usr/sbin/maildirchecksed -i "s/ rmtree/# rmtree/" /usr/sbin/maildirchecksed -i "s/'\$to_delete'/\$to_delete/" /usr/sbin/maildirchecksed -i "s/Need to delete/Orphaned/" /usr/sbin/maildircheckchmod 700 /usr/sbin/maildircheck

cd /etc/logrotate.dwget http://www200.pair.com/mecham/spam/maildircheck.txtmv maildircheck.txt maildircheck

To test, you need to delete a test user via the PostfixAdmin interface. Then run:maildircheck

If we deleted test@example.com, look and see (and make sure) that the mail directory was NOT deleted, for example,run ls -l /var/vmail/example.com/test . Then add the user back in. If you actually wanted to use this script to deletethe directories, you would have to uncomment the 'rmtree' line. I hope the script works and you don't end up deletingevery mailbox on the system.

Now I have an optional script that will automatically delete messages left in each user's Spam folder that is older than24 days. You could test it (at some point in the future) by temporarily modifying the number of days (-mtime 0 = 1 day).cd /etc/cron.dailywget http://www200.pair.com/mecham/spam/rmmailboxspam.txtmv rmmailboxspam.txt rmmailboxspamchmod +x rmmailboxspam

Configure SASL and TLSIndex Top Bottom

vi /etc/postfix/sasl/smtpd.conf

and insert the following:pwcheck_method: authdaemondlog_level: 3mech_list: PLAIN LOGIN CRAM-MD5authdaemond_path: /var/run/courier/authdaemon/socketauxprop_plugin: sqlsql_hostnames: 127.0.0.1sql_user: postfixsql_passwd: pfix_passwordsql_database: postfixsql_select: select clear from mailbox where username = '%u@%r'

The first three lines will authenticate against encrypted passwords in the 'password' field of the mailbox table in thepostfix database (when a client and the server use PLAIN or LOGIN). The remaining lines are for CRAM-MD5 loginsthat will instead look up the cleartext password from the 'clear' field. Look in /var/log/auth.log for error messages. Ireduce the log_level: to 0 when done testing. Passwords you enter in PostfixAdmin are encrypted but you will have to

manually add any cleartext passwords. This can be done with an SQL statement or via the phpMyAdmin interface.The cleartext passwords do not have the be the same as the encrypted passwords - the client simply has to use thecorrect password for the chosen mechanism.

Make sure we are not using saslauthd (don't worry if /etc/init.d/saslauthd does not exist):sed -i 's/START=yes/START=no/' /etc/default/saslauthd/etc/init.d/saslauthd stop

Since Debian runs Postfix chrooted, Postfix will need to find /var/run/courier/authdaemon/socket in the chroot jail. Wewill do this by making a hard link to the existing file:mkdir -p /var/spool/postfix/var/run/courier/authdaemonln /var/run/courier/authdaemon/socket /var/spool/postfix/var/run/courier/authdaemon/socketchown -R daemon:daemon /var/spool/postfix/var/run/courierchmod 755 /var/run/courier/authdaemon

We have to recreate this link to 'socket' prior to Postfix starting up so we will modify the init script:vi /etc/init.d/postfix

and just after # Make sure that the chroot environment is set up correctly. (around line 45) insert thefollowing:ln -f /var/run/courier/authdaemon/socket /var/spool/postfix/var/run/courier/authdaemon/socket

Now tell Postfix to use SASL (we make a backup copy of main.cf should you need to refer to it):cp -i /etc/postfix/main.cf /etc/postfix/main.cf-before-saslpostconf -e "broken_sasl_auth_clients = yes"postconf -e "smtpd_sasl_auth_enable = yes"postconf -e "smtpd_sasl_local_domain = \$myhostname"postconf -e "smtpd_sasl_security_options = noanonymous"postconf -e "smtpd_sasl_authenticated_header = yes"postconf -e "smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated,reject_unauth_destination"/etc/init.d/postfix restart

If SASL auth stops working with "warning: SASL authentication failure: cannot connect to Courier authdaemond:Connection refused", a likely cause is Postfix can no longer write to the socket (due to running chrooted). Restartingpostfix with the modified init script may solve the problem./etc/init.d/postfix restart

Once our SASL/TLS configuration is complete (we still have to modify master.cf before it is), you should experimentwith SASL and TLS. To help debug (if necessary) you can place "debug_peer_list=666.666.666.666" (the IP of theclient sending the messages) and/or "smtpd_tls_loglevel=3" (read this) in main.cf. Remove those settings when youare satisfied. Configure an Outlook Express IMAP account to require authentication and use SMTPS (AKA SSMTP)port 465 for outgoing, and IMAPS (secure IMAP) port 993 for incoming. Similar to this. Most other clients will use 465also. Clients that can't use a dedicated TLS port (Postfix offers this via smtpd_tls_wrappermode=yes) may use port4650 and instead use STARTTLS. Port 587 will be used for clients unable to get TLS working and will instead useCRAM-MD5 to encrypt the cleartext password. There is an issue with Mozilla Thunderbird. It tries to use CRAM-MD5before it tries PLAIN. This will result in a "SASL authentication failure: empty secret" warning unless you enter acleartext password for these clients. If you don't wish to do that, you can either fix Thunderbird, or not use CRAM-MD5. To fix Thunderbird, go to Tools->Options->Advanced->General->Config Editor and then double click onmail.smtpserver.default.trySecAuth (which is set to true by default) in order to set it to false.

While we are editing master.cf we will also disable address rewriting on the three ports. We will wait until afteramavisd-new has processed a message before any address rewriting takes place. You may want to use the WinSCPeditor for this. You want to replace everything between the two grayed out lines:vi /etc/postfix/master.cf

smtp inet n - - - - smtpd -o smtpd_use_tls=no -o smtpd_sasl_auth_enable=no# -o receive_override_options=no_address_mappings# If they want to relay, make them use port 587 (submission) or port 465 (smtps)# If using submission port, configure client to use CRAM-MD5submission inet n - - - - smtpd -o smtpd_use_tls=no -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject# -o receive_override_options=no_address_mappings

# Outlook and OE (and many others) expect smtpd_tls_wrappermode,# so have them submit here (port 465):smtps inet n - - - - smtpd -o smtpd_enforce_tls=yes -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject# -o receive_override_options=no_address_mappings# We will use port 4650 for clients that use STARTTLS:4650 inet n - - - - smtpd -o smtpd_enforce_tls=yes -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject# -o receive_override_options=no_address_mappings#628 inet n - - - - qmqpd

Then of course:/etc/init.d/postfix restart

FYI, at this point output from 'postconf -n' looks like:

alias_database = hash:/etc/aliasesalias_maps = hash:/etc/aliasesappend_dot_mydomain = nobiff = nobroken_sasl_auth_clients = yesconfig_directory = /etc/postfixinet_interfaces = allmailbox_command = procmail -a "$EXTENSION"mailbox_size_limit = 0mydestination = msa.example.com, localhost.example.com, localhostmydomain = example.commyhostname = msa.example.commynetworks = 127.0.0.0/8myorigin = example.comrecipient_delimiter = +relayhost =smtp_tls_session_cache_database = btree:${queue_directory}/smtp_scachesmtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destinationsmtpd_sasl_auth_enable = yessmtpd_sasl_authenticated_header = yessmtpd_sasl_local_domain = $myhostnamesmtpd_sasl_security_options = noanonymoussmtpd_tls_CAfile = /etc/postfix/ssl/cacert.example.com.pemsmtpd_tls_cert_file = /etc/postfix/ssl/cert.msa.example.com.pemsmtpd_tls_key_file = /etc/postfix/ssl/privkey.msa.example.com.pemsmtpd_tls_received_header = yessmtpd_tls_session_cache_database = btree:${queue_directory}/smtpd_scachesmtpd_use_tls = yesvirtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf, hash:/etc/postfix/virtualvirtual_gid_maps = static:6060virtual_mailbox_base = /var/vmail/virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cfvirtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cfvirtual_minimum_uid = 6060virtual_transport = maildropvirtual_uid_maps = static:6060

Please note that 'postconf -n' does not show every setting we have in main.cf.

Install and configure amavisd-newIndex Top Bottom

Here we install amavisd-new, SpamAssassin and ClamAV, then add the clamav user to the amavis group. We updateSpamAssassin's rules. Then we enable spam and virus scanning in amavisd-new:

apt-get update

apt-get install amavisd-new spamassassin razor pyzor lha apt-listchanges nomarch cabextract paxp7zip

apt-get install clamav clamav-daemon clamav-freshclam

apt-get install arj libio-string-perl libhtml-format-perl libmail-spf-query-perl libnet-dns-perl unrar

unrar (rar) is not free. See http://www.rarsoft.com/index.htm

gpasswd -a clamav amavis/etc/init.d/clamav-daemon stopfreshclam/etc/init.d/clamav-daemon start

sa-update

cd /etc/amavis/conf.d/sed -i 's/#@bypass_virus_/@bypass_virus_/' 15-content_filter_modesed -i 's/# \\%bypass_vi/ \\%bypass_vi/' 15-content_filter_modesed -i 's/#@bypass_spam_/@bypass_spam_/' 15-content_filter_modesed -i 's/# \\%bypass_s/ \\%bypass_s/' 15-content_filter_modecat 15-content_filter_modeamavisd-new reload

Note: during the time amavisd-new is restarting, mail cannot be delivered to it. Also note that amavisd-new may not beable to use the UNIX socket at /var/run/clamav/clamd.ctl until clamd has fully loaded the virus definition database -which can take minutes. Once this server has mail flowing through it, during the time amavisd-new is reloading Postfixmay complain "connect to localhost[127.0.0.1]: Connection refused". Postfix will defer this mail (for about 15 minutes).To speed things up, an impatient person may run 'postfix flush' to flush the deferred queue, but I would not.

We will install a script that runs sa-update daily:cd /usr/sbinwget http://www200.pair.com/mecham/spam/sa-update1.sh.txtmv sa-update1.sh.txt sa-update.shchmod +x sa-update.shsa-update.sh

And apply a couple small patches to amavisd-new:cd /usr/sbinwget http://www200.pair.com/mecham/spam/amavisd-new-trim-whitespace.patch.txtpatch amavisd-new <amavisd-new-trim-whitespace.patch.txtrm amavisd-new-trim-whitespace.patch.txtwget http://www200.pair.com/mecham/spam/amavisd-new-trim-whitespace.patch2.txtpatch amavisd-new <amavisd-new-trim-whitespace.patch2.txtrm amavisd-new-trim-whitespace.patch2.txt

You only need to run this script once a day. Place an entry in your crontab (on the first available blank line):crontab -e

Replace MM with a number between 0 and 59 and HH with a number between 0 and 23:MM HH * * * /usr/sbin/sa-update.sh

Now we reinstall clamav from Volatile (you would use this to upgrade to new versions):apt-get -t etch install clamav clamav-daemon clamav-freshclam

Now vi /etc/amavis/conf.d/50-user and insert the text below in the middle of the file (must be between "use strict;" and"1;"). You may prefer the WinSCP editor since vim will tend to comment out this text when you paste it in. If you arestill in the editor since the last edit, you may need to hit the refresh icon in order to see the /etc/amavis directory. Edit@local_domains_maps and include all your domains there. Also take a look at @mynetworks to see if you need tomodify it. You will probably want to temporarily leave your network out of @mynetworks during testing (so you cansend spam to test recipients):

# nice to have $log_level (1-5) available:$log_level = 0;

# If sender matches ACL, turn debugging fully up, just for this one message#@debug_sender_maps = ( ["test\@$mydomain"] );

# explicitly set $mydomain and $myhostname:$mydomain = 'example.com';$myhostname = 'msa.example.com';

# Set number of processes. Rough guide for dual processor, 1GB = 6, 2GB = 12, 4GB = 24# you MUST also change maxproc for the smtp-amavis transport to match this number, e.g:# smtp-amavis unix - - n - 6 smtp$max_servers = 6;

# We discard (and quarantine) viruses, discard (and quarantine) spam (>= kill_level), # bounce (and quarantine) banned files and pass bad headers:$final_virus_destiny = D_DISCARD;$final_banned_destiny = D_BOUNCE;$final_spam_destiny = D_DISCARD;$final_bad_header_destiny = D_PASS;

# don't quarantine bad headers (no need since we pass them all):$bad_header_quarantine_to = undef;

# We use plus addressing to place spam in user's Spam folder:$recipient_delimiter = '+';

# Spam gets the Subject line prepended with:$sa_spam_subject_tag = 'Spam> ';

# We tag all headers (for 'local' domains) with X-Spam info:$sa_tag_level_deflt = undef;

# This is the system default spam tag level that will be overridden by user's preferences in MySQL$sa_tag2_level_deflt = 6.31;

## For relay domains not set up in MySQL you can create a static domain wide (or individual) map: #@spam_tag2_level_maps = (# { 'postmaster@example.net' => 99.0,# '.example.net' => 8.0,# '.example.org' => 6.0 },# \$sa_tag2_level_deflt, # catchall default#);

# The default is to not quarantine any spam (outside of what users get in their Spam folder), # so set default kill_level high. Users can choose their own kill_level however. kill_level# will trigger quarantining (to MailZu).$sa_kill_level_deflt = 9999;

## Once again, relay domains may want something different:#@spam_kill_level_maps = (# { 'postmaster@example.net' => 99.0,# '.example.net' => 8.0,# '.example.org' => 10.0 },# \$sa_kill_level_deflt, # catchall default#);

## And some relay domains may wish to quarantine up to a certain level, then discard:#@spam_quarantine_cutoff_level_maps = (# { '.example.net' => 20.5, # '.example.org' => 25 },# \$sa_quarantine_cutoff_level, # catchall default (currently undef)#);

# We will quarantine viruses to /var/lib/amavis/virusmails (the default).# We will use a cron job to automatically delete these files older than 14 days from the quarantine.# We can use amavisd-release or MailZu to release quarantined messages. We warn the recipients

# and expect them to contact us (via the MailZu interface) if they need a banned file released.# Each domain can have their own administrators.@virus_admin_maps = ({ '.example.com' => 'postmaster@example.com', '.example.net' => 'postmaster@example.net', '.' => 'postmaster@example.com', });@banned_admin_maps = ({ '.example.com' => 'postmaster@example.com', '.example.net' => 'postmaster@example.net', '.' => 'postmaster@example.com', });$warnbannedrecip = 1;$defang_banned = 1;

# recipient's local address(es) will be rewritten to user+spam when spam exceeds tag2_level# and as a result will be delivered to their Spam folder (thanks to maildrop)@addr_extension_spam_maps = ('spam');

# list domains in an external file (created by local_domains.sh script):@local_domains_maps = ( read_hash("$MYHOME/local_domains") );

# Since we configured SQL, we can use penpals feature:$penpals_bonus_score = 5;$penpals_threshold_low = 1;$penpals_threshold_high = 18;

# We are going to create policy banks that will notify us of internally created spam# but also let banned files out (provided they are compressed).

@mynetworks = qw( 127.0.0.0/8 [::1] [FE80::]/10 [FEC0::]/10 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 );

$inet_socket_port = [10024, 10026]; ## If using Mailzu, use this instead:#$inet_socket_port = [10024, 10026, 9998];

$inet_socket_bind = '127.0.0.1';## If using Mailzu, use this instead:#$inet_socket_bind = undef;

## Interface to MailZu#$interface_policy{'9998'} = 'MAILZU';#$policy_bank{'MAILZU'} = {# protocol => 'AM.PDP',# inet_acl => [qw( 127.0.0.1 [::1] 111.111.111.111 )],#};

# We create a custom set of banned rules for the MYNETS and TRUSTED policy# banks. See also the 'DEFAULT' $banned_filename_re settings in 20-debian_defaults%banned_rules = ( 'BLOCK_EXE' => new_RE( # block double extensions in names: qr'\.[^./]*\.(exe|vbs|pif|scr|bat|cmd|com|cpl|dll)\.?$'i, # allow any name or type (except viruses) within an archive: [ qr'^\.(Z|gz|bz2|rpm|cpio|tar|zip|rar|arc|arj|zoo)$' => 0], # blocks MS executable file(1) types, unless allowed above: qr'^\.(exe|exe-ms)$', ), 'DEFAULT' => $banned_filename_re,);

$policy_bank{'MYNETS'} = { # mail originating from @mynetworks spam_admin_maps => ["postmaster\@$mydomain"], # alert of internal spam final_spam_destiny => D_BOUNCE, # so the sender knows they are a spammer spam_kill_level_maps => [10.0], spam_dsn_cutoff_level_maps => [9999], banned_filename_maps => ['BLOCK_EXE'],};

$interface_policy{'10026'} = 'TRUSTED';$policy_bank{'TRUSTED'} = { # mail originating from trusted senders spam_admin_maps => ["postmaster\@$mydomain"], # alert of internal spam final_spam_destiny => D_BOUNCE, # so the sender knows they are a spammer spam_kill_level_maps => [10.0], spam_dsn_cutoff_level_maps => [9999], banned_filename_maps => ['BLOCK_EXE'],};

# Here we set up access to MySQL data:@lookup_sql_dsn = ( ['DBI:mysql:amavis:localhost', 'amavis', 'amavis_password'] );@storage_sql_dsn = @lookup_sql_dsn;

# If using MailZu, store banned files and spam to MySQL if you want to give users the# ability to read those messages in the MailZu interface:#$banned_files_quarantine_method = 'sql:';#$spam_quarantine_method = 'sql:';

# If using MailZu and you do not wish to quarantine spam to MySQL but instead want to# quarantine to /var/lib/amavis/virusmails, MailZu cannot have spam messages# compressed (which is the default), so you would have to change from the default to this:#$spam_quarantine_method = 'local:spam-%m';

# Note: If you quarantine items locally, you would also need to create a script delete# old quarantined items. Look to /etc/cron.daily/rmvirusquar for an example

# required because we set msgs.time_iso to type TIMESTAMP (required by MailZu)$timestamp_fmt_mysql = 1;

# specific to the amavisnewsql SquirrelMail plugin$sql_select_white_black_list = 'SELECT wb FROM wblist'. ' WHERE (rid=?) AND (wblist.email IN (%k))'. ' ORDER BY wblist.priority DESC';

#----------------------------------------------------------

Now we will create the MySQL schema for amavisd-new. This schema is a combination of the recommended amavisd-new schema, and the schema provided with the amavisnewsql SquirrelMail Plugin:cdwget http://www200.pair.com/mecham/spam/amavis-sqmail.sql.txtsed -i "s/BY 'password'/BY 'amavis_password'/" amavis-sqmail.sql.txtchmod 600 amavis-sqmail.sql.txtmysql -u root -p < amavis-sqmail.sql.txt

You would have been prompted for roots_password. Secure 50-user from prying eyes (to protect the MySQLpassword):chmod 640 /etc/amavis/conf.d/50-user

We are going to create a script that will pull a list of our domains from a PostfixAdmin table:vi /usr/sbin/local_domains.sh

Insert the following (this is two lines - line 2 may wrap)#!/bin/bashmysql -upostfix -ppfix_password postfix -B -N -e "select concat('.',domain) from domain" >/var/lib/amavis/local_domains

Save the file. Then:chmod 700 /usr/sbin/local_domains.shlocal_domains.shcat /var/lib/amavis/local_domains

Our domains should be listed in the file. We will add this script to PostfixAdmin so it's updated every time we add orremove domains. We need to add another entry to /etc/sudoers so www-data can run this script:visudo

and insert at the bottom (noting once again the hostname of the server):

www-data msa=NOPASSWD: /usr/sbin/local_domains.sh

Now patch PostfixAdmin so it uses this script:cd /var/www/postFixadminx/admincp edit-domain.php edit-domain.php~wget http://www200.pair.com/mecham/spam/domain.patch.txtpatch -p0 < domain.patch.txtchown root:www-data *

You should spend a minute to convince yourself this works. Remove /var/lib/amavis/local_domains and log intoPostfixAdmin and edit a domain (you have to log in as the super-user in order to edit domains). Insure /var/lib/amavis/local_domains was created as expected, then:amavisd-new reload

Install a couple maintenance scripts to prevent the amavis database from growing forever (messages over 24 days aredeleted). If it grows forever, you or I made a mistake here:cd /usr/sbinwget http://www200.pair.com/mecham/spam/trim-amavis-msgs.txtmv trim-amavis-msgs.txt trim-amavis-msgssed -i 's/Passw0rd/amavis_password/' trim-amavis-msgschmod 750 trim-amavis-msgscd /etcwget http://www200.pair.com/mecham/spam/trim-amavis.sql.txtmv trim-amavis.sql.txt trim-amavis.sqlcd /etc/cron.daily/wget http://www200.pair.com/mecham/spam/trim-amavis.txtmv trim-amavis.txt ztrim-amavissed -i 's/password/amavis_password/' ztrim-amavischmod 750 ztrim-amavis./ztrim-amavis

Now configure postfix to use amavisd-new. I will show NEW changes to master.cf in red. Don't forget to matchmaxproc for the smtp-amavis transport to $max_servers. Also notice there are different port number involved for thecontent_filter overrides. You may also want to use the WinSCP editor here:vi /etc/postfix/master.cf

# ==========================================================================# service type private unpriv chroot wakeup maxproc command + args# (yes) (yes) (yes) (never) (100)# ==========================================================================smtp inet n - - - - smtpd -o smtpd_use_tls=no -o smtpd_sasl_auth_enable=no -o content_filter=smtp-amavis:[127.0.0.1]:10024# -o receive_override_options=no_address_mappings# If they want to relay, make them use port 587 (submission) or port 465 (smtps)# If using submission port, configure client to use CRAM-MD5submission inet n - - - - smtpd -o smtpd_use_tls=no -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o content_filter=smtp-amavis:[127.0.0.1]:10026# -o receive_override_options=no_address_mappings# Outlook and OE (and many others) expect smtpd_tls_wrappermode,# so have them submit here (PORT 465):smtps inet n - - - - smtpd -o smtpd_enforce_tls=yes -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o content_filter=smtp-amavis:[127.0.0.1]:10026# -o receive_override_options=no_address_mappings# We will use port 4650 for clients that use STARTTLS:4650 inet n - - - - smtpd -o smtpd_enforce_tls=yes -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o content_filter=smtp-amavis:[127.0.0.1]:10026

# -o receive_override_options=no_address_mappings#628 inet n - - - - qmqpdpickup fifo n - - 60 1 pickup -o content_filter=

[... other stuff is here, but does not need editing ...]

# Insert at the bottom and adjust maxproc from 6 if needed:#smtp-amavis unix - - n - 6 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 - n - - smtpd -o content_filter= -o local_recipient_maps= -o relay_recipient_maps= -o smtpd_restriction_classes= -o smtpd_delay_reject=no -o smtpd_client_restrictions=permit_mynetworks,reject -o smtpd_helo_restrictions= -o smtpd_sender_restrictions= -o smtpd_recipient_restrictions=permit_mynetworks,reject -o smtpd_data_restrictions=reject_unauth_pipelining -o smtpd_end_of_data_restrictions= -o mynetworks=127.0.0.0/8 -o smtpd_error_sleep_time=0 -o smtpd_soft_error_limit=1001 -o smtpd_hard_error_limit=1000 -o smtpd_client_connection_count_limit=0 -o smtpd_client_connection_rate_limit=0 -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks

When finished editing:postconf -e "recipient_delimiter = +"/etc/init.d/postfix restart

Configure pyzor (to use a mirror):pyzor discoversu amavis -c 'pyzor discover'echo "82.94.255.100:24441" > /var/lib/amavis/.pyzor/serversecho "82.94.255.100:24441" > /root/.pyzor/serverssu amavis -c 'pyzor ping'

Pyzor Ping should show 'OK'. If not, then it's possible your firewall is blocking udp replies from 82.94.255.100. Weneed amavisd-nanny which can be used as a diagnostic program and amavisd-release (for amavisd-new version 2.4.2)which can be used to release quarantined messages:cd /usr/local/srcwget http://www.ijs.si/software/amavisd/amavisd-new-2.4.2.tar.gztar xzf amavisd-new-2.4.2.tar.gzcp amavisd-new-2.4.2/amavisd-release /usr/sbincp amavisd-new-2.4.2/amavisd-nanny /usr/sbinsed -i 's|/var/amavis/amavisd.sock|/var/run/amavis/amavisd.sock|' /usr/sbin/amavisd-releasesed -i 's|/var/amavis/db|/var/lib/amavis/db|' /usr/sbin/amavisd-nanny

SpamAssassin, by default, will automatically attempt to figure out which Received: headers were inserted by mailservers in your network, and which were not. However, to be safe it's best to manually configure the trust path. The IPaddresses listed in internal_networks and trusted_networks should be the IP addresses (or network addresses) ofhosts on you network. If you are behind a NAT box, this would include your internal network, your public network andthe loopback interface. If mail is relayed to you from a trusted 3rd party (maybe you use something like Postini to filteryour mail), then those servers would be added to trusted_networks (but not internal_networks).vi /etc/spamassassin/local.cf

Here is an example of what should be inserted:# explicitly set our internal_networks (might be the same or similar to mynetworks)clear_internal_networks

internal_networks 127/8internal_networks 222.222.222.222/24internal_networks 10.10.10.10/24# add the same to trusted_networks, and possibly other computers/networks whose mail we trustclear_trusted_networkstrusted_networks 127/8trusted_networks 222.222.222.222/24trusted_networks 10.10.10.10/24

Always lint SpamAssassin after modifying or adding files:spamassassin --lint

Once you have correctly configured these settings:amavisd-new stopamavisd-new starttail -f /var/log/mail.log

Test by sending a message through and observing output from mail.log. It can take between 1 second and 30 seconds(or even longer) to process a message.If you get clamd errors, /etc/init.d/clamav-daemon stop , wait a moment, /etc/init.d/clamav-daemon start , andwait a minute before continuing.

I quarantine viruses locally for 14 days, then delete them. If you would like to accomplish this task, grab the script fromme:cd /etc/cron.dailywget http://www200.pair.com/mecham/spam/rmvirusquar.txtmv rmvirusquar.txt rmvirusquarchmod +x rmvirusquar./rmvirusquar

Create Bayes and AWL tables in MySQLIndex Top Bottom

Placing Bayes and AWL data in MySQL will put some load on the MySQL server, but as long as you have beenreasonably generous with innodb_buffer_pool_size and innodb_log_file_size you will greatly improve Bayesperformance (do these in sections):cd /etc/spamassassin/wget http://www200.pair.com/mecham/spam/gv-bayes-awl.sql.txtsed -i 's/paSSw0rd/amavis_password/' gv-bayes-awl.sql.txtmysql -u root -p < gv-bayes-awl.sql.txt

Enter roots_password to complete the process.

rm gv-bayes-awl.sql.txtwget http://www200.pair.com/mecham/spam/local.cf-bayes-awl.txtcp local.cf local.cf-before-mysqlcat local.cf-bayes-awl.txt local.cf-before-mysql > local.cfsed -i 's/paSSw0rd/amavis_password/' local.cfspamassassin --lintamavisd-new reload

cdwget http://www200.pair.com/mecham/spam/sample-spam.txtsa-learn --spam sample-spam.txtsa-learn --dump magicspamassassin --lint

It should show our nspam (number of spam) count is 1, and --lint should be clean. We should also createour .spamassassin directory and user_prefs file:su amavis -c 'spamassassin <sample-spam.txt'

We continue by adding an AWL and bayes_seen maintenance script (watch for errors):cd /etcwget http://www200.pair.com/mecham/spam/trim-awl.sql.txtmv trim-awl.sql.txt trim-awl.sql

cd /usr/sbinwget http://www200.pair.com/mecham/spam/trim-awl.txtmv trim-awl.txt trim-awlchmod +x trim-awlsed -i 's/paSSw0rd/amavis_password/' trim-awlcd /etc/cron.weekly/wget http://www200.pair.com/mecham/spam/trim-sql-awl-weekly.txtmv trim-sql-awl-weekly.txt trim-sql-awl-weeklychmod +x trim-sql-awl-weeklysu - amavis /usr/sbin/trim-awl./trim-sql-awl-weekly

Once again make sure amavisd-new is processing messages. Send at least one test message and then read theheaders of the message. It should show X-Spam headers and such. It will not show any BAYES hits yet - it is requiredthat Bayes learns at least 200 ham messages first. I use autolearn (with an occasional manual feeding to sa-learn). Ido not cover using other means of feeding spam and ham to SpamAssassin in this HOWTO - see man sa-learn . TheSquirrelMail Spam Buttons plugin allows users to mark messages as 'Spam' or 'Not Spam' and feed them to sa-learnas such, but in a site wide database one has to remember that "one man's garbage is another man's treasure" and"too many cooks spoil the pot". Plus, there is the addition server load to consider - sa-learn is CPU intensive.

It would be a good idea to test clamd. After temporarily disabling your desktop AV program I would send a testmessage through with ONLY the eicar string in the body of the message (absolutely no whitespace before or after thestring - it must start and end on the very first line). You can stop amavisd-new and debug it with 'amavisd-new debug'or 'amavisd-new sa-debug' or you can raise $log_level or temporarily set @debug_sender_maps.

Configure and customize SquirrelMailIndex Top Bottom

Tell apache-ssl to use squirrelmail:echo "Include /etc/squirrelmail/apache.conf" >> /etc/apache-ssl/httpd.conf

I am going to set the SquirrelMail URL to https://msa.example.com/mail/, so:cd /etc/squirrelmail/sed -i "s|Alias /squirrelmail|Alias /mail|" apache.confsed -i "s|allow from 127.0.0.1|allow from 666.666.666.666|" apache.conf

/etc/init.d/apache-ssl restart

The 'allow from' IP address above is the IP address of your computer (as the mailserver sees it). Download someplugins:cd /usr/share/squirrelmail/plugins/wget http://www.squirrelmail.org/plugins/quota_usage-1.3.1-1.2.7.tar.gztar xzf quota_usage-1.3.1-1.2.7.tar.gzcp quota_usage/config.php.sample quota_usage/config.phpwget http://www.squirrelmail.org/plugins/timeout_user-1.1.1-0.5.tar.gztar xzf timeout_user-1.1.1-0.5.tar.gzwget http://www.squirrelmail.org/plugins/compatibility-2.0.7-1.0.tar.gztar xzf compatibility-2.0.7-1.0.tar.gzwget http://www.squirrelmail.org/plugins/amavisnewsql-0.8.0-1.4.tar.gztar xzf amavisnewsql-0.8.0-1.4.tar.gzmkdir /var/lib/amavis/.notstoredchown -R amavis:amavis /var/lib/amavissed -i 's/minutes = 120;/minutes = 20;/' timeout_user/config.phpcd amavisnewsqlcp config.php.dist config.php

sed -i 's|pgsql://postgres:@localhost|mysql://amavis:amavis_password@localhost|' config.phpsed -i 's|"yourdomain.com"|"example.com"|' config.phpsed -i 's|use_quarantine"] = true|use_quarantine"] = false|' config.phpsed -i 's|http://webmail.yourdomain.com|https://msa.example.com/mail|' config.phpsed -i 's|noreply@yourdomain.com|noreply@example.com|' config.phpsed -i 's|/htdocs/squirrel/|/usr/share/squirrelmail/|' utils/cleanquarantine.phpsed -i 's|/htdocs/squirrel/|/usr/share/squirrelmail/|' utils/generatedigest.phpsed -i 's|/htdocs/squirrel/|/usr/share/squirrelmail/|' utils/process_bsmtp.phpsed -i 's|/var/virusmails|/var/lib/amavis/virusmails|' utils/process_bsmtp.php

chown -R root:root /usr/share/squirrelmail/plugins/amavisnewsqlchmod 644 *chmod 755 contrib htmlMimeMail-2.5.1 locale po utilschmod 640 contrib/*chmod 640 htmlMimeMail-2.5.1/*chmod 640 utils/soap/*chmod 640 utils/*phpchmod 640 utils/*sqlchmod 640 config.phpchown root:www-data config.php

We did some configuration of amavisnewsql. We turned off its (broken) quarantine function (and because it is brokenwe send spam to either a folder or MailZu). Now we put some sanity constraints on what users can enter for tag2_level and kill_level and modify some of the text that users see. I also add the ability for the users to set spam_quarantine_cutoff_level which gives them the option to discard high scoring spam. New users are added to thedatabase when they log into SquirrelMail and go to Options->SpamAssassin Configuration.wget http://www200.pair.com/mecham/spam/amavisnewsql.patch1.txtsed -i 's/host.domain.tld/msa.example.com/' amavisnewsql.patch1.txtcp -p functions.php functions.php~cp -p amavisnewsql.class.php amavisnewsql.class.php~cp -p amavisnewsql.php amavisnewsql.php~patch -p0 < amavisnewsql.patch1.txt

Now start configuration (hint: enter squ[Tab]). Navigate to the items below from the main menu:squirrelmail-configure

1. Organization preferences. 1. Organization Name Widgits Inc. 7. Provider link https://msa.example.com/mail/

4. General Options 5. Usernames in Lowercase true 7. Hide SM attributions true 10. Allow server thread sort true 11. Allow server-side sorting true

D. Set pre-defined settings for specific IMAP servers courier

8. Plugins Plugins Installed Plugins 1. amavisnewsql 2. quota_usage 3. timeout_user

S Save dataQ Quit

You should be able to test the setup. If not, check /etc/squirrelmail/apache.conf for IP address access toconfigtest.php: https://msa.example.com/mail/src/configtest.php

Browse to your SquirrelMail site, then log in to SquirrelMail with your own account (and the test account):https://msa.example.com/mail/

If you get an error: "Preference file, /test@example.com.pref.tmp, could not be opened." it means this user wouldneed to go to Options and Personal Information and enter their name and email address. When you add users inPostfixAdmin, the preferences file in /var/lib/squirrelmail/data/ should automatically be created via the maildirmake.shscript. At some point you will no doubt wish to replace the SquirrelMail logo with yours. Place it in /usr/share/squirrelmail/images/ and change the size as required in the "Organization preferences" page.

Configure RazorIndex Top Bottom

cdrm /etc/razor/razor-agent.confrazor-admin -create

razor-admin -createrazor-admin -register

If you get an error: Error 202 while performing register, aborting., you may need to run the 'razor-admin register'command more than once. Don't worry about it if /etc/razor/razor-agent.conf does not exist. Here we disable loggingand then give amavisd-new a copy of the razor files:sed -i 's/= 3/= 0/' /root/.razor/razor-agent.confcp -r /root/.razor /var/lib/amavischown -R amavis:amavis /var/lib/amavis

Install pflogsummIndex Top Bottom

apt-get install pflogsumm

cd /etc/cron.dailywget http://www200.pair.com/mecham/spam/pflogsumm.shsed -i 's|DAILY mail|DAILY msa mail|' pflogsumm.shmv pflogsumm.sh pflogsummchmod +x pflogsumm

Then just make sure you have a mailbox (or alias) for root. Root will get a report each morning after 06:25. Hint: cat /etc/crontab. There is one problem with the report. Any email that gets sent to amavisd-new, which includes most mailthat isn't rejected at the front door, also comes back from amavisd-new. This means Postfix sees the email twice. Sothe report lists them twice. For those that are interested, there are a couple scripts out there that pre-process the logfiles to prevent reporting amavis entries: http://web.tiscali.it/postfix/prepflog.html and http://www.caspergasper.com/spam.shtml

Install BINDIndex Top Bottom

apt-get install bind9

/etc/init.d/bind9 stop

sed -i 's|"-u bind"|"-u bind -t /var/lib/named"|' /etc/default/bind9mkdir -p /var/lib/named/etcmkdir /var/lib/named/devmkdir -p /var/lib/named/var/cache/bindmkdir -p /var/lib/named/var/run/bind/runmv /etc/bind /var/lib/named/etcln -s /var/lib/named/etc/bind /etc/bindmknod /var/lib/named/dev/null c 1 3mknod /var/lib/named/dev/random c 1 8chmod 666 /var/lib/named/dev/null /var/lib/named/dev/randomchown -R bind:bind /var/lib/named/var/*chown -R bind:bind /var/lib/named/etc/bind/etc/init.d/bind9 start

lsof -i | grep :domaintail -13 /var/log/syslog

The result of the last two commands should show 'named' is running without error. Now we create a new /etc/resolv.conf with the IP address of the server first and the IP address of the former primary DNS second:cp /etc/resolv.conf /etc/resolv.conf-oldecho "search example.com" > /etc/resolv.confecho "nameserver 111.111.111.111" >> /etc/resolv.confecho "nameserver 444.444.444.444" >> /etc/resolv.conf

Then restart bind9 and check for errors again:/etc/init.d/bind9 restartlsof -i | grep :domain

tail -13 /var/log/syslog

So far we have set up bind9 as a local caching only name server. Here we add an additional security measure thatprevents unauthorized machines from using our name server:vi /etc/bind/named.conf.options

On the line below "directory" we want to add a line that restricts use of our name server to the network our mailserveris on. Place a [Tab] in front of the entry so it lines up with the other entries. You can add more than one network hereif you like. Place a ";" (semicolon) after each network. Note that if you actually want to allow other clients to connect toour name server, as explained in the notes above you would also have to modify IP tables to allow this.allow-query {222.222.222.222/24;};

Then restart bind9 and check for errors again:/etc/init.d/bind9 restartlsof -i | grep :domaintail -13 /var/log/syslog

Optionally configure bind9 as a forwarding server. Bind9 as we have it configured now will first query the rootservers for hints when needed. I prefer to forward queries to another name server instead. There are advantages anddisadvantages in doing this, but I prefer it. It is absolutely imperative that any name servers listed here are known towork from our mailserver. These will almost certainly be the primary and secondary servers you previously configuredin /etc/resolv.conf or your ISP's servers (not 127.0.0.1, and not the IP address of the local machine). They shouldpoint to real name servers and not a DNS proxy like your Linksys broadband router or other gateway device (unlessthat proxy does not allow proper access to real name servers outside your network - which is sometimes the case).Add the 'forwarders' entry just below the 'allow-query' entry we just made:vi /etc/bind/named.conf.options

and add:forwarders {444.444.444.444; 555.555.555.555;};

To never query the root servers, optionally add (personally I do add this):forward only;

Then restart bind9 and check for errors again:/etc/init.d/bind9 restartlsof -i | grep :domaintail -13 /var/log/syslog

We added a new user to /etc/passwd so give Postfix a copy:LINUX2

Check that we can resolve names:dig yahoo.com

In the ANSWER SECTION you should see some A records with IP addresses and near the bottom the SERVER:should be this server.

Additional Postfix configurationIndex Top Bottom

A few of these lines wrap (considerably) so I will assume you are going to select the entire sections. If you need toedit anything, paste it into Notepad (with Word Wrap turned off) first.postmap /etc/postfix/sender_accesspostmap /etc/postfix/rbl_client_exceptionspostmap /etc/postfix/rbl_sender_exceptionspostmap /etc/postfix/rbl_recipient_exceptionspostmap /etc/postfix/reject_over_quota

cp /etc/postfix/main.cf /etc/postfix/main.cf-changespostconf -e "smtpd_hard_error_limit = 10"postconf -e "smtpd_soft_error_limit = 8"postconf -e "smtpd_helo_required = yes"postconf -e "smtpd_sender_restrictions = check_sender_access hash:/etc/postfix/sender_access,reject_non_fqdn_sender, reject_unknown_sender_domain"postconf -e "smtpd_data_restrictions = reject_unauth_pipelining"postconf -e "smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated,

reject_unauth_destination, reject_unlisted_recipient, check_recipient_access hash:/etc/postfix/reject_over_quota, check_sender_access hash:/etc/postfix/rbl_sender_exceptions, check_client_access hash:/etc/postfix/rbl_client_exceptions, check_recipient_access hash:/etc/postfix/rbl_recipient_exceptions, reject_rbl_client sbl-xbl.spamhaus.org"/etc/init.d/postfix restarttail -f /var/log/mail.log

Send another test message to make sure we did not break something. You can use sender_access to whitelistsenders that would get rejected by either reject_non_fqdn_sender or reject_unknown_sender_domain. You can userbl_sender_exceptions and/or rbl_client_exceptions to whitelist those who would otherwise get rejected by sbl-xbl.spamhaus.org. rbl_recipient_exceptions is for those recipients that wish to 'opt out' of RBL checks (postmaster andabuse come to mind). These next settings are not related to UCE.

If (and only if) the IP address you present to the world is not the IP address of this server (you are configured to runbehind a NAT firewall or a proxy server) please configure proxy_interfaces (1.2.3.4 represents the public IP address):postconf -e "proxy_interfaces = 1.2.3.4"

At some point in the future, if you have clients on the local network that are going to use this server as their outgoingSMTP server, you may need to configure $mynetworks. Clients in mynetworks will bypass the reject_unauth_destination restriction and therefore be allowed to relay to domains other than ours. You can use mynetworks or youcan use SASL auth. I have not had you configure $mynetworks until now because it is useful during testing to not be amember in $mynetworks.

Let's create a little report that runs each morning that shows us how much mail is in our queues. This could serve asan alarm if the queues are stacked up:vi /etc/cron.d/qshape-cron

and insert these two lines:PATH=/usr/sbin50 6 * * * postfix /usr/sbin/qshape incoming active deferred 2>&1 |/usr/bin/mail -s "qshape msa"root

Root should get a report tomorrow at 06:50. Then we have to shut logcheck up (this is on one line):echo "^\w{3} [ :0-9]{11} [._[:alnum:]-]+ postfix/pickup\[[0-9]+\]: [[:alnum:]]+: uid=[0-4]+from=<postfix>" >>/etc/logcheck/ignore.d.server/postfix

By default "message_size_limit = 10240000" which is 10MB. Later we will install MailZu. When we do, we will alsoneed to change memory_limit in /etc/php4/apache/php.ini to match this. Let's set that now:sed -i 's/memory_limit = 8M/memory_limit = 10M/' /etc/php4/apache/php.ini/etc/init.d/apache-ssl restart

Another setting that would need to be updated if we changed the limit is in /etc/clamav/clamd.conf. The setting isArchiveMaxFileSize. Let's change the limit to 20MB, just to show how it might be done:postconf -e "message_size_limit = 20480000"/etc/init.d/postfix restartsed -i 's/ArchiveMaxFileSize 10M/ArchiveMaxFileSize 20M/' /etc/clamav/clamd.conf/etc/init.d/clamav-daemon restartsed -i 's/memory_limit = 10M/memory_limit = 20M/' /etc/php4/apache/php.ini/etc/init.d/apache-ssl restart

postconf message_size_limitgrep ArchiveMaxFileSize /etc/clamav/clamd.confgrep memory_limit /etc/php4/apache/php.ini

Set up PostfixAdmin VacationIndex Top Bottom

There are a lot of good reasons not to use an autoresponder. One reason is: most of the mail we receive is spam andthe senders use forged addresses. You will either be sending notices to senders who did not send you mail, or you willfill up your deferred queue with undeliverable mail. There are often other problems like multiple deliveries or thepotential for infinite loops. The 'cache' field in the vacation table that stores email addresses of senders we havealready sent notices to can fill up and cause errors. Use at your own risk. We will not use vacation.pl as supplied withPostfixAdmin. I just want to make sure you are using version 3.2, so get a copy from me. My copy also makes onesmall change: the envelope sender will be the null sender <>. Even though we have the latest version, there may be

some lingering issues with vacation.pl; see http://high5.net/forum/

apt-get install libdbi-perl libdbd-mysql-perl

addgroup --gid 65501 vacationuseradd -c "Virtual Vacation" -d /nonexistent -u 65501 -g 65501 -s /sbin/false vacationmkdir /var/spool/vacationcd /var/spool/vacation/wget http://www200.pair.com/mecham/spam/gv-vac.txt

mv gv-vac.txt vacation.plsed -i "s/db_pass = 'postfixadmin/db_pass = 'pfixadm_password/" vacation.plchown -R vacation:vacation /var/spool/vacationchmod 750 vacation.plcd

We place an entry in /etc/postfix/transport that will send mail to the vacation script. This is a bogus (sub)domain name.It does not need to be set up in DNS:vi /etc/postfix/transport

and insert:autoreply.example.com vacation:

vi /etc/postfix/master.cf

and insert (just below the maildrop transport might be a good place):

vacation unix - n n - - pipe flags=Rq user=vacation argv=/var/spool/vacation/vacation.pl -f ${sender} -- ${recipient}

Then:postmap /etc/postfix/transportpostconf -e "transport_maps = hash:/etc/postfix/transport"LINUX2

Now we configure PostfixAdmin to use vacation:sed -i "s/vacation'] = 'NO/vacation'] = 'YES/" /var/www/postFixadminx/config.inc.php

To change their Auto Response settings, a user could log into:https://msa.example.com/postFixadminx/users

However, we can avoid users logging into PostfixAdmin by setting up a PostfixAdmin plugin in SquirrelMail (jumpahead to the next section to set it up - then return here) https://msa.example.com/mail. Test by logging into your ownaccount and setting yourself up. Remember that the database records the senders it has already seen (so only onenotice is sent per sender). To clear out the cache and start over, return from your vacation by choosing AutoResponse->Coming Back and then Auto Response->Going Away again. Use phpMyAdmin to browse the database asyou make changes.

Now that vacation is working, consider turning it off so no one can use it. First use https://msa.example.com/phpmyadmiNx to make sure there are no entries in the vacation table and no aliases that send mail to @autoreply.example.com, then:

sed -i "s/vacation'] = 'YES/vacation'] = 'NO/" /var/www/postFixadminx/config.inc.phpsed -i "s/Vacation = true/Vacation = false/" /usr/share/squirrelmail/plugins/postfixadmin/config.php

Install postfixadmin SquirrelMail pluginIndex Top Bottom

There are two versions of this plugin out there. The one I use may be more secure:pear install MDB2-2.4.1pear install MDB2_Driver_mysql-1.4.1

cd /usr/share/squirrelmail/plugins/wget http://codepoets.co.uk/files/postfixadmin-0.4.1.tar.gz

tar xzf postfixadmin-0.4.1.tar.gzmv postfixadmin-0.4.1 postfixadminchown -R root:root postfixadmincd postfixadmincp config.php.sample config.phpflip -u *.phpflip -u config.php.samplesed -i "s/postgres/mysql/" config.phpsed -i "s/xxxxx/pfix_password/" config.phpsed -i "s/autoreply.my.domain.com/autoreply.example.com/" config.phppostconf -e "vacation_destination_recipient_limit = 1"wget http://www200.pair.com/mecham/spam/postfixadmin_forward.patch.txtcp postfixadmin_forward.php postfixadmin_forward.php~patch -p0 < postfixadmin_forward.patch.txt

squirrelmail-configure

Then install the plugin (the order in which the plugins are listed may be different):8. Plugins Plugins Installed Plugins 1. amavisnewsql 2. quota_usage 3. timeout_user 4. postfixadmin

S Save dataQ Quit

Now users will not need to log into PostfixAdmin to change their password, forwarding or Out of Office. Now they havesimilar functions in SquirrelMail (on the Options page). https://msa.example.com/mail

If you turn off vacation in PostfixAdmin, then you also need to turn off vacation in the SquirrelMail postfixadmin plugin(first use https://msa.example.com/phpmyadmiNx to make sure there are no entries in the vacation table and noaliases that send mail to @autoreply.example.com):

sed -i "s/vacation'] = 'YES/vacation'] = 'NO/" /var/www/postFixadminx/config.inc.phpsed -i "s/Vacation = true/Vacation = false/" /usr/share/squirrelmail/plugins/postfixadmin/config.php

Install MailZuIndex Top Bottom

This little section represents two days of experimentation and research just to get MailZu running. All mail left in theMailZu quarantine longer than 24 days is deleted.

apt-get install php-mail-mime php4-imap

Continue installing libc-client without Maildir support? [YES]

apache-modconf apache-ssl enable mod_imap/etc/init.d/apache-ssl restart

We are going authenticate users using a couple imap functions (but we will actually use the imap functions toauthenticate via POP3), so we loaded in the mod_imap module. With the encrypted passwords we have, POP3 wasthe only interface I could get to work. The IMAP interface would have worked were it not for the AUTH=CRAM-MD5setting we placed in /etc/courier/imapd. It appears to confuse the imap_open function used to connect to the server.Use of POP3 is undocumented and requires a slight change in one line of code in IMAPAuth.class.php:cd /var/wwwwget http://www.MailZu.net/download/MailZu_0.8RC3.tar.gztar xzf MailZu_0.8RC3.tar.gzmv MailZu_0.8RC3.tar.gz /usr/local/src/mv MailZu_0.8RC3 mailzucd mailzu/configcp config.php.sample config.php

cp config.php.sample config.php~wget http://www200.pair.com/mecham/spam/mzcpatch.txtpatch -p0 < mzcpatch.txt

Note that the configuration changes below will only work if you first apply my mzcpatch.txt patch. The only thing thepatch does is change the example domain names (because they conflict with this howto).sed -i "s/'user'/'amavis'/" config.phpsed -i "s/'pass'/'amavis_password'/" config.phpsed -i "s/'dbname'/'amavis'/" config.phpsed -i "s/hostname.domain.tld/localhost/" config.phpsed -i "s/binquar'] = false/binquar'] = true/" config.phpsed -i "s/'auth']\['serverType'] = 'ldap'/'auth']\['serverType'] = 'imap'/" config.phpsed -i "s|imaphost.domain.tld:143|localhost:110/pop3/novalidate-cert|" config.phpsed -i "s/'imap_type'] = 'imapssl'/'imap_type'] = 'imap'/" config.phpsed -i "s/'imap_domain_name'] = 'domain.tld'/'imap_domain_name'] = ''/" config.phpsed -i "s/mailzuhost.domain.tld/msa.example.com/" config.phpsed -i "s/'emailType'] = 'mail'/'emailType'] = 'sendmail'/" config.phpsed -i "s/'recipient_delimiter'] = ''/'recipient_delimiter'] = '+'/" config.phpsed -i "s/support@domain.tld/postmaster@example.com/" config.phpsed -i "s/'allowBadHeaders'] = 0/'allowBadHeaders'] = 1/" config.phpcp ../lib/IMAPAuth.class.php ../lib/IMAPAuth.class.php~sed -i "s/, OP_HALFOPEN//" ../lib/IMAPAuth.class.phpcp ../lib/DBEngine.class.php ../lib/DBEngine.class.php~sed -i 's/dbtype/dbType/' ../lib/DBEngine.class.phptouch /var/log/mailzu.logchown www-data:www-data /var/log/mailzu.logchmod 660 /var/log/mailzu.logchown -R root:www-data /var/www/mailzuchmod 640 config.php

cd /etc/logrotate.dwget http://www200.pair.com/mecham/spam/mailzu.logrotate.txtmv mailzu.logrotate.txt mailzu

In 50-user we need to change a few things.vi /etc/amavis/conf.d/50-user

Change this:$inet_socket_port = [10024, 10026];## If using Mailzu, use this instead:#$inet_socket_port = [10024, 10026, 9998];

To this (add 9998 to $inet_socket_port):#$inet_socket_port = [10024, 10026];## If using Mailzu, use this instead:$inet_socket_port = [10024, 10026, 9998];

Change:$inet_socket_bind = '127.0.0.1';## If using Mailzu, use this instead:#$inet_socket_bind = undef;

To (listen on all interfaces):#$inet_socket_bind = '127.0.0.1';## If using Mailzu, use this instead:$inet_socket_bind = undef;

Then enable the policy bank; change:## Interface to MailZu#$interface_policy{'9998'} = 'MAILZU';#$policy_bank{'MAILZU'} = {# protocol => 'AM.PDP',# inet_acl => [qw( 127.0.0.1 [::1] 111.111.111.111 )],#};

Make sure this next entry contains our local IP address (where 111.111.111.111 is the IP address of this machine):

## Interface to MailZu$interface_policy{'9998'} = 'MAILZU';$policy_bank{'MAILZU'} = { protocol => 'AM.PDP', inet_acl => [qw( 127.0.0.1 [::1] 111.111.111.111 )],};

Enable quarantine to SQL; uncomment these two lines as shown:# If using MailZu, store banned files and spam to MySQL if you want to give users the# ability to read those messages in the MailZu interface:$banned_files_quarantine_method = 'sql:';$spam_quarantine_method = 'sql:';

Once finished editing, reload amavisd-new:amavisd-new reload

Quiet down logcheck:echo "amavis\[[0-9]+\]: \(rel-.{12}\) Quarantined message release:" >>/etc/logcheck/ignore.d.server/amavisd-newecho "amavis\[[0-9]+\]: \(rel-.{12}\) Quarantine release" >> /etc/logcheck/ignore.d.server/amavisd-new

This should be enough configuration for you to log in (as a regular user). https://msa.example.com/mailzu. Now youcan start experimenting. Log into SquirrelMail and change the recipient's SpamAssassin settings to "All spam toquarantine". This particular policy will quarantine at a score of 8 or higher and there is no spam_quarantine_cutoff_level in force. Send a message containing the gtube string (which will insure the message scores over 12) and thenwait for it to show up in the quarantine. Release the message and see if it is delivered. Double check your settings ifyou get an error. Review the "Amavisd-new Configuration" notes at vi /var/www/mailzu/docs/INSTALL . Make surethe hostname of the server resolves properly. If necessary, read the mailing list archives.

Now you will want to vi config.php and familiarize yourself with all the possible settings - including verbose logging.You may wish to make changes. One thing you will need to do is to create an administrator or two. See this section:

// Super Admins can do anything mail admins can plus// change settings$conf['auth']['s_admins'] = array ('user1', 'user2');

// Mail Admins can see other users' spam and attachments// and can perform any action on them$conf['auth']['m_admins'] = array ();

You will want to spend some time sending banned files and spam to your test user and having the test user releasesome spam and request banned files get released. You will want to spend some time as the administrator, respondingto this user's requests. As Jerry Seinfeld says: "Well.. good luck with all that!".

QuotaIndex Top Bottom

When we create a new mailbox, the maildirmake.sh script enters the quota information in a 'maildirsize' file located inthe user's maildir. When we edit a user's mailbox, the quotachange.sh script updates the quota information. Each timea message comes or goes from a user's INBOX the 'maildirsize' file is updated. Because we are using maildrop as aLDA (Local Delivery Agent), Postfix has no way of knowing how many bytes of data the recipient's mailbox contains,but maildrop can figure it out. In the maildrop transport in master.cf is a flag: "-w 90". This tells maildrop to send awarning message to the recipient when the size of their mailbox has reached 90% of their quota. You have to createthis message. Here is a sample we will install:vi /etc/quotawarnmsg

and insert (and edit as needed):

From: Mail Delivery System <Mailer-Daemon@example.com>Reply-To: postmaster@example.comTo: "Valued Customer";Subject: Mail quota warningMime-Version: 1.0

Content-Type: text/plain; charset=iso-8859-1Content-Transfer-Encoding: 7bit

Your mailbox on the example.com server is now more than 90% full.To continue to receive mail you must remove some messages from your mailbox.If you should reach 100% of your quota, mail delivery to you will stop.

If using an email client such as Microsoft Outlook Express or MozillaThunderbird (for example) to access your mail, moving messages to a localfolder may reduce the number of messages on our server.

Your quota is displayed in the web interface at https://msa.example.com/mail

If you feel your quota is too restrictive, please contact postmaster@example.com

Thank You

To test this you would first empty out all mail from the test user. https://msa.example.com/mail would be handy forthis task (and to test). Then log in to https://msa.example.com/postFixadminx and edit that user's mailbox, settingthe quota to 1MB. Verify maildirsize was updated:cat /var/vmail/example.com/test/maildirsize

My system shows:1024000S 0 0

Find a file that will not get rejected by amavisd-new (.txt .doc .xls .html .pdf) with a size around 70KB that can be usedas an attachment. We want to send a series of messages to the test user that contains this attachment. We want totrigger the quota warning message by sending a series of messages that will total over 900KB (use the Check Maillink in the SquirrelMail interface to refresh the quota usage data). Once you are over 90%, if you log out and log backin to SquirrelMail you will see a warning message. One thing the message suggests is that you empty your trash.That's nice, but the truth is trash does not count toward the quota. The recipient should also get our message with theSubject: "Mail quota warning". The recipient is only warned once every 24 hours (controlled by existence of 'quotawarn'file) so if you want to test again, you will have to remove the quotawarn file from the recipient's maildir:find /var/vmail -name quotawarn

Once you are satisfied with your message, send another message that puts this user over the top of their quota. If youlook in mail.log you will see that the message has not been sent to the user but instead has been placed in thedeferred queue (which can also be confirmed with the mailq command):Jul 1 10:20:11 msa postfix/pipe[7387]: 57FAA24156: to=<test@example.com>, relay=maildrop,delay=0.15, delays=0.08/0.02/0/0.05, dsn=4.3.0, status=deferred (temporary failure. Commandoutput: maildrop: maildir over quota. )

So now this mail will be stuck in the deferred queue until the user either deletes some messages to make room for it,or you increase their quota. Logcheck will notify you of the failure to deliver. If this user is unresponsive to requests toclean up their mailbox, all new mail for this user will get deferred (and eventually returned to the sender after 5 days -Postfix $maximal_queue_lifetime). If this is the case you may want to manually intervene and start rejecting mail to thisuser instead of holding on to it for them (don't be tempted to delete mail from the deferred queue when this machinegoes into production - it's not your mail to delete). To do so, you could add this recipient to /etc/postfix/reject_over_quota with something like this (this is all on one line):test@example.com REJECT The recipient's mailbox is full - your message was not delivered torecipients hosted on the example.com mail server

Then of course:postmap /etc/postfix/reject_over_quota

The downside to this is that the entire message will get rejected. If the message is addressed to multiple recipients onyour server, none will receive the message. This can't be fair to the sender, or the other recipients, so I wouldconsider it only in extreme cases.

Install Mailgraph - OptionalIndex Top Bottom

Mailgraph produces daily, weekly, monthly and yearly graphs of received/sent and bounced/rejected mail.apt-get install rrdtool mailgraph

sed -i 's/IGNORE_LOCALHOST=false/IGNORE_LOCALHOST=true/' /etc/default/mailgraphsed -i 's!) SPAM\\!) (SPAM|SPAMMY)\\!' /usr/sbin/mailgraph/etc/init.d/mailgraph restart

It may take a minute for this to work, but eventually if you browse to https://msa.example.com/cgi-bin/mailgraph.cgiyou should get some graphs.

Install mysql-zrmIndex Top Bottom

This nice little program can perform backups of our MySQL data. We will make local backups (and keep 3 days worth). We will talk about backing up the entire system later.apt-get install libxml-parser-perl

cd /usr/local/srcwget http://www.zmanda.com/downloads/community/ZRM-MySQL/1.2/Debian/mysql-zrm_1.2_all.debdpkg -i mysql-zrm_1.2_all.deb

sed -i 's/#user="wikiuser"/user="root"/' /etc/mysql-zrm/mysql-zrm.confsed -i 's/#password="userwiki"/password="roots_password"/' /etc/mysql-zrm/mysql-zrm.confsed -i 's/#retention-policy=10W/retention-policy=3D/' /etc/mysql-zrm/mysql-zrm.confsed -i 's/#mailto="mysqldba@company.com"/mailto="root@example.com"/' /etc/mysql-zrm/mysql-zrm.confchown root:root /usr/share/man/man5/mysql-zrm*chown root:root /usr/share/man/man1/mysql-zrm*chmod 644 /usr/share/man/man5/mysql-zrm*chmod 644 /usr/share/man/man1/mysql-zrm*

mysql-zrm-scheduler --now --backup-set dailyrun --backup-level 0

mysql-zrm-scheduler --add --interval daily --backup-set dailyrun --backup-level 0

This places entries in root's crontab. Run crontab -e and see if you have any extra newline characters separating anyentries (and edit them out). The details of what just happened can be found here: http://www.howtoforge.com/mysql_zrm_debian_sarge. I suggest you save all five pages of that HOWTO to your computer (and maybe read them too).This program will send you a couple (annoying) email messages each day.

The alias issueIndex Top Bottom

At this point, we have a little problem. The problem is with aliases. Alias expansion occurs twice, once when amessage comes in the front door via one of the smtpd daemons, and once again when amavis returns the message tothe Postfix reinjection port (listening on port 10025). So, address rewriting occurs both before amavisd-new, and afteramavisd-new. Why does this matter? For each user added via PostfixAdmin, there is an entry created in thepostfix.alias table in the form:

test@example.com test@example.com

If a user adds a forwarder (via either the SquirrelMail or PostfixAdmin interface - and if the PostfixAdmin interface isused, they choose "Deliver to the local mailbox."), the user's alias record may now look something like this:

test@example.com test@example.com,garyv@example.net

In this example, test@example.com is a real user on our system, and the garyv@example.net mailbox is hosted bysomeone else. So, the message will now be addressed to both test@example.com and garyv@example.net. Afteramavisd-new processes the message, two separate messages emerge, one to test@example.com, and one togaryv@example.net. It's the one addressed to test@example.com that is the problem. Since the reinjection port at127.0.0.1:10025 is just another smtpd daemon (which uses the cleanup daemon to facilitate rewriting the address),Postfix addresses this message to both test@example.com and garyv@example.net (again). The result is, garyv@

example.net gets two copies of the same message (test@example.com only gets one copy because the messagewas already addressed to test@example.com).

When I first wrote this document, I disabled address rewriting before amavisd-new (I used "-o receive_override_options=no_address_mappings" on the Internet facing smtpd daemons). This could work if all mail came in addressedto "hard" users (users with actual mailboxes), but if (as the administrator) you want to create an alias something likethis:

test.user@example.com test@example.com

where test@example.com has a mailbox (and is in the amavis database) and test.user@example.com is created bythe admin merely as a convenient way to redirect mail to the actual account, this does not work well if addressrewriting only occurs after amavisd-new. The reason is, test.user@example.com would end up using the defaultsettings in amavisd.conf or 50-user rather than the settings test@example.com desired (the settings stored in theMySQL database). So, what can we do? One option would be to edit the 127.0.0.1:10025 smtpd daemon and changethis override:

-o receive_override_options=no_header_body_checks,no_unknown_recipient_checks

to: -o receive_override_options=no_address_mappings,no_header_body_checks,no_unknown_recipient_checks

but the problem is, as shown in the next "Acting as a relay server" section, there are situations where we don't actuallywant to completely disable address rewriting after amavisd-new, we may simply want to use a different virtual aliastable (or no virtual alias table). To that end, we will add a new cleanup daemon that amavisd-new can use, then, forthe moment we tell this cleanup daemon not to use a virtual alias table. vi /etc/postfix/master.cf and copy the currentcleanup daemon, name the copy amavis-cleanup and add an override that disables the current virtual alias maps:

cleanup unix n - - - 0 cleanupamavis-cleanup unix n - - - 0 cleanup -o virtual_alias_maps=qmgr fifo n - n 300 1 qmgr

Then, on the reinjection port, tell Postfix to use this new cleanup daemon for mail that amavisd-new sends to it:

127.0.0.1:10025 inet n - n - - smtpd -o cleanup_service_name=amavis-cleanup -o content_filter= -o local_recipient_maps=

<...>

Save and exit the file, then:/etc/init.d/postfix stop/etc/init.d/postfix start

You can get more creative with this (if you need to). I suggest reading: http://www.ijs.si/software/amavisd/README.postfix.html and http://www.ijs.si/software/amavisd/README.postfix.old

Note, if the user uses the PostfixAdmin interface to change the Forwarding alias(es) and they choose the "Forward togiven email addresses only." option (as opposed to the "Deliver to the local mailbox." option), the postfix.alias recordwould look more like this:test@example.com garyv@example.net

In this example, garyv@example.net is still a remote mailbox. Keep in mind that remote mailboxes are not going tohave their email address in the amavis MySQL database (unless you manually add them), so this type of recipient willend up using the default (static) settings in the 50-user or amavisd.conf files.

Acting as a relay serverIndex Top Bottom

You may have domains that are not going to store their mail on this server but instead want this box to clean up theirmail for them and then relay it on to them. The biggest issue you have to deal with in this scenario is how to rejectmail to invalid users. The downstream servers may know who their valid users are, but this server does not.Nonetheless, you must obtain this information one way or another so you can reject mail to invalid users. But first weneed to get to the point where mail is routed to them. Note that the current mysql_virtual_domains_maps.cf is replaced

with one than is compatible with mysql_relay_domains_maps.cf:cd /etc/postfixtest -e mysql_relay_domains_maps.cf && mv mysql_relay_domains_maps.cf mysql_relay_domains_maps.cf-oldwget http://www200.pair.com/mecham/spam/mysql_relay_domains_maps.cfsed -i 's/password = postfix/password = pfix_password/' mysql_relay_domains_maps.cfmv mysql_virtual_domains_maps.cf mysql_virtual_domains_maps.cf-before-relay-domainswget http://www200.pair.com/mecham/spam/mysql_virtual_domains_maps.cf.v2mv mysql_virtual_domains_maps.cf.v2 mysql_virtual_domains_maps.cfsed -i 's/password = postfix/password = pfix_password/' mysql_virtual_domains_maps.cfchmod 640 mysql_*chown root:postfix mysql_*postconf -e "relay_domains = proxy:mysql:/etc/postfix/mysql_relay_domains_maps.cf"postconf -e "transport_maps = hash:/etc/postfix/transport"touch /etc/postfix/transportpostmap /etc/postfix/transport

We are not going to store transport map data in MySQL (if later you want to, I leave it up to you to figure out how todo it). Each domain you relay for will need an entry in the transport map. The left hand side is the domain and the righthand side is the host name or IP address of the next hop server (with square brackets used to turn off MX lookups).This is the general format of the contents of /etc/postfix/transport (you can vi /etc/postfix/transport and enter validdata for your situation):example.net relay:[777.777.777.777]example.org relay:[mail.example.org]

Use https://msa.example.com/postFixadminx/admin/ to add the relay domain(s). When you add the domain(s),check the "Mail server is backup MX:". The domain is now a relay domain. You cannot add mailboxes to relaydomains. You cannot create aliases for relay domains. Once the domains have been added, you can reload postfix,and because we have added a domain or domains to /var/lib/amavis/local_domains we should also reload amavisd-new:postmap /etc/postfix/transportpostfix reloadamavisd-new reloadcat /var/lib/amavis/local_domains

So now we have a problem. Let's say we have added two domains, one relays mail to a server running sendmail andthe other relays mail to a server running Microsoft Exchange 2000. Our server will accept mail addressed to anyrecipient in either domain. This particular sendmail server is configured to immediately reject mail to invalid users.When it rejects a message, Postfix will create a bounce notice and attempt to deliver it to the sender. If the sender iscompletely bogus, the message will sit in our deferred queue for days while delivery attempts are made. If the senderis faked but points to a real address, then we are spamming an innocent victim. This victim is getting "joe jobbed" -and we are facilitating it - and now we are a source of backscatter. If we send a message to the domain that forwardsto the sendmail server, we can see from the bounce notice that the downstream server (at the hypothetical address of777.777.777.777) rejected it:

<testgarbage@example.net>: host msa.example.com[111.111.111.111] said: 550 <testgarbage@example.net>: Recipient address rejected: undeliverable address: host 777.777.777.777[777.777.777.777] said: 550 5.1.1 <testgarbage@example.net>... User unknown (in reply to RCPT TO command) (in reply to RCPT TO command)

In this case (the case being the downstream server immediately rejects mail to invalid users) we can use eitheraddress verification or relay_recipient_maps. If we relay a message to the Exchange server, the Exchange serveraccepts the message and later generates a bounce notice which it mails to the sender. We can only use relay_recipient_maps in this case. Let's set up address verification for example.net. Since this will be a mixed setup (bothreject_unverified_recipient and relay_recipient_maps will be utilized), we will have to detect the recipient domain (thatis able to use reject_unverified_recipient):vi /etc/postfix/verify_domains

and insert the domain(s) that use server(s) that will immediately reject mail to unknown users:example.net reject_unverified_recipient

then postmap it:postmap /etc/postfix/verify_domains

vi /etc/postfix/main.cf , make smtpd_recipient_restrictions pretty like this and add the red item in the position shown.Read the beginning (half dozen lines or so) of http://www.postfix.org/postconf.5.html:

smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, reject_unlisted_recipient, check_recipient_access hash:/etc/postfix/verify_domains, check_recipient_access hash:/etc/postfix/reject_over_quota, check_sender_access hash:/etc/postfix/rbl_sender_exceptions, check_client_access hash:/etc/postfix/rbl_client_exceptions, check_recipient_access hash:/etc/postfix/rbl_recipient_exceptions, reject_rbl_client sbl-xbl.spamhaus.org

Also add these items to main.cf:address_verify_map = btree:/etc/postfix/address_verify_map# Uncomment this next line when finished testing address verification:#unverified_recipient_reject_code = 550

postfix reload and test the setup (by sending mail to invalid users in the relay domain and reading the log). Whenfinished testing, uncomment the unverified_recipient_reject_code line.

With the other domain (example.org) we need to set up relay_recipient_maps. We will create /etc/postfix/relay_recipients. Once relay_recipient_maps is configured in main.cf, any recipient or recipient domain of a relay domain notlisted in /etc/postfix/relay_recipients will get rejected. This means /etc/postfix/relay_recipients must contain everysingle recipient of every single relay domain this machine accepts mail for. However, domain wildcards can be used asplaceholders. In our example case, example.net is already using address verification to reject mail to invalid users, sowe can use a wildcard for that domain: @example.net. For example.org we can start out with a wildcard while we arein the process of gathering valid addresses:vi /etc/postfix/relay_recipients

@example.net 1@example.org 1

but once we have all the address gathered, we need to get rid of the wildcard:@example.net 1#@example.org 1user1@example.org 1user2@example.org 1user3@example.org 1user4@example.org 1

Then of course:postmap /etc/postfix/relay_recipients

The "1" after each entry could be something else, like "OK" or something. It's not important what the actual text isbecause it's not used for anything, but it must exist. To set up relay_recipient_maps:postconf -e "relay_recipient_maps = hash:/etc/postfix/relay_recipients"postfix reload

Since there are no mailboxes for relay domains, we cannot log into SquirrelMail to change amavisd-new settings(actually, in a moment I explain how this can be done). At the moment all relay domain recipients will use the staticsettings in amavisd.conf and/or the other configuration files in /etc/amavis/conf.d and elsewhere (settings like $sa_kill_level_deflt). You can configure per-user or per-domain static settings there, or you can manually add the policies andusers to MySQL. Each user or policy must have a unique id, so each time a user or policy is updated in theSquirrelMail interface (which can happen at any moment) the policy_id_seq and the users_id_seq are updated so theapplication can keep track of which number it used for the last policy or user. If you have just one or two relay usersyou need to add, you can cheat and put our test user to good use. In phpMyAdmin edit the amavis 'users' table for thetest user, replacing all the fields that need to be replaced - like email, fullname and username (but leave the id alone).The next time the test user logs in and goes to the SpamAssassin Configuration page a new record will be created.You can edit this one also and repeat the process, logging the test user in and out of SquirrelMail each time you needto create a new record.

If you need to enter a larger number of users or policies it would be easier to increment the users_id_seq (forexample) to a number large enough to accommodate the number of records you are going to add - before you add

them. Then make sure the id numbers in the records are both unique and within the allocated range of numbers. Here(as an example) we change users_id_seq from 15 to 19 in order to accommodate 3 new users (we left 16 unused incase someone uses it before we can change 15 to 19). Once users_id_seq is set to 19, the SquirrelMail plugin will use20 as the next number, so 17 through 19 is ours:

USE amavis;SELECT id FROM users_id_seq;+----+| 15 |+----+UPDATE `users_id_seq` SET `id` = '19';

INSERT INTO users (id, priority, policy_id, email, fullname, digest, username, retention) VALUES (17,7,6,'user1@example.net','User 1','WD','user1@example.net',14);INSERT INTO users (id, priority, policy_id, email, fullname, digest, username, retention) VALUES (18,7,6,'user2@example.net','User 2','WD','user2@example.net',14);INSERT INTO users (id, priority, policy_id, email, fullname, digest, username, retention) VALUES (19,7,6,'user3@example.net','User 3','WD','user3@example.net',14);

The same concept would apply to policies.

Now you have another problem to deal with. The next-hop server may not accept mail addressed to user+spam@example.net. If it does not, then you may have to create aliases. This can be done either on this server, or at thenexthop server. To do it on this server, I would manually create these aliases and place them in a special virtual aliastable created just for the purpose. This table is used after amavisd-new has processed a message. For example, let'screate /etc/postfix/amavis_virtual.touch /etc/postfix/amavis_virtualpostmap /etc/postfix/amavis_virtual

Then vi /etc/postfix/master.cf and modify the amavis-cleanup service (created in the previous "The alias issue"section) to use this table:

cleanup unix n - - - 0 cleanupamavis-cleanup unix n - - - 0 cleanup -o virtual_alias_maps=hash:/etc/postfix/amavis_virtualqmgr fifo n - n 300 1 qmgr

The format of the data in this table would be something like:garyv+spam@example.net garyv@example.nettest+spam@example.net test@example.net

A one to one mapping like this is ideal - especially because some recipients in the same domain may want to use 'plusaddressing' and others may not. I will tell you that is is possible to use a single entry in a regexp map to rewrite all theaddresses to a particular domain, but this breaks recipient validation. In other words, mail addressed toanyone+spam@example.net may not be rejected immediately. This requires a regexp (or pcre) map, so we wouldhave to add this map type to our list of virtual alias maps (the override is all on one line):touch /etc/postfix/regexp_amavis_virtual

And once again, add it to master.cf:

cleanup unix n - - - 0 cleanupamavis-cleanup unix n - - - 0 cleanup -o virtual_alias_maps=hash:/etc/postfix/amavis_virtual,regexp:/etc/postfix/regexp_amavis_virtualqmgr fifo n - n 300 1 qmgr

Then you could vi /etc/postfix/regexp_amavis_virtual and insert something to this effect:/^(.*)\+spam@example\.net$/ $1@example.net

Then:/etc/init.d/postfix stop/etc/init.d/postfix start

Don't forget to uncomment #unverified_recipient_reject_code = 550 once address verification is known to work asexpected (assuming you are using reject_unverified_recipient via the verify_domains map). Then test, test, test (makesure you send some spam). You may need to configure @spam_kill_level_maps and/or @spam_tag2_level_maps in /etc/amavis/conf.g/50-user for the relay domains. While testing, you may need to temporarily remove your network from

@mynetworks in /etc/amavis/conf.g/50-user so the MYNETS policy bank is not loaded for your client. If you are usingExchange, there are some HOWTOs out there that may help with pulling data out of Active Directory:http://www2.origogeneris.com:4000/relay_recipients.htmlhttp://www-personal.umich.edu/~malth/gaptuning/postfix/http://www.unixwiz.net/techtips/postfix-exchange-users.htmlhttp://postfix.state-of-mind.de/patrick.koetter/mailrelay/http://www200.pair.com/mecham/spam/PostfixAddressExtract.vbs.txt

Continue to Page 2

Index Top Page 1 Page 2

APR 18 2008