FreeBSD, nuestro servidor

Primeros pasos con FreeBSD... Una vez instalada, ¿qué es lo primero que haces tú?. Yo voy a detallarlo a continuación (solamente en español, que quede claro) ;).

PRIMEROS PASOS
Una vez instalada completamente me logueo. En estos primeros pasos voy a entrar como root porque todo lo que pretendo hacer así lo requiere y soy demasiado BOFH como para ponerme a usar su. Voy a instalar las aplicaciones (binarias) imprescindibles para comenzar a trabajar con sources. Lo principal para bajar y tener actualizado el árbol de ports es el cvsup:


# pkg_add -r cvsup-without-gui
# rehash
# cp /etc/defaults/make.conf /etc/make.conf
#vi /etc/make.conf (añadiendo lo siguiente)
CPUTYPE=p4
CFLAGS= -O2 -pipe -ffast-math //Juégatela
# Make Update
SUP_UPDATE=yes
SUP=/usr/local/bin/cvsup
SUPFLAGS= -g -L 2
SUPHOST=cvsup.es.FreeBSD.org
SUPFILE=/usr/share/examples/cvsup/stable-supfile
PORTSSUPFILE=/usr/share/examples/cvsup/ports-supfile
DOCSUPFILE=/usr/share/examples/cvsup/doc-supfile


Ahora estamos en condiciones de poder actualizar el árbol de ports, para no instalar ninguno antiguo, recordad, estamos atrapados por la moda!:


# cd /usr/ports
# make update
---------------------------------------
>>>>Running /usr/local/bin/cvsup
---------------------------------------
...


Una vez actualizados los ports instalamos la herramienta definitiva para la gestión de los mismos:


# cd /usr/ports/sysutils/portupgrade/
# make && make install



COMPILANDO UN KERNEL
A partir de aquí usaremos portinstall y portupgrade para la instalación / actualización de ports respectivamente, pero antes de meternos a configurar los servicios de la máquina probemos si realmente el SMP funciona, recompilación del kernel:


# cd /usr/src/sys/i386/conf/
# cp GENERIC GENERIC-SMP
# vi GENERIC-SMP // descomentamos las siguientes lineas
options SMP
options APIC_IO
# /usr/sbin/config GENERIC-SMP
Don't forget to do a "make depend"
Kernel build directory is ../../compile/GENERIC-SMP
# cd ../../compile/GENERIC-SMP/
# make depend
# make
# make install


