Tag Archives: domainkey

Linux #8 : How to Implement Dovecot, DKIM, DomainKey, MySQL in Postfix #2

5. Making and checking each configuration files for Postfix and dovecot

지난 시간에 이어서 각 file들의 대략적인 설정 내용을 확인 해 보도록 하자. 해당 설정 파일은 필자가 구축한 시스템에서 적용된 내용으로 모든 시스템에 적합하다고는 할 수 없다.

그럼, dovecot.conf를 살펴보자.

$ /etc/dovecot.conf
## Dovecot configuration
..
# Protocols we want to be serving: imap imaps pop3 pop3s
# If you only want to use dovecot-auth, you can set this to "none".
#protocols = imap imaps pop3 pop3s
protocols = imaps pop3s - 원하는 Protocol을 설정한다.

## Mailbox locations and namespaces
#mail_location = maildir:/home/popmail/%d/%u
mail_location = maildir:/home/popmail/%u <- Maildir 형식을 사용하고 /home/popmail을 Mailbox Directory로 지정했을 경우

# Don't use mmap() at all. This is required if you store indexes to shared
# filesystems (NFS or clustered filesystem).
#mmap_disable = no
mmap_disable=yes <- NFS나 clustered filesystem 사용 여부에 따라..

# Valid UID range for users, defaults to 500 and above. This is mostly
# to make sure that users can't log in as daemons or other system users.
# Note that denying root logins is hardcoded to dovecot binary and can't
# be done even if first_valid_uid is set to 0.
#first_valid_uid = 500
last_valid_uid = 80000 <- Mailbox에 대한 Permission을 80000으로 설정

# Valid GID range for users, defaults to non-root/wheel. Users having
# non-valid GID as primary group ID aren't allowed to log in. If user
# belongs to supplementary groups with non-valid GIDs, those groups are
# not set.
#first_valid_gid = 1
last_valid_gid = 80000

auth default {
# Space separated list of wanted authentication mechanisms:
# plain login digest-md5 cram-md5 ntlm rpa apop anonymous gssapi
# NOTE: See also disable_plaintext_auth setting.
mechanisms = plain login digest-md5 cram-md5 apop -> 인증 관련 mechanism을 설정

#passdb pam {
#{
<- comment passdb pam.
passdb sql {
# Path for SQL configuration file, see doc/dovecot-sql-example.conf
args = /etc/dovecot-mysql.conf
}
..
# It's possible to export the authentication interface to other programs:
socket listen {
..
client {
# The client socket is generally safe to export to everyone. Typical use
# is to export it to your SMTP server so it can do SMTP AUTH lookups
# using it.
path = /var/spool/postfix/private/auth
mode = 0660
user = postfix
group = root

}
}
}

다음은 postfix 설치시 mysql 연동을 위한 설정을 하였으므로, dovecot을 통해 mysql안의 user table을 참조 할 수 있도록 한다.

$ /etc/dovecot-mysql.conf
driver = mysql
#default_pass_scheme = PLAIN
default_pass_scheme = CRAM-MD5
connect = dbname=postfix user=postfix host=XXXXXXX password=XXXXXXX
password_query = SELECT password FROM mailbox WHERE username = '%u' AND active = '1'
user_query = SELECT concat('/home/popmail/', maildir) as home, 80000 as uid, 80000 as gid FROM mailbox WHERE username = '%u' AND active = '1'

필자는 위에서 “CLAM-MD5″를 사용하였는데, Webmail, postfixadmin, dovecot의 암호화 방식을 통일하기 위해서 입니다. PLAIN을 사용하면 dovecot의 log에서 바로 보이는게 문제가 되고, 다른 MD5를 쓰면 webmail에서 지원을 안하기도 하고 해서..

다음은 postfix의 main.cf의 설정이다. 이 또한 dovecot 연동을 위한 설정을 한다.

