Archive for the ‘Linux’ Category

exim rewrite subject based on spam

Wednesday, March 26th, 2008 by lane

Here is how I got exim to rewrite the Subject header after spamassassin marks a message as spam.

I have an spam ACL in my /etc/exim/exim.conf as follows:

  warn    spam       = spam/defer_ok
          add_header = X-Spam-Flag: YES

This will add the X-Spam-Flag: YES header to the email, but I also want to append *** SPAM *** to the Subject :. The way I got this working was to use a filter. Before the begin ACL section of the /etc/exim/exim.conf file, I added the following line:

system_filter = /etc/exim/spam.filter

Then I created a /etc/exim/spam.filter file with the following contents:

if $header_X-Spam-Flag: contains "YES" then
headers add "Old-Subject: $h_subject:"
headers remove "Subject"
headers add "Subject: *** SPAM *** $h_old-subject"
headers remove "Old-Subject"
endif

cyrus imap folder seen state problems

Wednesday, March 26th, 2008 by lane

I had a user with a problem where squirrelmail would not let him click on his INBOX. In thunderbird he would mark all the messages in his INBOX as read, but that would not stick so that the next time he logged in they would all be marked unread again. I looked in the /var/logs/maillog log file and found these messages:

Mar 26 23:21:12 imaps[30634]: DBERROR: skiplist recovery /var/lib/imap/user/b/buser.seen: ADD at 2FC0 exists
Mar 26 23:21:12 imaps[30634]: DBERROR: opening /var/lib/imap/user/b/buser.seen: cyrusdb error
Mar 26 23:21:12 imaps[30634]: Could not open seen state for buser (System I/O error)

Without stopping the cyrus-imap server, I cd’d into the directory above, deleted the buser.seen file, and everything started working again.

Skype on Fedora 8

Thursday, February 28th, 2008 by lane

Following are the steps I used to install skype 2.0 beta on Fedora 8.

  1. Download the latest Fedora 7 skype rpm from Skype. Install it with
    yum --nogpgcheck localinstall skype-2.0.0.43-fc5.i586.rpm
  2. Pulseaudio and skype used to have issues when I was using skype version 2.0.0.27. At that time I had to do the perform the following steps from www.pulseaudio.org:

    Although Skype is an Alsa application, for some reason, it doesn’t seem to like the “pulse” device. The work-around, is not to use the “default” sound device. Rather to use a specific hardware device, and use pasuspender to momentarily suspend pulseaudio. Here are the steps

    Note: These steps were tested on Fedora8 with Skype ver 2.0 beta

    * Launch Skype, right click on its tray icon, and click “options”
    * Click “sound devices” category
    * For the Sound out, Sound in, and Ringing devices, change the default device to the first plughw device (The exact name depends on your hardware)
    * Click apply
    * Click close
    * Right click on Skype’s tray icon, and click Quit
    * Now launch skype whether from the run dialog or from a shell using the command “pasuspender skype”. This momentarily suspends pulseaudio, and starts skype

    I do not seem to have do this for version 2.0.0.47

  3. Related links Skype and Linux

LDAP Authentication Server on Fedora 8

Wednesday, February 13th, 2008 by lane

This information comes primarily from the following sources:

