August 16, 2010

Determine Zimbra distribution list membership from Zimbra ldap or ldap backup

Filed under: Directory/LDAP, Messaging, Zimbra, linux — morgan @ 16:22

(all as the zimbra user)

Want to know a user’s distribution list membership?


$ ldapsearch -xh ldap1.domain.com -D uid=zimbra,cn=admins,cn=zimbra -w pass
-Lb dc=domain,dc=com zimbramailforwardingaddress=morgan@domain.com mail|egrep -i '^mail'|
awk '{print $2}'

(to get your ldap password: $ zmlocalconfig -s|grep ldap_password)

Deleted or re-created a user but forgot to note which lists to which they belonged?
You can get it from an ldap backup:


$ cd /opt/zimbra/backup/sessions/full-date.xxx.xxx/ldap
$ export i=morgan; egrep "^dn:|$i" ldap.bak | grep -B1 -i "zimbraMailForwardingAddress:
${i}@domain.com"|grep uid| cut -d '=' -f2|cut -d ',' -f 1

August 6, 2010

Zimbra/Postfix behind an AS/AV appliance

Filed under: Messaging, Zimbra — morgan @ 14:30

I’m working with an anti-virus/anti-spam (av/as) appliance that receives and sends all mail too/from the Internet but end users send directly through the Zimbra mtas. The latter requirement is actually because the av/as vendor does not support end users sending directly though it.

We chose to configure the Zimbra mtas to only accept mail from certain networks (the av/as appliance and a few servers) and authenticated users.

The base postfix smtpd_recipient_restrictions configuration looks like this:


smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject

Note that Postfix will no longer receive mail destined for the domain(s) for which it is authoritative unless it comes from an authenticated session or a host on $mynetworks. The downside is if mail comes from one of those sources there are no restrictions.

We added some “rejects” to provide better error messages to users and cut down on junk:


smtpd_recipient_restrictions = reject_non_fqdn_recipient, reject_unlisted_recipient,
reject_invalid_hostname,  reject_non_fqdn_sender, reject_unknown_sender_domain,
permit_sasl_authenticated, permit_mynetworks, reject

Here’s how we configured it within Zimbra: not particularly complex in retrospect but it’s helpful to see all the pieces in one place.

Set smtpd_recipient_restrictions:


$ zmprov mcf zimbraMtaRestriction reject_invalid_hostname zimbraMtaRestriction reject_non_fqdn_sender zimbraMtaRestriction reject_unknown_sender_domain
$ vi /opt/zimbra/conf/postfix_recipient_restrictions.cf
reject_non_fqdn_recipient
permit_sasl_authenticated
permit_mynetworks
reject_unlisted_recipient
[%%contains VAR: ...]
reject

Set mynetworks globally (rather than per mta):


$ zmprov mcf zimbraMtaMyNetworks 127.0.0.1/32,192.168.2.0/24
$ zmprov ms mta01.domain.com zimbramtamynetworks ""
$ zmprov ms mta02.domain.com zimbramtamynetworks ""
$ zmprov ms mta03.domain.com zimbramtamynetworks ""
...

Force users who auth to also use TLS:


$ zmprov mcf zimbraMtaTlsAuthOnly TRUE
$ zmprov ms mta01.domain.com zimbraMtaTlsAuthOnly ""
$ zmprov ms mta02.domain.com zimbraMtaTlsAuthOnly ""
$ zmprov ms mta03.domain.com zimbraMtaTlsAuthOnly ""
...
$ zmprov mcf zimbraMtaSaslAuthEnable TRUE
$ zmprov ms mta01.domain.com zimbraMtaSaslAuthEnable ""
$ zmprov ms mta02.domain.com zimbraMtaSaslAuthEnable ""
$ zmprov ms mta03.domain.com zimbraMtaSaslAuthEnable ""
...

rebuild the configuration and restart the mta:


$ zmmtactl restart

August 4, 2010

zimbra settings disambiguation

Filed under: Messaging, Zimbra, linux — morgan @ 12:16

I’ve been hunting down various mta settings in Zimbra and noticed something interesting: there are multiple places to set at least mta settings.

For example: I’m looking to set smtpd_sasl_auth_enable = yes. This setting is controlled by zimbraMtaSaslAuthEnable in zimbra.

