Postfix + Base de Dados + SASL = Kyapanel
Autor: Edson Cardoso Ribeiro Junior | Publicado: 2012-06-09T20:02:00-07:00

Já tive que resolver muitos problemas relacionados à servidores de e-mail.
Pessoalmente prefiro a combinação Linux + Postfix + Alguma base de dados (LDAP, SQL) + SASL.
No entremeio desses problemas, encontrei uma solução que considero adequada, robusta, escalável. Estou falando do Kyapanel.
Hoje o Kyapanel também se integra com outra solução de&nbsp;colaboração, o Zimbra.
Mas para efeito desse post, coloco uma contribuição que fiz para solucionar um problema de autenticação SASL com base de dados MySQL (http://www.kyapanel.com/wiki/doku.php?id=kyapanel:sasl_auth_mysql_pt_br)





SMTP autenticado com SASL na base MySQL do KyaPanel


Olhando o histórico desta lista, verifiquei que muitos administradores apresentam dificuldades em integrar o Kya Panel à autenticação SASL (principalmente com a base de dados em MySQL). A solução para LDAP já havia sido proposta aqui:

http://www.kyapanel.com/wiki/doku.php?id=kyapanel:sasl_auth_pt_br

Como queria utilizar o KP com MySQL, deparei-me com todos os problemas descritos pelos colegas até aqui. Por isso envio os passos que adotei na solução do meu problema específico.




1 - Problema


O Kya Panel não se encarrega de instalar o&nbsp;SMTP&nbsp;Relay de redes externas ao servidor, provendo algum tipo de autenticação de usuário para isso, conforme essa mensagem:

http://sourceforge.net/mailarchive/forum.php?thread_name=c037b98e0707311459y5cc226d3sf3512fbcbb8ba873%40mail.gmail.com&amp;forum_name=jegue-users

O Anahuac propõe duas soluções:&nbsp;SMTP-AUTH e&nbsp;POP-Before-SMTP. Como opinião pessoal, considero o&nbsp;POP-Before-SMTP&nbsp;um pouco mais inseguro (basta pensar num relay de rede atrás de NAT com 300 máquinas: uma vez aberto o relay, temos 300 servidores de e-mail potenciais para SPAM).






2 - SMTP-AUTH (SASL + MySQL)


O caminho das pedras começou com a mensagem do Roger Lovato:

http://sourceforge.net/mailarchive/forum.php?thread_name=11d703790801120357o75297e01n3200f3c6412c52a2%40mail.gmail.com&amp;forum_name=jegue-users

Aqui ele propõe o esquema (corretamente aliás) da integração do SASL + MySQL + Postfix. Após muita procura, encontrei esse tutorial (que com algumas mudanças, pois uso Debian Etch) montou a base principal da solução:&nbsp;http://www.nervous.it/txt/Postfix-SMTP-AUTH-4-DUMMIES.html






3 - libpam-mysql


Entretanto, após a configuração do meu sistema, o SASL teimava em não autenticar na base MySQL. Fazia o SELECT diretamente no banco, funcionava perfeitamente; mas quando o Postfix o fazia dava erro de autenticação:
SASL LOGIN authentication failed


Descobri que o problema era o pacote libpam-mysql para Debian. O mesmo possui um bug que não entende campos MD5 no MySQL. Você pode usar PASSWORD, CRYPT, mas MD5 não passa. Aqui o BUG:

http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=373834

Solução? Compilar o libpam-mysql na mão.






4 - Compilando libpam-mysql


- Baixar o código fonte do PAM-MySQL aqui:&nbsp;http://pam-mysql.sourceforge.net/

- Resolver as dependências da compilação:
apt-get install gcc g++ make libpam0g-dev libssl-dev mysql-client
libmysqlclient15-dev

- Desempacotar o PAM-MySQL
- ln -s /usr/include/openssl/md5.h /usr/include/md5.h
- ./configure --with-openssl=/usr/
- make install


O arquivo deve ser encontrado em /lib/security/pam_mysql.so Pronto, libpam-mysql instalado (aliás, boa idéia seria gerar um pacote .deb já corrigido; eu procurei, não encontrei)






5 - Configurando SASL + MySQL + Postfix


Criar um arquivo /etc/pam.d/smtp com o seguinte conteúdo:
auth required /lib/security/pam_mysql.so user=usuario passwd=senha
host=127.0.0.1 db=jp table=jp_accounts usercolumn=account_wmail
passwdcolumn=account_pwd crypt=3
account sufficient /lib/security/pam_mysql.so user=usuario passwd=senha
host=127.0.0.1 db=jp table=jp_accounts usercolumn=account_wmail
passwdcolumn=account_pwd crypt=3


Note que:

- O banco, as tabelas e as colunas são as padrões de instalação do KP - A opção “crypt=3” se refere à busca em campos MD5 no MySQL

Criar o arquivo /etc/postfix/sasl/smtpd.conf com o seguinte conteúdo:
pwcheck_method: saslauthd
mech_list: PLAIN LOGIN


Editar o arquivo /etc/default/saslauthd e marcar as seguintes opções:
START=yes
MECHANISMS="pam"


Editar o arquivo /etc/init.d/saslauthd (no Debian Etch) e localizar a seguinte linha:
DAEMON_ARGS="$DAEMON_ARGS -a $MECHANISMS $MECH_OPTIONS $OPTIONS
$THREAD_OPTIONS"


e modificá-la para:
DAEMON_ARGS="$DAEMON_ARGS -a $MECHANISMS $MECH_OPTIONS -r $OPTIONS
$THREAD_OPTIONS"


Como nosso Postfix roda em chroot por padrão, mover o diretório do sasl:
# mv /var/run/saslauthd /var/spool/postfix/var/run/saslauthd
# ln -s /var/spool/postfix/var/run/saslauthd /var/run/saslauthd


Adicionar o usuário postfix no grupo sasl:
# adduser postfix sasl


Até aqui, com pequenas alterações, você está seguindo o seguinte tutorial:

http://www.nervous.it/txt/Postfix-SMTP-AUTH-4-DUMMIES.html

Adicione as seguintes linhas em /etc/postfix/main.cf :
smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain = 
broken_sasl_auth_clients = yes


e não se esqueça de adicionar o parâmetro permit_sasl_authenticated em smtpd_recipient_restrictions, ficando parecido com isso:
smtpd_recipient_restrictions =
    check_client_access hash:/etc/postfix/whitelist_ip,
    check_sender_access hash:/etc/postfix/whitelist_dom,
    permit_sasl_authenticated,
    permit_mynetworks,
    reject_unauth_destination,
    reject_unknown_client,
    reject_non_fqdn_hostname,
    reject_unknown_sender_domain,
    reject_unknown_recipient_domain,
    reject_unauth_pipelining,
    reject_unauth_destination


Edite o arquivo /etc/initd.d/postfix e localize a seguinte linha (Debian Etch):
FILES="etc/localtime etc/services etc/resolv.conf etc/hosts \
                    etc/nsswitch.conf etc/nss_mdns.config"


e deixe-a da seguinte forma:
FILES="etc/localtime etc/services etc/resolv.conf etc/hosts \
                    etc/nsswitch.conf etc/nss_mdns.config
etc/postfix/sasl/smtpd.conf"


Reinicie o postfix e o saslauthd

# /etc/init.d/postfix restart # /etc/init.d/saslauthd start




6 - Testando


Adicione um domínio e usuário no KP. Rode o seguinte comando:
testsaslauthd -s smtp -u usuario em dominioquevccriou -p 'senha'


O resultado tem que ser esse:
0: OK "Success."


A autenticação está funcionando!

Caso queira tirar a limpo a história do campo MD5 do MySQL, edite o arquivo /etc/pam.d/smtp e mude as opções de crypt para:

crypt=1, ou crypt=2, ou ainda para tirar a criptografia, crypt=0

Rode novamente o comando:
testsaslauthd -s smtp -u usuario em dominioquevccriou -p 'senha'


Veja o resultado:
0: NO "authentication failed"







7 - Juntando tudo


Segue o meu main.cf com as alterações propostas:
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no
append_dot_mydomain = no
smtpd_tls_key_file = /etc/postfix/tls/smtpd.key
smtpd_tls_cert_file = /etc/postfix/tls/smtpd.crt
smtpd_tls_CAfile = /etc/postfix/tls/cacert.pem
smtpd_tls_loglevel = 3
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
tls_random_source = dev:/dev/urandom
smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain =
broken_sasl_auth_clients = yes
myhostname = mx03.hostname.com.br
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = mx03.hostname.com.br, mx03.hostname.dominio.com.br,
localhost.hostname.br, localhost
relayhost =
mynetworks = 127.0.0.0/8
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
home_mailbox = Maildir/
mailbox_transport = jeguepanel:
virtual_transport = jeguepanel:
local_recipient_maps=mysql:accounts,mysql:vamldap
mailbox_command_maps = mysql:accounts
alias_maps = mysql:vamldap
virtual_alias_maps = mysql:vamldap
virtual_mailbox_base = /
virtual_mailbox_maps = mysql:accounts
virtual_mailbox_limit = 0
virtual_uid_maps = static:1001
virtual_gid_maps = static:1001
canonical_maps = mysql:canodoms
sender_bcc_maps = mysql:senderbcc
recipient_bcc_maps = mysql:recipientbcc
always_bcc=
accounts_server_host = 127.0.0.1
accounts_user = usuario
accounts_password = senha
accounts_dbname = jp
accounts_query = select account_homedir from jp_accounts where account_wmail
= '%s'
vamldap_hosts = 127.0.0.1
vamldap_user = usuario
vamldap_password = senha
vamldap_dbname = jp
vamldap_query = select alias_users from jp_aliases where alias_name = '%s'
canodoms_hosts = 127.0.0.1
canodoms_user = usuario
canodoms_password = senha
canodoms_dbname = jp
canodoms_query = select domain_canonical from jp_domains where domain_name =
'%d'
senderbcc_hosts = 127.0.0.1
senderbcc_user = usuario
senderbcc_password = senha
senderbcc_dbname = jp
senderbcc_query = select account_bcc_sender from jp_accounts where
account_wmail = '%s'
recipientbcc_hosts = 127.0.0.1
recipientbcc_user = usuario
recipientbcc_password = senha
recipientbcc_dbname = jp
recipientbcc_query = select account_bcc_recipient from jp_accounts where
account_wmail = '%s'
header_checks = regexp:/etc/postfix/header_checks
smtpd_recipient_restrictions =
    check_client_access hash:/etc/postfix/whitelist_ip,
    check_sender_access hash:/etc/postfix/whitelist_dom,
    permit_sasl_authenticated,
    permit_mynetworks,
    reject_unauth_destination,
    reject_unknown_client,
    reject_non_fqdn_hostname,
    reject_unknown_sender_domain,
    reject_unknown_recipient_domain,
    reject_unauth_pipelining,
    reject_unauth_destination