$ /etc/postfix/main.cf
..
# INTERNET HOST AND DOMAIN NAMES
#
..
#myhostname = host.domain.tld
myhostname = [my.domain.com] <- FQDN을 지정
..
# SENDING MAIL
#
..
#myorigin = $mydomain
myorigin = $myhostname <- Mail 송신시 Sending address@dlgndml Domain 명을 기입

# RECEIVING MAIL
..
#inet_interfaces = localhost
inet_interfaces = all <- 외부로부터 Mail 수신을 허가

# TRUST AND RELAY CONTROL
..
mynetworks = [Add Trust IPs] , localhost, 127.0.0.1
..
# DELIVERY TO MAILBOX
#
..
#home_mailbox = Mailbox
home_mailbox = Maildir/ <- Mailbox 형식을 Maildir로 설정
..
# SHOW SOFTWARE VERSION OR NOT
#
#smtpd_banner = $myhostname ESMTP $mail_name ($mail_version)
smtpd_banner = $myhostname ESMTP unknown <- Version 정보의 제거
..
message_size_limit = 10485760 <- 수신 Mail Size를 제한 10485760은 10MB
...
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_local_domain = $myhostname
smtpd_recipient_restrictions =
permit_mynetworks
permit_sasl_authenticated
reject_unauth_destination

...
smtpd_use_tls = yes
smtpd_tls_cert_file = /etc/pki/tls/certs/mail.pem
smtpd_tls_key_file = /etc/pki/tls/certs/mail.pem
smtpd_tls_session_cache_database = btree:/etc/postfix/smtpd_scache
tls_daemon_random_source = dev:/dev/urandom
...

local_transport = virtual
virtual_transport = virtual
virtual_mailbox_base = /home/popmail
virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf
virtual_alias_domains = $virtual_alias_maps
virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf
virtual_minimum_uid = 80000
virtual_uid_maps = static:80000

virtual_gid_maps = static:80000
mailbox_size_limit = 51200000
message_size_limit = 10240000
virtual_mailbox_limit = 51200000
#virtual_mailbox_limit_maps = hash:/etc/postfix/vquota
virtual_mailbox_limit_override = yes
virtual_overquota_bounce = yes
virtual_mailbox_limit_inbox = yes

virtual_alias_maps = mysql:/etc/postfix,virtual_mailbox_domains = mysql:/etc/postfix,virtual_mailbox_maps = mysql:/etc/postfix 위 설정과 관련 된 DB 접근을 위한 설정 파일도 준비한다. Files은 mysql_virtual_alias_maps.cf mysql_virtual_domains_maps.cf mysql_virtual_mailbox_maps.cf와 같다.

$ more mysql_virtual_alias_maps.cf
user = [db username]
password = [password]
hosts = [hostname]
dbname = postfix
table = alias
select_field = goto
where_field = address

$ more mysql_virtual_domains_maps.cf
user = [db username]
password = [password]
hosts = [hostname]
dbname = postfix
table = domain
select_field = domain
where_field = domain
additional_conditions = and active = '1'

$ more mysql_virtual_mailbox_maps.cf
user = [db username]
password = [password]
hosts = [hostname]
dbname = postfix
table = mailbox
select_field = maildir
where_field = username

일단 여기까지라면 Postfix와 Dovecot, MySQL까지의 단계가 완료 된다.

6. Install DKIM, Domain Key Module on Postfix

• Crypt::OpenSSL::RSA
• Digest::SHA
• Digest::SHA1
• Error
• Mail::Address
• MIME::Base64
• Net::DNS
• Net::Server
• Test::More

DKIM, Domain Key Module을 설치하기 위해서 위와 같은 Perl module들이 필요하게 되고, 물론 Perl도 설치되어 있어야 한다. CPAN으로 설치가 가능한 환경이라면 아래와 같이 하면 된다.

cpan> install Crypt::OpenSSL::RSA Digest::SHA Digest::SHA1 Error Mail::Address MIME::Base64 Net::DNS Net::Server Test::More