However, there are two places to set it:


$ zmprov gs mta01.morganjones.org |grep -i zimbraMtaSaslAuthEnable
zimbraMtaSaslAuthEnable: FALSE
$ zmprov gacf |grep -i zimbraMtaSaslAuthEnable
zimbraMtaSaslAuthEnable: TRUE

If it is FALSE in 'gs' but TRUE in gacf smtpd_sasl_auth_enable will be set to 'no' on mta01 in this example.

So, if you want all your mtas to use auth you simply need to unset zimbraMtaSaslAuthEnable for each mta and set it globally:


$ zmprov ms mta01.morganjones.org zimbraMtaSaslAuthEnable ""
$ zmprov ms mta02.morganjones.org zimbraMtaSaslAuthEnable ""
...
$ zmprov mcf zimbraMtaSaslAuthEnable TRUE

and then restart the mta on each mta host:


$ zmmtactl restart
Rewriting configuration files...done.
Stopping zmmtaconfig...done.
Starting zmmtaconfig...done.
postfix/postfix-script: refreshing the Postfix mail system
Stopping saslauthd...done.
Starting saslauthd...done.
$

June 14, 2010

Country based packet filtering in RHEL 5.x

Filed under: Messaging, Redhat/Fedora, Zimbra, linux — morgan @ 23:51

This is adapted from the Debian instructions found here:
http://www.debian-administration.org/articles/518

install redhat source repository and yum-utils
http://www.cyberciti.biz/faq/yum-download-source-packages-from-rhn

# vi /etc/yum.repos.d/srpm.repo
[rhel-src]
name=Red Hat Enterprise Linux $releasever - $basearch - Source
baseurl=ftp://ftp.redhat.com/pub/redhat/linux/enterprise/$releasever/en/os/SRPMS/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
# yum install yum-utils
# mkdir /usr/src/redhat

get kernel source.

# yumdownloader --source kernel-2.6.18
# tar xfj /usr/src/redhat/SOURCES/linux-2.6.18.tar.bz2 -C /usr/src

get iptables source

# yumdownloader --source iptables
# tar xfj /usr/src/redhat/SOURCES/iptables-1.3.5.tar.bz2 -C /usr/src

get patch-o-matic—we will use it to patch iptables and the kernel.

# wget http://ftp.netfilter.org/pub/patch-o-matic-ng/snapshot/patch-o-matic-ng-20070414.tar.bz2
# tar xjf patch-o-matic-ng-20070414.tar.bz2

get the geoip patchlet:

# wget http://people.netfilter.org/peejix/patchlets/geoip.tar.gz
# tar xfz geoip.tar.gz -C patch-o-matic-ng-20070414/patchlets

Apply the geoip patchlet

# cd patch-o-matic-ng-20070414
# KERNEL_DIR=/usr/src/linux-2.6.18/ IPTABLES_DIR=/usr/src/iptables-1.3.5/ ./runme geoip

Loading patchlet definitions.................. done

Welcome to Patch-o-matic ($Revision: 6736 $)!

Kernel:   2.6.18, /usr/src/linux-2.6.18/

Iptables: 1.3.5, /usr/src/iptables-1.3.5
Each patch is a new feature: many have minimal impact, some do not.
Almost every one has bugs, so don't apply what you don't need!
-------------------------------------------------------
Already applied:
Testing geoip... not applied
The geoip patch:
   Author: Samuel Jean ; Nicolas Bouliane 
   Status: Stable

This patch makes possible to match a packet
by its source or destination country.

GeoIP options:
        [!]   --src-cc, --source-country country[,country,country,...]

                        Match packet coming from (one of)
                        the specified country(ies)

        [!]   --dst-cc, --destination-country country[,country,country,...]

                        Match packet going to (one of)
                        the specified country(ies)

           NOTE: The country is inputed by its ISO3166 code.

The only extra files you need is a binary db (geoipdb.bin) & its index file (geoipdb.idx).
Take a look at http://people.netfilter.org/peejix/geoip/howto/geoip-HOWTO.html
for a quick HOWTO.
-----------------------------------------------------------------
Do you want to apply this patch [N/y/t/f/a/r/b/w/q/?] ?
Answer one of the following:
  T to test that the patch will apply cleanly
  Y to apply patch
  N to skip this patch
  F to apply patch even if test fails
  A to restart patch-o-matic in apply mode
  R to restart patch-o-matic in REVERSE mode
  B to walk back one patch in the list
  W to walk forward one patch in the list
  Q to quit immediately
  ? for help