Tenemos en cuenta que el kernel antiguo queda renombrado a kernel.old (en algunas versiones de FreeBSD también queda como kernel.GENERIC para no confundirse, puesto que cada vez que se recompila el kernel antiguo se renombra a kernel.old, machacando así el archivo. Una vez acabado este proceso reiniciamos y cargamos el nuevo kernel. Si tuvieramos algún problema, en la cuenta atrás de 10 a 0 podemos seleccionar un kernel antiguo de la siguiente manera:


# unload
# boot kernel.old


Si todo arranca exitosamente podemos comprobar el número de CPU's cargadas (procesadores):


# dmesg | grep cpu
cpu0 (BSP): apic id: 0, version: 0x00040011, at 0xfee00000
cpu0 (AP): apic id: 1, version: 0x00040011, at 0xfee00000


Veamos como se comporta el doble procesador ante una gran operación de sincronización de datos, antes instalamos rsync, por supuesto:


# portinstall -prfv /usr/ports/net/rsync/


Ha ido perfecto, después de unos días de cambios y sincronizaciones ha llegado el momento de seguir instalando software y dejarlo totalmente operativo. Como bien se ha dicho, han pasado unos días de pruebas y testeos, por lo que actualizaremos el árbol de los ports mirando los desactualizados y actualizándolos:


# cd /usr/ports ; make update
# pkg_version -v | grep -v =
# portupgrade -a



INSTALANDO SOFTWARE
Seguimos instalando, ahora vamos por algún sistema gestor de bases de datos, MySQL concretamente (podríamos optar también por PostgreSQL, pero hay muchas webs que funcionan contra MySQL y debemos respetarlo). La rama 4.x presume de ser la que mejor funciona en FreeBSD. Después ya podemos meter ProFTPd con soporte MySQL (para usuarios virtuales, quotas y demás), lógico es que instalemos Apache también:


# portinstall -prfv /usr/ports/databases/mysql40-server
# portinstall -m WITH_MYSQL=y -prfv /usr/ports/ftp/proftpd
# portinstall -m WITH_MYSQL=y -prfv /usr/ports/www/apache13
# portinstall -m WITH_MYSQL=y -prfv /usr/ports/lang/php4 *


*En versiones posteriores a php-4.3.7 (osea, 4.3.8 y superiores) las extensiones de php se habilitan en otro port adicional situado en /usr/ports/lang/php4-extensions. Este port no va con portinstall, por lo que hay que entrar en ese directorio y por las bravas hacer un make, seleccionar las extensiones adecuadas de nuestro php y make install para finalizar. Mi tiempo me llevó averiguarlo.

Podemos tener ciertos problemas a la hora de iniciar Apache si antes no hemos configurado algunas variables como el nombre del servidor (hostname) y /etc/hosts. Nuestro rc.conf será algo similar a lo siguiente:


# Por defecto en el sistema (instalacion)
kern_securelevel_enable="NO"
keymap="spanish.iso.acc"
keyrate="fast"
moused_enable="YES"
saver="dragon"
sshd_enable="YES"
usbd_enable="YES"

# Varias opciones
hostname="maquina.dominio.com"
proftpd_enable="YES"
saslauthd_enable="YES"
saslauthd_flags="-a pam"
apache_enable="YES"
apache_flags="-DSSL"

# Bind
named_enable="YES"
named_program="/usr/sbin/named"
#named_flags="boot"

# Para Postfix
sendmail_enable="NONE"

# Tarjeta de red
ifconfig_em1="inet 192.168.0.2 netmask 255.255.255.0"
defaultrouter="192.168.0.100"


Análogamente tendremos que configurar bien /etc/hosts como bien se ha mencionado lineas más arriba:


::1 localhost localhost.my.domain
127.0.0.1 localhost localhost.my.domain
195.55.65.114 maquina maquina.dominio.com


Una vez hecho ésto, hemos de cambiar la directiva ServerName del /usr/local/etc/apache/httpd.conf para que quede de la siguiente manera:


ServerName localhost


Y (re)iniciamos apache. Puede ser que PHP no coja bien la extensión del mysql (o cualquier otra), probablemente sea porque en el php.ini no esté bien configurado el parámetro extension_dir, en mi caso concreto tuve que cambiarlo de la siguiente manera:


#extension_dir = "./"
extension_dir = "/usr/local/lib/php/20020429"
...
extension=ctype.so
extension=gd.so
extension=mysql.so
...


Ahora sí, reinicio de Apache y andando con todas las extensiones ;).

PRIMEROS SERVICIOS, APACHE Y AUTENTIFICACIÓN SMTP
Vamos a por el correo, primero son esenciales las librerías SASL para poder autentificarnos, a lo que seguiremos con Postfix, un sencillo y eficiente MTA. Algunos os preguntareis ¿Porqué no Sendmail?. Basicamente porque he tenido experiencias con él durante años y me he cansado de compilar cada 2 semanas por fallos de seguridad. Postfix cubre perfectamente todas mis necesidades y "presume" de ser mucho más simple y seguro (nótese el entrecomillado de presume). Para instalarlo haremos lo siguiente (la opción -m WITH_MYSQL=y no está soportada por todos los paquetes que la llevan aquí, debo repasar esto):


# portinstall -m WITH_MYSQL=y -prfv /usr/ports/security/cyrus-sasl2
# portinstall -m WITH_MYSQL=y -prfv /usr/ports/security/cyrus-sasl2-saslauthd
# portinstall -prfv /usr/ports/security/pam-mysql
# portinstall -prfv /usr/ports/mail/postfix


Seleccionar soporte para añadir SASL2 y MySQL y continuamos en la configuración de Posftix (ncurses). Arranquemos MySQL para ir mirando alguna que otra cosilla. También arrancaremos Apache, aquí debemos tener cuidado de tener bien asignado tanto el hostname, como /etc/hosts y la opción ServerName de Apache, como se indica a continuación:


# hostname
r0sk.dominio.com
# cat /etc/hosts | grep r0sk
192.168.1.1 r0sk.dominio.com r0sk
# cat /usr/local/etc/apache/httpd.conf | grep ServerName
ServerName r0sk


Arrancamos los servicios:


# vi /usr/local/etc/rc.d/mysql-server.sh
Añadimos --log=/var/log/mysqld.log en start) antes de > /dev/null &
# /usr/local/etc/rc.d/mysql-server.sh start
# /usr/local/etc/rc.d/apache.sh start


Para cualquier error o fallo miraremos los archivos /var/log/httpd-error_log y /var/log/mysqld.log de la siguiente manera:


# tail -f /var/log/httpd-error_log


