用Docker+Davmail換掉你的Outlook
簡介
不管你喜歡還是不喜歡,有時候不得不通過Exchange服務器去收發郵件,但是如果你不喜歡微軟系的郵件客戶端(指Outlook),就會給你帶來一定的不便,因為你可能更傾向于在兼容模式下,通過IMAP收取、SMTP發送您的郵件。
...好吧,這正是davmail出現的原因。
davmail是一個Java應用程序,它能在標準兼容的客戶端與Exchange服務器之間建立連接,這是一個非常棒的工具-這也是唯一的解決方案。它還是單機的,可以無狀態的使用,更有意思的是Java讓它非常適合運行在Docker容器里面。
目標
把Docker安裝在CenturyLink的云主機上,獲取一個無狀態的運行davmail的容器鏡像,然后讓系統通過upstart來管理容器。
附加說明
如何獲取一臺CenturyLink云主機就作為一項練習留給讀者。
為了簡單,我們在Ubuntu平臺使用docker.io包來安裝docker,然后手動配置它;當然你還可以使用一種更方便的方式即通過puppet-git-receiver和docker Puppet Forge module這兩個工具來管理Docker安裝包和容器關于upstart的配置,關于這兩個工具的使用會在以后的教程中講述。
安全是我們最關心的問題,尤其是在一個企業的環境中,所以請注意你的本地的工作站與云主機之間的連接是否安全。常見的和行之有效的方法包括ssh端口轉發和使用stunnel(一個不是那么隨意與方便(ad-hoc)的方法)。
無論你個人的郵件有多么不重要,也不要以明文的方式收取他們,因為這樣會影響到整個郵件服務器的安全,從而波及其他人。
前期準備
出于這篇文章的考慮,我們假設你已經做好了充分的準備,已經運行了一臺基于Ubuntu-14.04的云主機;如果沒有,請接著往下讀你可以非常容易的啟動一臺Ubuntu機器,然后安裝Vagrant v1.6.x+和VirtualBox并進行相關配置,我的前一篇關于Chef和Vagrant的教程會提供一些指導,這又是給讀者留下的一個練習。
好了,準備好了嗎,讓我們開始吧!
安裝Docker
我們從Ubuntu上從安裝docker開始:
- root@trusty:~# apt-get install docker.io
- Reading package lists... Done
- Building dependency tree
- Reading state information... Done
- The following extra packages will be installed:
- aufs-tools cgroup-lite
- Suggested packages:
- btrfs-tools debootstrap lxc rinse
- The following NEW packages will be installed:
- aufs-tools cgroup-lite docker.io
- 0 upgraded, 3 newly installed, 0 to remove and 15 not upgraded.
- Need to get 4,207 kB of archives.
- After this operation, 25.0 MB of additional disk space will be used.
- Do you want to continue? [Y/n]
- Get:1 http://archive.ubuntu.com/ubuntu/ trusty/universe aufs-tools amd64 1:3.2+20130722-1.1 [92.3 kB]
- Get:2 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe docker.io amd64 1.0.1~dfsg1-0ubuntu1~ubuntu0.14.04.1 [4,111 kB]
- Get:3 http://archive.ubuntu.com/ubuntu/ trusty/main cgroup-lite all 1.9 [3,918 B]
- Fetched 4,207 kB in 8s (480 kB/s)
- Selecting previously unselected package aufs-tools.
- (Reading database ... 61703 files and directories currently installed.)
- Preparing to unpack .../aufs-tools_1%3a3.2+20130722-1.1_amd64.deb ...
- Unpacking aufs-tools (1:3.2+20130722-1.1) ...
- Selecting previously unselected package docker.io.
- Preparing to unpack .../docker.io_1.0.1~dfsg1-0ubuntu1~ubuntu0.14.04.1_amd64.deb ...
- Unpacking docker.io (1.0.1~dfsg1-0ubuntu1~ubuntu0.14.04.1) ...
- Selecting previously unselected package cgroup-lite.
- Preparing to unpack .../cgroup-lite_1.9_all.deb ...
- Unpacking cgroup-lite (1.9) ...
- Processing triggers for man-db (2.6.7.1-1) ...
- Processing triggers for ureadahead (0.100.0-16) ...
- Setting up aufs-tools (1:3.2+20130722-1.1) ...
- Setting up docker.io (1.0.1~dfsg1-0ubuntu1~ubuntu0.14.04.1) ...
- Adding group `docker' (GID 114) ...
- Done.
- docker.io start/running, process 2353
- Setting up cgroup-lite (1.9) ...
- cgroup-lite start/running
- Processing triggers for libc-bin (2.19-0ubuntu6.3) ...
- Processing triggers for ureadahead (0.100.0-16) ...
在安裝日志的第33行(注:Adding group `docker' (GID 114) ...這行),我們看到系統創建了一個docker用戶組;值得一提的是,如果把用戶加入到這個“docker用戶組”后,此后再通過命令行與docker服務(或者說是進程)交互的時候就不用每次在命令前面加sudo了,這同樣作為一個練習留給讀者。
#p#
創建或者挑選我們需要的鏡像
在Docker hub中有一些可用的davmail鏡像,我們選擇鏡像rsrchboy/davmail-savvis-docker(https://registry.hub.docker.co ... file/)理由很簡單,它是一個配置好了的davmail容器:
- 他不需要掛載/綁定其他任何資源,也不需要掛載外部的數據卷(volume);
- 他是單機運行的 ;
- 沒有以root身份運行。
你可能需要根據Exchange的運行環境與配置來修改此鏡像(rsrchboy/davmail-savvis-docker)中davmail的配置;如果是這樣的話,你就可以把此鏡像作為一個基礎;把對配置的修改疊加(ADD)到它之上,然后保存成一個新的鏡像,再在新鏡像的基礎上重新構建davmail服務。
下面是該鏡像的Dockerfile:
- # This software is Copyright (c) 2014 by Chris Weyl <christopher.weyl@centurylink.com>
- (That is, effectively by CenturyLinkLabs.)
- #
- This work is licensed under a Creative Commons Attribution-ShareAlike 4.0
- International License (CC-BY-SA-4.0).
- #
- http://creativecommons.org/licenses/by-sa/4.0/
- FROM gimoh/davmail:latest
- MAINTAINER Chris Weyl <christopher.weyl@centurylink.com>
- RUN mkdir /etc/davmail
- ADD davmail.properties /etc/davmail/
- add a non-root system user
- note we specify a id so as to try to avoid collisions on the host
- RUN adduser --system --uid 500 --group --home /var/lib/davmail davmail
- RUN chmod 0644 /etc/davmail/*
- ...and use it!
- USER davmail
- override default entry point as we've supplied a config
- ENTRYPOINT ["/usr/local/davmail/davmail.sh", "/etc/davmail/davmail.properties"]
實在是迫不及待了,我們先試運行一下:
- root@trusty:~# docker run rsrchboy/davmail-savvis-docker
- 2014-09-26 18:37:32,226 INFO [main] davmail - DavMail Gateway 4.5.0-2292 listening on SMTP port 1025 POP port 1110 IMAP port 1143 CALDAV port 1080 LDAP port 1389
配置容器,通過upstart讓容器像系統服務一樣運行
upstart是類unix系統中的一種服務管理方式,最近的Ubuntu發行版本已經默認采用upstart來管理系統服務了,它可以非常方便的實現我們的要求。
- Originally created by Gareth Rushgrove's puppetforge docker module
- description "start and stop corporate-davmail in docker"
- author "Chris Weyl <christopher.weyl@centurylink.com>"
- start on (started docker.io)
- stop on stopping docker.io
- setuid root
- respawn
- respawn limit 5 20
- script
- docker run --cidfile=/var/run/docker-corporate-davmail.cid \
- -p 127.0.0.1:11025:1025 \
- -p 127.0.0.1:11110:1110 \
- -p 127.0.0.1:11143:1143 \
- -p 127.0.0.1:11080:1080 \
- -p 127.0.0.1:11389:1389 \
- --net bridge \
- -m 0 \
- rsrchboy/davmail-savvis-docker \
- &&
- exec docker wait "$(cat /var/run/docker-corporate-davmail.cid)"
- end script
- post-stop script
- if [ -e "/var/run/docker-corporate-davmail.cid" ]; then
- docker kill "$(cat /var/run/docker-corporate-davmail.cid)" && \
- rm "/var/run/docker-corporate-davmail.cid"
- fi
- end script
- vim: set ft=upstart :
在這里我們要注意的關于upstart配置項如下(配置文件):
- 聲明docker.io服務的依賴項(6-7行)
- 聲明服務在異常終止時要重啟服務(11行)還有建立安全的限定(12行)
- 聲明如何啟動(15-27行)和關閉(30-35行)服務
毋庸置疑,upstart配置中最核心的還是在docker run命令。
- docker run --cidfile=/var/run/docker-corporate-davmail.cid \
- -p 127.0.0.1:11025:1025 \
- -p 127.0.0.1:11110:1110 \
- -p 127.0.0.1:11143:1143 \
- -p 127.0.0.1:11080:1080 \
- -p 127.0.0.1:11389:1389 \
- --net bridge \
- -m 0 \
- rsrchboy/davmail-savvis-docker
在日志中我們看到,Docker的端口轉發已經建立,davmail監聽的端口有:
- SMTP port 1025
- POP port 1110
- IMAP port 1143
- CALDAV port 1080
- LDAP port 1389
這里要記得 類unix系統中non-privliged的進程是無法啟動小于1024的端口的,所以我們重新做了映射。
我們告訴docker在云主機也就是宿主機上綁定端口時,只綁定大于10000的端口,且只綁定在loopback上。
這樣,當你要訪問IMAP時,你就可以再云主機上通過127.0.0.1:11143訪問,這樣就可以阻止攻擊者遠程的連接你的davmail進行攻擊。
現在我們已經有了一個upstart配置文件,剩下就是如果安裝這個文件了,就是把他復制到/etc/init下,然后啟動服務:
- root@trusty:~# cp docker-corporate-davmail.conf /etc/init/
- root@trusty:~# service docker-corporate-davmail status
- docker-corporate-davmail stop/waiting
- root@trusty:~# service docker-corporate-davmail start
- docker-corporate-davmail start/running, process 4149
- root@trusty:~# docker ps
- CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- 7f93d3b35b60 rsrchboy/davmail-savvis-docker:latest /usr/local/davmail/d 3 seconds ago Up 2 seconds 127.0.0.1:11025->1025/tcp, 127.0.0.1:11080->1080/tcp, 127.0.0.1:11110->1110/tcp, 127.0.0.1:11143->1143/tcp, 127.0.0.1:11389->1389/tcp kickass_mestorf
這個容器是無狀態的,它只是在標準的客戶端和Exchange之間做一個轉譯(translate),你可以對容器進行啟動,關閉,終止,禁用,啟用等操作;現在davmail容器安全的運行在云主機里面,你不用有其他擔心,除非客戶端到服務器的連接中斷。因此,我們解決了復雜的問題同時,還節省了我們成把的時間。
享受的時刻
到目前為止,你的davmail已經運行在容器里面了,通過正確的端口映射配置,現在你可以選擇你喜歡的客戶端去跟Exchange server 通信收發郵件了!davmail建議的客戶端是pine,當然這只是個建議而已。