-----------------------------------------------------------------
Do you want to apply this patch [N/y/t/f/a/r/b/w/q/?] T
Patch geoip applies cleanly
-----------------------------------------------------------------
Do you want to apply this patch [N/y/t/f/a/r/b/w/q/?] y

Excellent! Source trees are ready for compilation.

Recompile the kernel image (if there are non-modular netfilter modules).
Recompile the netfilter kernel modules.
Recompile the iptables binaries.
#

Build the kernel module

# cd /usr/src/linux-2.6.18
# make oldconfig
…
    geoip match support (IP_NF_MATCH_GEOIP) [N/m/?] (NEW) m
…
# make modules_prepare


Compile just the netfilter modules

# make -C $(pwd) M=net/ipv4/netfilter/ modules
# cp -i net/ipv4/netfilter/ipt_geoip.ko /lib/modules/2.6.18-128.1.10.el5/kernel/net/ipv4/netfilter/

Build the iptables libipt_geoip.so library

# cd /usr/src/iptables-1.3.5
# make KERNEL_DIR=/usr/src/linux-2.6.18/ extensions/libipt_geoip.so
Making dependencies: please wait...
cc -O2 -Wall -Wunused -I/usr/src/linux-2.6.18//include -Iinclude/ -DIPTABLES_VERSION=\"1.3.5\"  -fPIC -o extensions/libipt_geoip_sh.o -c extensions/libipt_geoip.c
ld -shared  -o extensions/libipt_geoip.so extensions/libipt_geoip_sh.o
# cp extensions/libipt_geoip.so /lib64/iptables

Insert the module into the kernel

# depmod
# modprobe ipt_geoip


Todo: load the module on boot?

Create the IP-country mapping

# wget http://www.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip
# unzip  GeoIPCountryCSV.zip
# wget http://people.netfilter.org/peejix/geoip/tools/csv2bin-20041103.tar.gz
# tar tzf csv2bin-20041103.tar.gz
# cd csv2bin
# make
# ./csv2bin ../GeoIPCountryWhois.csv
# mkdir /var/geoip
# mv geoipdb* /var/geoip

Test
World Cup mania means we happened to have a colleague in South Africa so we blocked the whole country on a test server and had him attempt to connect to https:

# /sbin/iptables -A INPUT -p tcp --dport 443 -m geoip --src-cc ZA -j REJECT

May 27, 2010

“no such account…” during zimbra restores

Filed under: Messaging, Zimbra — morgan @ 10:59

I’m working on a migration where we’re moving users one by one from a production environment to a dev environment. To oversimplify, the process is:
- backup in production,
- zmbackupquery -lb

So:
zmbackup -f -z -a user@domain.com
then


$ zmrestore -c -lb full-20100527.153703.317 -a user@domain.com
Error occurred during restore. Check logs for more details.
The following accounts have not been restored:
  user@domain.com

A look at mailbox.log reveals:


com.zimbra.cs.account.AccountServiceException: no such account: ef423485-424b-4fec-a064-f797ffc4ae29
ExceptionId:btpool0-116://localhost:7071/service/admin/soap/RestoreRequest:1274974984703:209afa27e2965ffa
Code:account.NO_SUCH_ACCOUNT
	at com.zimbra.cs.account.AccountServiceException.NO_SUCH_ACCOUNT(AccountServiceException.java:177)
	at com.zimbra.cs.mailbox.Mailbox.getAccount(Mailbox.java:515)
...

“ef423485-424b-4fec-a064-f797ffc4ae29″ is presumably a zimbraid. I can’t for the life of me figure out where it originates–I can’t find it anywhere in either environment.

The workaround is surprisingly straightforward. Instead of the zmrestore above, restore to a restored_ account and rename the account:


$ zmrestore -c -ca -pre restored_ -lb full-20100527.153703.317 -a user@domain.com
$ zmprov ra restored_user@domain.com user@domain.com

May 14, 2010

Turn on recipient verify in Zimbra