Following are the steps I used to install an openldap server on a Fedora 8 machine. This server is used for user login or authentication.

  1. Begin by installing the necessary packages:
    yum install openldap openldap-clients nss_ldap openldap-servers phpldapadmin

    In /etc/openldap/slapd.conf, change the following to match your domain name

    suffix          "dc=example,dc=com"
    rootdn          "cn=Manager,dc=example,dc=com"
  2. Run slappasswd command to generate an encrypted root password and insert the result in the slapd.conf file as:
    rootpw  {SSHA}E3lVqyY8YaieZTro
  3. Give users the ability to change their password by adding the following to the slapd.conf file
    access to attrs=userPassword
            by dn="uid=root,ou=People,dc=domain,dc=com" write
            by dn="cn=Manager,dc=example,dc=com" write
            by anonymous auth
            by self write
            by * none
    access to dn.base="" by * read
    access to *
             by dn="cn=Manager,dc=example,dc=com" write
             by * read
  4. Copy the DB_CONFIG.example template provided into the ldap database directory
    cp /etc/openldap/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
  5. Generate TLS certificates for secure ldap access:
    cd  /etc/pki/tls/certs/
    make -B slapd.pem

    The -B forces the slapd.pem file to be regenerated.

    Then back in the slapd.conf, uncomment the following TLS lines:

    TLSCACertificateFile /etc/pki/tls/certs/ca-bundle.crt
    TLSCertificateFile /etc/pki/tls/certs/slapd.pem
    TLSCertificateKeyFile /etc/pki/tls/certs/slapd.pem
  6. Then update the /etc/openldap/ldap.conf with the
    following entries:

    URI ldap://localhost
    BASE dc=example,dc=com
    TLS_CACERTDIR /etc/openldap/cacerts

    and update the base directive in the /etc/ldap.conf
    file as well.

  7. Start the LDAP server
    service ldap start
    chkconfig ldap on
  8. Setup the ldap directory. I found using the migration tools in the /usr/share/openldap/migration directory the easiest way to do this. First edit the migrate_common.ph to update the domain name
    $DEFAULT_MAIL_DOMAIN = "example.com";
    $DEFAULT_BASE = "dc=example,dc=com";

    Then from the /etc/openldap/ directory, run the following command

    /usr/share/openldap/migration/migrate_base.pl > base.ldif

    The resulting base.ldif file can then be incorporated into the ldap server with the following command

    ldapadd -f base.ldif -x -D "cn=Manager,dc=example,dc=com" -W
  9. Fill in directory with desired users, groups, mounts, etc. You can use the remainder of the migration scripts, but I prefer to use the web interface provided by phpldapadmin. Edit the /etc/phpldapadmin/config.php and uncomment the following line
    $ldapservers->SetValue($i,'server','host','127.0.0.1');
    $ldapservers->SetValue($i,'server','base',array('dc=example,dc=com'));

    Change the login attribute from ‘uid’ to ‘dn’ to be

    $ldapservers->SetValue($i,'login','attr','dn');

    This will allow you login with the rootdn username and password. You can change it back later to uid if you want users to be able to login with their unix accounts. You may need to edit the /etc/httpd/conf.d/phpldapadmin.conf file to give your machine access to the phpldapadmin directory. Restart the web server

    service httpd restart
  10. Point your web browser to the phpldapadmin directory and login with your Manager dn username, e.g. cn=Manager,dc=example,dc=com. First create a new group. Then create a new user. I had to manually edit the user and add the attribue of loginShell after creating the user.
  11. Enable authentication via LDAP with the following command
    authconfig --enableldap --enableldapauth --ldapserver='ldap://localhost' --ldapbasedn='dc=example,dc=com' --update

    I thought you could just update the /etc/nsswhich.conf to include ldap authentication as follows to get things working, but the authconfig does something else as well that I do not know about yet.

    passwd:     files ldap
    shadow:     files ldap
    group:      files ldap

    You can also to automounts in this manner as well.

  12. Test it. Run the following command to see that your new users appear in the list
    getent passwd

    And try logging as the new user.

  13. I found that sometimes that LDAP stuff was *slow*. It would take several seconds for getent passwd to look print up the LDAP entries. Using strace, I saw that it was query to mail.example.com was occurring that was taking a long time. I am not sure who was using that name, but adding mail.example.com to /etc/hosts file under the 127.0.0.1 line solved the problem.

Exim-Cyrus-IMAP-Sieve-Spamassassin-Mailman Email Server on Fedora 8

Friday, February 8th, 2008 by lane

My notes on setting up an email server on Fedora 8.

