Volver al blog

Servidor de Correo con Postfix, Mariadb y PostfixAdmin en Debian9. 2da Parte

i1

En esta segunda parte del tutorial vamos a preparar e instalar el servidor de correo. Ya tenemos funcional nuestro phpmyadmin. Lo que necesitamos es dos bases de datos, una para el roundcube y otra para el postfixadmin, lo cual podemos usar el phpmyadmin para crearlas. Cada base de datos sólo la usará el usuario que la necesite[en este caso roundcube o postfixadmin] y nadie más. Recomiendo crear un usuario por la consola si desean usar el phpmyadmin, pues si usan root, tendrán problemas de autenticación via web.

mysql -u root -p -e "CREATE USER 'admin'@'%' IDENTIFIED BY 'pass';"
mysql -u root -p -e "GRANT ALL PRIVILEGES ON *.* TO 'admin'@'%' WITH GRANT OPTION;"
mysql -u root -p -e "FLUSH PRIVILEGES;"
/etc/init.d/mysql restart

Ahora se pueden loguear con el usuario admin por la interfaz web del phpmyadmin.

En la web de PHPMyAdmin:

Crear usuario y base de datos para:
- PostfixAdmin
- Roundcube

Ir a Privilegios/Agregar nuevo usuario:
nombre: postfixadmin
servidor: localhost
password: ***************
confirmar password: ***************
marcar: Crear base de datos con el mismo nombre y otorgar todos los privilegios

Hacer el mismo proceso para la base de datos de Roundcube

En el terminal:

Base de datos para Roundcube:

# mysql -u root -p
mysql> CREATE DATABASE roundcube DEFAULT CHARACTER SET = utf8;
mysql> USE roundcube;
mysql> CREATE USER 'roundcube'@'localhost' IDENTIFIED BY 'roundcube';
mysql> GRANT USAGE ON *.* TO 'roundcube'@'localhost' IDENTIFIED BY 'roundcube';
mysql> GRANT ALL PRIVILEGES ON roundcube .* TO 'roundcube'@'localhost';
mysql> FLUSH PRIVILEGES;
mysql> quit;

Base de datos para Postfixadmin:

# mysql -u root -p
mysql> CREATE DATABASE postfixadmin DEFAULT CHARACTER SET = utf8;
mysql> USE postfixadmin;
mysql> CREATE USER 'postfixadmin'@'localhost' IDENTIFIED BY 'postfixadmin';
mysql> GRANT USAGE ON *.* TO 'postfixadmin'@'localhost' IDENTIFIED BY 'postfixadmin';
mysql> GRANT ALL PRIVILEGES ON postfixdamin .* TO 'postfixadmin'@'localhost';
mysql> FLUSH PRIVILEGES;
mysql> quit;

Ahora crearemos un virtualhosting para roundcube, que veremos más adelante:

En /etc/nginx/sites-available/ crear el archivo roundcube.conf y añadirle el siguiente contenido:

roundcube.conf

server {
listen 80;
server_name webmail.inutil.cu;
include /etc/nginx/php.conf;
index index.php index.html index.htm;
root /var/www/webmail.inutil.cu;
index index.php index.html index.htm;

location / {
try_files $uri $uri/ /index.php?$args ;
}
access_log /var/log/nginx/roundcube-access.log;
error_log /var/log/nginx/roundcube-error.log;

include /etc/nginx/ban_exploits.conf;
include /etc/nginx/favicon.conf;
}

server {
listen 443 ssl http2;
server_name webmail.inutil.cu;
include /etc/nginx/ssl.conf;
include /etc/nginx/php.conf;
include /etc/nginx/ban_exploits.conf;
include /etc/nginx/favicon.conf;
index index.php index.html index.htm;
root /var/www/webmail.inutil.cu;
index index.php index.html index.htm;

location / {
try_files $uri $uri/ /index.php?$args;
}
access_log /var/log/nginx/roundcube-access.log;
error_log /var/log/nginx/roundcube-error.log;
}

Creamos la carpeta del virtualhosting:

mkdir -p /var/www/webmail.inutil.cu