그렇지 않다면 상당히 번거로운 작업이 되는데, 아래와 같이 각 Source들을 직접 download 받은 뒤 순서대로 작업을 하면 된다. 각 Module들이 각각 dependency가 존재 해 먼저 설치되어야만 하는 것들이 있다.

[PERL :Error] Error-0.17016.tar.gz
[PERL :Crypt::OpenSSL::RSA]
WITH Crypt::OpenSSL::Random
Crypt-OpenSSL-Random-0.04.tar.gz
Crypt-OpenSSL-RSA-0.26.tar.gz
[PERL :Net::DNS]
WITH Digest-HMAC
WITH Digest::SHA1
WITH Net::IP
WITH Digest::SHA
Digest-SHA1-2.12.tar.gz
Digest-HMAC-1.02.tar.gz
Net-IP-1.25.tar.gz
Digest-SHA-5.48.tar.gz
Net-DNS-0.66.tar.gz
[PERL :Mail::Address]
WITH Date::Format
WITH Date::Parse
WITH Test::Pod
TimeDate-1.20.tar.gz
Test-Pod-1.41.tar.gz
MailTools-2.06.tar.gz
[PERL :Mail-DomainKeys-0.80]
Mail-DomainKeys-0.80.tar.gz
[PERL :AppConfig-1.56]
AppConfig-1.56.tar.gz

위 추가적인 Perl Module을 설치해야만 Mail-DKIM과 DKIMPROXY가 설치가능하게 된다. Perl의 경우 압축 해제 후 perl Makefile.PL;make;make install 명령어로 설치한다.