Filed under: Messaging, Zimbra — morgan @ 16:05

I’d love to know why Zimbra does not ship with recipient verify turned on. Here’s the use case: a user sends a message from the web interface with an invalid recipient. He/she does not get an error when the message is sent but instead receives an immediate bounce. Sure the info is in the bounce but it’s easy to miss in a cluttered inbox and it’s a hassle to parse.

The solution is very simple. On each host running postfix:

As zimbra:

$ vi /opt/zimbra/postfix/conf/main.cf
relay_recipient_maps = ldap:/opt/zimbra/conf/ldap-vam.cf

$ vi /opt/zimbra/conf/zmmta.cf
POSTCONF smtpd_reject_unlisted_recipient yes

$ zmmtactl restart

This works in zcs 5.0.x and 6.0.6. It will likely work in other versions as well.

October 23, 2009

SSL Certificates in Zimbra 5.0.x

Filed under: Messaging, Zimbra, linux — morgan @ 11:28

Using these links as a starting place,

http://www.jransomed.com/mywiki/Zimbra/InstallingSSLCertificate

http://wiki.zimbra.com/index.php?title=5.x_Commercial_Certificates_Guide

Here’s a run-down of installing SSL certificates in Zimbra Collaboration Suite (ZCS) 5.0.x. It’s relatively straightforward once you wrap your head around the steps. You’ll want to do these steps as root.

The customer on which this example is based had existing Comodo wildcard certificates for their *.domain.edu.

Browse to http://instantssl.com
log in
Arrow over to Comodo PreimumSSL Wildcard Certificate for *.domain.edu
click on ‘Download as .zip’

You should have three files that start with ‘STAR.’ rename them:
STAR_domain_edu.crt to commercial.crt
STAR_domain_edu.crt to commercial_ca.crt
STAR_domain_edu.key to commercial.key

Copy the commercial* files to each of the Zimbra hosts.


# mv commercial.key /opt/zimbra/ssl/zimbra/commercial
# mv commercial.crt commercial_ca.crt /var/tmp

Deploy the cert:


# cd /var/tmp
# zmcertmgr deploycrt comm ./commercial.crt commercial_ca.crt

This may not apply to you but we were unable to get openssl and by extension Zimbra to verify the Comodo cert chain. If zmcertmgr deploycrt is failing for you and you’re relatively confident your certs are okay here’s how I fixed it. It’s unconventional but it works. I am open to correction if someone has a more conventional fix for this..

Cd to /opt/zimbra/bin, copy zmshutil and zmcertmgr to /var/tmp and edit zmcertmgr in /var/tmp. Comment out the lines as below and add two lines also as below:


# cd /opt/zimbra/bin
# cp zmshutil /var/tmp/zmshutil
# cp zmcertmgr /var/tmp/zmcertmgr
# vi /var/tmp/zmcertmgr
    #  result=`${openssl} verify -purpose sslserver -CAfile $ca_crt $crt`
    #  if [ x"${result}" = x"${crt}: OK" ]; then
    #   echo "Valid Certificate: $result"
    echo "(artificially) Valid Certificate: $result"
    #  else
    #    echo "${ERROR_PREFIX} Invalid Certificate: $result"
    #    exit 1
    #  fi

    #  result=`${openssl} verify -purpose sslserver -CAfile $cafile $crt`

    #  if [ x"${result}" = x"${crt}: OK" ]; then
    #      echo "Valid Certificate Chain: $result"
    echo "(artificially) Valid Certificate Chain: $result"
    #  else
    #    echo "${ERROR_PREFIX} Invalid Certificate Chain: $result"
    #    exit 1
    #  fi

Once you’ve saved the modified version of zmcertmgr, run it from /var/tmp to deploy the certificates:


# cd /var/tmp
# ./zmcertmgr deploycrt comm ./commercial.crt commercial_ca.crt
** Verifying ./commercial.crt against /opt/zimbra/ssl/zimbra/commercial/commercial.key
Certificate (./commercial.crt) and private key (/opt/zimbra/ssl/zimbra/commercial/commercial.key) match.
(artificially) Valid Certificate:
** Copying ./commercial.crt to /opt/zimbra/ssl/zimbra/commercial/commercial.crt
** Appending ca chain commercial_ca.crt to /opt/zimbra/ssl/zimbra/commercial/commercial.crt
** Saving server config key zimbraSSLCertificate...done.
** Saving server config key zimbraSSLPrivateKey...done.
** Installing mta certificate and key...done.
** Installing slapd certificate and key...done.
** Installing proxy certificate and key...done.
** Installing CA to /opt/zimbra/conf/ca...done.