Ahora pongámosle toda la seguridad necesaria:

Si tenemos conexión a internet podemos ponerle certificados Let´s Encrypt. Tutoriales de uso de Let´s Encrypt hay miles en internet. Pero como esto es un tutorial offline, generaremos los certificados SSL, autofirmados.

mkdir -p /etc/nginx/ssl
cd /etc/nginx/ssl
openssl req -x509 -nodes -days 3650 -newkey rsa:4096 -keyout /etc/nginx/ssl/cert.key -out /etc/nginx/ssl/cert.pem
openssl dhparam -out /etc/nginx/ssl/dh_2048.pem -2 2048

Ahora crearemos los archivos incluidos en el procesamiento del virtualhosting con SSL:

/etc/nginx/ssl.conf
/etc/nginx/php.conf
/etc/nginx/ban_exploits.conf
/etc/nginx/favicon.conf

ssl.conf

resolver 10.10.2.2 valid=300s;
resolver_timeout 5s;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/cert.key;
#ssl_trusted_certificate /etc/nginx/ssl/chain.pem;
ssl on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/nginx/ssl/dh_1024.pem;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP';
ssl_session_timeout 1d;
ssl_session_cache builtin:1000 shared:SSL:50m;
#spdy_headers_comp 0;

location ~ /.well-known {
allow all;
}

if ($request_method !~ ^(GET|HEAD|POST)$ ) {
return 444;
}

location ~ /(\.|wp-config.php|readme.html|license.txt|schema.txt|password.txt|passwords.txt)
{
deny all;
}

php.conf

location ~ \.php$ {
include fastcgi_params;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
}

#location ~ \.php$ {
# try_files $uri =404;
# fastcgi_split_path_info ^(.+\.php)(/.+)$;
# fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# include fastcgi_params;
# }

/etc/nginx/ban_exploits.conf

## Block SQL injections
set $block_sql_injections 0;
if ($query_string ~ "union.*select.*\(") {
set $block_sql_injections 1;
}
if ($query_string ~ "union.*all.*select.*") {
set $block_sql_injections 1;
}
if ($query_string ~ "concat.*\(") {
set $block_sql_injections 1;
}
if ($block_sql_injections = 1) {
return 403;
}

## Block file injections
set $block_file_injections 0;
if ($query_string ~ "[a-zA-Z0-9_]=http://") {
set $block_file_injections 1;
}
if ($query_string ~ "[a-zA-Z0-9_]=(\.\.//?)+") {
set $block_file_injections 1;
}
if ($query_string ~ "[a-zA-Z0-9_]=/([a-z0-9_.]//?)+") {
set $block_file_injections 1;
}
if ($block_file_injections = 1) {
return 403;
}

## Block common exploits
set $block_common_exploits 0;
if ($query_string ~ "(<|%3C).*script.*(>|%3E)") {
set $block_common_exploits 1;
}
if ($query_string ~ "GLOBALS(=|\[|\%[0-9A-Z]{0,2})") {
set $block_common_exploits 1;
}
if ($query_string ~ "_REQUEST(=|\[|\%[0-9A-Z]{0,2})") {
set $block_common_exploits 1;
}
if ($query_string ~ "proc/self/environ") {
set $block_common_exploits 1;
}
if ($query_string ~ "mosConfig_[a-zA-Z_]{1,21}(=|\%3D)") {
set $block_common_exploits 1;
}
if ($query_string ~ "base64_(en|de)code\(.*\)") {
set $block_common_exploits 1;
}
if ($block_common_exploits = 1) {
return 403;
}

## Block spam
set $block_spam 0;
if ($query_string ~ "\b(ultram|unicauca|valium|viagra|vicodin|xanax|ypxaieo)\b") {
set $block_spam 1;
}
if ($query_string ~ "\b(erections|hoodia|huronriveracres|impotence|levitra|libido)\b") {
set $block_spam 1;
}
if ($query_string ~ "\b(ambien|blue\spill|cialis|cocaine|ejaculation|erectile)\b") {
set $block_spam 1;
}
if ($query_string ~ "\b(lipitor|phentermin|pro[sz]ac|sandyauer|tramadol|troyhamby)\b") {
set $block_spam 1;
}
if ($block_spam = 1) {
return 403;
}

