howtos:mailserver
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
howtos:mailserver [09/09/2006 11:16] – domingo | howtos:mailserver [16/02/2023 07:09] (current) – domingo | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Setting up a mail server with Postfix, Postfixadmin, | ||
+ | ===== Introduction ===== | ||
+ | This is a howto on setting up a nice spam-virus fighting mailserver. It's based on a singlebox install but spreading out the components, isn't that difficult. I've tried building it so it could scale and still be easy to manage, with a lot of good webinterfaces. I think I have accomplished that - hope you can agree :-) | ||
+ | |||
+ | On a average day I get between 50-100 spammails (in my mailbox alone), so having a mailserver without a spamfighter would be utopia. Using Dspam has proven a very good choice, today (09-09-06) my spam catch rate is 99,680% (and that is without any kind of RBL/ | ||
+ | |||
+ | I hope that my time putting this together will help out others getting their mailservers up and running. Just through me a mail if you have questions or good ideas. | ||
+ | |||
+ | |||
+ | Please check the Reference section as it holds more information than I have written about here. Also they have helped me getting through this essay - thank you all for your help! | ||
+ | |||
+ | |||
+ | Good luck! | ||
+ | --- // | ||
+ | |||
+ | ===== Components involved ===== | ||
+ | * Apache2 | ||
+ | * PHP4 | ||
+ | * Courier | ||
+ | * Courier-authlibs | ||
+ | * Postfix | ||
+ | * Postfixadmin | ||
+ | * MySQL | ||
+ | * Dspam | ||
+ | * Mod_auth_imap | ||
+ | * Antivir | ||
+ | |||
+ | I'm always been a fan of SuSE so I'm going to use SuSE 9.3 Pro for this howto. I'm gonna use as much SuSE defaults as possible as it make my life easier. This setup is by no mean bound to SuSE, and a lot of similar implementations run on other distributions. | ||
+ | A couple of these components are included in SuSE 9.3 but I'm only gonna use Apache, PHP4 and MySQL. The rest are handbuild and handinstalled. | ||
+ | I like the idea that as much as possible is used from the distribution. That way I'm not gonna use time keeping the software up-to-date. Unfortunaly that is not possible when you use SuSE 9.3. Some of the components are not in the distribution and some are build without support for what we need. | ||
+ | |||
+ | I will not describe every little component involved (I don't know all of them) but when building the different software there may be dependencies. The good thing about SuSE is that its bundled with a gazillian packages of software so you hardly need anything other than the install DVD to satisfy the dependencies. | ||
+ | |||
+ | An other thing to mention is that this is a singlebox install. It's possible to distribute the varies pieces to make this scale but my needs (and wallet) are not compatible with such an implementation :-D | ||
+ | |||
+ | ===== Postfix ===== | ||
+ | Start out by upgrading your Postfix as we need MySQL support build in (the one provided from SuSE hasn't got that support): | ||
+ | < | ||
+ | # wget ftp:// | ||
+ | # wget ftp:// | ||
+ | # rpm -Uhv postfix-* | ||
+ | </ | ||
+ | |||
+ | You can also get the files here: | ||
+ | |||
+ | Due to an error somewhere in the install/ | ||
+ | < | ||
+ | scache | ||
+ | </ | ||
+ | |||
+ | Create the directory where the mailboxes are to be placed: | ||
+ | < | ||
+ | # mkdir / | ||
+ | # chown -R postfix.postfix / | ||
+ | # chmod 751 / | ||
+ | </ | ||
+ | |||
+ | The Postfix-user needs to be able to write in here as it is delivering the mail. | ||
+ | |||
+ | Now we need to change some of the Postfix configuration files, and create a couple of new ones. | ||
+ | Append following inside main.cf: | ||
+ | |||
+ | < | ||
+ | virtual_alias_maps = proxy: | ||
+ | virtual_gid_maps = static:51 | ||
+ | virtual_mailbox_base = / | ||
+ | virtual_mailbox_domains = proxy: | ||
+ | virtual_mailbox_limit = 51200000 | ||
+ | virtual_mailbox_maps = proxy: | ||
+ | virtual_minimum_uid = 51 | ||
+ | virtual_transport = virtual | ||
+ | virtual_uid_maps = static:51 | ||
+ | </ | ||
+ | |||
+ | //The virtual_gid_maps and virtual_uid_maps are the id for the postfix user taken from / | ||
+ | |||
+ | Now create the lookup sql files. The username " | ||
+ | |||
+ | / | ||
+ | < | ||
+ | user = postfix | ||
+ | password = postfix | ||
+ | hosts = localhost | ||
+ | dbname = postfix | ||
+ | query = SELECT goto FROM alias WHERE address=' | ||
+ | </ | ||
+ | |||
+ | / | ||
+ | < | ||
+ | user = postfix | ||
+ | password = postfix | ||
+ | hosts = localhost | ||
+ | dbname = postfix | ||
+ | #query = SELECT description FROM domain WHERE domain=' | ||
+ | #optional query to use when relaying for backup MX | ||
+ | query = SELECT description FROM domain WHERE domain=' | ||
+ | </ | ||
+ | |||
+ | / | ||
+ | < | ||
+ | user = postfix | ||
+ | password = postfix | ||
+ | hosts = localhost | ||
+ | dbname = postfix | ||
+ | query = SELECT maildir FROM mailbox WHERE username=' | ||
+ | </ | ||
+ | |||
+ | ===== MySQL ===== | ||
+ | |||
+ | Now lets create the database for Postfix. Download Postfixadmin and untar it. Inside there is a textfile that we use to create and fixup the database portion for Postfix: | ||
+ | |||
+ | < | ||
+ | # mysql -u root -p < DATABASE_MYSQL.TXT | ||
+ | </ | ||
+ | |||
+ | ét voila and we have created the database and all the tables, users and their rights - how easy can it get :-P. Inside the textfile you can see what is done. It's a good idea to check it out, as usernames and password my be different in the version you have downloaded. | ||
+ | Also it might be a good idea to install mysql-administrator (or mysqlcc prior to 4.1). It's an easy-to-use GUI for MySQL. I may like cli but some colors and graphics are nice to have sometimes, especially when you're not a hardcore DBA. | ||
+ | |||
+ | Remember also to set the MySQL root password: | ||
+ | |||
+ | < | ||
+ | # mysqladmin -u root password ' | ||
+ | # mysqladmin -u root -h mailserver.example.com password ' | ||
+ | </ | ||
+ | |||
+ | ===== Courier-authlibs ===== | ||
+ | |||
+ | Courier-authlibs is the component which does the actual authentication. It can be used as a big swiss army knife, but we only utilize the interface to MySQL. | ||
+ | |||
+ | Create a user and group named "// | ||
+ | |||
+ | Unpack the tar-ball and configure it. **Remember to have both zlib-devel and mysql-devel installed, it is required to make authmysql** (took me two days and two nights to figure that out): | ||
+ | |||
+ | < | ||
+ | # cd courier-authlib-0.57 | ||
+ | # ./configure | ||
+ | </ | ||
+ | be patient configure will run for some time and look like it is looping, which it is not of course. | ||
+ | |||
+ | < | ||
+ | # su - | ||
+ | # make WITH_MYSQL=yes install | ||
+ | # make install-configure | ||
+ | </ | ||
+ | |||
+ | Create /// | ||
+ | |||
+ | < | ||
+ | MYSQL_CRYPT_PWFIELD | ||
+ | MYSQL_DATABASE | ||
+ | MYSQL_GID_FIELD | ||
+ | MYSQL_HOME_FIELD | ||
+ | MYSQL_LOGIN_FIELD | ||
+ | MYSQL_MAILDIR_FIELD | ||
+ | MYSQL_NAME_FIELD | ||
+ | MYSQL_OPT | ||
+ | MYSQL_PASSWORD | ||
+ | # | ||
+ | # Uncomment below if you want quota support. | ||
+ | # | ||
+ | MYSQL_SERVER | ||
+ | # Default FreeBSD Socket | ||
+ | # | ||
+ | # Default RedHat Socket | ||
+ | MYSQL_SOCKET | ||
+ | MYSQL_UID_FIELD | ||
+ | MYSQL_USERNAME | ||
+ | MYSQL_USER_TABLE | ||
+ | # | ||
+ | </ | ||
+ | |||
+ | Add the a symbolic link to secure the daemon will start at boot: | ||
+ | |||
+ | < | ||
+ | # ln -s / | ||
+ | </ | ||
+ | |||
+ | Use Yast to enable the daemon in the different runlevels ((Remember to verify that Yast has put the authdaemond daemon after networking - if that's not the case the authdaemond will not start)). | ||
+ | |||
+ | ===== Courier-Imap ===== | ||
+ | |||
+ | Unpack the courier-imap (**not as root!**): | ||
+ | |||
+ | < | ||
+ | # cd courier-imap-4.0.4 | ||
+ | # ./configure --bindir=/ | ||
+ | # make | ||
+ | # su - | ||
+ | # make install-strip | ||
+ | # make install-configure | ||
+ | </ | ||
+ | |||
+ | If you encounter problems compiling it with the openssl libraries in non-standard locations, try making a symbolic link: | ||
+ | |||
+ | < | ||
+ | # ln -s / | ||
+ | </ | ||
+ | (thanks to [[kjohnson@hanoveruniform.com|Kyle Johnson]] for this tip) | ||
+ | |||
+ | Add the a symbolic link to secure the daemon will start at boot: | ||
+ | |||
+ | < | ||
+ | # ln -s / | ||
+ | </ | ||
+ | Use Yast to enable the daemon in the different runlevels((Again check when the daemon is started)). | ||
+ | |||
+ | ===== Postfixadmin ===== | ||
+ | |||
+ | Prepare the Apache2 configuration for Postfixadmin. Start out by creating a new config file, lets call it postfixadmin.conf. I like to use SSL when we are dealing with password protected sites, no sniffing here. Create the certificates with " | ||
+ | |||
+ | / | ||
+ | < | ||
+ | Listen 555 | ||
+ | < | ||
+ | DocumentRoot "/ | ||
+ | ServerName localhost: | ||
+ | ServerAdmin you@example.com | ||
+ | ErrorLog / | ||
+ | TransferLog / | ||
+ | SSLEngine on | ||
+ | SSLCipherSuite ALL: | ||
+ | SSLCertificateFile / | ||
+ | SSLCertificateKeyFile / | ||
+ | < | ||
+ | SSLOptions +StdEnvVars | ||
+ | SSLRequireSSL | ||
+ | </ | ||
+ | SetEnvIf User-Agent " | ||
+ | | ||
+ | | ||
+ | CustomLog / | ||
+ | "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \" | ||
+ | < | ||
+ | AllowOverride AuthConfig | ||
+ | Order deny,allow | ||
+ | Allow from all | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | Unpack Postfixadmin into "/// | ||
+ | Lets make sure only root and the webserver can read the files: | ||
+ | |||
+ | < | ||
+ | # chgrp -R www / | ||
+ | # cd / | ||
+ | # chmod 640 *.php *.css | ||
+ | # cd / | ||
+ | # chmod 640 *.php .ht* | ||
+ | # cd / | ||
+ | # chmod 640 *.gif *.png | ||
+ | # cd / | ||
+ | # chmod 640 *.lang | ||
+ | # cd / | ||
+ | # chmod 640 *.tpl | ||
+ | # cd / | ||
+ | # chmod 640 *.php | ||
+ | </ | ||
+ | |||
+ | Inside "/// | ||
+ | |||
+ | Next we need to configure the Postfixadmin' | ||
+ | |||
+ | < | ||
+ | $CONF[' | ||
+ | $CONF[' | ||
+ | </ | ||
+ | |||
+ | so that domains and usernames are separated in the directory structure, it gives a better overall view. | ||
+ | |||
+ | ===== SquirrelMail ===== | ||
+ | |||
+ | Download and unpack the SquirrelMail (SM) into "/// | ||
+ | < | ||
+ | # cvs -d: | ||
+ | (When it asks for password, just press ENTER) | ||
+ | |||
+ | # cvs -d: | ||
+ | </ | ||
+ | |||
+ | Set the proper permissions: | ||
+ | |||
+ | < | ||
+ | #chown -R root.www / | ||
+ | #chmod 770 / | ||
+ | </ | ||
+ | |||
+ | Run the config script "/// | ||
+ | |||
+ | Put the following in "/// | ||
+ | |||
+ | < | ||
+ | Listen 443 | ||
+ | < | ||
+ | DocumentRoot "/ | ||
+ | ServerName localhost: | ||
+ | ServerAdmin you@example.com | ||
+ | ErrorLog / | ||
+ | TransferLog / | ||
+ | SSLEngine on | ||
+ | SSLCipherSuite ALL: | ||
+ | SSLCertificateFile / | ||
+ | SSLCertificateKeyFile / | ||
+ | < | ||
+ | SSLOptions +StdEnvVars | ||
+ | SSLRequireSSL | ||
+ | </ | ||
+ | SetEnvIf User-Agent " | ||
+ | | ||
+ | | ||
+ | CustomLog / | ||
+ | "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \" | ||
+ | < | ||
+ | AllowOverride None | ||
+ | Order deny,allow | ||
+ | Allow from all | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | Inside the Postfixadmin "// | ||
+ | |||
+ | ===== Dspam ===== | ||
+ | |||
+ | No mailserver with out a spamfilter. Dspam has showed its worth when installed and trained correctly, so far I have >99% catch rate. It can be a little tricky, and done in a million ways, but the philosophy " | ||
+ | |||
+ | Create the user and group "// | ||
+ | |||
+ | < | ||
+ | # wget http:// | ||
+ | </ | ||
+ | |||
+ | Configure and make Dspam: | ||
+ | < | ||
+ | # ./configure --enable-daemon \ | ||
+ | --with-storage-driver=mysql_drv \ | ||
+ | --with-mysql-includes=/ | ||
+ | --enable-preferences-extension \ | ||
+ | --with-dspam-home-owner=dspam \ | ||
+ | --with-dspam-home-group=dspam \ | ||
+ | --with-dspam-home=/ | ||
+ | --enable-long-usernames \ | ||
+ | --with-dspam-mode=dspam \ | ||
+ | --with-dspam-group=dspam \ | ||
+ | --enable-mysql4-initialization \ | ||
+ | --enable-domain-scale \ | ||
+ | --enable-virtual-users \ | ||
+ | --enable-debug \ | ||
+ | --enable-verbose-debug | ||
+ | |||
+ | # make && make install | ||
+ | </ | ||
+ | I have compiled Dspam with debug enabled. To use these options look in "/// | ||
+ | |||
+ | If you recieve mail through an inbound mailhop you should add an IgnoreHeader in your // | ||
+ | < | ||
+ | IgnoreHeader Received: from backup-mx.post.tele.dk | ||
+ | </ | ||
+ | |||
+ | ==== MySQL ==== | ||
+ | |||
+ | Create dspam database: | ||
+ | < | ||
+ | # mysqladmin -u root -p create dspam | ||
+ | </ | ||
+ | |||
+ | Import tables and set permissions: | ||
+ | |||
+ | < | ||
+ | # mysql -u root -p dspam < ./ | ||
+ | # mysql -u root -p dspam < ./ | ||
+ | # mysql -u root -p dspam < ./ | ||
+ | # mysql -u root -p | ||
+ | # mysql> grant all on dspam.* to dspam@localhost identified by ' | ||
+ | </ | ||
+ | |||
+ | ==== Web UI ==== | ||
+ | |||
+ | Create the Web UI: | ||
+ | |||
+ | < | ||
+ | # mkdir / | ||
+ | # cp -R ./cgi/* / | ||
+ | # chown -R dspam.dspam / | ||
+ | # cd / | ||
+ | # chmod 444 *.* | ||
+ | # chmod 554 *.cgi | ||
+ | # chmod 555 templates | ||
+ | # chmod 444 templates/* | ||
+ | </ | ||
+ | |||
+ | Put the users/email addresses that you want to be admins into this file: | ||
+ | |||
+ | < | ||
+ | # vi / | ||
+ | </ | ||
+ | |||
+ | Depending on how you would like to use the UI you have several options. The UI can be used in a way so that every user has his own interface and learning information. I learn and control all spam/ham through one account (my own) and therefor I use a password file to authenticate to UI - because it's simple: | ||
+ | |||
+ | < | ||
+ | # htpasswd2 -c / | ||
+ | # chown dspam.www / | ||
+ | # chmod 660 / | ||
+ | </ | ||
+ | |||
+ | If you choose to give all users their own training facility you should use mod_auth_imap. More on that later. | ||
+ | |||
+ | Modify Apache2. Create "/// | ||
+ | |||
+ | < | ||
+ | Listen 444 | ||
+ | < | ||
+ | |||
+ | # | ||
+ | DocumentRoot "/ | ||
+ | ServerName localhost: | ||
+ | ServerAdmin you@example.com | ||
+ | ErrorLog / | ||
+ | TransferLog / | ||
+ | |||
+ | SSLEngine on | ||
+ | |||
+ | SSLCipherSuite ALL: | ||
+ | |||
+ | SSLCertificateFile / | ||
+ | SSLCertificateKeyFile / | ||
+ | |||
+ | <Files ~ " | ||
+ | SSLOptions +StdEnvVars | ||
+ | </ | ||
+ | < | ||
+ | SSLOptions +StdEnvVars | ||
+ | </ | ||
+ | |||
+ | SetEnvIf User-Agent " | ||
+ | | ||
+ | | ||
+ | |||
+ | CustomLog / | ||
+ | "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \" | ||
+ | |||
+ | |||
+ | RewriteEngine on | ||
+ | RewriteRule ^/$ /dspam.cgi [R] | ||
+ | |||
+ | SuexecUserGroup dspam dspam | ||
+ | |||
+ | < | ||
+ | |||
+ | Options +ExecCGI FollowSymLinks | ||
+ | AddHandler cgi-script cgi pl | ||
+ | # AllowOverride None | ||
+ | # Order deny,allow | ||
+ | # Deny from all | ||
+ | #Turn on IMAP Authentication | ||
+ | # | ||
+ | |||
+ | #Give a name to the authentication domain, whatever you want: | ||
+ | #AuthName " | ||
+ | |||
+ | #Only basic authentication is supported for now: | ||
+ | #AuthType Basic | ||
+ | |||
+ | #If you feel like it, restrict the users or allow all " | ||
+ | #Require user user1 user2 | ||
+ | |||
+ | #Make IMAP Authentication authoritative for this .htaccess file: | ||
+ | # | ||
+ | |||
+ | #Set the IMAP Server to which you want to connect (default=localhost): | ||
+ | # | ||
+ | |||
+ | #Set the port on which the imap server is running (default=143): | ||
+ | # | ||
+ | |||
+ | #Turn on some extra logging (login attempts, etc.) in Apache' | ||
+ | # | ||
+ | |||
+ | |||
+ | AuthType Basic | ||
+ | AuthName " | ||
+ | AuthUserFile / | ||
+ | Require valid-user | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | We need to append the rewrite module in "/// | ||
+ | |||
+ | < | ||
+ | APACHE_MODULES=" | ||
+ | </ | ||
+ | |||
+ | Please also pay attention to the certificate part, you may need to point the statements somewhere else. I've just used the same certificate files as with Postfixadmin, | ||
+ | |||
+ | Due to SuExec you can't put the Web UI files anywhere else than where I have put them (/// | ||
+ | |||
+ | ==== Postfix integration ==== | ||
+ | |||
+ | Dspam is integrated into Postfix through a content filter. This makes a lot of things easy for us. How ever Dspam will be called by Postfix every time a mail runs through it. This can be okay but I only want incoming mail to be scanned as I don't send spam to the world (why should I?). This require some scripting. | ||
+ | Start out by creating /// | ||
+ | |||
+ | < | ||
+ | #!/bin/sh | ||
+ | |||
+ | PATH=/ | ||
+ | SENDMAIL="/ | ||
+ | DSPAM="/ | ||
+ | MYDOMAIN1=" | ||
+ | MYDOMAIN2=" | ||
+ | MYDOMAIN3=" | ||
+ | |||
+ | # Get arguments | ||
+ | sender=" | ||
+ | recip=" | ||
+ | |||
+ | # Parse out the username from the recipient | ||
+ | user=`echo $recip | sed -n ' | ||
+ | |||
+ | # Parse out domain from the recipient | ||
+ | domain=`echo $recip | sed -n ' | ||
+ | |||
+ | if [ -z " | ||
+ | echo " | ||
+ | exit 75 # EX_TEMPFAIL | ||
+ | fi | ||
+ | |||
+ | if [ " | ||
+ | $DSPAM --deliver=innocent --user user@example.com -i -f " | ||
+ | elif [ " | ||
+ | $DSPAM --user user@example.com --class=spam --source=error | ||
+ | elif [ " | ||
+ | $DSPAM --user user@example.com --class=innocent --source=error | ||
+ | else | ||
+ | $SENDMAIL -i -f " | ||
+ | fi | ||
+ | |||
+ | exit $? | ||
+ | </ | ||
+ | |||
+ | The script require some configuration to fit your installation. First of all the three "// | ||
+ | What the script does, is to only scan for spam when the recipient is from one of the three domains. If the recipient is the subdomain ham.MYDOMAIN then the mail is used for training (correcting a false positive) and if it's for spam.MYDOMAIN then it is retrained as spam. It doesn' | ||
+ | Mail sent from one of the MYDOMAIN to an other in MYDOMAIN will get trained. This could also be handled in the script but I have been lazy :-P. | ||
+ | Remember to set the script' | ||
+ | |||
+ | < | ||
+ | # chown dspam.dspam / | ||
+ | # chmod 770 / | ||
+ | </ | ||
+ | |||
+ | Next append the following into // | ||
+ | |||
+ | < | ||
+ | dspamit | ||
+ | flags=Rhqu user=dspam argv=/ | ||
+ | </ | ||
+ | |||
+ | and change it to use the content filter: | ||
+ | |||
+ | < | ||
+ | #smtp inet n | ||
+ | smtp inet n | ||
+ | -o content_filter=dspamit: | ||
+ | </ | ||
+ | |||
+ | The original smtp daemon is commented out with at hash (#) and replaced with one containing a content filter call. You can call Dspam in other places of the mail loop, fx after antivirus, this is up to you. Whether to filter spam before or after antivirus is a long and, some times religious debate, that I don't want to comment on here, I have chosen to do it this way, and it works. | ||
+ | |||
+ | Also put the following into your // | ||
+ | < | ||
+ | dspamit_destination_recipient_limit = 1 | ||
+ | </ | ||
+ | Otherwise the script will not work properly as it only handles one recipient (Thanks to [[ Ralf.Hildebrandt@charite.de|Ralf Hildebrandt]] for pointing that out to me) | ||
+ | |||
+ | To protect my two re-learning aliases (*@ham.example.com and *@spam.example.com), | ||
+ | < | ||
+ | spam.example.com | ||
+ | ham.example.com | ||
+ | </ | ||
+ | |||
+ | Add this file as a // | ||
+ | < | ||
+ | smtpd_recipient_restrictions = | ||
+ | check_client_access hash:/ | ||
+ | check_sender_access hash:/ | ||
+ | reject_non_fqdn_sender | ||
+ | reject_non_fqdn_recipient | ||
+ | permit_mynetworks | ||
+ | check_recipient_access hash:/ | ||
+ | reject_unauth_destination | ||
+ | ... | ||
+ | ... | ||
+ | ... | ||
+ | </ | ||
+ | |||
+ | This way external senders can't use the two aliases. | ||
+ | |||
+ | ==== Mod_auth_imap ==== | ||
+ | |||
+ | The easiest way of handling multiuser access to the Dspam Web UI, is to use mod_auth_imap. This way don't need to handle a separate username/ | ||
+ | |||
+ | < | ||
+ | # apxs2 -i -a -c mod_auth_imap.c | ||
+ | </ | ||
+ | |||
+ | Make sure the mod_auth_imap.so is in "/// | ||
+ | To load the module append the module in "/// | ||
+ | |||
+ | < | ||
+ | APACHE_MODULES=" | ||
+ | </ | ||
+ | |||
+ | In "/// | ||
+ | |||
+ | To enter the Dspam Web UI open a browser and point it at https:// | ||
+ | |||
+ | If the graphics don't work you probably need to install perl-GD and perl-GD-Graph3d (which is at your disposal in the SuSE distribution). | ||
+ | |||
+ | A couple of places inside "/// | ||
+ | |||
+ | < | ||
+ | TrustedDeliveryAgent "/ | ||
+ | </ | ||
+ | |||
+ | You also need this in the file: | ||
+ | |||
+ | < | ||
+ | Trust dspam | ||
+ | </ | ||
+ | |||
+ | Dspam relies heavily on MySQL, in my configuration that is, so this also needs to be reflected in the /// | ||
+ | |||
+ | < | ||
+ | MySQLServer | ||
+ | #MySQLPort | ||
+ | MySQLUser | ||
+ | MySQLPass | ||
+ | MySQLDb | ||
+ | MySQLCompress | ||
+ | </ | ||
+ | |||
+ | I use the socket as everything runs on the same machine. If you prefer to use the tcp port instead, fx if you're distributing the installation, | ||
+ | |||
+ | < | ||
+ | MySQLServer | ||
+ | MySQLPort | ||
+ | </ | ||
+ | |||
+ | This should get you going as a start with Dspam. There are millions of combinations and you may wish to use Dspam differently, | ||
+ | Dspam has tons of options for a reason. To make a solution work for both a single user and giant corporations some tweaking possibilities are required. It takes time to get under the hood but when you get there you realize what powerful a tool Dspam really is. | ||
+ | |||
+ | Inside "/// | ||
+ | |||
+ | < | ||
+ | $CONFIG{' | ||
+ | " | ||
+ | </ | ||
+ | |||
+ | ==== Training Dspam ==== | ||
+ | |||
+ | Dspam is a statistical tool and hence needs a statistical foundation to be able to take the right decisions. So what we need here is a lot of spam mails and ham mails - **__both types are required and equally important__**. If either type is overrepresented you can be sure that you will get a lot of false positives and bad spam-catch-rate. | ||
+ | Dspam comes with a tool, dspam_corpus, | ||
+ | I have a lot of spam mails but most are wrapped in SA. I don't want SA's reports as part of my statistical foundation, so first we start out by stripping the spam mails (we must have SA and procmail installed for this to work): | ||
+ | |||
+ | < | ||
+ | # formail -s spamassassin -d < Spam >> cleaned.spam.inbox | ||
+ | </ | ||
+ | |||
+ | " | ||
+ | |||
+ | Now we can start training: | ||
+ | |||
+ | < | ||
+ | # dspam_corpus --addspam user@domain.tld cleaned.spam.inbox | ||
+ | </ | ||
+ | |||
+ | Change out " | ||
+ | |||
+ | Now don't forget the ham mails: | ||
+ | |||
+ | < | ||
+ | # dspam_corpus user@domain.tld mbox-files | ||
+ | </ | ||
+ | |||
+ | ==== Dspam database maintenance ==== | ||
+ | |||
+ | In time the Dspam database will grow and fill out a lot of diskspace. This is of course not desirable so some housecleaning is required. Luckily Dspam comes with a sql cleanup file called " | ||
+ | |||
+ | < | ||
+ | # mysql -u root -p dspam < purge-4.1.sql | ||
+ | </ | ||
+ | |||
+ | I don't need to run it every night, only once a week just before I take my backup. I then run it in combination with an analyze and optimization: | ||
+ | |||
+ | < | ||
+ | # mysql -u root -p dspam < analyze.sql | ||
+ | </ | ||
+ | |||
+ | This is how my // | ||
+ | |||
+ | < | ||
+ | ANALYZE TABLE `dspam_neural_data`, | ||
+ | |||
+ | OPTIMIZE TABLE `dspam_neural_data`, | ||
+ | </ | ||
+ | |||
+ | ==== Dspam training mode ==== | ||
+ | |||
+ | After processing around 3500 mails I changed trainingmode from " | ||
+ | |||
+ | I also learned that training spam is a constant necessity. After my server was shutdown for almost a month, due to change of ISP, my catch rate dropped dramatically. This however quickly changed after a couple of days but it was an interesting experience and showes the constant change of spam. | ||
+ | |||
+ | ==== Spam with pictures ==== | ||
+ | |||
+ | Recent time has shown a different approach by the spam' | ||
+ | |||
+ | I've had a few spammails slipping through with the picture-only-design but after a couple of retrainings, | ||
+ | |||
+ | ===== Upgrading from 3.4.9 to 3.6.6 ===== | ||
+ | |||
+ | Today (27/5-06) I upgraded my dspam installation to 3.6.6. I thought it was time to catch up, not that I realy needed it but eventually you need to upgrade not to fall too far behind. | ||
+ | |||
+ | //**Update (21-07-06)**: | ||
+ | |||
+ | The process was fairly easy. I used the same configure flags as with 3.4.9. Ran //make// and //make install// and the files got compiled and put in the right places. | ||
+ | Next I updated my dspam.conf file with a few new flags: | ||
+ | |||
+ | < | ||
+ | #3.6.6 upgrade addon stuff | ||
+ | TestConditionalTraining on | ||
+ | ProcessorBias off #default on but due to markov it is turned off | ||
+ | </ | ||
+ | |||
+ | I wanted to try out the new CRM114 algorithm so a couple of other things needed to be changed in // | ||
+ | < | ||
+ | Feature sbph | ||
+ | #Feature noise | ||
+ | #Feature chained | ||
+ | Feature tb=5 | ||
+ | Feature whitelist | ||
+ | </ | ||
+ | |||
+ | To activate CRM114 algorithm I also changed: | ||
+ | < | ||
+ | #PValue robinson | ||
+ | #PValue graham | ||
+ | PValue markov | ||
+ | </ | ||
+ | |||
+ | Next I upgraded the WebUI. This was done by copying the following files into /// | ||
+ | < | ||
+ | admin.cgi | ||
+ | admingraph.cgi | ||
+ | base.css* | ||
+ | configure.pl | ||
+ | configure.pl.in | ||
+ | default.prefs | ||
+ | dspam-logo-small.gif | ||
+ | dspam.cgi | ||
+ | graph.cgi | ||
+ | rgb.txt | ||
+ | </ | ||
+ | |||
+ | And the following into /// | ||
+ | < | ||
+ | nav_admin_preferences.html | ||
+ | nav_alerts.html | ||
+ | nav_fragment.html | ||
+ | nav_preferences.html | ||
+ | nav_admin_status.html | ||
+ | nav_analysis.html | ||
+ | nav_history.html | ||
+ | nav_quarantine.html | ||
+ | nav_admin_error.html | ||
+ | nav_admin_user.html | ||
+ | nav_error.html | ||
+ | nav_performance.html | ||
+ | nav_viewmessage.html | ||
+ | </ | ||
+ | |||
+ | I then went into /// | ||
+ | < | ||
+ | chown dspam.dspam * | ||
+ | chown root.root configure.pl | ||
+ | chmod 555 *.cgi | ||
+ | chmod 444 admins base.css configure.pl rgb.txt | ||
+ | cd templates | ||
+ | chmod 440 * | ||
+ | </ | ||
+ | |||
+ | To reflect my setup I had to edit // | ||
+ | < | ||
+ | $CONFIG{' | ||
+ | " | ||
+ | $CONFIG{' | ||
+ | $CONFIG{' | ||
+ | # Add customized settings below | ||
+ | $CONFIG{' | ||
+ | </ | ||
+ | |||
+ | I few good things has happend to the WebUI so that part is worth upgrading. When it comes to the rest, only time can tell. So far things are functional and catching spam. | ||
+ | |||
+ | |||
+ | ==== dspam.conf ==== | ||
+ | < | ||
+ | Home / | ||
+ | TrustedDeliveryAgent "/ | ||
+ | OnFail error | ||
+ | Trust root | ||
+ | Trust mail | ||
+ | Trust mailnull | ||
+ | Trust smmsp | ||
+ | Trust daemon | ||
+ | #Trust nobody | ||
+ | #Trust majordomo | ||
+ | Trust dspam | ||
+ | TrainingMode toe | ||
+ | # | ||
+ | #3.6.6 upgrade addon stuff | ||
+ | TestConditionalTraining on | ||
+ | ProcessorBias off #default on | ||
+ | Feature sbph | ||
+ | #Feature noise | ||
+ | #Feature chained | ||
+ | Feature tb=5 | ||
+ | Feature whitelist | ||
+ | #Algorithm chi-square | ||
+ | Algorithm graham burton | ||
+ | #PValue robinson | ||
+ | #PValue graham | ||
+ | PValue markov | ||
+ | Preference " | ||
+ | Preference " | ||
+ | Preference " | ||
+ | #Preference " | ||
+ | #Preference " | ||
+ | AllowOverride trainingMode | ||
+ | AllowOverride spamAction spamSubject | ||
+ | AllowOverride statisticalSedation | ||
+ | AllowOverride enableBNR | ||
+ | AllowOverride enableWhitelist | ||
+ | AllowOverride signatureLocation | ||
+ | AllowOverride showFactors | ||
+ | AllowOverride optIn optOut | ||
+ | AllowOverride whitelistThreshold | ||
+ | MySQLServer | ||
+ | #MySQLPort | ||
+ | MySQLUser | ||
+ | MySQLPass | ||
+ | MySQLDb | ||
+ | MySQLCompress true | ||
+ | IgnoreHeader Received: from backup-mx.post.tele.dk | ||
+ | Notifications off | ||
+ | PurgeSignatures 14 # Stale signatures | ||
+ | PurgeNeutral | ||
+ | PurgeUnused | ||
+ | PurgeHapaxes | ||
+ | PurgeHits1S 15 | ||
+ | PurgeHits1I 15 | ||
+ | LocalMX 127.0.0.1 | ||
+ | SystemLog on | ||
+ | UserLog | ||
+ | Opt out | ||
+ | |||
+ | ## EOF | ||
+ | </ | ||
+ | |||
+ | ==== configure.pl ==== | ||
+ | < | ||
+ | # | ||
+ | |||
+ | # DSPAM | ||
+ | # COPYRIGHT (C) 2002-2006 JONATHAN A. ZDZIARSKI | ||
+ | # | ||
+ | # This program is free software; you can redistribute it and/or | ||
+ | # modify it under the terms of the GNU General Public License | ||
+ | # as published by the Free Software Foundation; version 2 | ||
+ | # of the License. | ||
+ | # | ||
+ | # This program is distributed in the hope that it will be useful, | ||
+ | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
+ | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
+ | # GNU General Public License for more details. | ||
+ | # | ||
+ | # You should have received a copy of the GNU General Public License | ||
+ | # along with this program; if not, write to the Free Software | ||
+ | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
+ | |||
+ | |||
+ | # This configuration file is read by all the CGI scripts to configure both the | ||
+ | # environment that DSPAM is working in and the way it will display information | ||
+ | # to the web user. | ||
+ | |||
+ | # Default DSPAM enviroment | ||
+ | $CONFIG{' | ||
+ | $CONFIG{' | ||
+ | $CONFIG{' | ||
+ | $CONFIG{' | ||
+ | $CONFIG{' | ||
+ | " | ||
+ | $CONFIG{' | ||
+ | $CONFIG{' | ||
+ | $CONFIG{' | ||
+ | |||
+ | $CONFIG{' | ||
+ | |||
+ | # Default DSPAM display | ||
+ | $CONFIG{' | ||
+ | # if undefined use default DSPAM display format | ||
+ | $CONFIG{' | ||
+ | $CONFIG{' | ||
+ | $CONFIG{' | ||
+ | $CONFIG{' | ||
+ | $CONFIG{' | ||
+ | $CONFIG{' | ||
+ | $CONFIG{' | ||
+ | $CONFIG{' | ||
+ | |||
+ | # Add customized settings below | ||
+ | $CONFIG{' | ||
+ | |||
+ | $ENV{' | ||
+ | |||
+ | # Autodetect filesystem layout and preference options | ||
+ | $CONFIG{' | ||
+ | |||
+ | # Or, if you're running dspam.cgi as untrusted, it won't be able to auto-detect | ||
+ | # so you will need to specify some features manually: | ||
+ | # | ||
+ | # | ||
+ | # | ||
+ | # | ||
+ | |||
+ | $CONFIG{' | ||
+ | |||
+ | # Configuration was successful | ||
+ | 1; | ||
+ | </ | ||
+ | |||
+ | ===== Antivir (to become Clam-AV) ===== | ||
+ | |||
+ | **//Update 26-7-06: I just discovered today that my mailserver isn't catching any viruses - not even the eicar testvirus. That is bad!!! Unfortunatly there is nothing wrong with my setup - it looks like Antivir/ | ||
+ | |||
+ | Now we have a good tool against spam, however we cannot setup a mailserver without catching the viruses as well. I have chosen to use AntiVir UNIX MailGate from [[http:// | ||
+ | |||
+ | As a personal user you will need a registration key (free of charge). Provide info [[http:// | ||
+ | (**Note - according to the Antivir homepage it is no langer nessesary to register for at key. I haven' | ||
+ | |||
+ | Download the latest AntiVir UNIX MailGate and unpack it somewhere. | ||
+ | Inside the tarball you will find and install script called "// | ||
+ | Of course without the // | ||
+ | IP's and domains are written to /// | ||
+ | |||
+ | When the installation wizard has finished we move on to /// | ||
+ | Inside avmailgate.conf look for: "// | ||
+ | |||
+ | < | ||
+ | ForwardTo SMTP: localhost port 10025 | ||
+ | </ | ||
+ | |||
+ | This gets mail back into Postfix after scanning. | ||
+ | Next, in the same file, look for: "// | ||
+ | |||
+ | < | ||
+ | ListenAddress localhost port 10024 | ||
+ | </ | ||
+ | |||
+ | This will be the Antivir smtp-listen port where Postfix will inject mail for scanning. | ||
+ | |||
+ | Next step is to configure /// | ||
+ | |||
+ | < | ||
+ | content_filter = smtp: | ||
+ | </ | ||
+ | |||
+ | This will tell Postfix to forward all mail (incoming and outgoing) to Antivir. | ||
+ | |||
+ | The last step is to open Postfix for reinjection of scanned mail. Now insert the following into / | ||
+ | |||
+ | < | ||
+ | localhost: | ||
+ | -o content_filter= | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===== Master.cf ===== | ||
+ | |||
+ | My final /// | ||
+ | |||
+ | < | ||
+ | # ========================================================================== | ||
+ | # service type private unpriv | ||
+ | # | ||
+ | # ========================================================================== | ||
+ | #smtp inet n | ||
+ | smtp inet n | ||
+ | -o content_filter=dspamit: | ||
+ | |||
+ | localhost: | ||
+ | -o content_filter= | ||
+ | |||
+ | # | ||
+ | # -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes | ||
+ | # | ||
+ | # -o smtpd_enforce_tls=yes -o smtpd_sasl_auth_enable=yes -o smtpd_etrn_restrictions=reject | ||
+ | #628 inet n | ||
+ | pickup | ||
+ | cleanup | ||
+ | qmgr fifo n | ||
+ | #qmgr | ||
+ | # | ||
+ | rewrite | ||
+ | bounce | ||
+ | defer | ||
+ | trace | ||
+ | verify | ||
+ | flush | ||
+ | proxymap | ||
+ | smtp unix - | ||
+ | relay | ||
+ | # -o smtp_helo_timeout=5 -o smtp_connect_timeout=5 | ||
+ | showq | ||
+ | error | ||
+ | local | ||
+ | virtual | ||
+ | lmtp unix - | ||
+ | anvil | ||
+ | scache | ||
+ | |||
+ | # | ||
+ | # | ||
+ | # Interfaces to non-Postfix software. Be sure to examine the manual | ||
+ | # pages of the non-Postfix software to find out what options it wants. | ||
+ | # | ||
+ | # maildrop. See the Postfix MAILDROP_README file for details. | ||
+ | # | ||
+ | maildrop | ||
+ | flags=DRhu user=vmail argv=/ | ||
+ | cyrus | ||
+ | user=cyrus argv=/ | ||
+ | uucp unix - | ||
+ | flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient) | ||
+ | ifmail | ||
+ | flags=F user=ftn argv=/ | ||
+ | bsmtp | ||
+ | flags=Fq. user=foo argv=/ | ||
+ | procmail | ||
+ | flags=R user=nobody argv=/ | ||
+ | |||
+ | dspamit | ||
+ | flags=Rhqu user=dspam argv=/ | ||
+ | </ | ||
+ | |||
+ | ===== Main.cf ===== | ||
+ | |||
+ | And my final /// | ||
+ | |||
+ | < | ||
+ | queue_directory = / | ||
+ | command_directory = /usr/sbin | ||
+ | daemon_directory = / | ||
+ | mail_owner = postfix | ||
+ | unknown_local_recipient_reject_code = 550 | ||
+ | debug_peer_level = 2 | ||
+ | debugger_command = | ||
+ | | ||
+ | xxgdb $daemon_directory/ | ||
+ | |||
+ | sendmail_path = / | ||
+ | newaliases_path = / | ||
+ | mailq_path = / | ||
+ | setgid_group = maildrop | ||
+ | html_directory = / | ||
+ | manpage_directory = / | ||
+ | sample_directory = / | ||
+ | readme_directory = / | ||
+ | mynetworks = 192.168.1.0/ | ||
+ | inet_protocols = all | ||
+ | biff = no | ||
+ | mail_spool_directory = /var/mail | ||
+ | canonical_maps = hash:/ | ||
+ | virtual_maps = hash:/ | ||
+ | relocated_maps = hash:/ | ||
+ | transport_maps = hash:/ | ||
+ | sender_canonical_maps = hash:/ | ||
+ | masquerade_exceptions = root | ||
+ | masquerade_classes = envelope_sender, | ||
+ | myhostname = mail.example.com | ||
+ | program_directory = / | ||
+ | inet_interfaces = all | ||
+ | masquerade_domains = | ||
+ | mydestination = $myhostname, | ||
+ | defer_transports = | ||
+ | disable_dns_lookups = no | ||
+ | relayhost = | ||
+ | mailbox_command = | ||
+ | mailbox_transport = | ||
+ | smtpd_sender_restrictions = hash:/ | ||
+ | smtpd_client_restrictions = | ||
+ | smtpd_helo_required = no | ||
+ | smtpd_helo_restrictions = | ||
+ | strict_rfc821_envelopes = no | ||
+ | dspamit_destination_recipient_limit = 1 | ||
+ | |||
+ | smtpd_restriction_classes = | ||
+ | has_our_domain_as_sender | ||
+ | |||
+ | has_our_domain_as_sender = | ||
+ | check_sender_access hash:/ | ||
+ | reject | ||
+ | |||
+ | smtpd_data_restrictions = | ||
+ | reject_multi_recipient_bounce | ||
+ | permit | ||
+ | |||
+ | smtpd_recipient_restrictions = | ||
+ | check_client_access hash:/ | ||
+ | check_sender_access hash:/ | ||
+ | reject_non_fqdn_recipient | ||
+ | reject_non_fqdn_sender | ||
+ | # | ||
+ | # | ||
+ | permit_mynetworks | ||
+ | check_recipient_access hash:/ | ||
+ | reject_unauth_destination | ||
+ | check_recipient_access hash:/ | ||
+ | check_helo_access pcre:/ | ||
+ | reject_non_fqdn_hostname | ||
+ | reject_invalid_hostname | ||
+ | # | ||
+ | # | ||
+ | # | ||
+ | # | ||
+ | # | ||
+ | # | ||
+ | permit | ||
+ | |||
+ | smtp_sasl_auth_enable = no | ||
+ | smtpd_sasl_auth_enable = no | ||
+ | smtpd_use_tls = no | ||
+ | smtp_use_tls = no | ||
+ | alias_maps = hash:/ | ||
+ | mailbox_size_limit = 0 | ||
+ | message_size_limit = 102400000 | ||
+ | content_filter = smtp: | ||
+ | virtual_alias_maps = proxy: | ||
+ | virtual_gid_maps = static:51 | ||
+ | virtual_mailbox_base = / | ||
+ | virtual_mailbox_domains = proxy: | ||
+ | virtual_mailbox_limit = 512000000 | ||
+ | virtual_mailbox_maps = proxy: | ||
+ | virtual_minimum_uid = 51 | ||
+ | virtual_transport = virtual | ||
+ | virtual_uid_maps = static:51 | ||
+ | </ | ||
+ | |||
+ | Both master.cf and main.cf can be tweaked a lot more than this but this is working. I have commented out some of the recipient restrictions for performance reasons. The commented out restrictions are not bad as per say, but the time it takes to evaluate, if we should accept the mail or not, is to long and will slow down mail delivery to a non acceptable stage. Have a look in the [[http:// | ||
+ | |||
+ | ===== Restriction maps ===== | ||
+ | Restriction maps used in main.cf: | ||
+ | |||
+ | ==== our_domain_as_sender ==== | ||
+ | |||
+ | < | ||
+ | #List of domains we relay/ | ||
+ | example.com | ||
+ | example.net | ||
+ | example.org | ||
+ | testlokale.org | ||
+ | <> | ||
+ | </ | ||
+ | |||
+ | ==== internal_networks ==== | ||
+ | |||
+ | < | ||
+ | #When comming from these IP addresses the sending mail address must match our mail domains. | ||
+ | #That way we prevent spoofed mail comming from our gateway. | ||
+ | 127.0.0 | ||
+ | 192.168.1 | ||
+ | </ | ||
+ | |||
+ | ==== not_our_domain_as_sender ==== | ||
+ | |||
+ | < | ||
+ | #External mail with our domains as senders must be fake and are rejected | ||
+ | example.com | ||
+ | example.net | ||
+ | example.org | ||
+ | </ | ||
+ | |||
+ | ==== roleaccount_exceptions ==== | ||
+ | |||
+ | < | ||
+ | #Addresses that you must always accept | ||
+ | postmaster@ | ||
+ | abuse@ | ||
+ | webmaster@ | ||
+ | ftpmaster@ | ||
+ | </ | ||
+ | |||
+ | ==== helo_checks ==== | ||
+ | |||
+ | < | ||
+ | #We will not accept mail when the helo command contains parts of our hostname, IP address or non compliant values. | ||
+ | / | ||
+ | / | ||
+ | / | ||
+ | / | ||
+ | </ | ||
+ | |||
+ | ==== protect_ham_spam_accounts ==== | ||
+ | < | ||
+ | #We don't want externals the ability to send to these domains, as they might by poisoned by spammers | ||
+ | spam.example.com | ||
+ | ham.example.com | ||
+ | </ | ||
+ | |||
+ | ===== Notes on firewalling ===== | ||
+ | |||
+ | As I am only using one machine, my mailserver also works as gateway for my home lan. This requires that I'm using, at least, two network interfaces. From SuSE 9.3 and beyond the interface names are allocated dynamically, | ||
+ | To handle this behavior you can do two things: | ||
+ | |||
+ | |||
+ | - Inside / | ||
+ | - Or you can force the ethX names through mac mapping in a file called /// | ||
+ | < | ||
+ | eth0 mac 00: | ||
+ | eth1 mac 00: | ||
+ | </ | ||
+ | |||
+ | |||
+ | Some applications((Like VMware Workstation)) don't like interface names like "// | ||
+ | |||
+ | ===== Conclusion ===== | ||
+ | |||
+ | With a combination of the right tools and enough investigation time, it is possible to make a powerful mail server that does the job, for a single geek (like me :-D ) or a larger corporation, | ||
+ | |||
+ | Utilizing Open-Source software can really make you wonder -- why use anything else... | ||
+ | |||
+ | Please feel free to comment or correct this howto. I can be reached at [[lnxgeek@domingo.dk]] | ||
+ | |||
+ | ===== References ===== | ||
+ | |||
+ | I have found a lot of inspiration from these sites, and borrowed a lot of scripts and ideas. Check them out to get more ideas or further help. | ||
+ | |||
+ | [[http:// | ||
+ | |||
+ | [[http:// | ||
+ | |||
+ | [[http:// | ||
+ | |||
+ | [[http:// | ||
+ | |||
+ | [[http:// | ||
+ | |||
+ | [[http:// | ||
+ | |||
+ | [[http:// | ||
+ | |||
+ | [[http:// | ||
+ | |||
+ | [[http:// | ||
+ | |||
+ | Chat on IRC in #dspam on irc.freenode.net | ||
+ | |||
+ | ===== Warranty ===== | ||
+ | |||
+ | There are no warrantys here, either expressed or implied. By using the advice provided herein, you agree to hold the author, Thomas D Dahlmann, harmless from any and all losses, including loss of data, loss of profits, loss of girlfriend or wifes, time wasted, and/or any drugs you may have done in the 1960' |