My first task was to select the MTA. I am tired of dealing with sendmail, so I wanted to try something new. Fedora 8 has rpm packages for sendmail, postfix, and exim. After reading an MTA comparison, I decided to try exim. So far I have enjoyed Exim considerably. The experience has been much better than sendmail.

Install everything

yum install exim spamassassin cyrus-imapd squirrelmail mailman mod_ssl pyzor perl-Mail-SPF

Exim Setup

  1. Switch from sendmail to exim as the default MTA with the following commands
    alternatives --display mta
    alternatives --config mta
    chkconfig sendmail off
    chkconfig exim on
  2. Create the exim certificates for
    cd /etc/pki/tls/certs
    make -B exim.pem SERIAL=2

    Thunderbird does not like the certificates to have the same serial number, so I give it an arbitrary serial number of 2 to avoid conflict with other certificates that I have.

  3. Setup the /etc/exim/exim.conf file. Here is a diff of my setup file to the default one shipped:
    --- exim.conf.orig      2008-03-25 17:52:35.000000000 -0400
    +++ exim.conf   2008-03-25 18:38:19.000000000 -0400
    @@ -48,7 +48,7 @@
     # uname() function is called to obtain the name. In many cases this does
     # the right thing and you need not set anything explicitly.
    
    -# primary_hostname =
    +primary_hostname = example.com
    
     # The next three settings create two lists of domains and one list of hosts.
    @@ -129,7 +129,7 @@
     # is shown in this commented example. As for virus scanning, you must also
     # modify the acl_check_data access control list to enable spam scanning.
    
    -# spamd_address = 127.0.0.1 783
    +spamd_address = 127.0.0.1 783
    
     # If Exim is compiled with support for TLS, you may want to enable the
    @@ -151,7 +151,7 @@
     # options.
    
     tls_certificate = /etc/pki/tls/certs/exim.pem
    -tls_privatekey = /etc/pki/tls/private/exim.pem
    +#tls_privatekey = /etc/pki/tls/private/exim.pem
    
     # In order to support roaming users who wish to send email from anywhere,
     # you may want to make Exim listen on other ports as well as port 25, in
    @@ -212,7 +212,7 @@
     # an alias for root that redirects such mail to a human administrator.
    
     never_users = root
    -
    +trusted_users = apache
    
     # The setting below causes Exim to do a reverse DNS lookup on all incoming
     # IP calls, in order to get the true host name. If you feel this is too
    @@ -229,7 +229,7 @@
     # too. Once a user is authenticated, the acl_check_rcpt ACL then
     # allows them to relay through the system.
     #
    -# auth_advertise_hosts = ${if eq {$tls_cipher}{}{}{*}}
    +auth_advertise_hosts = ${if eq {$tls_cipher}{}{}{*}}
     #
     # By default, we set this option to allow SMTP AUTH from nowhere
     # (Exim's default would be to allow it from anywhere, even on an
    @@ -238,7 +238,7 @@
     # Comment this one out if you uncomment the above. Did you make sure
     # saslauthd is actually running first?
     #
    -auth_advertise_hosts =
    +#auth_advertise_hosts =
    
     # The settings below, which are actually the same as the defaults in the
     # code, cause Exim to make RFC 1413 (ident) callbacks for all incoming SMTP
    @@ -251,7 +251,7 @@
     # reduced from 30s to 5s for release 4.61.)
    
     rfc1413_hosts = *
    -rfc1413_query_timeout = 5s
    +rfc1413_query_timeout = 0s
    
     # By default, Exim expects all envelope addresses to be fully qualified, that
    @@ -511,8 +511,8 @@
       # messages too, though -- although it's not hard for the offender to fix
       # after they receive a bounce because of it.
       #
    -  # deny    condition  = ${if !def:h_Message-ID: {1}}
    -  #         message    = RFC2822 says that all mail SHOULD have a Message-ID header.\n\
    +  deny    condition  = ${if !def:h_Message-ID: {1}}
    +          message    = RFC2822 says that all mail SHOULD have a Message-ID header.\n\
       #                      Most messages without it are spam, so your mail has been rejected.
       #
       # Alternatively if we're feeling more lenient we could just use it to
    @@ -529,28 +529,24 @@
    
       # Bypass SpamAssassin checks if the message is too large.
       #
    -  # accept  condition  = ${if >={$message_size}{100000} {1}}
    -  #         add_header = X-Spam-Note: SpamAssassin run bypassed due to message size
    +  accept  condition  = ${if >={$message_size}{100000} {1}}
    +          add_header = X-Spam-Note: SpamAssassin run bypassed due to message size
    
       # Run SpamAssassin, but allow for it to fail or time out. Add a warning message
       # and accept the mail if that happens. Add an X-Spam-Flag: header if the SA
       # score exceeds the SA system threshold.
       #
    -  # warn    spam       = spam/defer_ok
    -  #         add_header = X-Spam-Flag: YES
    -  #
    -  # accept  condition  = ${if !def:spam_score_int {1}}
    -  #         add_header = X-Spam-Note: SpamAssassin invocation failed
    -  #
    +  warn    spam       = nobody/defer_ok
    +          add_header = X-Spam-Flag: YES
    +
    +  accept  condition  = ${if !def:spam_score_int {1}}
    +          add_header = X-Spam-Note: SpamAssassin invocation failed
    +
    
    -  # Unconditionally add score and report headers
    -  #
    -  # warn    add_header = X-Spam-Score: $spam_score ($spam_bar)\n\
    -  #                      X-Spam-Report: $spam_report
    -
       # And reject if the SpamAssassin score is greater than ten
       #
    -  # deny    condition = ${if >{$spam_score_int}{100} {1}}
    +  deny    condition = ${if >{$spam_score_int}{100} {1}}
    +          message = Mail cannot be delivered
       #         message   = Your message scored $spam_score SpamAssassin point. Report follows:\n\
       #                    $spam_report
    
    @@ -558,6 +554,11 @@
       #
       # warn    condition = ${if >{$spam_score_int}{5} {1}}
       #         set acl_m_greylistreasons = Message has $spam_score SpamAssassin points\n$acl_m_greylistreasons
    +  # Unconditionally add score and report headers
    +  #
    +  warn    add_header = X-Spam-Score: $spam_score ($spam_bar)\n\
    +                       X-Spam-Report: $spam_report
    +
    
       # If you want to greylist _all_ mail rather than only mail which looks like there
    @@ -709,26 +710,26 @@
     # forwarding generates a direct delivery to a file, or to a pipe, or sets
     # up an auto-reply, respectively.
    
    -userforward:
    -  driver = redirect
    -  check_local_user
    -# local_part_suffix = +* : -*
    -# local_part_suffix_optional
    -  file = $home/.forward
    -  allow_filter
    -  no_verify
    -  no_expn
    -  check_ancestor
    -  file_transport = address_file
    -  pipe_transport = address_pipe
    -  reply_transport = address_reply
    -
    -procmail:
    -  driver = accept
    -  check_local_user
    -  require_files = ${local_part}:+${home}/.procmailrc:/usr/bin/procmail
    -  transport = procmail
    -  no_verify
    +#userforward:
    +#  driver = redirect
    +#  check_local_user
    +## local_part_suffix = +* : -*
    +## local_part_suffix_optional
    +#  file = $home/.forward
    +#  allow_filter
    +#  no_verify
    +#  no_expn
    +#  check_ancestor
    +#  file_transport = address_file
    +#  pipe_transport = address_pipe
    +#  reply_transport = address_reply
    +#
    +#procmail:
    +#  driver = accept
    +#  check_local_user
    +#  require_files = ${local_part}:+${home}/.procmailrc:/usr/bin/procmail
    +#  transport = procmail
    +#  no_verify
    
     # This router matches local user mailboxes. If the router fails, the error
     # message is "Unknown user".
    @@ -743,7 +744,7 @@
       check_local_user
     # local_part_suffix = +* : -*
     # local_part_suffix_optional
    -  transport = local_delivery
    +  transport = lmtp_delivery
       cannot_route_message = Unknown user
    
    @@ -826,22 +827,22 @@
       return_path_add
    
    -# This transport is used for handling autoreplies generated by the filtering
    -# option of the userforward router.
    -
    -address_reply:
    -  driver = autoreply
    +## This transport is used for handling autoreplies generated by the filtering
    +## option of the userforward router.
    +#
    +#address_reply:
    +#  driver = autoreply
    
     # This transport is used to deliver local mail to cyrus IMAP server via UNIX
     # socket. You'll need to configure the 'localuser' router above to use it.
     #
    -#lmtp_delivery:
    -#  home_directory = /var/spool/imap
    -#  driver = lmtp
    -#  command = "/usr/lib/cyrus-imapd/deliver -l"
    -#  batch_max = 20
    -#  user = cyrus
    +lmtp_delivery:
    +  home_directory = /var/spool/imap
    +  driver = lmtp
    +  command = "/usr/lib/cyrus-imapd/deliver -l"
    +  batch_max = 20
    +  user = cyrus
    
     ######################################################################
    @@ -923,12 +924,12 @@
     # use $auth2 as a lookup key, and compare $auth3 against the result of the
     # lookup, perhaps using the crypteq{}{} condition.
    
    -#PLAIN:
    -#  driver                     = plaintext
    -#  server_set_id              = $auth2
    -#  server_prompts             = :
    -#  server_condition           = ${if saslauthd{{$2}{$3}{smtp}} {1}}
    -#  server_advertise_condition = ${if def:tls_cipher }
    +PLAIN:
    +  driver                     = plaintext
    +  server_set_id              = $auth2
    +  server_prompts             = :
    +  server_condition           = ${if saslauthd{{$2}{$3}{smtp}} {1}}
    +  server_advertise_condition = ${if def:tls_cipher }
    
     # LOGIN authentication has traditional prompts and responses. There is no
     # authorization ID in this mechanism, so unlike PLAIN the username and