## Block user agents
set $block_user_agents 0;

# Don't disable wget if you need it to run cron jobs!
#if ($http_user_agent ~ "Wget") {
# set $block_user_agents 1;
#}

# Disable Akeeba Remote Control 2.5 and earlier
if ($http_user_agent ~ "Indy Library") {
set $block_user_agents 1;
}

# Common bandwidth hoggers and hacking tools.
if ($http_user_agent ~ "libwww-perl") {
set $block_user_agents 1;
}
if ($http_user_agent ~ "GetRight") {
set $block_user_agents 1;
}
if ($http_user_agent ~ "GetWeb!") {
set $block_user_agents 1;
}
if ($http_user_agent ~ "Go!Zilla") {
set $block_user_agents 1;
}
if ($http_user_agent ~ "Download Demon") {
set $block_user_agents 1;
}
if ($http_user_agent ~ "Go-Ahead-Got-It") {
set $block_user_agents 1;
}
if ($http_user_agent ~ "TurnitinBot") {
set $block_user_agents 1;
}
if ($http_user_agent ~ "GrabNet") {
set $block_user_agents 1;
}

if ($block_user_agents = 1) {
return 403;
}

favicon.conf

location ~ /favicon.ico {
access_log off;
log_not_found off;
alias /var/www/favicon.ico;
}

El favicon no es tan importante, por lo cual si no lo tenemos no dará error en los logs.

Ahora solo queda activar el virtualhost y reiniciar nginx:

ln -s /etc/nginx/sites-available/roundcube.conf /etc/nginx/sites-enabled/roundcube.conf

Finalmente reiniciamos el nginx:

/etc/init.d/nginx restart

Ahora instalaremos nuestro webmail RoundCube.

La ruta de instalacion de roundcube en el virtualhosting fue /var/www/webmail.inutil.cu.Después de descargarlo:

cd /var/www/webmail.inutil.cu
tar xfv roundcubemail-1.3.3-complete.tar.gz
rm roundcubemail-1.3.4-complete.tar.gz
cd roundcubemail-1.3.4
mv * ../
cd ..
rm -rf roundcubemail-1.3.4
chmod -R 755 *; chown -R www-data:www-data *
mkdir -p /etc/roundcube
mv config /etc/roundcube
ln -s /etc/roundcube/config/ /var/www/webmail.inutil.cu/
chmod 777 logs
chmod 777 temp

Para ahorrarnos molestias cuando termine el instalador copiando/pegando la configuración, le daremos permisos de escritura a la carpeta /etc/roundcube/config para que automáticamente se acabe la instalación de roundcube cree el archivo de configuración, el cual posteriormente le daremos permisos de sólo lectura.

chmod 777 /etc/roundcube/config

Abrir el navegador e ir a http://ip_del_server/roundcube/installer/-Revisar que todos los valores necesarios están en "ON" y hacer click en "NEXT"- Revisar los campos del setup y editar según nuestras preferencias. En este punto sólo deberíamos editar "identities_level" dejándolo en "one identity with possibility to edit only signature"- Configurar la conexion a MySQL en el apartado "Database setup"- En el apartado "username_domain" debemos poner nuestro dominio
- Idioma "es_ES", y rellenar cualquier info necesaria en dependencia de nuestras necesidades y hacer click en "NEXT"- Copiar/guardar la config en nuestro directorio de configuración /etc/roundcube/config/config.inc.php. Si usted le dio permisos de escritura a /etc/roundcube/config, sólo debe dar next y listo, la configuración de roundcube será salvada automáticamente sin preguntar nada.

NOTA: En caso de usar "*" en los password debemos editar la config y arreglar ese detalle puesto que php nos genera el caracter html para el * y cuando roundcube intenta conectarse a la base de datos no va a poder.
- Dar click en "Continue" e inicializar la base de datos, recuerde hacer los cambios pertinentes a la configuración antes de dar siguiente.
- Inicializar la base de datos dando click en el boton "Initialize database"- Si todo ha ido bien[si no, reintentar instalar desde el principio], sólo nos restará borrar el instalador