Probemos que nuestro Apache funciona correctamente, con PHP y MySQL incluidos, para ello seguimos los siguientes pasos:


# cat /usr/local/etc/apache/httpd.conf | grep php
LoadModule php4_module libexec/apache/libphp4.so
AddModule mod_php4.c
<IfModule mod_php4.c>
DirectoryIndex index.php index.html
<IfModule mod_php4.c>
AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps
# cat /usr/local/etc/apache/httpd.conf | grep ServerRoot
ServerRoot "/usr/local"
# vi /usr/local/www/data/phpinfo.php
<?php phpinfo(); ?>
# links http://localhost
// Miramos las referencias a MySQL


Hasta aquí tenemos funcionando Apache con PHP y MySQL respectivamente. Ahora nos meteremos a la configuración del correo con Postfix. Empecemos por el principio, la autentificación. Para autentificarnos con Postfix (SMTP) usaremos PAM, como queremos una configuración un tanto especial, debemos decirle de alguna forma a PAM que use una base de datos MySQL (pam_mysql instala pam_mysql.so) como origen de datos de dicha autentificación. En FreeBSD lo hacemos a través del archivo /etc/pam.conf. Añadimos al final del mismo las siguientes líneas:


# vi /etc/pam.conf
# Para SMTP
smtp auth sufficient pam_unix.so
smtp auth required pam_mysql.so user=usuario passwd=pass db=maildb table=users usercolumn=id passwdcolumn=clear

smtp account sufficient pam_unix.so
smtp account required pam_mysql.so user=usuario passwd=pass db=maildb table=users usercolumn=id passwdcolumn=clear
smtp session required pam_permit.so


*OJO: Un simple espacio o una tabulación mal hecha puede tirar por tierra todos nuestros planes de conectar con MySQL.
*OJO2: La instalación de pam_mysql pone el módulo de autentificación pam_mysql.so bajo /usr/local/lib/ y PUEDE SER que la configuración lo requiera en /usr/lib, el truco sería el siguiente:


# ln -s /usr/local/lib/pam_mysql.so /usr/lib


Bien, ahora PAM ya sabe que tiene que conectar con MySQL para verificar los datos de autentificación, la pregunta ahora es, ¿quién llamará a la puerta de PAM?. En nuestro caso concreto, para aumentar la seguridad, haremos que sea SASL el que llame. El esquema sería algo similar:


SASL >-(a través de saslauthd llama a)-> PAM >-(que a su vez consulta a)-> MySQL >-(si todo es correcto)-> Postfix


Esto tiene que quedar claro, es el funcionamiento básico. Ahora le diremos a SASL que cuando alguien se conecte al smtp utilice el demonio saslauthd y el tipo de mecanismo de autentificación por defecto:


# vi /usr/local/lib/sasl2/smtpd.conf
pwcheck_method: saslauthd
mech_list: plain login


Una vez hecho esto y configurado, debemos cerciorarnos de que la próxima vez que encendamos la máquina se ejecute automáticamente con los scripts de inicio el demonio saslauthd y que llame a PAM. Lo hacemos en /etc/rc.conf:


sasl_saslauthd_enable="YES"
sasl_saslauthd_flags="-a pam"


Si queremos arrancar saslauthd ahora, sin tener que reiniciar, basta con escribir lo siguiente:


# saslauthd -a pam


Comprobemos por un instante si tenemos el saslauthd funcionando correctamente en nuestro sistema:

# ps aux | grep saslauth
root    74025  0.0  0.3  1808 1428  p0  R+    5:45PM   0:00.00 grep saslauth (bash)
root    74019  0.0  0.1  1064  576  ??  Ss    5:45PM   0:00.00 saslauthd -a pam
root    74020  0.0  0.1  1064  576  ??  S     5:45PM   0:00.00 saslauthd -a pam
root    74021  0.0  0.1  1064  576  ??  S     5:45PM   0:00.00 saslauthd -a pam
root    74022  0.0  0.1  1064  576  ??  S     5:45PM   0:00.00 saslauthd -a pam
root    74023  0.0  0.1  1064  576  ??  S     5:45PM   0:00.00 saslauthd -a pam



POSTFIX
Genial. Ahora el ordenador ya sabe como comportarse desde que recibe una petición SMTP hasta llegar a Postfix. Repasemos:


1.- Recibe una petición SMTP de un cliente.
2.- SASL la recoge y utiliza saslauthd (el demonio de autentificación para gestionar dicha petición, sabe también que métodos de autentificación usará por defecto si el cliente no los especifica (login plain).
3.- El demonio de autentificación saslauthd está lanzado con las opciones -a pam, por lo que pasa la tarea a PAM.
4.- PAM se encarga de conectar con MySQL (/etc/pam.conf) comprobando si los datos enviados por el cliente corresponden con algún registro de la base de datos.
5.- Si los datos coinciden (y los mecanismos de autentificación también) todo está correcto, a partir de aquí queda todo en manos de Postfix. De no ser así se generará un error.


Nuestro gran amigo Postfix entra en acción en estos momentos. Lo que hace básicamente es volver a preguntar a MySQL (a través de SASL de nuevo, para mayor seguridad) si los datos son correctos o no. En parte es una redundancia, pero funciona así, supongo que será para una mayor seguridad. Lo que vamos a hacer ahora es decirle a Postfix todos los parámetros con los que se tendrá que conectar a MySQL (base de datos, usuario, contraseña...) y la configuración principal. Comenzamos con /usr/local/etc/postfix/main.cf:


# Confiruacion general
queue_directory = /var/spool/postfix
command_directory = /usr/local/sbin
daemon_directory = /usr/local/libexec/postfix
mail_owner = postfix

myhostname = r0sk.dominio1.com
mydomain = dominio1.com
mydestination = dominio1.com, $transport_maps
unknown_local_recipient_reject_code = 450
maps_rbl_reject_code = 554
alias_maps = hash:/etc/mail/aliases
alias_database = hash:/etc/mail/aliases
mail_spool_directory = /var/spool/mail
home_mailbox = Maildir/
local_destination_concurrency_limit = 2
default_destination_concurrency_limit = 10
debug_peer_level = 2
debugger_command =
PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
xxgdb $daemon_directory/$process_name $process_id & sleep 5
sendmail_path = /usr/local/sbin/sendmail
newaliases_path = /usr/local/bin/newaliases
mailq_path = /usr/local/bin/mailq
setgid_group = maildrop
manpage_directory = /usr/local/man
sample_directory = /usr/local/etc/postfix
readme_directory = no

# Anadidos para MySQL
local_recipient_maps =
transport_maps=mysql:/usr/local/etc/postfix/transport.cf
virtual_mailbox_maps=mysql:/usr/local/etc/postfix/mysql_virt.cf
virtual_uid_maps=mysql:/usr/local/etc/postfix/uids.cf
virtual_gid_maps=mysql:/usr/local/etc/postfix/gids.cf
virtual_mailbox_base=/
mydestination = $mydomain, $myhostname, $transport_maps
virtual_maps =mysql:/usr/local/etc/postfix/virtual.cf

# Anadidos para SASL
smtpd_sasl_auth_enable = yes
#smtpd_sasl2_auth_enable = yes
smtpd_sasl_security_options = noanonymous
broken_sasl_auth_clients = yes
smtpd_sasl_local_domain = $myhostname

smtpd_recipient_restrictions =
permit_sasl_authenticated,
permit_mynetworks,
reject_unauth_destination,
reject_rbl_client list.dsbl.org,
reject_rbl_client relays.ordb.org,
reject_rbl_client dynablock.wirehub.net,
reject_rbl_client blackholes.wirehub.net,
reject_rbl_client dnsbl.njabl.org


Como veis, hemos definido algunos archivos en la configuración principal que aún no tenemos, debemos crearlos uno a uno.
transport.cf:


user=usuario
password=contrasenia
dbname=maildb
table=transport
select_field=transport
where_field=domain
hosts= localhost


mysql_virt.cf


user=usuario
password=contrasenia
dbname=maildb
table=users
select_field=maildir
where_field=address
hosts=localhost


uids.cf


user=usuario
password=contrasenia
dbname=maildb
table=users
select_field=uid
where_field=address
hosts=localhost


gids.cf


user=usuario
password=contrasenia
dbname=maildb
table=users
select_field=gid
where_field=address
hosts=localhost


virtual.cf


user=usuario
password=contrasenia
dbname=maildb
table=virtual
select_field=goto
where_field=address
hosts=localhost


Es el momento de crear un usuario, hacerle el directorio de su maildir (el especificado en la base de datos), darle permisos correctos a ese directorio (dependiendo del uid y gid que hayamos puesto por defecto para que el demonio de correo pueda dejar ahí los correos correctamente) y reiniciar Postfix para ver si nos deja enviar y recibir correo con ese usuario. Para ello creamos el usuario normalmente añadiendo un registro en la base de datos y después ponemos los logs a funcionar a ver si realmente se conecta a la base de datos y autentifica sin dar errores. Os recomiendo tener los logs (tanto el mysql.log como el mail.log activos en pantalla en todo momento, dan muchas pistas de porqué puede fallar la cosa)


# grc tail -f /var/log/mysql.log
# grc tail -f /var/log/maillog
# postfix start


En caso de querer que nuestro postfix se ejecute siempre cada vez que encendemos el ordenador tendremos que crear un rc de inicio. Ésto se hace en /usr/local/etc/rc.d/ y el archivo que tenemos que crear se llamará postfix.sh (la extensión .sh es obligatoria para que se ejecute al inicio). El contenido del fichero será el siguiente:

#!/bin/sh
    
POSTFIX="/usr/local/sbin/postfix"
CONF="/usr/local/etc/postfix/main.cf"
    
case "$1" in
start)
    if [ -r ${CONF} -a -x ${POSTFIX} ]; then
        echo -n ' Postfix'
        ${POSTFIX} $1 > /dev/null 2>&1
    fi
    ;;