[PERL :MAIL-DKIM]
Mail-DKIM-0.36.tar.gz
[DKIMPROXY : http://dkimproxy.sourceforge.net/download.html]
WITH PERL :Net::Server
Net-Server-0.97.tar.gz
tar zxvf dkimproxy-1.2.tar.gz
cd dkimproxy-1.2
./configure --prefix=/usr/local/dkimproxy
make;make install

이후 Rebooting시 자동으로 시작 되도록 등록하면 설치 완료.

$ cp source-directory/dkimproxy /etc/init.d/dkimproxy
$ vi dkimproxy
..
### BEGIN CONFIGURABLE BITS
DKIMPROXYDIR=/usr/local/dkimproxy
DKIMPROXYUSER=postfix
DKIMPROXYGROUP=postfix
### END CONFIGURABLE BITS
..
$ chkconfig dkimproxy on

7. Configure DKIM, Domain Key Module on Postfix

위 과정대로 설치를 하였다면 dkimproxy는 /usr/local/dkimproxy에 설치되어 있을 것이다. 그럼, inbound, outbound와 관련 된 설정파일을 설정하는데, 이 파일의 Inbound, outbound Port 즉 아래 설정 내용은 10025, 10026, 10027, 10028은 Postfix의 master.cf의 설정과 연동이 된다.

## Inbound
$ more /usr/local/dkimproxy/etc/dkimproxy_in.conf
# specify what address/port DKIMproxy should listen on
listen 127.0.0.1:10025

# specify what address/port DKIMproxy forwards mail to
relay 127.0.0.1:10026

## Outbound
$ more /usr/local/dkimproxy/etc/dkimproxy_out.conf
# specify what address/port DKIMproxy should listen on
listen 127.0.0.1:10027

# specify what address/port DKIMproxy forwards mail to
relay 127.0.0.1:10028

# specify what domains DKIMproxy can sign for (comma-separated, no spaces)
domain [each domain information]

# specify what signatures to add
signature dkim(c=relaxed)
signature domainkeys(c=nofws)

# specify location of the private key
keyfile /etc/domainkeys/default

# specify the selector (i.e. the name of the key record put in DNS)
selector default

그리고, Domain Key를 생성하고, 아래와 같이 Permission과 Ownership 설정을 한다.

mkdir -p /etc/domainkeys
cd /etc/domainkeys
openssl genrsa -out rsa.private 768
openssl rsa -in rsa.private -out rsa.public -pubout -outform PEM
chown -R root.postfix /etc/domainkeys
chmod 755 /etc/domainkeys

$ rsa.private
-----BEGIN RSA PRIVATE KEY-----
MIIBygIBAAJhALgNMgOmSOtOSD3wcDBKb+y2tM1ZOQGTgWIYzzY/TivZvGAaQWMW
K1XuLscr89pqw9tIXrJYrlN0lLhtiddXc9FZwL0AE3LtQQQFUjMgc4JtAHZ13PR7
DNYWFGcF+oQh3QIDAQABAmB5VGGLHFxnmjRveIhMnVWJQ6yOzmmRC284fship3rd
12yiIczHCD9LJ3f43pWjf8s9G6NmpbYO5PZlhGMI9Sc0CM+ZOSfzQgaa2T/Jp7ol
GxgA+PIR+I8uvA7+3iNtIfUCMQDZfEaqFxl2X/Vx7HDIlkioN05Rq4JWIR0e60Ot
vZ6Swy1naK55hCmKJ4GqR+rzRu8CMQDYpTCaied2MJbAbdAf1jKB2GjqHroCCDI0
rqu4Nkp2vW/vt7k6C/I9MBTTkphtA/MCMQCkkKsPzUbREa8xsw1sWntD/gVfOv32
mjvkx3SApPi2aMWUd9t9y4l7JoWxCZY42zUCMDHXBvB2i1ZIZVYNrVS1rVbr128M
9JPlGM+/42d0rfrVJ/xJEwbEmszy08e8sO5bewIwaPvjrQG6sepZ3gSWcL+8Lg5f
dX2fJEbvJjNUFOgzqvmqaPujOR6nvhArLc/ZViDx
-----END RSA PRIVATE KEY-----

$ rsa.public
-----BEGIN PUBLIC KEY-----
MHwwDQYJKoZIhvcNAQEBBQADawAwaAJhALgNMgOmSOtOSD3wcDBKb+y2tM1ZOQGT
gWIYzzY/TivZvGAaQWMWK1XuLscr89pqw9tIXrJYrlN0lLhtiddXc9FZwL0AE3Lt
QQQFUjMgc4JtAHZ13PR7DNYWFGcF+oQh3QIDAQAB

여기서 rsa.public에 있는 내용이 DNS TXT record의 p value로서 사용되게 된다. 아래 예를 참조.

k=rsa; t=y; p=MHwwDQYJKoZIhvcNAQEBBQADawAwaAJhALgNMgOmSOtOSD3wcDBKb+y2tM1ZOQGT
gWIYzzY/TivZvGAaQWMWK1XuLscr89pqw9tIXrJYrlN0lLhtiddXc9FZwL0AE3Lt
QQQFUjMgc4JtAHZ13PR7DNYWFGcF+oQh3QIDAQAB;

여기서 주의 할 점은 해당 Key는 한줄짜리 임으로 copy & paste 시 line 넘김이 발생하지 않도록 하는 것이다. 이것 때문에 문제가 생긴 적이 있었다.

그럼, Postfix에 dkimproxy를 적용 해 보자. Inbound, outbound에서 설정한 내용대로 Receive & Send가 적절하게 이루어 질 수 있도록 Postfix의 master.cf를 설정해야 한다.

## inbound and outbound filter
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
smtp inet n - n - - smtpd
-o smtpd_proxy_filter=127.0.0.1:10024
-o smtpd_client_connection_count_limit=10
dksign-in unix - - n - 2 smtp
-o smtp_data_done_timeout=1200
-o smtp_send_xforward_command=yes
127.0.0.1:10026 inet n - n - - smtpd
-o content_filter=
-o smtpd_authorized_xforward_hosts=127.0.0.0/8
-o smtpd_client_restrictions=
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o smtpd_data_restrictions=
-o mynetworks=127.0.0.0/8
-o receive_override_options=no_unknown_recipient_checks
submission inet n - n - - smtpd
-o smtpd_etrn_restrictions=reject
-o smtpd_sasl_auth_enable=yes
-o content_filter=dksign:[127.0.0.1]:10027
-o receive_override_options=no_address_mappings
-o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
# -o smtpd_enforce_tls=yes
# -o smtpd_sasl_auth_enable=yes
# -o smtpd_client_restrictions=permit_sasl_authenticated,reject
smtps inet n - n - - smtpd
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
# -o smtpd_client_restrictions=permit_sasl_authenticated,reject
dksign unix - - n - 10 smtp
-o smtp_send_xforward_command=yes
-o smtp_discard_ehlo_keywords=8bitmime
127.0.0.1:10028 inet n - n - 10 smtpd
-o content_filter=
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
-o smtpd_helo_restrictions=
-o smtpd_client_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o mynetworks=127.0.0.0/8
-o smtpd_authorized_xforward_hosts=127.0.0.0/8

여기서 일반 Mail을 보낼 때는 Port 25를 사용하면 되고 Domain Key가 Signed 된 Mail을 보낼 때는 submission Port 587을 사용하면 된다.

$ more /etc/services | grep 587
submission 587/tcp msa # mail message submission
submission 587/udp msa # mail message submission

8. Configure Domain Key on DNS

DNS는 아래와 같이 TXT 형식으로 저장을 하고,

[Zone File]
_domainkey TXT "t=n; o=-;"
[select name]._domainkey TXT "k=rsa; t=n; p=MHwwDQYJKoZIhvcNAQEBBQADawAwaAJhALgNMgOmSOtOSD3wcDBKb+y2tM1ZOQGT
gWIYzzY/TivZvGAaQWMWK1XuLscr89pqw9tIXrJYrlN0lLhtiddXc9FZwL0AE3Lt
QQQFUjMgc4JtAHZ13PR7DNYWFGcF+oQh3QIDAQAB;"

dig로 확인을 하면 아래와 같다.

$ dig _domainkey.[domain.com] txt
..
;; ANSWER SECTION:
_domainkey.[domain.com]. 300 IN TXT "t=y\; o=-\;"

$ dig [select name]._domainkey.[domain.com] txt
..
;; ANSWER SECTION:
_domainkey.[domain.com]. 300 IN TXT "k=rsa; t=y; p=MHwwDQYJKoZIhvcNAQEBBQADawAwaAJhALgNMgOmSOtOSD3wcDBKb+y2tM1ZOQGT
gWIYzzY/TivZvGAaQWMWK1XuLscr89pqw9tIXrJYrlN0lLhtiddXc9FZwL0AE3Lt
QQQFUjMgc4JtAHZ13PR7DNYWFGcF+oQh3QIDAQAB;"

또한, 아래 Site에서 정상 등록 여부 확인이 가능하다.
http://domainkeys.sourceforge.net/policycheck.html
http://domainkeys.sourceforge.net/selectorcheck.html

9. Start Postfix with Dovecot, DKIM, DomainKey, MySQL

각 Daemon의 기동은 간단하고, netstat를 통해 각 Port를 확인 할 수 있다.

$ /etc/init.d/dovecot start
$ /etc/init.d/dkimproxy start
$ /etc/init.d/postfix start
$ /etc/init.d/httpd start

$ netstat -an
..
tcp 0 0 127.0.0.1:10025 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:10026 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:587 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:10027 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:10028 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:25 0.0.0.0:* LISTEN
tcp 0 0 :::993 :::* LISTEN
tcp 0 0 :::995 :::* LISTEN
tcp 0 0 :::80 :::* LISTEN

각 Port의 대한 정보는 아래와 같다.

DKIM, DomainKey Processing => Local : 10025, 10026, 10027, 10028
DKIM, DomainKey Signed SMTP => 587
Normal SMTP => 25
POP3S => 995
IMAPS => 993
HTTP(WebMail) => 80 (Web Mail 서버가 설치되고, 기동 되었다면)

다음 시간에 위 Mail Server상에 Spam Filtering 설치 해 보도록 하겠습니다.