rm -rf /var/www/webmail.inutil.cu/installer

- Dar permisos de lectura nuevamente a la carpeta de la configuración.

chmod 755 /etc/roundcube/config   chmod -R 755 /etc/roundcube/config/; chown -R www-data:www-data /etc/roundcube/config/
  • Plugin de cambio de password

En config.inc.php:

Ir a /usr/share/roundcube/plugins/password y renombrar config.inc.php.dist

mv config.inc.php.dist config.inc.php

Editar:

$config['plugins'] = array('password');
$config['password_driver'] = 'sql';
$config['password_db_dsn'] = 'mysql://postfix:contraseña_de_postfixdb@localhost/postfix';
$config['password_query'] = 'UPDATE mailbox SET password=%c,modified=NOW() WHERE username=%u LIMIT 1';

Ahora, cuando un usuario desee cambiarse el password solamente debe ir a "Configuración/Contraseña", rellenar los campos y listo.

NOTA: Si usted tiene implementada la politica de correos nacionales e internacionales[muy común en Cuba], debe cambiar en la configuración de roundcube[config.inc.php] el default_host[$config['default_host'] = 'localhost';] por el ip de su server de correo así obliga al usuario a hacer login por el ip no por localhost, y postfix lo reconoce como una ip externa a 127.0.0.1.

  • SASL

Instalando SASL:

apt install sasl2-bin libsasl2-modules libpam-mysql libsasl2-modules-sql

Como bien nos dice el instalador de saslauthd debe iniciar con el sistema por lo que debemos hacerlo en /etc/default/saslauthd

START=yes

Guardamos y salimos

Ahora debemos modificar la carpeta donde va a trabajar Postfix con SASL, hay que hacerle algunos pequeños ajustes:

mkdir -p /var/spool/postfix/var/run/saslauthd
rm -rf /var/run/saslauthd
ln -s /var/spool/postfix/var/run/saslauthd /var/run/saslauthd

Ahora bien, debemos crear el fichero para extraer las contraseñas encriptadas de la base de datos con los datos del usuario, contraseña, base de datos, tabla, la columna donde se encuentra el usuario y la columna donde se encuentra la contraseña.

touch /etc/pam.d/smtp

smtp

auth required pam_mysql.so user=postfix passwd=password_usuario_mysql host=127.0.0.1 db=postfix table=mailbox usercolumn=name passwdcolumn=password crypt=1 md5=1

account sufficient pam_mysql.so user=postfix passwd=password_usuario_mysql host=127.0.0.1 db=postfix table=mailbox usercolumn=name passwdcolumn=password crypt=1 md5=1

Cada sentencia anterior debe ir en una sola línea. Es decir, el fichero smtp sólo debe contener dos líneas.

Y por supuesto, los permisos:

chmod 644 /etc/pam.d/smtp

Y reiniciamos SASL

/etc/init.d/saslauthd restart

Ya tenemos listo nuestro webmail y además esta publicado en forma segura. En el próximo tutorial les mostraré como adminstarlo.

Link a la 3ra parte.

Suscríbete · Newsletter

Mantente al día, cada semana

Artículos prácticos sobre Linux, redes, seguridad, virtualización y la nube — escritos por sysadmins cubanos.

  • Guías y tutoriales de administración de sistemas
  • Nuevos artículos sobre servidores, redes y nube
  • Sin spam, cancela cuando quieras

Respetamos tu bandeja de entrada. Cancela con un clic.

Patrocinado por SYSCU

¿Tu infraestructura en la nube te cuesta de más?

SYSCU optimiza tu nube de punta a punta — FinOps, DevOps & CI/CD, migraciones a AWS, seguridad y observabilidad. Equipo 100 % senior que reduce tu factura hasta un 40 % y acelera tus despliegues en semanas.

Nuevo · BetaSYSCU Atlas Insight — la plataforma FinOps que convierte tu gasto AWS en decisiones: visibilidad multi-cuenta, recomendaciones automáticas y alertas de anomalías.

No comments yet