Cyrus IMAP Setup

  1. Build the TLS certificates
    cd /etc/pki/tls/certs/
    make -B cyrus-imapd.pem

    Update the /etc/imapd.conf to point to these certificates

    tls_cert_file: /etc/pki/tls/certs/cyrus-imapd.pem
    tls_key_file:  /etc/pki/tls/certs/cyrus-imapd.pem
    tls_ca_file:   /etc/pki/tls/certs/ca-bundle.crt
  2. Start the saslauthd and cyrus-imapd services:
    chkconfig saslauthd on
    chkconfig cyrus-imapd on
    service saslauthd start
    service cyrus-imapd start
  3. Give the user cyrus a password:
    passwd cyrus
  4. Create user mailboxes
    cyradm -u cyrus -auth login localhost
    createmailbox user.[username]

Sieve
To get sieve working, I had to add the following to the /etc/imapd.conf

allowplaintext: 1

Spamassassin

  • Change /etc/sysconfig/spamassassin to
    SPAMDOPTIONS="-d -c -m5 -H /var/lib/spamassassin"
  • Create a spam user for baysian learning by adding
    spam:x:499:99:SPAM:/var/lib/spamassassin:/sbin/nologin

    to your /etc/passwd file

  • Create /var/lib/spamassassin with spam as the owner
  • In /etc/mail/spamassassin/v310.pre, enable DDC checking. Install DDC client. I found one in atrpms yum repo
  • Start spamassassin
    service spamassassin start
    chkconfig spamassassin on
  • Test things with these commands
    spamassassin -D < /usr/share/doc/spamassassin-3.2.4/sample-nonspam.txt
    spamassassin -D < /usr/share/doc/spamassassin-3.2.4/sample-spam.txt

Mailman
I was quite pleasantly surprised that Exim has built-in support for Mailman. That means I can create lists without having to add them to my /etc/aliases file.