Now your certificates are installed. You need to restart Zimbra for them to take effect:


# su - zimbra -c "zmcontrol stop && zmcontrol start"

You’ll need to repeat the above for each of your servers if you have a multi-server environment: stores, mtas, ldap, etc.

If you have a relatively recent version of openssl you can test that your certificate is working by testing tls on your mta(s):


$ openssl s_client -starttls smtp -connect mta.domain.edu:25

June 30, 2009

imapsync between Zimbra environments

Filed under: Messaging, Zimbra — morgan @ 15:33

I spent entirely too much time in the last few days setting up to imapsync between two Zimbra environments. I will spare you the whole story but suffice to say we moved some users from production to a newly upgraded development environment and then managed to wipe out a significant portion of their mail. They were already receiving mail in the dev environment so re-copying the mail from prod wasn’t an option. Zimbra’s backup and restore isn’t smart enough to restore from one address (@prod.com->@dev.com). The obvious solution is to imapsync from prod to dev. Simple, right?

Well..

It turns out Zimbra adds headers when messages are added to the destination side. This means if you run imapsync more than once, say, to test on a folder and then run it for a whole account it will re-upload messages it just uploaded as the new headers on the destination side made the messages different. The solution is to –skipsize and ‘useheader’ enough headers so you’re sure they’ll make messages unique even if all headers aren’t in all messages (Message-ID is not in all messages for instance) but they won’t be changed on the destination side. I used –useheader Message-ID –useheader ‘From’ –useheader ‘To’ –useheader ‘Date’


imapsync --sep1 '/' --prefix1 ''  --authmech1 PLAIN --ssl1 \
    --host1 imap.prod.com --user1 user --password1 pass \
    --authmech2 PLAIN -ssl2 --host2 imap.dev.com --user2 user2 \
    --password2 pass2 --useheader Message-ID --useheader 'From' \
    --useheader 'To' --useheader 'Date' --skipsize

We also saw problems with messages presumably larger than 10mb:


++++ From [Sent] Parse 1 ++++
++++ To   [Sent] Parse 1 ++++
++++ Verifying [Sent] -> [Sent] ++++
+ NO msg #286039 [VsZ9lgHjrPxeOAn7S9sU6Q] in Sent
+ Copying msg #286039:12572025 to folder Sent
flags from : [\Seen]["04-May-2009 07:46:14 -0400"]
parse_headers want an ARRAY ref
Couldn't append msg #286039 (Subject:[0]) to folder Sent: Error trying to
append: 6568 NO [TOOBIG] request too long

A look in the user’s sent folder for a message at 07:46 showed a 12mb message. Search the zimbra forums and:


[zimbra@store01 ~]$ zmprov gacf|grep -i zimbraMtaMaxMessageSize
zimbraMtaMaxMessageSize: 10485760
[zimbra@store01 ~]$ zmprov mcf zimbraMtaMaxMessageSize 50000000
[zimbra@store01 ~]$

You can now re-run imapsync as above and the message will be copied.

Also of note is –sep1 ‘/’ and –prefix ”: Apparently the Zimbra 5.0.7 imap server does not have NAMESPACE capability.

edit 090706: changed zimbraFileUploadMaxSize to zimbraMtaMaxMessageSize. According to http://wiki.zimbra.com/index.php?title=Guide_to_imapsync this was changed in 5.0.6.

February 6, 2009

Sun pam_ldap/pam_unix and correct subtree LDAP searches

Filed under: Directory/LDAP, JES, Java Enterprise System, Messaging, Solaris 10 — morgan @ 0:26

Though addressed in the context JES Messaging this post is really about getting Sun’s pam_ldap or pam_unix to do what some might consider correct subtree searches. Read on:

If you’re using JES messaging with hosted domains you have an ldap tree that looks like this:
o=firstdomain.com,o=isp; o=seconddomain.com,o=isp; etc.