stop)
    if [ -x ${POSTFIX} ]; then
        echo -n ' Postfix'
        ${POSTFIX} $1 > /dev/null 2>&1
    fi
    ;;
*)
    ;;
esac


Nota: en caso de no tener log de MySQL(creo que safe_mysqld no lleva opciones de log por defecto), arrancaremos el MySQL de la siguiente manera:


# /usr/local/libexec/mysqld --basedir=/usr/local
--datadir=/var/db/mysql --user=mysql --pid-file=/var/db/mysql/r0sk.pid
--log=/var/log/mysql.log



COURIER, POP E IMAP
A tales momentos ya podemos enviar y recibir correo en el servidor. Ahora falta abrir un puerto y un demonio que gestione la descarga de ese correo al programa del cliente (MUA). Para ello usaremos Courier, lógico es que usemos también soporte MySQL puesto que los datos siguen estando en la misma base de datos usada anteriormente para el procedimiento de envío de correos (de hecho los datos son los mismos):


# portinstall -m WITH_MYSQL=y -prfv /usr/ports/mail/courier-imap


Una vez instalado, podemos pasar a los primeros pasos de configuración. Vemos que la instalación nos proporciona archivos de configuración dentro de /usr/local/etc/courier-imap/(*.dist), ahora debemos copiar algunos archivos (para dejar intactos los originales) y editarlos a nuestro gusto. Vamos paso a paso:
/usr/local/etc/courier-imap/pop3d:
Hacemos una copia del archivo pop3d.dist llamándole pop3d. En el archivo /usr/local/etc/courier-imap/pop3d tenemos que cerciorarnos que hay las siguientes opciones:


AUTHMODULES="authdaemon"
POP3AUTH="LOGIN CRAM-MD5 CRAM-SHA1"
POP3DSTART=YES



/usr/local/etc/courier-imap/authdaemonrc
Hacemos una copia del archivo authdaemonrc.dist llamándole authdaemonrc. En authdaemonrc miraremos que haya:


authmodulelist="authmysql"
version="authdaemond.mysql"



/usr/local/etc/courier-imap/authmysqlrc
Hacemos una copia del archivo authmysqlrc.dist llamándole authmysqlrc. Y en authmysqlrc:


MYSQL_SERVER localhost
MYSQL_USERNAME postfix
MYSQL_PASSWORD pass_postfix
MYSQL_PORT 0
MYSQL_OPT 0
MYSQL_DATABASE maildb
MYSQL_USER_TABLE users

MYSQL_LOGIN_FIELD id
MYSQL_CLEAR_PWFIELD clear
MYSQL_UID_FIELD uid
MYSQL_GID_FIELD gid
MYSQL_HOME_FIELD home
MYSQL_MAILDIR_FIELD maildir


Si nos fijamos en la instalación de courier-imap veremos que instala los archivos de rc para su inicialización con la máquina en /usr/local/etc/rc.d/, nos situamos en ese directorio y hacemos lo siguiente:


# cd /usr/local/etc/rc.d/
# cp courier-imap-pop3d.sh.sample courier-imap-pop3d.sh


Ahora ya estamos preparados para arrancar el daemon (la próxima vez que se reinicie la máquina ya se iniciará automáticamente):


# /usr/local/etc/rc.d/courier-imap-pop3d.sh start


Podemos comprobar con un nmap o cualquier otro escaneador de puertos si se ha iniciado correctamente :).

About the author

Óscar
has doubledaddy super powers, father of Hugo and Nico, husband of Marta, *nix user, Djangonaut and open source passionate.