so your user DNs look like this: uid=morgan,ou=people,o=firstdomain,o=isp; uid=matt,ou=people,o=seconddomain,o=isp; etc.

Under normal circumstances you would supply a basedn of “o=isp,” a scope of “sub,” and the application would search all of your hosted domains in search of the username.

Sun’s pam_ldap (and I believe pam_unix) prepend “ou=people” before doing a search. So if you specify “o=isp,” pam_ldap will search within “ou=people, o=isp” which either doesn’t exist or is empty.

After searching for a way to specify multiple base dns in the ldap profile (defaultSearchBase is SINGLE-VALUE in objectclass DUAConfigProfile) it turns out there is a straightforward work-around. From the ldapclient(1) man page:


serviceSearchDescriptor
           Override the default base DN for LDAP searches  for  a
           given  service.  The  format  of  the descriptors also
           allow overriding the default search scope  and  search
           filter  for  each  service. The syntax of serviceSear-
           chDescriptor is defined in  the  profile  IETF  draft.
           The  default value for all services is NULL. This is a
           multivalued attribute. In the example,

           serviceSearchDescriptor=passwd:ou=people,dc=a1,dc=acme,dc=com?one

           the LDAP  client  would  do  a  one  level  search  in
           ou=people,dc=a1,dc=acme,dc=com       rather       than
           ou=people,defaultSearchBase for the passwd service.
 

So set serviceSearchDescriptor=passwd:o=isp and it will search under o=isp, allowing users in all of your hosted domains to authenticate. Of course this does open you up to problems where uids can conflict.

August 27, 2008

Controlling sender domain in Postfix/Zimbra 5

Filed under: Messaging, Zimbra, linux — morgan @ 16:54

A client has asked that mail through his Zimbra MTA only be allowed from or to valid domains within their organization. This is particularly applicable to Zimbra as Zimbra will only archive mail if it’s from or to a domain for which it is authoritative. The idea is to archive all mail through their Zimbra environment.. If it is not one of their domains, refuse it.

If this were my organization it would look like this:
mail from user@morganjones.org to any domain would work
mail from user@1038east.com to any domain would work
mail from any domain to user@morganjones.org would work
mail from any domain to user@1038east.com would work
of course mail from and to user@morganjones.org or 1038east.com will work
all other mail will be considered relaying.

One thing we did not do that I might want to do is force authentication. The problem with this configuration is it does open up to spamming as it only validates from or to domain.

This is really a discussion about Postfix configuration but I did the work in Zimbra so I might as well add the additional steps to configure it in Zimbra.. These instructions will be applicable to straight Postfix or Zimbra.

You’ll want to do all the work as the zimbra user:
Run the zmprov command for each of your mtas.


# su - zimbra

$ zmprov ms mta01.morganjones.org zimbraMtaMyNetworks 127.0.0.0/8

$ vi /opt/zimbra/postfix/conf/main.cf
smtpd_sasl_auth_enable = no
# if you want enable sending to domains for which your environment is not
#   authoritative this is also handy for testing in your dev environment
#   that is only authoritative for a dev domain
relay_domains = 1038east.com, morganjones.org

You also want to modify smtpd_recipient_restrictions but in Zimbra you must modify that with in the zimbra configuration:


$ vi /opt/zimbra/conf/postfix_recipient_restrictions.cf
# remove permit_sasl_authenticated
check_sender_access hash:/opt/zimbra/postfix/conf/access

$ vi /opt/zimbra/postfix/conf/access
1038eaast.com OK
morganjones.org OK

$ zmmtactl reload

You might want to check that /opt/zimbra/postfix/conf/main.cf now contains this:


smtpd_recipient_restrictions = reject_non_fqdn_recipient,
check_sender_access
hash:/opt/zimbra/postfix/conf/access, permit_mynetworks,
reject_unauth_destination, reject_unlisted_recipient,
reject_invalid_hostname, reject_non_fqdn_sender, permit

You should now be set.

It’s worth mentioning: check_sender_access will only check and allow the sender domain. if you don’t set relay_domains the recipient domain is allowed because your environment is the final destination for that/those domain(s). As noted above you can set relay_domains above if you want to allow relaying to domains for which this environment is not the final destination.

Older Posts »

Powered by WordPress