Configure a Centos 7 postfix mail server with virtual users

Configure a mail server is one of top sysadmins nightmares, here i will try to make your painful  journey a bit less unpleasant.

Starting from Centos 7 minimal install.

If in any moment something doesn’t work just leave a comment and i will try to give you some feedback

Before run this guide ensure that:

  • Your server has an public ip
  • Your ISP will configure a reverse dns for your public ip
  • You can modify DNS records for all domains that you can attach to your new mailserver

 

Step 1: Enable extra repositories


yum install epel-release

yum -y install http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm

yum -y update

Step 2: install packages


yum -y install perl-MailTools perl-MIME-EncWords perl-Email-Valid perl-Test-Pod roundcubemail dovecot dovecot-mysql  dovecot-pigeonhole  perl-Mail-Sender perl-Log-Log4perl imapsync offlineimap amavisd-new clamav perl-Razor-Agent mariadb-server opendkim vim wget crypto-utils mod_ssl.x86_64 nginx php php-mysql php-fpm  clamav-update php-imap.x86_64 NetworkManager-tui mailx lrzip lzop  arj  unzoo cabextract p7zip fail2ban php-mcrypt.x86_64


yum install http://pkgs.repoforge.org/unrar/unrar-5.0.3-1.el7.rf.x86_64.rpm

Step 3: Change your servers hostname

To avoid problems with hostname resolution the easy way is use NotworkManager-tui to set you hostname to a FQDN, when you configure your MX registers these point to a hostname, like mail.mydomain.com select your desired FQDN and execute


nmtui

this will show nmtui dialog

nmtui main screenselect Set system hosname

nmtui set hostname dialogput your desired hostname and click OK

finaly exit nmtui

and apply changues


systemctl restart systemd-hostnamed

Step 4: Verify postifx local delivery

At this step we will ensure that postfix can send email to local users firstly we will add a two new users joe and alfred


useradd -d /home/joe -M -N -s /sbin/nologin joe

we will send a local mail


echo "Hello" | mail -s "test" joe@localhost

and verify if mail has been delivered


tail /var/log/maillog

May  6 18:57:34 localhost postfix/pickup[1705]: 3D20F1000ED: uid=0 from=<root>
May  6 18:57:34 localhost postfix/cleanup[2444]: 3D20F1000ED: message-id=<20150506165734.3D20F1000ED@mail.yourfqdn.com>
May  6 18:57:34 localhost postfix/qmgr[1706]: 3D20F1000ED: from=<root@mail.yourfqdn.com>, size=494, nrcpt=1 (queue active)
May  6 18:57:34 localhost postfix/local[2446]: 3D20F1000ED: to=<joe@localhost.yourfqdn.com>, orig_to=<joe@localhost>, relay=local, delay=0.11, delays=0.07/0.03/0/0.01, dsn=2.0.0, status=sent (delivered to mailbox)
May  6 18:57:34 localhost postfix/qmgr[1706]: 3D20F1000ED: removed

if it’s delivered next step is add a domain like centostestmail.com


vim /etc/postfix/main.cf

edit myhostname property near line 77

myhostname= yourfqdndomain

near line  164

mydestination = $myhostname, localhost.$mydomain, localhost, centostestmail.com

finaly execute


systemctl restart postfix.service

verify that postfix is running


systemctl status postfix.service

if postfix is running we will verify if postfix delivers mail to adress with domain centostestmail.com


echo "Hello" | mail -s "test" joe@centostestmail.com

verify if mail has been delivered


tail /var/log/maillog

ay  6 19:58:01 mail postfix/pickup[2818]: 9AC9D10025A: uid=0 from=<root>
May  6 19:58:01 mail postfix/cleanup[2829]: 9AC9D10025A: message-id=<20150506175801.9AC9D10025A@mail.yourfqdn.com>
May  6 19:58:01 mail postfix/qmgr[2819]: 9AC9D10025A: from=<root@mail.yourfqdn.com>, size=459, nrcpt=1 (queue active)
May  6 19:58:01 mail postfix/local[2831]: 9AC9D10025A: to=<joe@centostestmail.com>, relay=local, delay=0.14, delays=0.1/0.04/0/0.01, dsn=2.0.0, status=sent (delivered to mailbox)
May  6 19:58:01 mail postfix/qmgr[2819]: 9AC9D10025A: removed

if your log appears like example we can move to the next step

Step 5: Configure Clam Antivirus

If you want to run a mail server you will be a happy sysadmin if you put an antivirus inspecting incoming mail.  Minimize viruses risk is a plus. In my case I will use clam.


setsebool -P antivirus_use_jit on

we need to configure how clam refreshes his database


vim /etc/sysconfig/freshclam

comment or remove last line

#  FRESHCLAM_DELAY=disabled-warn    # REMOVE ME

now we will make a edit clamav config file


vim /etc/freshclam.conf

remove the line that puts

example

finally update your viruses database


freshclam

after we get an updated antivirus we should check if it’s working as expected for these purposes there’s a string called EICAR that should be detected as a virus always.

download EICAR string


wget  http://www.eicar.org/download/eicar.com

analyze EICAR string


clamscan --infected --remove eicar.com

output should be like these

eicar.com: Eicar-Test-Signature FOUND
eicar.com: Removed.

----------- SCAN SUMMARY -----------
Known viruses: 3802265
Engine version: 0.98.6
Scanned directories: 0
Scanned files: 1
Infected files: 1
Data scanned: 0.00 MB
Data read: 0.00 MB (ratio 0.00:1)
Time: 27.957 sec (0 m 27 s)

Step 6: Configure basic settings in spamassasin

At this point we have an antivirus in our server that is’s updated every 3 hours, viruses is a problem for our users but the BIG problem is spam, most of your users incoming mail will be spam, and our users will complaining about that they can work because lost his precious time removing spam in his incoming mail, another part will be losing her time buying magical blue pills, expensive watches and helping African kings moving her money outside Africa.

Anyway first step is configure selinux


setsebool -P spamassassin_can_network on

enable spamassasin service


systemctl start spamassassin.service
systemctl status spamassassin.service
systemctl enable spamassassin.service

update spamassasin definitions


sa-update

a cron task is added when you install spamassin that will update spamassasin definitions is located at  /etc/cron.d/sa-update

Step 7: Integrate spamassasin and clamav with amavisd

At this point clamav and spamassasin are isolated services for integrate these elements we will use amavisd he will be responsive of deliver mails in order of get a virus and spam check.

Clamav is not a lightweight service instead launch a local copy for every mail, we load a service to be ready faster.

we need to provide some config files


cp /usr/share/doc/clamav-server*/clamd.sysconfig /etc/sysconfig/clamd.amavisd

we need to adapt config file to our actual configuration


vi /etc/sysconfig/clamd.amavisd

CLAMD_CONFIGFILE=/etc/clamd.d/amavisd.conf
CLAMD_SOCKET=/var/run/clamd.amavisd/clamd.sock

we will create a couple of new files


vi /etc/tmpfiles.d/clamd.amavisd.conf

add this content

d /var/run/clamd.amavisd 0755 amavis amavis -

vi /usr/lib/systemd/system/clamd@.service

with this content

[Unit]
Description = clamd scanner (%i) daemon
After = syslog.target nss-lookup.target network.target
[Service]
Type = simple
ExecStart = /usr/sbin/clamd -c /etc/clamd.d/%i.conf --nofork=yes
Restart = on-failure
PrivateTmp = true
[Install]
WantedBy=multi-user.target

now we can enable clamd@amavisd service


systemctl start clamd@amavisd

systemctl enable clamd@amavisd

now we need configure amavisd service


vim /etc/amavisd/amavisd.conf

at line 16 set number of amavisd childrens

more childres uses more ram but delivers more mail at once, one amavisd children consumes near 40% of cpu in a low end server, be careful if you receive a lot of mails at once can be a big punch in your cpu have too many childrens

$max_servers = <a number>

at line 20 set $mydomain we need to put step 3 domain name

$mydomain = ‘desireddomain.com’;

at line 152 aprox set your hostname

$myhostname= ‘mail.desireddomain.com’;


systemctl start amavisd.service

after this we must search in file /var/log/maillog strings like these

Mar 19 17:51:48 mail amavis[21284]: ANTI-SPAM-SA code    loaded

Mar 19 17:51:48 mail amavis[21284]: Using primary internal av scanner code for ClamAV-clamd

to ensure that amavisd detects our antivirus and spamassasin

next step is enable service


systemctl enable amavisd.service

Step 8:Integrate postfix with amavisd

Amavisd will pass all incoming mail to our antivirus and antispam and verify that we are receiving a clean mail, but at this moment we have postfix and amavisd isolated, we need make a small integration.


vim /etc/postfix/main.cf

append this line at the end

content_filter=smtp-amavis:[127.0.0.1]:10024

vim /etc/postfix/master.cf

append these lines at the end

smtp-amavis unix -      -       n       -       6       smtp
        -o smtp_data_done_timeout=1200
        -o smtp_send_xforward_command=yes
        -o disable_dns_lookups=yes
127.0.0.1:10025 inet n  -       n      -        -       smtpd
        -o content_filter=
        -o local_recipient_maps=
        -o relay_recipient_maps=
        -o smtpd_restriction_classes=
        -o smtpd_client_restrictions=
        -o smtpd_helo_restrictions=
        -o smtpd_sender_restrictions=
        -o smtpd_recipient_restrictions=permit_mynetworks,reject
        -o mynetworks=127.0.0.0/8
        -o strict_rfc821_envelopes=yes
        -o smtpd_error_sleep_time=0
        -o smtpd_soft_error_limit=1001
        -o smtpd_hard_error_limit=1000

 

in line smtp-avavis unix – – n – <number> smtp

try that number value be the same that amavisd children

restart postfix service


systemctl stop postfix.service

systemctl start postfix.service

now we need to check that our  postfix and amavisd service are integrated, the easy way is send an spam mail and a virus mail, one with gtube string another with eicar

we need to put EICAR and GTUBE strings in a mail.

EICAR String

Gtube String

test spam and virus mail

after send this couple of test you need to check in /var/log/maillog and output like these

May  7 00:20:14 mail postfix/pickup[4434]: 578BA100322: uid=0 from=<root>
May  7 00:20:14 mail postfix/cleanup[4458]: 578BA100322: message-id=<20150506222014.578BA100322@mail.yourfqdn.com>
May  7 00:20:14 mail postfix/qmgr[4435]: 578BA100322: from=<root@mail.yourfqdn.com>, size=527, nrcpt=1 (queue active)
May  7 00:20:15 mail amavis[2388]: (02388-02) Blocked SPAM {DiscardedOpenRelay,Quarantined}, <root@mail.yourfqdn.com> -> <joe@centostestmail.com>, Message-ID: <20150506222014.578BA100322@mail.yourfqdn.com>, mail_id: TcgB4ovK5t1h, Hits: 999.999, size: 527, 1596 ms
May  7 00:20:15 mail postfix/smtp[4460]: 578BA100322: to=<joe@centostestmail.com>, relay=127.0.0.1[127.0.0.1]:10024, delay=1.6, delays=0.03/0/0.01/1.6, dsn=2.7.0, status=sent (250 2.7.0 Ok, discarded, id=02388-02 - spam)
May  7 00:20:15 mail postfix/qmgr[4435]: 578BA100322: removed
May  7 00:20:22 mail postfix/pickup[4434]: 4D335100323: uid=0 from=<root>
May  7 00:20:22 mail postfix/cleanup[4458]: 4D335100323: message-id=<20150506222022.4D335100323@mail.yourfqdn.com>
May  7 00:20:22 mail postfix/qmgr[4435]: 4D335100323: from=<root@mail.yourfqdn.com>, size=527, nrcpt=1 (queue active)
May  7 00:20:22 mail clamd[1084]: /var/spool/amavisd/tmp/amavis-20150507T001929-02391-G5h5_dlo/parts/p002: Eicar-Test-Signature FOUND
May  7 00:20:22 mail clamd[1084]: /var/spool/amavisd/tmp/amavis-20150507T001929-02391-G5h5_dlo/parts/p001: Eicar-Test-Signature FOUND
May  7 00:20:22 mail amavis[2391]: (02391-02) Blocked INFECTED (Eicar-Test-Signature) {DiscardedOpenRelay,Quarantined}, <root@mail.yourfqdn.com> -> <joe@centostestmail.com>, Message-ID: <20150506222022.4D335100323@mail.yourfqdn.com>, mail_id: yIy3drLObXjq, Hits: -, size: 527, 134 ms
May  7 00:20:22 mail postfix/smtp[4460]: 4D335100323: to=<joe@centostestmail.com>, relay=127.0.0.1[127.0.0.1]:10024, delay=0.16, delays=0.02/0/0.01/0.13, dsn=2.7.0, status=sent (250 2.7.0 Ok, discarded, id=02391-02 - INFECTED: Eicar-Test-Signature)
May  7 00:20:22 mail postfix/qmgr[4435]: 4D335100323: removed

Step 9: Configure mariadb

At this point we have a working postfix mail server with antivirus and antispam, at this point we can add local user accounts and they will get a mail account. But i prefer to have all users in a database and foget to have hundreds of accounts


vim /etc/my.cnf.d/server.cnf

#
# These groups are read by MariaDB server.
# Use it for options that only the server (but not clients) should see
#
# See the examples of server my.cnf files in /usr/share/mysql/
#

# this is read by the standalone daemon and embedded servers
[server]
innodb_file_per_table
innodb_file_format = Barracuda
# this is only for the mysqld standalone daemon
[mysqld]

# this is only for embedded server
[embedded]

# This group is only read by MariaDB-5.5 servers.
# If you use the same .cnf file for MariaDB of different versions,
# use this group for options that older servers don't understand
[mysqld-5.5]

# These two groups are only read by MariaDB servers, not by MySQL.
# If you use the same .cnf file for MySQL and MariaDB,
# you can put MariaDB-only options here
[mariadb]

[mariadb-5.5]

enable mariadb service


systemctl  enable mariadb.service

Start mariadb database server


systemctl  start mariadb.service

secure mariadb installation


mysql_secure_installation

follow screen instructions

Optional: if you will need access to database open port using this command


firewall-cmd --permanent --add-service=mysql
firewall-cmd --reload

Remember configure a backup script for your database

Step 10: Generate SSL Certificate


genkey --days 3650 mail.yourdamain.com

follow on screen instructions and this will generate two files.

private part of certificate at

/etc/pki/tls/certs/mail.yourdomain.com.0.csr

and public part of certificate at

/etc/pki/tls/private/mail.yourdomain.com.key

you should get your certificate signed by a certification autority search for one pay and follor certification authority instructions :-(

Step 11: Create a user account and a folder were store  mails


mkdir /var/vmail

chmod 770 /var/vmail/

useradd -r -u 101 -g mail -d /var/vmail/ -s /sbin/nologin -c "Virtual Mailbox" vmail

chown vmail:mail /var/vmail/

Step 12: Configure nginx

Fist step is verify that nginx server is installed and working


systemctl enable nginx.service
systemctl start nginx.service

firewall-cmd --permanent --zone=public --add-service=http
firewall-cmd --permanent --zone=public --add-service=https
firewall-cmd --reload

select your favorite webbrowser and navigate to your server ip

you should see something like this

welcome nginx

Step 13: Configure php


vim  /etc/php.ini

line 763 should be

cgi.fix_pathinfo=0

line 878 should be your timezone

search here http://php.net/manual/en/timezones.php

date.timezone = Continent/Country

Step 14: Configure PostfixAdmin

in my case i will create a domain like mailadmin.yourdomain.com

we have to download postfixadmin


wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.92/postfixadmin-2.92.tar.gz

and move to a valid ubication


mv postfixadmin-2.92.tar.gz /var/www

cd /var/www

tar xzvf postfixadmin-2.92.tar.gz

rm postfixadmin-2.92.tar.gz

mv postfixadmin-2.92/ postfixadmin.yourdomain.com

chown -R  nginx:nginx postfixadmin.yourdomain.com

mkdir /var/lib/php/postfixadmin.yourdomain.com

disable php-fpm default socket


mv  /etc/php-fpm.d/www.conf /etc/php-fpm.d/www.conf.dis

create a php-fpm postfixadmin socket


vim /etc/php-fpm.d/postfixadmin.yourdomain.com.conf

[postfixadmin.yourdomain.com]
listen = /var/run/php-fpm/postfixadmin.yourdomain.com.socket
listen.allowed_clients = 127.0.0.1
user = nginx
group = nginx
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 35
slowlog = /var/log/php-fpm/postfixadmin.log
rlimit_files = 1024
rlimit_core = 0
chdir = /var/www/postfixadmin.yourdomain.com
php_flag[display_errors] = off
php_admin_value[error_log] = /var/log/php-fpm/postfixadmin.yourdomain.com-error.log
php_admin_flag[log_errors] = on
php_admin_value[memory_limit] = 128M
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/postfixadmin.yourdomain.com

start php-fpm service


systemctl start  php-fpm.service

check if php-fpm has started


systemctl status  php-fpm.service

output should appear like these

php-fpm.service - The PHP FastCGI Process Manager
   Loaded: loaded (/usr/lib/systemd/system/php-fpm.service; disabled)
   Active: active (running) since Thu 2015-05-07 00:52:05 CEST; 2s ago
 Main PID: 5499 (php-fpm)
   Status: ;Ready to handle connections;
   CGroup: /system.slice/php-fpm.service
           ├─5499 php-fpm: master process (/etc/php-fpm.conf)
           ├─5501 php-fpm: pool postfixadmin.yourdomain.com
           ├─5502 php-fpm: pool postfixadmin.yourdomain.com
           ├─5503 php-fpm: pool postfixadmin.yourdomain.com
           ├─5504 php-fpm: pool postfixadmin.yourdomain.com
           └─5505 php-fpm: pool postfixadmin.yourdomain.com

May 07 00:52:05 yourfqdn systemd[1]: Started The PHP FastCGI Process Manager.

enable php-fpm service to start at boot


systemctl enable  php-fpm.service

Next we need to create postfix user database from a shell execute:


mysql -u root -p -e "CREATE DATABASE postfix;"

mysql -u root -p -e "CREATE USER postfix@localhost IDENTIFIED BY 'put_here_your_password';"

mysql -u root -p -e "GRANT ALL PRIVILEGES ON postfix . * TO postfix@localhost;"

at this point we need to create a host for postfixadmin in nginx

I will use a selfsigned certificate for https you can pay a certification authority to bypass bad certificate errors in your browser


genkey --days 3650 postfixadmin.yourdomain.com

follow screen instructions, if you put a password in your keys every time that you reboot your system you will need to put that

trick- collecting random data could take a lot of time, to acelerate this process you can dowload a linux distro iso to acelerate this process, it reads data from network card


vim /etc/nginx/conf.d/put_here_your_postfixadmin_domain.conf

 

server {

  listen 80;
  server_name postfixadmin.yourfqdn.com;
  error_log  /var/log/nginx/postfixadmin.yourfqdn.com.error.log warn;
  access_log  /var/log/nginx/postfixadmin.yourfqdn.com.access.log;

  return 301 https://$server_name$request_uri; # enforce https

}

server {

   listen          443 ssl;
   server_name     postfixadmin.yourfqdn.com;

 error_log /var/log/nginx/postfixadmin.yourfqdn.com.secure.error.log warn;
 access_log /var/log/nginx/postfixadmin.yourfqdn.com.secure.access.log;
   root            /var/www/postfixadmin.yourfqdn.com;
   index           index.php;
   charset         utf-8;

   ## SSL settings
   ssl_certificate           //etc/pki/tls/certs/postfixadmin.yourfqdn.com.crt;
   ssl_certificate_key       /etc/pki/tls/private/postfixadmin.yourfqdn.com.key;
   ssl_protocols             TLSv1.2;
   ssl_ciphers               "EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4";
   ssl_prefer_server_ciphers on;
   ssl_session_cache         shared:SSL:10m;
   ssl_session_timeout       10m;
   ssl_ecdh_curve            secp521r1;

   add_header Strict-Transport-Security max-age=31536000;
   # add_header X-Frame-Options DENY;

   # auth_basic "Restricted area";
   # auth_basic_user_file /etc/nginx/passwd;

   location / {
      try_files $uri $uri/ index.php;
   }

   location ~* \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        include       fastcgi_params;
        fastcgi_pass  unix:/var/run/php-fpm/postfixadmin.yourfqdn.com.socket;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
   }

}

 

we need to allow in selinux communication between nginx and php-fpm


setsebool -P httpd_can_network_connect on

and allow selinux that permits nginx to write files in server


setsebool -P httpd_unified on

and allow php-fpm to write session files


chown nginx:nginx /var/lib/php/postfixadmin.yourdomain.com

now configure postfixadmin parameters


vim /var/www/postfixadmin.yourdomain.com/config.inc.php

it’s self explanatory but you will need to changue these parameters


$CONF['configured'] = true;

$CONF['setup_password'] = 'puthereastrongpassword';

$CONF['database_type'] = 'mysqli';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'postfix';
$CONF['database_password'] = 'yourpassword';
$CONF['database_name'] = 'postfix';

$CONF['emailcheck_resolve_domain']='NO';

$CONF['default_aliases'] = array (
    'abuse' => 'abuse@amaindomainthatyouwilluse.com',
    'hostmaster' => 'hostmaster@amaindomainthatyouwilluse.com',
    'postmaster' => 'postmaster@amaindomainthatyouwilluse.com',
    'webmaster' => 'webmaster@amaindomainthatyouwilluse.com'
);

now we can setup our postfixadmin instance

open in your browser

https://postfixadmin.yourdomain.com/setup.php

postfixadmin setupfill all data and follow instructions

finally access to  https://postfixadmin.yourdomain.com and login in order to configure your domains

postfixadmin main screen

we will create one test domain like newcentostestmail.com

in tab Domain List we will select new domain

postixadmin add domainafter add new domain we will create a mailbox

go to Domain List -> Domain List

click on newcentostestmail.com

an Add Mailbox and create joe@newcentostestmail.com mailbox

postfixadmin create mailboxfinally we have created a mailbox we need to link our database with postfix

step 15: Cleanup some test config

Do you want to have a user in your system called joe? you don’t


userdel joe

Do you want map mails from @centostestmail.com? neither

remove centostestmail.com from mydestination values


vim /etc/postfix/main.cf

at line 164 approx leave these values for mydestination

mydestination = $myhostname, localhost.$mydomain, localhost

restart postfix


systemctl restart postfix

step 16: Connect postfix with mariadb:

we have a database that contains a domain list and and a list of emails we need that postfix can access to database in order to read all data

because postfix and other components only will need read permisions we will create a only read user


mysql -u root -p -e "CREATE USER postfixread@localhost IDENTIFIED BY 'put_here_your_password';"

mysql -u root -p -e "GRANT SELECT ON postfix . * TO postfixread@localhost ;"

we will need to link three elements domains, mailboxes and aliases

we will start with domains


vim /etc/postfix/mysql-virtual_domains_maps.cf

using this content

hosts = localhost
user = postfixread
password = put_here_your_password
dbname = postfix
query = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '0' AND active = '1'

vim /etc/postfix/mysql-relay_domains_maps.cf

using this content

hosts = localhost
user = postfixread
password = put_here_your_password
dbname = postfix
query = SELECT domain FROM domain WHERE domain='%s' and backupmx = '1'

next step are mailboxes


vim /etc/postfix/mysql-virtual_mailbox_maps.cf

with this content

hosts = localhost
user = postfixread
password = put_here_your_password
dbname = postfix
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'

vim /etc/postfix/mysql-virtual_mailbox_limit_maps.cf

hosts = localhost
user = postfixread
password = put_here_your_password
dbname = postfix
query = SELECT quota FROM mailbox WHERE username='%s' and active=1

and finally we need to configure aliases


vim /etc/postfix/mysql-virtual_alias_maps.cf

hosts = localhost
user = postfixread
password = put_here_your_password
dbname = postfix
query = SELECT goto FROM alias WHERE address='%s' AND active = '1'

now we need to link our sql queries with postfix config file


vim /etc/postfix/main.cf

at line 297 we need to paste this

relay_domains = proxy:mysql:/etc/postfix/mysql-relay_domains_maps.cf

at line 399 we need to paste this,

virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-virtual_alias_maps.cf,
                     regexp:/etc/postfix/virtual_regexp
virtual_mailbox_base = /var/vmail
virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual_domains_maps.cf
virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailbox_maps.cf
virtual_mailbox_limit_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailbox_limit_maps.cf
virtual_minimum_uid = 101
virtual_uid_maps = static:101
virtual_gid_maps = static:12

proxy_read_maps = $local_recipient_maps $mydestination $virtual_alias_maps $virtual_alias_domains $virtual_mailbox_maps $virtual_mailbox_domains $relay_recipient_maps $relay_domains $canonical_maps $sender_canonical_maps $recipient_canonical_maps $relocated_maps $transport_maps $mynetworks $smtpd_sender_login_maps $sender_bcc_maps $recipient_bcc_maps $smtp_generic_maps $lmtp_generic_maps $alias_maps $virtual_mailbox_limit_maps

finally we need to create virtual_regexp file


touch /etc/postfix/virtual_regexp

if we restart postfix no problems should appear


systemctl restart postfix.service

if we check our maillog file


tail -f /var/log/maillog

we should see something like this

May  9 17:07:56 mail postfix/postfix-script[2967]: starting the Postfix mail system
May  9 17:07:56 mail postfix/master[2969]: daemon started -- version 2.10.1, configuration /etc/postfix

postfix has started and aparently it has been linked to our database but it’s better verify this

for this we will use postfixadmin but before we need to allow write in our virtual mail storage folder because our directory is not labeled


chcon -R -t mail_spool_t /var/vmail

now we will send a test email to a created mailbox in postfixadmin


echo "Hello" | mail -s "test" joe@newcentostestmail.com

in your maillog you should view something like these


tail /var/log/maillog

May  9 17:10:03 mail postfix/pickup[2970]: 1FD7C10041D: uid=0 from=<root>
May  9 17:10:03 mail postfix/cleanup[2992]: 1FD7C10041D: message-id=<20150509151003.1FD7C10041D@mail.yourfqdn.com>
May  9 17:10:03 mail postfix/qmgr[2971]: 1FD7C10041D: from=<root@mail.yourfqdn.com>, size=462, nrcpt=1 (queue active)
May  9 17:10:04 mail postfix/smtpd[3000]: connect from localhost[127.0.0.1]
May  9 17:10:04 mail postfix/smtpd[3000]: 295DD1004F0: client=localhost[127.0.0.1]
May  9 17:10:04 mail postfix/cleanup[2992]: 295DD1004F0: message-id=<20150509151003.1FD7C10041D@mail.yourfqdn.com>
May  9 17:10:04 mail postfix/qmgr[2971]: 295DD1004F0: from=<root@mail.yourfqdn.com>, size=943, nrcpt=1 (queue active)
May  9 17:10:04 mail amavis[2722]: (02722-01) Passed CLEAN {RelayedOpenRelay}, <root@mail.yourfqdn.com> -> <joe@newcentostestmail.com>, Message-ID: <20150509151003.1FD7C10041D@mail.yourfqdn.com>, mail_id: Yppl42y970Wc, Hits: -0.001, size: 462, queued_as: 295DD1004F0, 975 ms
May  9 17:10:04 mail postfix/smtp[2997]: 1FD7C10041D: to=<joe@newcentostestmail.com>, relay=127.0.0.1[127.0.0.1]:10024, delay=1.2, delays=0.19/0.04/0.04/0.96, dsn=2.0.0, status=sent (250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as 295DD1004F0)
May  9 17:10:04 mail postfix/qmgr[2971]: 1FD7C10041D: removed
May  9 17:10:04 mail postfix/virtual[3003]: 295DD1004F0: to=<joe@newcentostestmail.com>, relay=virtual, delay=0.09, delays=0.02/0.04/0/0.03, dsn=2.0.0, status=sent (delivered to maildir)
May  9 17:10:04 mail postfix/qmgr[2971]: 295DD1004F0: removed

Hurrah we have virtual mail

your sent mail should be at /var/vmail/newcentostestmail.com/joe/new

step 17: open smtp port, 25, and enable remote access in postfix

Our mailserver accepts connections from port 25 but only in localhost interface, that means that we can’t receive mail from a outside server and our users can’t send email from theirs applications.

firs of all we need to tell to postfix that listens from all interfaces


vim /etc/postfix/main.cf

at line 116 replace content with this

inet_interfaces = all

and restart postfix


systemctl restart postfix.service

postfix is listening at port 25 but firewalld is blocking any attemp from outside, we need to open port 25 in firewalld we just need to execute these commands


firewall-cmd --permanent --zone=public --add-service=smtp

firewall-cmd --reload

at this moment postfix should be contacted from any computer in the internet.

users, spammers, phishers and west Europe sexy women are ready to send tons of emails, we should check that this is correct.

from another computer execute this command


telnet <mailserver ip> 25

and you should get this output

Trying mailserver_ip...
Connected to mailserver_ip.
Escape character is '^]'.
220 mail.yourfqdn.com ESMTP Postfix

Eureka we can receive mails from a lot of people.

step 18: enable smtp security

At this moment if   user try send an email using your new server, it only has support for smtp that is a plain protocol, that means that is really easy read communication contents and get his password. we don’t want this for us.

A long time ago, at the beginning of secure smtp times, that’s 1997. Some people decided that best way to  secure smtp will be wrap it over a ssl or tls connection, that means that all connections should be realized starting a ssl/tls session since first data packet.

To differentiate secure and insecure smtp servers the best way it use a port for insecure smtp,  25, and another for secure connections 465. This strategy is a bit irritating because if another server want deliver a email in a secure mode it should verify if port 465 it’s opened.

Two years after some people  decided that the best way  should be implement STARTTLS this allows to  secure our communication  over a plain  textcommunication at  port 25.

using port 465 smtmps is deprecated and you shouldn’t give support.

if you remember at step 6 you generated a certificate located at

/etc/pki/tls/private/mail.yourdomain.com.key
/etc/pki/tls/certs/mail.yourdomain.com.0.csr

it’s recommendable have our certificate signed by and certification authority,  sorry you must pay :-(  . Otherwise you can generate a self-signed certificate which will you a lot of security warnings in mail clients.

openssl x509 -req -days 365 -in /etc/pki/tls/certs/mail.yourdomain.com.0.csr -signkey /etc/pki/tls/private/mail.yourdomain.com.key -out /etc/pki/tls/certs/mail.yourdomain.com.crt

we need to tell to postfix where are these certificates and enable smtps


vim /etc/postfix/main.cf

1

at the end of the file we need to append this content at the end of file

smtpd_tls_key_file = /etc/pki/tls/private/mail.yourfqdn.com.key
smtpd_tls_cert_file = /etc/pki/tls/certs/mail_yourfqdn_com.crt
smtpd_tls_CAfile = /etc/pki/tls/certs/intermediate.mail.yourfqdn.com.cer

postfix also needs to know that we want to use starttls appending this line

smtpd_tls_security_level = may

Once when we have our certificate variables setted we need restart our postfix service


systemctl restart postfix.service

and check /var/log/maillog output


tail  /var/log/maillog

May  9 17:22:12 mail postfix/postfix-script[3614]: starting the Postfix mail system
May  9 17:22:12 mail postfix/master[3616]: daemon started -- version 2.10.1, configuration /etc/postfix

 

now we need to verify that our smtp port supports STARTTLS this can be done from another computer using telnet.


telnet mailserverip 25

Trying ...
Connected to .
Escape character is '^]'.
220 mail.yourfqdn.com ESMTP Postfix
ehlo testing
250-mail.mail.yourfqdn.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN

You should have a line that puts 250-STARTTLS startttls is enabled

now we will check if ssl works


openssl s_client -starttls smtp -crlf -connect your_server_ip:25

this command should give info about your ssl certificate

step 19: Secure smtp ssl

Unfortunately during last months openssl and his protocols appears to be broken, this security problems should be resolved using two ways:

  • maintain your Openssl packages updated.
  • disable broken protocols and cyphers.

if you’re following this guide I assume that you know  how to use yum update, next step is about cyphers and broken protocols.

openssl supports these protocols:

  • SSLv2 broken
  • SSLv3 broken https://poodle.io/
  • TLS 1.0 Use for interoperability purposes where needed Has known issues that cannot be mitigated
  • TLS 1.1 Use for interoperability purposes where needed  Does not support modern cipher suites.
  • TLS 1.2 Recommended version. Supports the modern AEAD cipher suites.

These protocols use different ciphers

  • Minimal encryption should be 128bits.
  • ADH  Anonymous Diffie-Hellman doesn’t provide authentication
  • NULL no encryption no party
  • Export key exchange suites can be broken easily
  • RC4 is prohibited RFC7465
  • 3DES uses 112bits it’s strong but have performance problems avoid it

At this moment your STARTTLS configuration allow insecure protocols and insecure ciphers we need to fix this.

Simply append these content in your main.cf file

#Disable sslv2 ad SSLv3
smtpd_tls_protocols= !SSLv2, !SSLv3
smtpd_tls_mandatory_protocols= !SSLv2, !SSLv3

#set minimum TLS ciphers grade for tls
smtpd_tls_mandatory_ciphers = high

#use server ciphers instead client preference
tls_preempt_cipherlist = yes

#ciphers to exclude
smtpd_tls_mandatory_exclude_ciphers = aNULL, MD5 , DES, ADH, RC4, PSD, SRP, 3DES, eNULL

with this configuration you just avoided SSLv2, SSLv3 and remove insecure ciphers from TLS1.1

You should be tuned about security problems with openSSL.

step 20: enable Perfect forward secrecy  in postfix

We have secured our SSL/TLS configuration? Yes

we can do more for our security? Yes

HOW? enabling Perfect forward secrecy.

perfect forward secrecy generates a  public  keys per session that means theoretically if our private key is compromised your information is secret.

There are two options

Prime-field groups (EDH) – Server uses a large prime number and a generator

Elliptic-curve groups (EECDH) – Instead a large prime serve uses a elliptic curve algorithm

To configure EDH we need to create  some keys


openssl gendh -out /etc/postfix/dh_512.pem -2 512

openssl gendh -out /etc/postfix/dh_1024.pem -2 1024

openssl gendh -out /etc/postfix/dh_2048.pem -2 2048

append this lines in your /etc/postfix/main.cf


vim /etc/postfix/main.cf

#Perfect forwatd secrecy Prime Field Groups EDH
smtpd_tls_dh1024_param_file = ${config_directory}/dh_2048.pem
smtpd_tls_dh512_param_file = ${config_directory}/dh_512.pem

now we can restart postfix service


systemctl reload postfix.service

for security reasons we should generate a new group of prime numbers daily or hourly, we will create a bash script in order to generate these prime numbers every day


vim /etc/cron.daily/postfix_pfs_edh_regenerate

and copy this content

#!/bin/bash
cd /etc/postfix
umask 022
for legth in 512 1024 2048
do
openssl dhparam -out dh_$legth.tmp $legth && mv dh_$legth.tmp dh_$legth.pem
chmod 644 dh_$legth.pem
done

and give correct permissions

chmod 700 /etc/cron.daily/postfix_pfs_edh_regenerate

To configure EECDH we should add these lines in main.cf

vim /etc/postfix/main.cf

#Perfect forward secrecy Elliptic-curve Groups EECDH
smtpd_tls_eecdh_grade = strong
tls_eecdh_strong_curve = prime256v1
tls_eecdh_ultra_curve = secp384r1

now we can restart postfix service

systemctl restart postfix.service

Step 21: enable POP and IMAP services

Our users need to read their incoming mail in laptops, mobile devices, fridges….

with smtp user can send mails but can’t read new emails and maintain philosophical conversations about last season most viewed soap opera.

Receiving emails from server can be done using POP, IMAP or both

In my case i preffer use only IMAP but i will both configurations

POP is older than IMAP if your users reads email from multiple devices IMAP should be better, check users email volume and number of devices to select what configuration fits better for each one, new soap operas are really intense.

For provide POP and IMAP connectivity we will use dovecot, Dovecot also includes SASL support for centralized logins, Tradicionally tutorials uses cyrus-sasl to implement authentication, but dovecot includes a SASL implementation, i will try to use it instead include cyrus-sasl package.

Dovecot configuration files are located at /etc/dovecot/conf.d

 Step  22: create config files to Link dovecot with MariaDB user database

With postfixadmin we create a mariadb database, we should give access to dovecot in order to get these data

we need a file with needed queries to provide data about users

vim /etc/dovecot/conf.d/dovecot-mysql.conf.ext

driver = mysql
connect = host=localhost dbname=postfix user=postfixread password=yourpassword

password_query = SELECT username as user, password, concat('/var/vmail/', maildir) as userdb_home,  concat('maildir:/var/vmail/', maildir) as userdb_mail, 101 as userdb_uid, 12 as userdb_gid FROM mailbox  WHERE username = '%u' AND active = '1'

user_query = SELECT concat('/var/vmail/', maildir) as home, concat('maildir:/var/vmail/', maildir) as mail,  101 AS uid, 12 AS gid, CONCAT('*:bytes=', quota) as quota_rule FROM mailbox WHERE  username = '%u' AND active = '1'

also we need a file to provide information about accounts quota

vim /etc/dovecot/conf.d/dovecot-mysql-quota.conf.ext

connect = host=localhost dbname=postfix user=postfixread password=your_password
map {
  pattern = priv/quota/storage
  table = quota2
  username_field = username
  value_field = bytes
}
map {
  pattern = priv/quota/messages
  table = quota2
  username_field = username
  value_field = messages
}

with these files dovecot will query  mariadb info about users and mailbox quotas.

step 23: configure dovecot ssl protocols

now we will configure some setting in dovecot main config file

vim /etc/dovecot/dovecot.conf

line 24 tells dovecot what protocols  should serve it needs to be like

protocols = imap pop3

line 30 is what interfaces where dovecot will be listening

listen = *, ::

line 67 defines behavior when reboot dovecot service

shutdown_clients = yes

now we will restart dovecot service

 systemctl restart dovecot.service

and verify if service has started correctly

tail /var/log/maillog

you should see a line like these

May 10 15:42:02 mail dovecot: master: Dovecot v2.2.10 starting up for imap (core dumps disabled)

 step 24: Configure Dovecot users authentification

Now dovecot is listening in desired ports, but blocked by firewalld, before open these ports we need to do some modifications

When a user request their emails using pop3 or imap, he will need to pass his username and password, there are several ways to send login information:

plain: passed as clear text, secure if is send over a TLS/SSL conection

login: another clear text mechanism, used by outlook clients, secure if is send over a TLS/SSL conection

CRAM-MD5: not clear text, uses HMAC-MD5

these are main supported  authentication protocols

by default dovecot only uses PLAIN mechanism, to add more mechanism we need to edit /etc/dovecot/conf.d/10-auth.conf file

vim /etc/dovecot/conf.d/10-auth.conf

at line 100 the content should be these:

auth_mechanisms = plain login cram-md5

now dovecot should support all these auth_mechanisms but we need to restart our dovecot service to check that

 systemctl restart dovecot.service

and verify if service has restarted correctly

tail /var/log/maillog

you should see a line like these

May 10 15:44:57 mail dovecot: master: Warning: Killed with signal 15 (by pid=1 uid=0 code=kill)
May 10 15:44:57 mail dovecot: master: Dovecot v2.2.10 starting up for imap (core dumps disabled)

step 25: configure Dovecot SSL

like postfix dovecot needs to configure SSL. Dovecot supports these modes:

  • POP3: insecure port 110
  • POP3 with StartTLS: secure port 110
  • POP3S:  POP3 wraped over a TLS/SSL connection 995
  • IMAP: insecure port 143
  • IMAP  with StartTLS: secure port 143
  • IMAPS: IMAP wraped over a TLS/SSL connection 993

some people disable port 110 and port 143 because some email clients make a plain login even if communication over port 143 indicates that only use of    StartTLS is avaliable.

What you should do with 110 and 143 is your decision, it depends of what kind of email clients you support. In mi case I will configure POP3 with StartTLS, POP3S, IMAP with StartTLS and IMAPS

We need to provide info about certificates to dovecot

vim /etc/dovecot/conf.d/10-ssl.conf

and replace certificates configuration chains

ssl_key = </etc/pki/tls/private/mail.yourdomain.com.key
ssl_cert = </etc/pki/tls/certs/mail_yourdomaiun_com.crt
ssl_ca = </etc/pki/tls/certs/intermediate.mail.yourdomain.com.cer

as you learn configuring postfix certificates providing only certificates allow using insecure protocols, we should hardening dovecot configuration near line 52

vim /etc/dovecot/conf.d/10-ssl.conf

# SSL protocols to use
ssl_protocols = !SSLv2 !SSLv3
# SSL ciphers to use
ssl_cipher_list = EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH+aRSA+RC4:EECDH:EDH+aRSA:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4

# Prefer the server's order of ciphers over client's.
ssl_prefer_server_ciphers = yes

step 26: configure Dovecot mailbox location

Now dovecot uses secure ssl ciphers but need to know were are located accounts mailboxes, this configuration options are located in:

/etc/dovecot/conf.d/10-mail.conf

edit this file

vim /etc/dovecot/conf.d/10-mail.conf

and configure these parameters

mail_location = maildir:/var/vmail/%d/%n/:INDEX=/var/vmail/%d/%n/indexes
mail_uid =101
mail_gid =12
first_valid_uid = 101
last_valid_uid = 101
first_valid_gid = 12
last_valid_gid = 12

now dovecot knows where are located mailboxes

step 27: configure Dovecot pop3 pop3s imap and imaps

Now dovecot needs to know what protocols will  serve and how

vim /etc/dovecot/conf.d/10-master.conf

 

service imap-login {
  inet_listener imap {
    port = 143
  }
  inet_listener imaps {
    port = 993
    ssl = yes
  }

service pop3-login {
  inet_listener pop3 {
    port = 110
  }
  inet_listener pop3s {
    port = 995
    ssl = yes
  }
}

service auth {

  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = vmail
    group = mail
  }

we need to advertise to dovecot that we will only accept login over encrypted connections

vim /etc/dovecot/conf.d/10-auth.conf

disable_plaintext_auth = yes

and new need to link dovecot with mariadb

vim /etc/dovecot/conf.d/auth-sql.conf.ext

# Authentication for SQL users. Included from 10-auth.conf.
#
# <doc/wiki/AuthDatabase.SQL.txt>

passdb {
  driver = sql

  # Path for SQL configuration file, see example-config/dovecot-sql.conf.ext
  args = /etc/dovecot/conf.d/dovecot-mysql.conf.ext
}

# "prefetch" user database means that the passdb already provided the
# needed information and there's no need to do a separate userdb lookup.
# <doc/wiki/UserDatabase.Prefetch.txt>
#userdb {
#  driver = prefetch
#}

userdb {
  driver = sql
  args = /etc/dovecot/conf.d/dovecot-mysql.conf.ext
}

# If you don't have any user-specific settings, you can avoid the user_query
# by using userdb static instead of userdb sql, for example:
# <doc/wiki/UserDatabase.Static.txt>
#userdb {
  #driver = static
  #args = uid=vmail gid=vmail home=/var/vmail/%u
#}

vim /etc/dovecot/conf.d/10-auth.conf

#!include auth-system.conf.ext
!include auth-sql.conf.ext

at this point we have a basical dovecot service running

systemctl restart dovecot.service

but we dont enable service if we restart our computer we don’t have dovecot enabled

systemctl enable dovecot.service

step 28: open Dovecot ports in firewall

dovecot is ready but we need to open ports in firewall

firewall-cmd –permanent –zone=public –add-service=pop3s

firewall-cmd –permanent –zone=public –add-port=110/tcp

firewall-cmd –permanent –zone=public –add-service=imaps

firewall-cmd –permanent –zone=public –add-port=143/tcp
firewall-cmd –reload

step 29: configure postfix smtp authentcation

when we configured dovecot we configure embebed sasl authentication, now we will integrate dovecot auth in postfix

we need to append these lines to our main.cf file

vim  /etc/postfix/main.cf

smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination

step 30: avoid plain logins in smtp connections

Security parameters appear to be well configured, but if we leave configuration in hand of users, they will try to use plain login, this is easily to sniff we avoid these options

vim /etc/postfix/main.cf

and append these lines

#disallow plain login
smtpd_tls_auth_only = yes

 

step 31: enable smtp submission port

At this moment we know that our smtp service should run only in port 25, unfortunately some Internet Service Providers decided that the best way to  stop spam is deny conections to smtp port. If you leave only port 25 opened some users can’t send email because their ISP deny connections. To solve this problem we can enable  SMTP submission port, 587. and forget phone calls from users complaining about that they can’t send email from cafes, or their homes.

we need to modify file  /etc/postfix/master.cf

vim /etc/postfix/master.cf

and remove comments in these lines

submission inet n       -       n       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_client_restrictions=$mua_client_restrictions
  -o smtpd_helo_restrictions=$mua_helo_restrictions
  -o smtpd_sender_restrictions=$mua_sender_restrictions
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING

we also need to define mua variables

vim /etc/postfix/main.cf


mua_client_restrictions = permit_sasl_authenticated,reject
mua_helo_restrictions = permit_sasl_authenticated,reject
mua_sender_restrictions = permit_sasl_authenticated,reject

now we will restart postifx service

 systemctl restart postfix.service

and we should get one output like these is /var/log/maillog

tail -f /var/log/maillog

May 10 16:08:51 mail postfix/postfix-script[13671]: stopping the Postfix mail system
May 10 16:08:51 mail postfix/master[3802]: terminating on signal 15
May 10 16:08:52 mail postfix/postfix-script[13752]: starting the Postfix mail system
May 10 16:08:52 mail postfix/master[13754]: daemon started -- version 2.10.1, configuration /etc/postfix

we need to open smtp submission port too

firewall-cmd –permanent –zone=public –add-port=587/tcp

firewall-cmd –reload

 Step 32: Test configuration against a mail client

In my case I will use Thunderbird, there are a lot of mail clients. If you use self signed certificates you should search in google, duck duck go or another web searcher how it’s the client behavior.

Configuring this data is easy.

  • all your servers will be your fully qualified domain name,
  • your username will be the email account
  • and the password will be that you put in postfixadmin

check and send some emails between accounts, don’t send to hotmail or gmail probabily it will appear in spam.

it should work.

if doesn’t work check /var/log/maillog output or leave a comment

step 33:link amavisd-new with mariadb database

amavisd neew to know what domains is serving we need to link Mariadb database with amavisd-new.

In order to maintain a security lever we will create a view and a new user that only can access to this view.

we will append these lines in amavisd config file

vim /etc/amavisd/amavisd.conf

@lookup_sql_dsn = (
    ['DBI:mysql:database=postfix;host=127.0.0.1;port=3306', 'postfixread', 'yourpassword']
);

$sql_select_policy =  'SELECT "Y" AS local FROM domain WHERE CONCAT("@", domain) IN (%k)';

amavisd default config will discard spam mail we want to changue this behavior

vim /etc/amavisd/amavisd.conf

and edit final_spam_destiny variable

$final_spam_destiny       = D_PASS;  #!!!  D_DISCARD / D_REJECT

now amavisd will deliver spam messages to inbox and knows what domains are hosted with postfixadmin.

Amavisd sends a copy of email to spamassasin and reads spamassasin results, this means that  if spamassasin modifies email subject these will not appears in our detected email. we should modify several parameters in amavis config file to always write spamassasing analysis results.

vim /etc/amavisd/amavisd.conf

just modify these values

$sa_tag_level_deflt  = -9999;  # add spam info headers if at, or above that level
$sa_tag2_level_deflt = 6.2;  # add 'spam detected' headers at that level
$sa_kill_level_deflt = 6.9;  # triggers spam evasive actions (e.g. blocks mail)
$sa_dsn_cutoff_level = 10;   # spam level beyond which a DSN is not sent
$sa_crediblefrom_dsn_cutoff_level = 18; # likewise, but for a likely valid From

We will  reconfigure some parameters in spamassasin

 

step 34: Configure spamassasin

vim /etc/mail/spamassassin/local.cf

should be like these

required_hits 5.0
report_safe 0
required_score 5
remove_header ham Status
remove_header ham Level

We can link spamassasing with a mariadb database that force us to create a database

mysql -u root -p

CREATE DATABASE mail_spamassassin;
CREATE USER 'spamassassin'@'localhost' IDENTIFIED BY 'new_password';
GRANT ALL PRIVILEGES ON `mail_spamassassin` . * TO 'spamassassin'@'localhost';
FLUSH PRIVILEGES;
quit;

we need to create several tables

mysql -u root -p mail_spamassassin


CREATE TABLE bayes_expire (
  id int(11) NOT NULL default '0',
  runtime int(11) NOT NULL default '0',
  KEY bayes_expire_idx1 (id)
) ENGINE=InnoDB;

CREATE TABLE bayes_global_vars (
  variable varchar(30) NOT NULL default '',
  value varchar(200) NOT NULL default '',
  PRIMARY KEY  (variable)
) ENGINE=InnoDB;

INSERT INTO bayes_global_vars VALUES ('VERSION','3');

CREATE TABLE bayes_seen (
  id int(11) NOT NULL default '0',
  msgid varchar(200) binary NOT NULL default '',
  flag char(1) NOT NULL default '',
  PRIMARY KEY  (id,msgid)
) ENGINE=InnoDB;

CREATE TABLE bayes_token (
  id int(11) NOT NULL default '0',
  token binary(5) NOT NULL default '',
  spam_count int(11) NOT NULL default '0',
  ham_count int(11) NOT NULL default '0',
  atime int(11) NOT NULL default '0',
  PRIMARY KEY  (id, token),
  INDEX bayes_token_idx1 (id, atime)
) ENGINE=InnoDB;

CREATE TABLE bayes_vars (
  id int(11) NOT NULL AUTO_INCREMENT,
  username varchar(200) NOT NULL default '',
  spam_count int(11) NOT NULL default '0',
  ham_count int(11) NOT NULL default '0',
  token_count int(11) NOT NULL default '0',
  last_expire int(11) NOT NULL default '0',
  last_atime_delta int(11) NOT NULL default '0',
  last_expire_reduce int(11) NOT NULL default '0',
  oldest_token_age int(11) NOT NULL default '2147483647',
  newest_token_age int(11) NOT NULL default '0',
  PRIMARY KEY  (id),
  UNIQUE bayes_vars_idx1 (username)
) ENGINE=InnoDB;

CREATE TABLE awl (
  username varchar(100) NOT NULL default '',
  email varbinary(255) NOT NULL default '',
  ip varchar(40) NOT NULL default '',
  count int(11) NOT NULL default '0',
  totscore float NOT NULL default '0',
  signedby varchar(255) NOT NULL default '',
  PRIMARY KEY (username,email,signedby,ip)
) ENGINE=InnoDB;

quit;

once when we have created these tables we need to link spamassasin with these tables

Auto-Whitelists linking

we need to enable autowhitelist check in spamassasin config

 vim /etc/mail/spamassassin/v310.pre

edit line 45 removing comment

# AWL - do auto-whitelist checks
#
loadplugin Mail::SpamAssassin::Plugin::AWL

and configure database access

vim /etc/mail/spamassassin/auto-whitelist.cf

auto_whitelist_factory Mail::SpamAssassin::SQLBasedAddrList

user_awl_dsn                 DBI:mysql:mail_spamassassin:localhost
user_awl_sql_username        spamassassin
user_awl_sql_password        yourpassword

use_auto_whitelist 1

Bayesian Storage Module

vim /etc/mail/spamassassin/bayesian-storage.cf

bayes_store_module                 Mail::SpamAssassin::BayesStore::SQL

bayes_sql_dsn                 DBI:mysql:mail_spamassassin:localhost
bayes_sql_username            spamassassin
bayes_sql_password            yourpassword

use_bayes          1
bayes_auto_learn   1
bayes_auto_expire  1

at this point we will restart spamassassin service

systemctl restart spamassassin.service

we should see a log like this in /var/log/maillog

May 11 12:18:30 mail spamd[23346]: logger: removing stderr method
May 11 12:18:36 mail spamd[23348]: spamd: server started on IO::Socket::IP [127.0.0.1]:783, IO::Socket::IP [::1]:783 (running version 3.4.0)
May 11 12:18:36 mail spamd[23348]: spamd: server pid: 23348
May 11 12:18:36 mail spamd[23348]: spamd: server successfully spawned child process, pid 23354
May 11 12:18:36 mail spamd[23348]: spamd: server successfully spawned child process, pid 23355
May 11 12:18:36 mail spamd[23348]: prefork: child states: IS
May 11 12:18:36 mail spamd[23348]: prefork: child states: II

Now we will give a spam message to spamassassin to start learning

 sa-learn –spam /usr/share/doc/spamassassin-3.4.0/sample-spam.txt

output should be like these

Learned tokens from 1 message(s) (1 message(s) examined)

this acction will add some data into database if we loged on mariadb

and execute a

select * from mail_spamassassin.bayes_vars;

we should see one record.

step 35: Sending spam to a dedicated folder in each account

When someone send spam it will appear in our inbox with text ***SPAM***  in the subject.

inbox spam detectedif stats about 99% of received email are right, that means that we will get 99 ***Spam*** mails before get a valid one. Leaving a lot of Spam a inbox could be irritating for our users.

One smart solution used by providers like Google, Microsoft or Yahoo is deliver spam in a dedicated folder.  Probably your users are familiarized with these behavior.

In our actual configuration deliver email to mailbox is managed by postfix virtual domain agent delivery VIRTUAL(8) , virtual agent can’t deliver email to spam folder. We need to use one alternative like Dovecot.

With dovecot acting as local delivery we can use sieve  filters to manage messages location.

For local delivery Dovecot offers two options, LDA and LMTP

  • LDA works like a binary command, each time that postfix sends a email lda deliver is called.
  • LMTP is like a long-running process started by Dovecot.

obviously  LMTP is better and is the option that we should use.

We need to change delivery agent in postfix. This requires some configuration changes in dovecot.

 

vim /etc/dovecot/conf.d/10-master.conf

and fill lmtp settings like these

service lmtp {
   unix_listener /var/spool/postfix/private/dovecot-lmtp {
     group = postfix
     mode = 0600
     user = postfix
    }
  unix_listener lmtp {
    #mode = 0666
   }

  # Create inet listener only if you can't use the above UNIX socket
  #inet_listener lmtp {
    # Avoid making LMTP visible for the entire internet
    #address =
    #port =
  #}
}

next step is configure lmtp protocol itself

 vim /etc/dovecot/conf.d/20-lmtp.conf

here you will need to give a postmaster address

protocol lmtp {
postmaster_address = postmaster@yourdomain.com
}

finally we will enable lmtp protocol

vim /etc/dovecot/dovecot.conf


protocols = imap pop3  lmtp

our configuration is ready we should restart dovecot service to apply configuration modifications

systemctl restart dovecot.service

now postfix need to use dovecot lda instead virtual

append these lines in postfix main config file

vim /etc/postfix/main.cf

#use dovecot lmtp as virtual transport
virtual_transport = lmtp:unix:private/dovecot-lmtp

after these modifications we can restart postfix service

systemctl restart postfix.service

at this point send and email from one virtual account to another, it should work without problems.

in /var/log/maillog it should appear a line like this

dovecot: lmtp(3762, youruser@yourdomain.com): XXXXXXXXXXXXXXXXXX: msgid=XXXXXXXXXXX.YYYYYYYYY@yourdomain.com: saved mail to INBOX

Now dovecot is our local delivery agent

before enable sieve plugin we need to ensure that every IMAP user will have a spam folder

vim /etc/dovecot/conf.d/15-mailboxes.conf

We will create an typical set of folders

##
## Mailbox definitions
##

# NOTE: Assumes &quot;namespace inbox&quot; has been defined in 10-mail.conf.
namespace inbox {

  #mailbox name {
    # auto=create will automatically create this mailbox.
    # auto=subscribe will both create and subscribe to the mailbox.
    #auto = no

    # Space separated list of IMAP SPECIAL-USE attributes as specified by
    # RFC 6154: \All \Archive \Drafts \Flagged \Junk \Sent \Trash
    #special_use =
  #}

  # These mailboxes are widely used and could perhaps be created automatically:
  mailbox Drafts {
    auto = subscribe
    special_use = \Drafts
  }
  mailbox Junk {
    auto = subscribe
    special_use = \Junk
  }
  mailbox Trash {
    auto = subscribe
    special_use = \Trash
  }

  # For \Sent mailboxes there are two widely used names. We'll mark both of
  # them as \Sent. User typically deletes one of them if duplicates are created.
  mailbox Sent {
    auto=subscribe
    special_use = \Sent
  }

  # If you have a virtual &quot;All messages&quot; mailbox:
  #mailbox virtual/All {
  #  special_use = \All
  #}

  # If you have a virtual &quot;Flagged&quot; mailbox:
  #mailbox virtual/Flagged {
  #  special_use = \Flagged
  #}
}

restart dovecot service

systemctl restart dovecot.service

now if we open our mail client, thunderbird, we should see a list of new folders

imap folders

after all those steps we can enable sieve plugin

we will create a sieve global filter

cd /var/vmail

mkdir sieve

vim globalfilter.sieve

fill file with this content

require "fileinto";
  if exists "X-Spam-Flag" {
          if header :contains "X-Spam-Flag" "NO" {
          } else {
          fileinto "Junk";      
          stop;
      }
  }
  if header :contains "subject" ["***SPAM***"] {
    fileinto "Junk";
    stop;
  }

chown -R vmail:mail /var/vmail/sieve

we need to enable sieve services in dovecot

vim /etc/dovecot/conf.d/20-managesieve.conf


##
## ManageSieve specific settings
##

# Uncomment to enable managesieve protocol:
#protocols = $protocols sieve

# Service definitions

service managesieve-login {
  inet_listener sieve {
    port = 4190
  }

  #inet_listener sieve_deprecated {
  #  port = 2000
  #}

  # Number of connections to handle before starting a new process. Typically
  # the only useful values are 0 (unlimited) or 1. 1 is more secure, but 0
  # is faster. <doc/wiki/LoginProcess.txt>

  service_count = 1

  # Number of processes to always keep waiting for more connections.
  process_min_avail = 0

  # If you set service_count=0, you probably need to grow this.
  vsz_limit = 64M
}

service managesieve {
  # Max. number of ManageSieve processes (connections)
  #process_limit = 1024
}

# Service configuration

protocol sieve {
  # Maximum ManageSieve command line length in bytes. ManageSieve usually does
  # not involve overly long command lines, so this setting will not normally
  # need adjustment
  managesieve_max_line_length = 65536

  # Maximum number of ManageSieve connections allowed for a user from each IP
  # address.
  # NOTE: The username is compared case-sensitively.
  #mail_max_userip_connections = 10

  # Space separated list of plugins to load (none known to be useful so far).
  # Do NOT try to load IMAP plugins here.
  #mail_plugins =

  # MANAGESIEVE logout format string:
  #  %i - total number of bytes read from client
  #  %o - total number of bytes sent to client
  #managesieve_logout_format = bytes=%i/%o

  # To fool ManageSieve clients that are focused on CMU's timesieved you can
  # specify the IMPLEMENTATION capability that Dovecot reports to clients.
  # For example: 'Cyrus timsieved v2.2.13'
  managesieve_implementation_string = Dovecot Pigeonhole

  # Explicitly specify the SIEVE and NOTIFY capability reported by the server
  # before login. If left unassigned these will be reported dynamically
  # according to what the Sieve interpreter supports by default (after login
  # this may differ depending on the user).
  #managesieve_sieve_capability =
  #managesieve_notify_capability =

  # The maximum number of compile errors that are returned to the client upon
  # script upload or script verification.
  managesieve_max_compile_errors = 5

  # Refer to 90-sieve.conf for script quota configuration and configuration of
  # Sieve execution limits.
}

vim /etc/dovecot/conf.d/90-plugin.conf


plugin {
  #setting_name = value
  sieve_global_path = /var/vmail/sieve/globalfilter.sieve
  sieve_max_script_size = 1M
}

local delivery should use sieve

vim /etc/dovecot/conf.d/20-lmtp.conf


protocol lmtp {
  # Space separated list of plugins to load (default is global mail_plugins).
  postmaster_address =  postmaster@yourdomain.com
  mail_plugins = $mail_plugins sieve
}

at this point we should restart dovecot to apply these changues

systemctl restart dovecot.service

check service status if something is bad

systemctl status dovecot.service

now you can send a gtube string to yourself, it should appear in junk folder


May 12 12:01:07 mail postfix/submission/smtpd[12410]: connect from yourcomputer[yourip]
May 12 12:01:07 mail postfix/submission/smtpd[12410]: 8D6F310095C: client=XEON.cafeingles[yourip], sasl_method=PLAIN, sasl_username=destination@domain.com
May 12 12:01:07 mail postfix/cleanup[12420]: 8D6F310095C: message-id=<5551CF63.8070307@yourfqdnsourcedomain.com>
May 12 12:01:07 mail postfix/qmgr[1977]: 8D6F310095C: from=<destination@domain.com>, size=629, nrcpt=1 (queue active)
May 12 12:01:07 mail postfix/submission/smtpd[12410]: disconnect from XEON.cafeingles[yourip]
May 12 12:01:07 mail amavis[2763]: (02763-08) NOTICE: reconnecting in response to: err=2006, HY000, DBD::mysql::st execute failed: MySQL server has gone away at (eval 129) line 172.
May 12 12:01:08 mail postfix/smtpd[12427]: connect from localhost[127.0.0.1]
May 12 12:01:08 mail postfix/smtpd[12427]: 74AB1100960: client=localhost[127.0.0.1]
May 12 12:01:08 mail postfix/cleanup[12420]: 74AB1100960: message-id=<5551CF63.8070307@yourfqdnsourcedomain.com>
May 12 12:01:08 mail postfix/qmgr[1977]: 74AB1100960: from=<destination@domain.com>, size=1395, nrcpt=1 (queue active)
May 12 12:01:08 mail postfix/smtpd[12427]: disconnect from localhost[127.0.0.1]
May 12 12:01:08 mail amavis[2763]: (02763-08) Passed SPAM {RelayedTaggedInternal,Quarantined}, MYNETS LOCAL [yourip]:36125 <destination@domain.com> -> <destination@domain.com>, Queue-ID: 8D6F310095C, Message-ID: <5551CF63.8070307@yourfqdnsourcedomain.com>, mail_id: PxRBJkjebYHJ, Hits: 999.001, size: 629, queued_as: 74AB1100960, 885 ms
May 12 12:01:08 mail postfix/smtp[12421]: 8D6F310095C: to=<destination@domain.com>, relay=127.0.0.1[127.0.0.1]:10024, delay=0.99, delays=0.04/0.03/0.02/0.89, dsn=2.0.0, status=sent (250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as 74AB1100960)
May 12 12:01:08 mail postfix/qmgr[1977]: 8D6F310095C: removed
May 12 12:01:08 mail dovecot: lmtp(12429): Connect from local
May 12 12:01:08 mail dovecot: lmtp(12429, destination@domain.com): UOvhIGTPUVWNMAAAiaI7Ow: sieve: msgid=<5551CF63.8070307@yourfqdnsourcedomain.com>: stored mail into mailbox 'Junk'
May 12 12:01:08 mail postfix/lmtp[12428]: 74AB1100960: to=<destination@domain.com>, relay=mail.yourfqdn.com[private/dovecot-lmtp], delay=0.1, delays=0.01/0.03/0.03/0.02, dsn=2.0.0, status=sent (250 2.0.0 <destination@domain.com> UOvhIGTPUVWNMAAAiaI7Ow Saved)
May 12 12:01:08 mail postfix/qmgr[1977]: 74AB1100960: removed
May 12 12:01:08 mail dovecot: lmtp(12429): Disconnect from local: Successful quit

and your mail client should show a new mail in junk folder

spam in junk folder

Step 36: Training spamassasin

Our detected spam travels to junk folder, but if forget to train spamassasin we will get a lot of spam in our Inbox folder or false positives in our Junk folder.

To avoid this we can launch sa-learn command but do this by hand is a tedious work. Good sysadmins automatize these task, I make a small script in python, my first python script, to launch sa-learn automatically.

This script will scan each mailbox and check if user has created an extra imap folder, to ignore pop3 only users, adding all mail in junk folder as spam and rest of folders as ham mail.

I created a project in github if you want to colaborate I will accept all help

https://github.com/luzemail/spamAssasingTraining

to add this script to our server we will execute a set of commands

 

cd /var/vmail

wget https://raw.githubusercontent.com/luzemail/spamAssasingTraining/master/trainspamassasin.py

chmod +x trainspamassasin.py

now we will add a crontab line to execute this script all days

vim /etc/crontab

add this line


0  0  *  *  * vmail       /var/vmail/trainspamassasin.py

adding a little of python magic helps to forget about what is learning spamassasin.

A small trick to start this is tell to our user that they should create a folder called nospam or whatever you prefer and recommend  users to move false posivitives to this folder and undetected spam to junk folder.

This script scans all mail folders in account and ads all mail as ham except junk folder which is added as spam. You should need to change this behavior feel free to modify this script and colaborate.

Step 37:Enabling greylisting (optional)

One technique to avoid spam is use a greylisting, basically when we receive a mail for first time our mailserver will answer with an internal error forcing to sender, if senders server is well configures it will try in a few minutes to deliver message again and it will be acepted. Spamers doesn’t resend emails they simply forget our mailserver.

So using a greylisting adds delay receiving mails or they can be undelivered because another server isn’t well configured.

first we need to install postgrey

yum install postgrey

postgrey works as a daemon we need to activate it

systemctl start postgrey.service

and enable service

systemctl enable postgrey.service

we can check postgrey service status running

systemctl status postgrey.service

we should get an output like this


postgrey.service - Postfix Greylisting Service
Loaded: loaded (/usr/lib/systemd/system/postgrey.service; disabled)
Active: active (running) since Sat 2015-05-23 15:35:24 CEST; 13s ago
Docs: man:postgrey(8)
Process: 8176 ExecStart=/usr/sbin/postgrey --unix=/var/spool/postfix/postgrey/socket --pidfile=/var/run/postgrey.pid --group=postgrey --user=postgrey --greylist-text=Greylisted for %%s seconds --daemonize $POSTGREY_OPTS (code=exited, status=0/SUCCESS)
Process: 8173 ExecStartPre=/bin/rm -f /var/run/postgrey.pid (code=exited, status=0/SUCCESS)
Main PID: 8177 (/usr/sbin/postg)
CGroup: /system.slice/postgrey.service
└─8177 /usr/sbin/postgrey --unix=/var/spool/postfix/postgrey/socket --pidfile=/var/run/postgrey.pid --group=postgrey --user=postgrey --greylist-text=Greylisted for %s seconds --daemonize --delay=60...

now we need to link postgrey with postfix

just edit postfix config file

vim /etc/postfix/main.cf

and append these lines


smtpd_recipient_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
check_policy_service unix:/var/spool/postfix/postgrey/socket

and restart  postfix service

 systemctl restart postfix.service

if you need to modify postgrey behavior you can use these files:

  • /etc/postfix/postgrey_whitelist_clients
  • /etc/postfix/postgrey_whitelist_recipients
  • /etc/postfix/postgrey_whitelist_clients.local

 

Step 38: Configuring smtpd_recipient_restrictions

Like greylisting we can add some restrictions when receiving email to avoid receive unsolicited mail.

we can add these restriction to our smtpd_sender_restrictions line

  • reject_unknown_address –> mails without from
  • reject_unknown_sender_domain –> no know sender
  • reject_invalid_hostname –> when a server make helo with a malformed hostname
  • reject_unknown_recipient_domain –> If postfix is not final distination for recipient domain
  • reject_unauth_pipelining –> stops mail from bulk mail software that doesn’t comply ESMTP command pipelining

finally we can use RBL’s, Real time Blackhole lists is a list of know spammers ips that will be rejected by postfix

command is basically


reject_rbl_client server1,

reject_rbl_client server2,

....,

reject_rbl_client servern,

permit

this will help you to stop a lot of spam and free system resources.

here you get a list of rbls http://en.wikipedia.org/wiki/Comparison_of_DNS_blacklists

here you have an example configuration

vim /etc/postfix/main.cf


smtpd_recipient_restrictions =
reject_invalid_hostname,
reject_unknown_recipient_domain,
reject_unauth_pipelining,
permit_mynetworks,
reject_unauth_destination,
permit_sasl_authenticated,
check_policy_service unix:/var/spool/postfix/postgrey/socket,
reject_rbl_client zen.spamhaus.org,
reject_rbl_client bl.spamcop.net,
reject_rbl_client dnsbl.sorbs.net,
reject_rbl_client cbl.abuseat.org,
reject_rbl_client b.barracudacentral.org,
reject_rbl_client dnsbl-1.uceprotect.net,
permit

and finally restart postfix

 systemctl restart postfix.service

Step 39: Enabling spf

SPF (Sender Policy Framework) is basically a TXT dns record that indicates what ips and/or domains are authorized to send email.

A minimal spf record should be like this


spf=v1 mx -all

if your webserver send emails too


spf=v1 a mx -all

if you want to add an ip


spf=v1 a mx ip4:255.255.255.255 -all

 

in function of what servers will be generating email you should configure your spf records.

Maintain a spf record in your domains is important to avoid that spammers use your domain as as sender part of domain

Step 40: Enabling DKIM

DKIM, DomainKeys Identified Mail, helps to verify that a received email is sender from a valid mail server. Basically is a digital signature that can be verified using a public key published into senders domain dns record.

We need to generate a public and private key for each domain.

basically for each domain we need to execute a command like this

opendkim-genkey –bits=4096 –domain=example.com –selector=example.com –restrict

be careful with your dns provider 4096 bits could generate a long public key that couldn’t fit in your txt box, in this case you can reduce your key length to 2048 or changue dns provider

for generate these keys we should follow these steps:

go to opendkim keys dir

cd /etc/opendkim/keys

generate one keypair for each domain

opendkim-genkey –bits=4096 –domain=example.com –selector=example.com –restrict

this command will create two files

  • domain.com.private your private key
  • domain.com.txt contains public part in dns record format

Note: your should renew your keys every year.

we will to changue private keys ownership

 chown opendkim:opendkim /etc/opendkim/keys/*.private

we need to configure opendkim edit config file

vim /etc/opendkim.conf

options should be like these

PidFile    /var/run/opendkim/opendkim.pid
Mode    sv
Syslog    yes
SyslogSuccess    yes
LogWhy    yes
UserID    opendkim:opendkim
Socket    inet:8891@localhost
Umask    002
Canonicalization    relaxed/relaxed
Selector    default
MinimumKeyBits 1024
KeyTable    refile:/etc/opendkim/KeyTable
SigningTable    refile:/etc/opendkim/SigningTable
ExternalIgnoreList    refile:/etc/opendkim/TrustedHosts
InternalHosts    refile:/etc/opendkim/TrustedHosts

OpenDKim needs a list of host whose mail should signed by Opendkim-

vim /etc/opendkim/TrustedHosts

content should be like these


127.0.0.1
::1
mail.yourdomain.com

mail.yourdomain.com should be your hostname

all mail originated from these host will be signed otherwise is ignored, if you have a relay server you should add these ip.

We will host several domains in our configuration, OpenDkim needs to know a list of domains and keys to sign.

vim /etc/opendkim/KeyTable

we need to link each domain with one key adding lines like this


default._domainkey.domain1.com domain1.com:default:/etc/opendkim/keys/domain1.com.private
default._domainkey.domain2.com domain2.com:default:/etc/opendkim/keys/domain2.com.private

using these list opendkim knows relations between domains and private keys.

now opendkim needs to know relation between mail adress and domains whe should configure SigningTable file

vim /etc/opendkim/SigningTable

if we want to sign all email address we shoild add a line like these


*@domain1.com default._domainkey.domain1.com

*@domain2.com default._domainkey.domain2.com

complete with all your domains and restart opendkim

systemctl restart opendkim.service

now you can check opendkim service status

 systemctl status opendkim.service

output should be like these


opendkim.service - DomainKeys Identified Mail (DKIM) Milter
Loaded: loaded (/usr/lib/systemd/system/opendkim.service; enabled)
Active: active (running) since Wed 2015-05-27 16:26:39 CEST; 1s ago
Docs: man:opendkim(8)
man:opendkim.conf(5)
man:opendkim-genkey(8)
man:opendkim-genzone(8)
man:opendkim-testadsp(8)
man:opendkim-testkey
http://www.opendkim.org/docs.html
Process: 23824 ExecStart=/usr/sbin/opendkim $OPTIONS (code=exited, status=0/SUCCESS)
Main PID: 23825 (opendkim)
CGroup: /system.slice/opendkim.service
└─23825 /usr/sbin/opendkim -x /etc/opendkim.conf -P /var/run/opendkim/opendkim.pid

May 27 16:26:39 mail.yourdomain.com systemd[1]: Started DomainKeys Identified Mail (DKIM) Milter.
May 27 16:26:39 mail.yourdomain.com opendkim[23825]: OpenDKIM Filter v2.10.1 starting (args: -x /etc/opendkim.conf -P /var/run/opendkim/opendkim.pid)

At this point we have a opendkim daemon working we need to integrate opendkim with postfix

we need to open postfix main config file

vim /etc/postfix/main.cf

and finally append these lines


milter_default_action = accept
smtpd_milters = inet:127.0.0.1:8891

and restart postfix to see these changues applied

systemctl restart postfix.service

Finally the most important step is publish your public keys in each domain

for example for a file example.com.txt

whit these content


example.com._domainkey    IN    TXT    ( "v=DKIM1; k=rsa; s=email; "
"p=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzGqMtyZwjFzNsvFVSnsPvyHcsAGpqglHcKtRSIGKyzbAigp18LARojk5UlTAHmED46THNbo8q6IS/fysaGBBR97oZLK2/8Vl6FOc0hdU1alEaAr/MpI+0MquCqjaAFdVWKHtGRthCzJ0HuDqbQFBnc3eUOe8RxkYWwxyKs+Tze/FCQ/mso/Gm/Zp/z7v8jTRbaIZtKRB+1oBrc"
"L2WuFEOkZyxCEq0gYLNV2AYcfIdvBXqHsHLeeEZMEbxIHOQGg3fINd3bbP2hxWtlnCrIGFQxdkOH4hx75wfZ+QRWh0d7jmW4c0Jnwvw0HLIJSzfS1kOUCPSq+MR7h4bT17sfWMXSvwqWca1R0eVRZdkuuBBeK5897vvRCA/44WMhv2GeWM6uHrRLy8Z8CAoCVd4FrZ6UQ+eQ2SjJaObInWbXC0/VRNHLRHVqW3pZROH3tYWAD39EUKpAWO"
"vr6YfwD/7PeM/283LLDuQceqIVg4kYcNeZR9iL65sLXWkHPb8rJeGFqQhUC+Cvm1HkhLbm5m/OHl41EF+dfLDT+c8EpCT3khSebKvwHFbd2l6XQhy+zQSvQtPSgtWJ2mgq4FIHFBJFdQRUv/KQdhDDapYkcM80DyyRnzXv4erfNcC//LaI4LmJBd36KTNKWUbrBibxOWye3ZheiaPGYrdwrp/X0rPXnnju8CAwEAAQ==" )  ; ----- DKIM key example.com for example.com

you need to add a _domainkey txt record whit this text


v=DKIM1; k=rsa; s=email; p=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzGqMtyZwjFzNsvFVSnsPvyHcsAGpqglHcKtRSIGKyzbAigp18LARojk5UlTAHmED46THNbo8q6IS/fysaGBBR97oZLK2/8Vl6FOc0hdU1alEaAr/MpI+0MquCqjaAFdVWKHtGRthCzJ0HuDqbQFBnc3eUOe8RxkYWwxyKs+Tze/FCQ/mso/Gm/Zp/z7v8jTRbaIZtKRB+1oBrcL2WuFEOkZyxCEq0gYLNV2AYcfIdvBXqHsHLeeEZMEbxIHOQGg3fINd3bbP2hxWtlnCrIGFQxdkOH4hx75wfZ+QRWh0d7jmW4c0Jnwvw0HLIJSzfS1kOUCPSq+MR7h4bT17sfWMXSvwqWca1R0eVRZdkuuBBeK5897vvRCA/44WMhv2GeWM6uHrRLy8Z8CAoCVd4FrZ6UQ+eQ2SjJaObInWbXC0/VRNHLRHVqW3pZROH3tYWAD39EUKpAWOr6YfwD/7PeM/283LLDuQceqIVg4kYcNeZR9iL65sLXWkHPb8rJeGFqQhUC+Cvm1HkhLbm5m/OHl41EF+dfLDT+c8EpCT3khSebKvwHFbd2l6XQhy+zQSvQtPSgtWJ2mgq4FIHFBJFdQRUv/KQdhDDapYkcM80DyyRnzXv4erfNcC//LaI4LmJBd36KTNKWUbrBibxOWye3ZheiaPGYrdwrp/X0rPXnnju8CAwEAAQ=

Step 41: Configuring DMARC records for each domain

Basically Dmarc is a method that joins SPF and DKIM defining what to do when a received mail doesn’t pass DKIM or SPF

we need to create a DNS TXT record like _dmarc.your_domain.com

with this text

v=DMARC1 p=pvalue optinalparameter1=value optinalparameter2=value …

Mandatory Parameters

Policy of domain
p= pvalues
Defines policy of domain.

pvalues are:

  • none ->The Domain Owner requests no specific action be taken regarding delivery of messages
  • quarantine -> if check dkim and/or spf fails, Depending on the capabilities of the Mail Receiver, this can mean “place into spam folder”, “scrutinize with additional intensity”, and/or “flag as suspicious”.
  • reject  -> check dkim and/or spf fails Mail Receiver will reject mail during smtp transaction

Optional Parameters

Policy of Subdomains

sp= spvalues

spvalues are:

  • none ->The Domain Owner requests no specific action be taken regarding delivery of messages
  • quarantine -> if check dkim and/or spf fails, Depending on the capabilities of the Mail Receiver, this can mean “place into spam folder”, “scrutinize with additional intensity”, and/or “flag as suspicious”.
  • reject  -> check dkim and/or spf fails Mail Receiver will reject mail during smtp transaction

DKIM identifier alignment

adkim= dkimvalues

dkimvalues are:

s -> strict, sender domain name must be the same that d=name in DKIM mail headers else fails
r-> relaxed, if sender domain is a subdomain will pass

if omitted adkim tag in domain txt default value is r (relaxed)

SPF-authenticated Identifiers

aspf= aspfvalues

aspfvalues are:

s -> strict, MAIL FROM command in SMTP and from:header in email must mach
r-> relaxed, if sender domain is a subdomain will pass

if omitted aspf tag in domain txt default value is r (relaxed)

Percentage of messages where DMARC mechanism is to be applied

pct=pctvalue

pctvalue= a number between 0 and 100

Interval between Aggregaye reports
ri = rivalue

rivalue= number of seconds between reports default 86400 (24 hours)

Reporting URL of aggregate reports

rua:mailto:address@domain.com

Each server will send an aggregate feedback to this adress

if domain lies outside sending zone you must validate, use a web searcher

Reporting URL of aggregate feedback

ruf:mailto:address@domain.com

Used for forensic reports about messagest that fail spf and/or dkim evaluation

if domain lies outside sending zone you must validate, use a web searcher

here you have a example of dmarc record


v=DMARC1; p=quarantine; pct=100 rua=mailto:dmarc.rua@customddomain.com

DMARC is not a point and shoot implementation you should follow a sequence like this in function of your mail volume:

  1.     Monitor all.
  2.    Quarantine 1%.
  3.     Quarantine 5%.
  4.     Quarantine 10%.
  5.   Quarantine 25%.
  6.   Quarantine 50%.
  7.   Quarantine all.
  8.   Reject 1%.
  9.   Reject 5%.
  10.   Reject 10%.
  11.   Reject 25%.
  12.   Reject 50%.
  13.   Reject all.

 

Step 42: Enabling DMARC suport in postfix

Receive reports from DMARC helps to verify our configurations, configure a mailserver that send DMARC reports to another sysadmins makes you a good sysadmin and a better person :-P.

To make this we need to configure openDMARC

Actually in centos 7 openDMARC needs libspf2 that is avaliable in testing repo.

if you try to install opendmarc running this command

yum install opendmarc

and you get an output like these


---> Package libopendmarc.x86_64 0:1.3.1-4.el7 will be updated
---> Package libopendmarc.x86_64 0:1.3.1-13.el7 will be an update
--> Processing Dependency: libspf2.so.2()(64bit) for package: libopendmarc-1.3.1-13.el7.x86_64
---> Package opendmarc.x86_64 0:1.3.1-4.el7 will be updated
---> Package opendmarc.x86_64 0:1.3.1-13.el7 will be an update
--> Processing Dependency: libspf2.so.2()(64bit) for package: opendmarc-1.3.1-13.el7.x86_64
--> Finished Dependency Resolution
Error: Package: libopendmarc-1.3.1-13.el7.x86_64 (epel)
Requires: libspf2.so.2()(64bit)
Error: Package: opendmarc-1.3.1-13.el7.x86_64 (epel)
Requires: libspf2.so.2()(64bit)
You could try using --skip-broken to work around the problem
You could try running: rpm -Va --nofiles --nodigest

run this command

yum install opendmarc –enablerepo=epel-testing

OpenDMARK will need a MariaDB database  in order to store all info needed to generate reports.

We will create this database as first step

  mysql -u root -p

CREATE DATABASE opendmarc;
CREATE USER 'dmarc'@'localhost' IDENTIFIED BY 'dmarcdatabaseuserpassword';
GRANT ALL PRIVILEGES ON `opendmarc` . * TO 'dmarc'@'localhost';
FLUSH PRIVILEGES;
quit;

once we’ve created database and user, next step is populate tables.

mysql -u dmarc -p opendmarc < /usr/share/doc/opendmarc-1.3.1/schema.mysql

should be easy now we can configure opendmarc

vim /etc/opendmarc.conf

replace line 15 to have these aspect


AuthservID HOSTNAME

now we will configure opendmarc service


systemctl enable opendmarc
systemctl start opendmarc

next step is integrate opendmarc service with postfix

vim /etc/postfix/main.cf

just modify smtpd_milters values


smtpd_milters = inet:127.0.0.1:8891 , inet:127.0.0.1:8893
non_smtpd_milters = $smtpd_milters

now you can restart postfix

systemctl restart postfix.service

some domains can use aname.domain.com instead top-level domain this can be a problem during dmarc verification, Mozilla maintais a database calle Public Suffix list that can be added to our opendmarc server to make it more effective

just execute these commands

/usr/bin/wget –no-check-certificate -q -N -P /etc/opendmarc https://publicsuffix.org/list/effective_tld_names.dat
chown opendmarc:opendmarc /etc/opendmarc/effective_tld_names.dat

we should maintain this database updated we can add a cron job to do this job

just edit crontab

vim /etc/crontab

and append these line


@weekly /usr/bin/wget --no-check-certificate -q -N -P /etc/opendmarc https://publicsuffix.org/list/effective_tld_names.dat #Get latest effective_tld_names for OpenDMARC

Opendmarc needs know where Pubblic Suffix List is located

vim /etc/opendmarc.conf

line 221 should be like this


PublicSuffixList /etc/opendmarc/effective_tld_names.dat

we will restart opendmarc service to apply configuration changes

systemctl restart opendmarc

now we will configure opendmarc to maintain a history file

vim /etc/opendmarc.conf

uncomment line 166


HistoryFile /var/spool/opendmarc/opendmarc.dat

and restart opendmarc again

systemctl restart opendmarc

now we will process this file with a script every hour

vim /etc/cron.hourly/processdmarc.cron

it should have this content.

Remenber put your dmarc password in dbpass variable

and correct domain settings in /usr/sbin/opendmarc-reports command

#!/bin/bash
# Imports data from OpenDMARC's opendmarc.dat file into a local MySQL DB
# and sends DMARC failure reports to domain owners.
# Based on a script from Hamzah Khan (http://blog.hamzahkhan.com/)

set -e

# Database and History File Info
DBHOST='localhost'
DBUSER='dmarc'
DBPASS='yourpassword'
DBNAME='opendmarc'
HISTDIR='/var/spool/opendmarc'
HISTFILE='opendmarc'

# Make sure history file exists
touch ${HISTDIR}/${HISTFILE}.dat

# Move history file temp dir for processing
mv ${HISTDIR}/${HISTFILE}.dat /tmp/${HISTFILE}.$$

# Import temp history file data and send reports
/usr/sbin/opendmarc-import -dbhost=${DBHOST} -dbuser=${DBUSER} -dbpasswd=${DBPASS} -dbname=${DBNAME} -verbose < /tmp/${HISTFILE}.$$
/usr/sbin/opendmarc-reports -dbhost=${DBHOST} -dbuser=${DBUSER} -dbpasswd=${DBPASS} -dbname=${DBNAME} -verbose -interval=86400 -report-email 'postmaster@cheatcodes.com' -report-org 'CheatCodes.com'
/usr/sbin/opendmarc-expire -dbhost=${DBHOST} -dbuser=${DBUSER} -dbpasswd=${DBPASS} -dbname=${DBNAME} -verbose

# Delete temp history file
rm -rf /tmp/${HISTFILE}.$$

finaly we will make this file executable

chmod +x /etc/cron.hourly/processdmarc.cron

Now your postfix has dmarc support and every hour will send necesary reports

 

Step 43: Configuring Roundcube webmail

Smartphones are a inclredible good technology but sometimes we don’t have signal and we need to check our email, using roundcube we provide a webmail infrastructure to our users, where they can read and send emails using a web browser.

In order to configure roundcube we need to create a database, yes another one, using these  commands

    mysql -u root -p

CREATE DATABASE roundcubemail;
CREATE USER 'roundcube'@'localhost' IDENTIFIED BY 'a_secure_password';
GRANT ALL PRIVILEGES ON `roundcubemail` . * TO 'roundcube'@'localhost';
FLUSH PRIVILEGES;
quit;
 

next step is populate tables

 mysql -uroundcube -p roundcube </usr/share/roundcubemail/SQL/mysql.initial.sql

we also need to enable some selinux options for our case

setsebool -P httpd_can_sendmail on

now we need to configure roundcubemail to access database and know were are located the mailservers

we will move example config file to use as template

mv /etc/roundcubemail/config.inc.php.sample /etc/roundcubemail/config.inc.ph

we need to modify some values


$config['db_dsnw'] = 'mysql://roundcube:your_password@localhost/roundcubemail';

$config['default_host'] = 'tls://yourfqdndomain.com';

$config['smtp_server'] = 'tls://yourfqdndomain.com';

$config['imap_auth_type'] = 'login';
$config['smtp_auth_type'] = 'login';
$config['smtp_port'] = 587;

$config['smtp_user'] = '%u';

$config['smtp_pass'] = '%p';

$config['des_key'] = 'PUTHEREA24CHARACTERRANDOMSTRING';

 

next we need to generate php-fpm pool to server roundcubemail config

we will create a dir for store sessions

mkdir /var/lib/php/yourfqdndomain.com

adjust group ownership

chown root:apache /var/lib/php/yourfqdndomain.com

adjust group permissions

chmod 770 /var/lib/php/yourfqdndomain.com

and set a valid selinux labeling

chcon -R -t httpd_var_run_t /var/lib/php/yourfqdndomain.com

now we can create a valid  php-fpm pool

vim /etc/php-fpm.d/yourfqdndomain.com.conf

adapt this content


[yourfqdndomain]
listen = /var/run/php-fpm/yourfqdndomain.socket
listen.allowed_clients = 127.0.0.1
user = apache
group = apache
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 35
slowlog = /var/log/php-fpm/yourfqdndomain.slow.log
rlimit_files = 1024
rlimit_core = 0
chdir = /usr/share/roundcubemail
php_flag[display_errors] = off
php_admin_value[error_log] = /var/log/php-fpm/yourfqdndomain-error.log
php_admin_flag[log_errors] = on
php_admin_value[memory_limit] = 128M
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/yourfqdndomain.com

once edited we can restart php-fpm service to load new configuration

systemctl restart php-fpm.service

check if any error appears reading this command output

 systemctl status php-fpm.service

next step is create a nginx record and certificate

nginx doesn’t have intermediate certificate config option we need to append pulic key with intermidiate certificate in one file executing a command like this.

cat publiccertificate.crt intermediatecertificate.crt > bundle_certificate.crt

Order of cat command is important public certificate will be at the beginning otherwise you will get ssl errors in nginx.

finally we can create our nginx config file

vim /etc/nginx/conf.d/yourfqdndomain.conf

and adapt these template


server {

listen 80;
server_name yourfqdndomain.com;
error_log  /var/log/nginx/yourfqdndomain.error.log warn;
access_log  /var/log/nginx/yourfqdndomain.access.log;

return 301 https://$server_name$request_uri; # enforce https

}

server {

listen          443 ssl;
server_name    yourfqdndomain;

error_log  /var/log/nginx/yourfqdndomain.secure.error.log warn;
access_log  /var/log/nginx/yourfqdndomain.secure.access.log;

root            /usr/share/roundcubemail;
index           index.php;
charset         utf-8;

## SSL settings
ssl_certificate           /etc/pki/tls/certs/yourfqdndomain.bundle.crt;
ssl_certificate_key       /etc/pki/tls/private/yourfqdndomain.key;

ssl_protocols             TLSv1.2;
ssl_ciphers               "EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4";
ssl_prefer_server_ciphers on;
ssl_session_cache         shared:SSL:10m;
ssl_session_timeout       10m;
ssl_ecdh_curve            secp521r1;

add_header Strict-Transport-Security max-age=31536000;
# add_header X-Frame-Options DENY;

# auth_basic "Restricted area";
# auth_basic_user_file /etc/nginx/passwd;

location / {
try_files $uri $uri/ index.php;
}

location ~/(plugins/enigma/home|bin|installer) {
      deny all;
      return 403;
}

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

}

now we should restart nginx

systemctl restart nginx.service

now we can open a web browser write our fqdn and check our roundcube webpage

roundcube mail loginlog with and account and check if everything is working, send an email respond create a folder …

Now you have a working webmail to your users 😛 .

Step 44: Protecting against brute force attacks using fail2ban

At this point we are filtering spam and using a huge number of antispam technologies.  Unfortunately your mailserver will be exposed to internet and a lot of automatic tool will try get your passwords using bruteforce attacks.

To mitigate these actions we will use fail2ban, fail2ban reads system logs and block  temporaly a ip making a bruteforce attacks, generally this means that we attackers avoid our server because temporally block makes bruteforce attack imposible

To make this fail2ban read logs and counts invalid logins when a number of invalid logins is detected fail2ban adds a rule to firewalld blocking source ip of invalid logins during a penalty time, typical brute force attacks abandom because they can’t test more

first we need to enable several triggers in fail2ban

modifiy needed lines to sections look like these

vim /etc/fail2ban/jail.conf


...

[roundcube-auth]
enabled = true
port     = http,https
logpath  = /var/log/roundcubemail/errors

....

[postfix]
enabled = true
port     = smtp,465,submission
logpath  = %(postfix_log)s

....

[dovecot]
enabled = true
port    = pop3,pop3s,imap,imaps,submission,465,sieve
logpath = %(dovecot_log)s

...

[sieve]
enabled = true
port   = smtp,465,submission
logpath = %(dovecot_log)s

now we need to enable fail2ban service

systemctl enable fail2ban.service

and start service

 systemctl start fail2ban.service

Step 45: Enable imap quota

Some users will send a lot of attachments , and they need to know how many free space leave in their mailbox, we will enable imap_quota plugin to avoid support call about that they can’t receive or send mails with titanic attachments.

Responsive of inform about how many free space left in their mailbox is dovecot, we need to enable some plugins.

vim /etc/dovecot/conf.d/10-mail.conf

line 208 should be


mail_plugins = $mail_plugins quota

vim /etc/dovecot/conf.d/20-imap.conf

line 56 should be


mail_plugins = $mail_plugins imap_quota

finally

vim  /etc/dovecot/conf.d/90-quota.conf

line 68 should look like these


quota = maildir:User quota

Now we need reboot dovecot service

 systemctl restart dovecot.service

 

congrats now you should have a funcional mailserver running.

 

References:

http://www.campworld.net/thewiki/pmwiki.php/LinuxServersCentOS/Cent6VirtMailServer

http://dokuwiki.nausch.org/doku.php/centos:mail_c7:spam_7

https://qmail.jms1.net/test-auth.shtml

http://en.linuxreviews.org/HOWTO_Stop_spam_using_Postfix

https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/

https://www.ssllabs.com/downloads/SSL_TLS_Deployment_Best_Practices.pdf

https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Security_Guide/sec-Hardening_TLS_Configuration.html

https://www.df.eu/de/service/df-faq/cloudserver/anleitungen/spam-und-virenschutz-mit-postfix-debian/

https://z0z0.me/2014/10/26/install-postfix-dovecot-auth-tls-mysql-postfixadmin-spamassassin-and-clamav-on-centos7/

https://www.2realities.com/blog/2014/02/13/secure-ssl-configuration-for-apache-postfix-dovecot/

https://bettercrypto.org/

https://wiki.gentoo.org/wiki/Complete_Virtual_Mail_Server

http://www.gentoo-wiki.info/Amavisd-new

http://www.iredmail.org/forum/topic3800-iredmail-support-localdomainsmaps-in-amavisdnew.html

http://gogs.info/books/debian-mail/chunked/antispam.amavis.html

http://www.nervous.it/2010/03/amavisd-and-per-user-spam-folder/#Howto

https://github.com/hardware/nginx-config/blob/master/virtual-hosts/https/postfixadmin

http://peketamin.hatenablog.jp/entry/2014/06/26/%28ubuntu_14_04%29_postfix_%E3%82%92%E5%A4%96%E9%83%A8%E3%81%8B%E3%82%89%E6%8E%A5%E7%B6%9A%E5%87%BA%E6%9D%A5%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%99%E3%82%8B_%E2%86%92_dovecot_%E4%BD%BF%E3%81%A3

https://community.rackspace.com/products/f/43/t/51

https://bugzilla.redhat.com/show_bug.cgi?id=1225596

http://www.zytrax.com/books/dns/ch9/dmarc.html

http://dmarc.org/draft-dmarc-base-00-01.txt

http://www.stevejenkins.com/blog/2015/03/installing-opendmarc-rpm-via-yum-with-postfix-or-sendmail-for-rhel-centos-fedora/

Contraseñas router EPC3928AD

Si R te cambia tu router por un EPC3928AD estas son las contraseñas de acceso

EPC3928AD

Sin aprovisionar, antes de que lo enchufes a R

  • usuario y contraseña en blanco

Aprovisionado, 45 minutos despues de que lo enchufes a R

  • usuario admin
  • contraseña: clientesR

Si lo quereis poner en modo bridge debereis de aprovisionarlo para que actualize el firmware.

Si tenias ip estatica, prepara el nombre del titular, en dni y los 6 ultimos digitos de la cuenta bancaria para verificar que eres tu el cliente

Recovering passwords from a windows 2003 server

Sometimes when a business decide to switch his computer maintenance to another company switched company rejects to give server passwords with or without good reason.

There’s a lot of ways of reset administrator password, but recover any of then can be better.

If you need to recover passwords from a windows 2003 server a easy way is shutdown the server and start a linux live CD like ubuntu.

If you can access to windows filesystem you can access to SAM data, a database with local passwords 😛 .

You only need to copy %SystemRoot%/system32/config directory to a flash memory or another storage device.

Install into another computer Ophcrack software. In my laptop running fedora 21 executeas root

dnf install ophcrack

Download XP rainbow tables from here http://ophcrack.sourceforge.net/tables.php

Open ophcrack

Click on Tables -> install

and load downloaded tables

ophcrack load tables

Now at load button select Encrypted SAM and open the folder %SystemRoot%/system32/config recovered using Linux liveCD

ophcrack main windowand finally click on Crack button

recovered passwordsOnly took half minute, literally in recover 13 of 14 passwords.

Enjoy

 

 

 

creating replacing and resizing mdadm Raid 1

Raid controller

Sometimes hardware Raid controllers are very expensive to fit in low budget solutions, when this happens you can use software raid, like mdadm.

Normally hard disks have a limited lifetime. To avoid disasters I replace hard disk every two years, at same time that means that new hard disk will come in a bigger capacity. I will simulate this workflow.

Unfortunately I’m not a rich engineer yet and need to simulate hard disk, if you want to donate some hard disk leave me a comment :-)

step 1 and 2 are for create virtual hard disk,

REMEMBER MAKE BACKUPS BEFORE DO DANGEROUS THINGS LIKE THESE

Step 1: Create virtual hard disk

Imagine that in a beginning we have a couple of two hard disk with a capacity of one terabyte (1HD and 2HD), and after two years  we acquired two new hard drives with a capacity of three terabyte (3HD and 4HD).

I will use gigabytes instead terabytes for time and capacity reasons

as root

  • cd
  • mkdir mdadmtesting
  • cd mdadmtesting
  • fallocate -l 1G 1HD.raw
  • fallocate -l 1G 2HD.raw
  • fallocate -l 3G 3HD.raw
  • fallocate -l 3G 4HD.raw

Step 2: Associate created files with loop devices

  • losetup /dev/loop0 /root/mdadmtesting/1HD.raw
  • losetup /dev/loop1 /root/mdadmtesting/2HD.raw
  • losetup /dev/loop2 /root/mdadmtesting/3HD.raw
  • losetup /dev/loop3 /root/mdadmtesting/4HD.raw

Step3: create a mdadm device in raid 1 mode

  •  mdadm –create –verbose /dev/md0 –level=1 –raid-devices=2 /dev/loop0 /dev/loop1
  • mkfs.ext4 /dev/md0

finally we need to mount new raid and make some files

  • mount /dev/md0 /mnt
  • cd /mnt
  • for i in {1..100}; do echo $i > $i; done

Step 4 Replace one hard disk

we need to mark one hard disk as fail to replace

  • mdadm –manage /dev/md0 –fail /dev/loop0

remove disk from array

  • mdadm –manage /dev/md0 –remove /dev/loop0

attach new hard disk

  • mdadm –manage /dev/md0 –add /dev/loop2

check raid status and wait until raid state is setted as clear and not

State : clean, degraded, recovering

  • mdadm –detail /dev/md0

Step 5: Replace second hard disk

  • mdadm –manage /dev/md0 –fail /dev/loop1
  • mdadm –manage /dev/md0 –remove /dev/loop1
  • mdadm –manage /dev/md0 –add /dev/loop3

wait until state is clean

  • mdadm –detail /dev/md0

Step 6 Grow raid device

At this moment we have removed our old 1Tb disk and they have been replaced with a new 3Tb drive but our raid size is 1Tb we need to grow it

  • mdadm –grow /dev/md0 –size=max

Step 7 Grow filesystem

Our raid size is 3Tb but our file system is still at 1Tb we need to resize it

  • resize2fs /dev/md0

and finally we have our mdadm raid with new drives and a lot of free space.

Enjoy

Centos 7 Backup MariaDB using MySQL-zrm

One common mistake when we configure a server is forgot run backups, No enough time and other excuses can convince you that make a backup of a new server is not a priority, but sometimes a hipervisor fails and recover data from your virtual machine is hard or impossible. Trust me i saw a lot of unrecoverable databases in development environments unrecoverable after a power outage or hardware fail.

There are a big set of possible ways to backup mysql databases, it depends of several factors like database size, number of databases, reliability …

This tutorial will covered a basic backup for a database server with a small number of small – medium size databases.

Suppose that you have a MariaDB, Percona or Mysql service running and secured,

1 step create a mysql backup user.

  • mysql -uroot -p
  • grant select, insert, update, create, drop, reload, shutdown, alter, super, lock tables, replication client on *.* to ‘zrmbackup’@’localhost’ identified by ‘pass123’;
  • flush PRIVILEGES;

verify permissions

  • show grants for ‘zrmbackup’@’localhost’;

 2 step install Mysql-zrm

yum install epel-release

yum install MySQL-zrm.noarch

3 Step create a backup dir

mkdir /var/backup

*trick in my case I mounted a nfs share in this directory.

4 Step configure Mysql-zrm

We need edit mysql-zrm config file

vim /etc/mysql-zrm/mysql-zrm.conf


#
# Template for Zmanda Recovery Manager for MySQL configuration file
#
# Global configuration file is /etc/mysql-zrm/mysql-zrm.conf
# The file should be copied to /etc/mysql-zrm/<backup set name>/mysql-zrm.conf
# if backup set specific modifications are required.
#
# MySQL ZRM configuration file describes the backup configuration for
# a backup set. This file is organized into five sections for convenience
# - Backup parameters,
# - Databases/tables that are part of backup set,
# - MySQL server parameters
# - ZRM parameters.
# - ZRM plugin parameters.
#
# For more information about Zmanda Recovery Manager for MySQL, please
# see mysql-zrm(1) and/or Administration manual at Zmanda Network.
#
#
# Any line starting with '#' are comments and will be ignored

#
# Backup parameters
#

# Backup comment. This is a text string which can be retrieved
# using the mysql-zrm-reporter(1) tool. You can store some notes
# about the backup set.
# This parameter is optional and has no defaults.
#comment=This is a comment

# Backup level. It can be full or incremental
# Use 0 for full and 1 for incremental backups
# This parameter is optional and default value is full backup.
#
backup-level=0

# Backup method
# Values can be "raw" or "logical". Logical backup are backups using
# mysqldump(1) tool
# This parameter is optional and default value is "raw".
#
backup-mode=logical

# Size of LVM snapshot. This parameter is optional and  is required only
# for "raw" backup-mode and if the MySQL database data are stored in
# LVM logical volumes.
# A size suffix of k for kilobyte, m for megabyte, g for gigabyte
# or t for terabyte
#
#lvm-snapshot=10M

# specifies the plugin for snapshot operations
#
#snapshot-plugin="/usr/share/mysql-zrm/plugins/lvm-snapshot.pl"

# Specifies the type of backup
# Values can be "regular" or "quick".
# Quick backup type uses the snapshot itself as the backup
# without copying the data from the snapshot volume
#backup-type=quick

# Directory to which backups are done. All backups are stored under this
# directory.  This parameter is optional and the default
# value is "/var/lib/mysql-zrm"
#
destination=/var/backup/database

# Specifies how long the backup should be retained. The value can be
# specified in days (suffix D), weeks (suffix: W), months (suffix: M) or
# years (suffix Y). 30 days in a month and 365 days in a year are assumed
# This parameter is optional and the default is the backups are retained
# forever.
#
retention-policy=1Y

# This parameter should be set to 1 if MySQL ZRM backups are being on done on a
# MySQL replication slave.
#replication=1

# This parameter should be set to 1 if backups should be compressed. If this
# parameter is set, gzip(1) command is used by default. If different
# compression algorithm should be used, it must be set in "compress-plugin"
# parameter. Default: There is no data compression.
compress=1

# This specifies the program to be used for compression. The "compression"
# parameter must be set for this parameter to be used. The compression
# command should also support -d option for uncompress backup images. If
# value is not specified then gzip(1) is used for compression.
#compress-plugin=/usr/bin/gzip

# This parameter should be set to 1 if backups should be encrypted.
# The "encrypt-plugin" parameter must be configured. Default: There is no
# data encryption.
#encrypt=1

# This parameter specifies that the program that should be used for
# backup data encryption. "decrypt-option" parameter should also be specified.
#encrypt-plugin="/usr/share/mysql-zrm/plugins/encrypt.pl"

# This specifies the option to be passed to the encryption
# program specified as "encrypt-plugin" parameter for decryption.
#decrypt-option="-d"

#
# Databases/Tables in the backup set
#
# One of the "all-databases" or "databases" or "tables"/"database" parameters
# should be specified. If none of the them are specified, "all-databases"
# is assumed.
#

# This parameter should be set to 1 if all databases are part of this backup set
#
all-databases=1

# List of databases that are part of this backup set. Multiple database
# names are separated by space character. This parameter is ignored if
# "all-databases" is set 1.
#
#databases=wikidb forums

# List of specific tables that are part of this backup set. This parameter
# should not be specified if all tables in the databases in "databases"
# parameter are part of the backup set. Multiple table names should be
# separated by space character. The database to which these tables belong
# to should be specified in "database" parameter.
#
#tables=text user page
#database="wikidb"

#
# The list of databases or tables that are excluded from the backup if the
# database name or table name matches the pattern. Wildcard characters *, ?,
# [, ] are supported. See mysql-zrm-backup man page for details
#
# exclude-pattern=<pattern>

# MySQL server parameters
#

# MySQL database user used for backup and recovery of the backup set.
# This parameter is optional. If this parameter is not specified, values from
# my.cnf configuration file.
#
user="zrmbackup"

# MySQL database user password.
# This parameter is optional. If this parameter is not specified, values from
# my.cnf configuration file or no password is used.
#
password="pass123"

# Fully qualified domain name of the MySQL server.
# This parameter is optional. If this parameter is not specified, values from
# my.cnf configuration file.
#
#host="localhost.company.com"

# Port to which the MySQL server is listening to. This parameter is optional
# and default value is 3306
#
#port=3306

#Name of Socket file that can be used for connecting to MySQL
#
#socket=/var/lib/mysql/mysql.sock

# ssl-options are arguments that are passed to MySQL client commands
# for SSL connection to the MySQL server. This parameter is optional and is
# required only if MySQL server allows SSL connections.
#
#ssl-options="--ssl --ssl-ca=file1 --ssl-cert=file2 --ssl-key=file3"

# This can be set to specify that mysqldump should dump stored routines also.
# This paramter is optional and the default is that stored routines are
# not dumped my mysqldump
routines=1

# This can be set to 0 to specify that the --single-transaction
# should not be used for mysqldump
single-transaction=1

# This can be used to specif the character set name that mysqldump should
# use as default. This parameter is optional.
# If not specified utf8 is used as the default character set.
#default-character-set=latin1

# Directory where MySQL commands can be found. The parameter is optional.
#
#mysql-binpath="/opt/lampp/bin"

# Directory where MySQL binary logs can be found. The parameter is optional.
#
#mysql-binlog-path="/var/log/mysql"

# Directory to use for temporary storage. This parameter is optional
#
#tmpdir=/tmp

#
# ZRM parameters
#

# This parameter controls the verbosity of MySQL ZRM logging. The MySQL ZRM logs
# are available at /var/log/mysql-zrm/mysql-zrm.log. This parameter is optional
# default value is 0 (less verbose).
# The valid values are 0 and 1
#
verbose=1

# After a backup run the backup report is emailed to the mailto address
# This parameter is optional and default behavior is not to send mail
# notifications.
#
mailto="backups@youremail.com"

# Policy on when the mail should be sent
# Values can be "always", "never" or "only-on-error"
mail-policy=only-on-error

# The list of backup reports that are generated after each backup run if
# "html-report-directory" parameter is specified.
# If this parameter is not specified, "backup-status-info" report is generated.
# Valid report names are : backup-method-info, backup-status-info,
#                          backup-retention-info, backup-performance-info,
#                          restore-full-info, restore-incr-info,
#                          replication-info, backup-app-performance-info
# See mysql-zrm-reporter(1) for details of backup reports.
# Multiple report names should be separated by ",".
#
html-reports=backup-status-info

# Directory in which Text/HTML reports will be created by mysql-zrm-reporter(1)
# tool. If this parameter is specified, the mysql-zrm-reporter(1) creates the
# backup reports in this directory after each successful or unsuccessful
# backup run.
# Text reports will be created under "Text" sub-directory
# HTML reports will be created under "Html" sub-directory
#
#html-report-directory=/var/www/mysql-zrm/reports/

# If backup reports are required as RSS feed, "webserver-url" parameter must
# be specified. The value must be set to a valid location on the web server
# in which HTML reports are located and that URL can be used by
# administrator/user to browse HTML reports and can get to the RSS feeds.
# If this parameter is not specified, backup reports are not generated as
# RSS feeds. The list of reports that are available as RSS feed is specified
# in "html-reports".
#
#webserver-url=http://www.company.com/reports/html/

# Location of RSS header file. Administrators can customize RSS channel
# properties using this file. A template for RSS header is available in
# /usr/share/mysql-zrm/plugins/RSS.header file. Location of RSS header
# must be provided if "webserver-url" is specified.
#
#rss-header-location=/etc/mysql-zrm/

#
# ZRM plugin parameters.
# ZRM provides plugin interfaces to allow MySQL administrators to customize
# the backup to their environment.
#

# COPY plugin: Only one copy-plugin must be configured for a backup set.
#
# Socket Copy plugin is to used to transfer backup files from MySQL server to
# the machine running ZRM for MySQL with sockets.
#
# Please read the Notes at /usr/share/doc/mysql-zrm/README-plugin-socket-copy
#
#copy-plugin=/usr/share/mysql-zrm/plugins/socket-copy.pl

# SSH Copy plugin is to used to transfer backup files from MySQL server to
# the machine running ZRM for MySQL with ssh
#
# Please read the Notes at /usr/share/doc/mysql-zrm/README-plugin-ssh-copy
#
#copy-plugin=/usr/share/mysql-zrm/plugins/ssh-copy.pl

# PRE-BACKUP plugin: Plugin that will be called before a backup run for
# the backup set.
#pre-backup-plugin="/usr/share/mysql-zrm/plugins/pre-backup.pl"

# Set of parameters passed to the pre-backup-plugin. These parameters are
# passed to "pre-backup-plugin" before a backup run for the backup set.
# "pre-backup-plugin" parameter must be specified.
#pre-backup-plugin-options="option1 option2"

# POST-BACKUP plugin: Plugin that will be called after a backup run for
# the backup set.
#post-backup-plugin="/usr/share/mysql-zrm/plugins/post-backup.pl"

# Set of parameters passed to the post-backup-plugin. These parameters are
# passed to "post-backup-plugin" after a backup run for the backup set.
# "post-backup-plugin" parameter must be specified.
#post-backup-plugin-options="option1 option2"

# PRE-SCHEDULER plugin: Plugin that can be used to dynamically determine the
# start time for a backup run.
#pre-scheduler-plugin="/usr/share/mysql-zrm/plugins/pre-scheduler.pl"

# ZRM Plugin configuration parameters

# This parameter is used by the encrypt plugin and
# specifies the file containing the passphrase.
#passfile="/tmp/a.pass"

# This parameter is used by ssh-plugin.pl plugin to specify the user to be
# used to ssh to the  remote host
#ssh-user="root"

# This parameter is used by the ssh-copy.pl and socket-copy.pl plugins
# to specify the location of mysql client binaries on the remote host.
#remote-mysql-binpath="/usr/bin"

# This parameter is used by the socket-copy.pl plugin to specify the port
# to be opened on the remote host.
#socket-remote-port="25300"

# This parameter is used by the windows-copy.pl plugin to specify the port
# to be opened on the windows machine during backup
#windows-backup-port="10080"

# This parameter is used by the windows-copy.pl plugin to specify the port
# to be opened on the windows machine during restore
#windows-restore-port="10081"

Step 5. Launch a backup

mysql-zrm-scheduler -now

 

 

Configure ups in centos 7

Having small servers at office requires try to avoid a small number of problems one of then are electrical supply falitures, a quick way to solve this is connecting a UPS to the server and forget about cross your fingers when a power outtage makes act of presence.

yukai_ups

In my case i have to configure a couple of small servers one with an old Yukai UPS and other with a Salicru ups.

If you want to get an ups  linux communication working follow  this steps:

Enable epel

yum install https://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm

Install packages

yum install nut.x86_64 vim

Configure NUT

First search if your ups is supported in nut database and ensure that you select the desired driver Linux UPS Hardware Compatibility list

if your ups doesn’t appears in this list youl use your favourite web searcher for someone who try to fix these problems in case of Salicru appears to work with blazer_usb driver

vim /etc/ups/ups.conf

at the end of the file append these lines for mustek Yukai series


[yukai]
driver = blazer_usb
port = auto
desc = "Yukai PowerMust 600 usb"

next step is verify if your selected configuration is valid just type in your terminal

  upsdrvctl start

and shoud get some output like these

Network UPS Tools - UPS driver controller 2.7.2
Network UPS Tools - Megatec/Q1 protocol USB driver 0.11 (2.7.2)
Supported UPS detected with megatec protocol
Vendor information unavailable
No values provided for battery high/low voltages in ups.conf

Using 'guestimation' (low: 10.400000, high: 13.000000)!
Battery runtime will not be calculated (runtimecal not set)

after this you should configure your permissions ACL, in my case I only want query SAI status from the server only

so edit file /etc/ups/upsd.conf using this command

vim /etc/ups/upsd.conf

and append these text


ACL all 0.0.0.0/0
ACL localhost 127.0.0.1/32
ACCEPT localhost
REJECT all

 

 

after this you should add a user to check UPS status edditing   /etc/ups/upsd.users file

vim  vim /etc/ups/upsd.users

and append this text


[local_mon]
password = secretpass
allowfrom = localhost
upsmon master

Next step is link your ups with created user

add a line in file

 vim /etc/ups/upsmon.conf

with these content

MONITOR </etc/ups/ups.conf UPS name>@localhost 1 </etc/ups/upsd.users selected username> </etc/ups/upsd.users selected password> master

in this case

MONITOR yukai@localhost 1 local_mon secretpass master

Enable services

systemctl enable nut-monitor.service

systemctl enable nut-server.service

and start these services

systemctl start nut-server.service

systemctl start nut-monitor.service

sometimes at execute after execute “upsdrvctl start” command  it hijacks usb communication, this can be solved restarting system.

to check if ups is working just launch

upsc “ups name” and you should get an output like these

upsc yukai


battery.charge: 100
battery.voltage: 13.20
battery.voltage.high: 13.00
battery.voltage.low: 10.40
battery.voltage.nominal: 12.0
device.type: ups
driver.name: blazer_usb
driver.parameter.pollinterval: 2
driver.parameter.port: auto
driver.version: 2.7.2
driver.version.internal: 0.11
input.current.nominal: 1.0
input.frequency: 49.9
input.frequency.nominal: 50
input.voltage: 231.5
input.voltage.fault: 231.5
input.voltage.nominal: 230
output.voltage: 231.5
ups.beeper.status: enabled
ups.delay.shutdown: 30
ups.delay.start: 180
ups.load: 27
ups.productid: 5161
ups.status: OL
ups.type: offline / line interactive

references:

http://blog.shadypixel.com/monitoring-a-ups-with-nut-on-debian-or-ubuntu-linux/

Centos 7 Samba server workgroup

Step 1: Enable epel

yum install http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm

Step 2: Install packages

yum install samba samba-client samba-common vim

Step 3: enable service and open firewalld ports

systemctl enable smb.service
systemctl enable nmb.service
systemctl start smb.service
systemctl start nmb.service
firewall-cmd –permanent –zone=public –add-service=samba
firewall-cmd –reload

Step 4: Configure samba

cp smb.conf  smb.conf.orig

vim  /etc/samba/smb.conf


[global]
workgroup = "Put here your workgroup name"
server string = Samba Server Version %v
netbios name = "Put here host name you desire"
log file = /var/log/samba/log.%m
max log size = 50
security = user
passdb backend = tdbsam
local master = yes
load printers = no
cups options = raw
map to guest = Bad User

restart samba services

systemctl restart smb.service

systemctl restart nmb.service

now a computer running windows 7 your server should be visible in network host list

server visible in workgroupnow we will add a shared folder where all users can write even guest.

Step 5: Add a global write shared folder:

create a directory in your linux system where is located your shared folder

mkdir -p /home/commonfolder

chmod -R 0755 /home/commonfolder/

setsebool -P samba_enable_home_dirs on

chown -R nobody:nobody /home/commonfolder/

chcon -t samba_share_t /home/commonfolder/

add shared folder in smb.conf file

vim /etc/samba/smb.conf

it should look similar this example


[global]
workgroup = "Put here your workgroup name"
server string = Samba Server Version %v
netbios name = "Put here host name you desire"
log file = /var/log/samba/log.%m
max log size = 50
security = user
passdb backend = tdbsam
local master = yes
load printers = no
cups options = raw
map to guest = Bad User

[commonfolder]
path = /home/commonfolder
read only = No
guest ok = Yes

verify your config file

testparm

reload your samba configuratión

systemctl restart smb.service
systemctl restart nmb.service

In your windows client machine click your samba server and verify that you can read and write in your shared folder

anonymous shared folderwriting anonymous shared folder

 Step 6: Add a secured shared folder

Now we will create a shared folder for our user peter, first we will create a system user

 useradd -s /sbin/nologin peter

groupadd smbgroup

usermod  -a -G smbgroup peter

set samba password for peter user

smbpasswd -a peter

mkdir -p  /samba/peter_share

chmod -R 0775 /samba/peter_share/

chown -R peter:smbgroup /samba/peter_share

chcon -t samba_share_t /samba/peter_share/

add Peter share in smb config file

vim /etc/samba/smb.conf

it should be like these

[global]
    workgroup = "Put here your workgroup name"
    server string = Samba Server Version %v
    netbios name = "Put here host name you desire"
    log file = /var/log/samba/log.%m
    max log size = 50
    security = user
    passdb backend = tdbsam
    local master = yes
    load printers = no
    cups options = raw

[commonfolder]
    path = /home/commonfolder
    read only = No
    guest ok = Yes

[peter]
        path= /samba/peter_share
        writable = yes
        browsable = yes
        guest ok = no
        valid users = peter

After this  restar your samba services

systemctl restart smb.service
systemctl restart nmb.service

now you can access to your shared folder

samba autentificationSolving problems with user permissions in guest share

If user Peter try to modify data from commonfolder all data will be mapped agains user peter and can have problems to solve this add the option guest only = yes in commonfolder share options


[commonfolder]
path = /home/commonfolder
browsable =yes
writable = yes
guest ok = yes
read only = no
guest only = yes

 

References:

https://www.howtoforge.com/samba-server-installation-and-configuration-on-centos-7

http://www.unixmen.com/install-configure-samba-server-centos-7/

Installing a SheevaPlug

I needed a small file server at home, focused on  storage backups. Searching in my circuit warehouse i found my old sheevaplug and decided use it.

sheeva plug
sheeva plug

I choose install a Debian on it.

Step 1: Identify sheevaplug serial console

Plug sheeva plug microusb port to your desktop computer and execute dmesg in your computer.

Output will be like this

[ 3016.391801] ftdi_sio ttyUSB0: FTDI USB Serial Device converter now disconnected from ttyUSB0
[ 3016.391820] ftdi_sio 2-4.3:1.1: device disconnected
[ 3019.518529] usb 2-4.3: new full-speed USB device number 4 using ehci-pci
[ 3019.611536] usb 2-4.3: New USB device found, idVendor=9e88, idProduct=9e8f
[ 3019.611542] usb 2-4.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 3019.611545] usb 2-4.3: Product: SheevaPlug JTAGKey FT2232D B
[ 3019.611548] usb 2-4.3: Manufacturer: FTDI
[ 3019.611551] usb 2-4.3: SerialNumber: FTT39IJR
[ 3019.615454] usb 2-4.3: Ignoring serial port reserved for JTAG
[ 3019.618652] ftdi_sio 2-4.3:1.1: FTDI USB Serial Device converter detected
[ 3019.618696] usb 2-4.3: Detected FT2232C
[ 3019.619289] usb 2-4.3: FTDI USB Serial Device converter now attached to ttyUSB0

That means that our serial console is attached to device /dev/ttyUSB0

Step 2: Connect to sheeva serial console

 cu -s 115200 -l /dev/ttyUSB0

with this command you can access to sheeva console

Connected.

Marvell>>

Step 3: Verify U-Boot version

Marvell>> version

U-Boot 2011.12 (Mar 11 2012 – 18:59:46)
Marvell-Sheevaplug – eSATA – SD/MMC
gcc (Debian 4.6.3-1) 4.6.3
GNU ld (GNU Binutils for Debian) 2.22

I found in blaicher.com a newer uboot versión and newer versions are always better i decided to update it (you con download here -> u-boot_sheeva_plug_2013_10_rc1)

You need to know your MAC Address before update

Marvell>> printenv ethaddr
ethaddr=YOUR-MAC-ADDRESS
Marvell>>

I uncompress zip file and put into a flash memory, attached flash to sheeva and execute there commands

usb start
fatload usb 0:1 0x0800000 u-boot.kwb
nand erase 0x0 0x60000
nand write 0x0800000 0x0 0x60000
reset
setenv ethaddr YOUR-MAC-ADDRESS
saveenv
reset

Now you have a newer u-boot version

 

Step 4: Install Debian

I copied uImage and uInitrd into a flash memory (uImage and uInitrd debian sheeva) and execute

usb start
fatload usb 0:1 0x00800000 /uImage
fatload usb 0:1 0x01100000 /uInitrd

and started installer

setenv bootargs console=ttyS0,115200n8 base-installer/initramfs-tools/driver-policy=most
bootm 0x00800000 0x01100000

Follow on screen instructions and when finished installer will reboot sheeva.

Stop u-boot loading and execute

setenv bootargs_console console=ttyS0,115200
setenv bootcmd_usb ‘usb start; ext2load usb 0:1 0x00800000 /uImage; ext2load usb 0:1 0x01100000 /uInitrd’
setenv bootcmd ‘setenv bootargs $(bootargs_console); run bootcmd_usb; bootm 0x00800000 0x01100000’
saveenv

and start your linux

run bootcmd

 

references:

http://www.blaicher.com/2012/07/installing-debian-on-a-sheevaplug-into-flash/

http://cyrius.com/debian/kirkwood/sheevaplug/

Centos 6.6 Zabbix Server 2.4 with Nginx 1.6 and MySql 5.6

Starting from a minimal install.

step 1: enable extra repositories


yum install http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm

yum install http://repo.zabbix.com/zabbix/2.4/rhel/6/x86_64/zabbix-release-2.4-1.el6.noarch.rpm

yum install http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm

yum install http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm

yum -y update

step 2: configure  mysql database


yum -y install mysql-server.x86_64

vim /etc/my.cnf

Your config file should be like these.

Note: I activate binlog without purge because can be useful if you need to recover data or attach a mysql slave.

 


# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.6/en/server-configuration-defaults.html

[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock

# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0

# Recommended in standard MySQL setup
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

#allow tcp connections
port = 3306

#innodb options
innodb_file_format=Barracuda
innodb_file_per_table
innodb_flush_method=O_DIRECT

#replication
log-bin=mysql-bin
binlog_format=MIXED
max_binlog_size=256M

#Enable performance schema
performance_schema

[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

enable mysql daemon


chkconfig mysqld on

start mysql daemon

service mysqld start

secure mysql installation

/usr/bin/mysql_secure_installation

allow incoming 3306 connections


/sbin/iptables -A INPUT -i eth0 -p tcp --destination-port 3306 -j ACCEPT
service iptables save

step 3: configure database backup

This is important because after a lot of power outages and hard disk problems sometimes you can’t recover your database and restore a backup is faster than reinstall or the only way.


yum install wget pbzip2
mysql -uroot -p

create backup user


GRANT LOCK TABLES, SELECT ON *.* TO 'BACKUPUSER'@'%' IDENTIFIED BY 'PASSWORD';
flush privileges;
exit

install AutoMysqlBackup

wget http://www.mirrorservice.org/sites/downloads.sourceforge.net/a/au/automysqlbackup/AutoMySQLBackup/AutoMySQLBackup%20VER%203.0/automysqlbackup-v3.0_rc6.tar.gz
tar xzvf automysqlbackup-v3.0_rc6.tar.gz
/install.sh
mkdir /var/backup/
mkdir /var/backup/db

we need to adjust our config file


vim /etc/automysqlbackup/myserver.conf

should look like these

note: I select bzip because it gets better results


#version=3.0_rc2
# DONT'T REMOVE THE PREVIOUS VERSION LINE!
#
# Uncomment to change the default values (shown after =)
# WARNING:
# This is not true for UMASK, CONFIG_prebackup and CONFIG_postbackup!!!
#
# Default values are stored in the script itself. Declarations in
# /etc/automysqlbackup/automysqlbackup.conf will overwrite them. The
# declarations in here will supersede all other.

# Edit $PATH if mysql and mysqldump are not located in /usr/local/bin:/usr/bin:/bin:/usr/local/mysql/bin
#PATH=${PATH}:FULL_PATH_TO_YOUR_DIR_CONTAINING_MYSQL:FULL_PATH_TO_YOUR_DIR_CONTAINING_MYSQLDUMP

# Basic Settings

# Username to access the MySQL server e.g. dbuser
CONFIG_mysql_dump_username='backupuser'

# Password to access the MySQL server e.g. password
CONFIG_mysql_dump_password='yourbackupuserpass'

# Host name (or IP address) of MySQL server e.g localhost
CONFIG_mysql_dump_host='localhost'

# &amp;amp;quot;Friendly&amp;amp;quot; host name of MySQL server to be used in email log
# if unset or empty (default) will use CONFIG_mysql_dump_host instead
#CONFIG_mysql_dump_host_friendly=''

# Backup directory location e.g /backups
CONFIG_backup_dir='/var/backup/db'

# This is practically a moot point, since there is a fallback to the compression
# functions without multicore support in the case that the multicore versions aren't
# present in the system. Of course, if you have the latter installed, but don't want
# to use them, just choose no here.
# pigz -&amp;amp;gt; gzip
# pbzip2 -&amp;amp;gt; bzip2
CONFIG_multicore='yes'

# Number of threads (= occupied cores) you want to use. You should - for the sake
# of the stability of your system - not choose more than (#number of cores - 1).
# Especially if the script is run in background by cron and the rest of your system
# has already heavy load, setting this too high, might crash your system. Assuming
# all systems have at least some sort of HyperThreading, the default is 2 threads.
# If you wish to let pigz and pbzip2 autodetect or use their standards, set it to
# 'auto'.
CONFIG_multicore_threads='auto'

# Databases to backup

# List of databases for Daily/Weekly Backup e.g. ( 'DB1' 'DB2' 'DB3' ... )
# set to (), i.e. empty, if you want to backup all databases
CONFIG_db_names=()
# You can use
#declare -a MDBNAMES=( &amp;amp;quot;${DBNAMES[@]}&amp;amp;quot; 'added entry1' 'added entry2' ... )
# INSTEAD to copy the contents of $DBNAMES and add further entries (optional).

# List of databases for Monthly Backups.
# set to (), i.e. empty, if you want to backup all databases
#CONFIG_db_month_names=()

# List of DBNAMES to EXLUCDE if DBNAMES is empty, i.e. ().
CONFIG_db_exclude=( 'information_schema' 'performance_schema' )

# List of tables to exclude, in the form db_name.table_name
# You may use wildcards for the table names, i.e. 'mydb.a*' selects all tables starting with an 'a'.
# However we only offer the wildcard '*', matching everything that could appear, which translates to the
# '%' wildcard in mysql.
#CONFIG_table_exclude=()

# Advanced Settings

# Rotation Settings

# Which day do you want monthly backups? (01 to 31)
# If the chosen day is greater than the last day of the month, it will be done
# on the last day of the month.
# Set to 0 to disable monthly backups.
CONFIG_do_monthly=&amp;amp;quot;01&amp;amp;quot;

# Which day do you want weekly backups? (1 to 7 where 1 is Monday)
# Set to 0 to disable weekly backups.
CONFIG_do_weekly=&amp;amp;quot;5&amp;amp;quot;

# Set rotation of daily backups. VALUE*24hours
# If you want to keep only today's backups, you could choose 1, i.e. everything older than 24hours will be removed.
CONFIG_rotation_daily=6

# Set rotation for weekly backups. VALUE*24hours
CONFIG_rotation_weekly=35

# Set rotation for monthly backups. VALUE*24hours
CONFIG_rotation_monthly=150

# Server Connection Settings

# Set the port for the mysql connection
CONFIG_mysql_dump_port=3306

# Compress communications between backup server and MySQL server?
#CONFIG_mysql_dump_commcomp='no'

# Use ssl encryption with mysqldump?
#CONFIG_mysql_dump_usessl='yes'

# For connections to localhost. Sometimes the Unix socket file must be specified.
CONFIG_mysql_dump_socket='/var/lib/mysql/mysql.sock'

# The maximum size of the buffer for client/server communication. e.g. 16MB (maximum is 1GB)
#CONFIG_mysql_dump_max_allowed_packet=''

# This option sends a START TRANSACTION SQL statement to the server before dumping data. It is useful only with
# transactional tables such as InnoDB, because then it dumps the consistent state of the database at the time
# when BEGIN was issued without blocking any applications.
#
# When using this option, you should keep in mind that only InnoDB tables are dumped in a consistent state. For
# example, any MyISAM or MEMORY tables dumped while using this option may still change state.
#
# While a --single-transaction dump is in process, to ensure a valid dump file (correct table contents and
# binary log coordinates), no other connection should use the following statements: ALTER TABLE, CREATE TABLE,
# DROP TABLE, RENAME TABLE, TRUNCATE TABLE. A consistent read is not isolated from those statements, so use of
# them on a table to be dumped can cause the SELECT that is performed by mysqldump to retrieve the table
# contents to obtain incorrect contents or fail.
CONFIG_mysql_dump_single_transaction='yes'

# http://dev.mysql.com/doc/refman/5.0/en/mysqldump.html#option_mysqldump_master-data
# --master-data[=value]
# Use this option to dump a master replication server to produce a dump file that can be used to set up another
# server as a slave of the master. It causes the dump output to include a CHANGE MASTER TO statement that indicates
# the binary log coordinates (file name and position) of the dumped server. These are the master server coordinates
# from which the slave should start replicating after you load the dump file into the slave.
#
# If the option value is 2, the CHANGE MASTER TO statement is written as an SQL comment, and thus is informative only;
# it has no effect when the dump file is reloaded. If the option value is 1, the statement is not written as a comment
# and takes effect when the dump file is reloaded. If no option value is specified, the default value is 1.
#
# This option requires the RELOAD privilege and the binary log must be enabled.
#
# The --master-data option automatically turns off --lock-tables. It also turns on --lock-all-tables, unless
# --single-transaction also is specified, in which case, a global read lock is acquired only for a short time at the
# beginning of the dump (see the description for --single-transaction). In all cases, any action on logs happens at
# the exact moment of the dump.
# ==================================================================================================================
# possible values are 1 and 2, which correspond with the values from mysqldump
# VARIABLE=    , i.e. no value, turns it off (default)
#
#CONFIG_mysql_dump_master_data=

# Included stored routines (procedures and functions) for the dumped databases in the output. Use of this option
# requires the SELECT privilege for the mysql.proc table. The output generated by using --routines contains
# CREATE PROCEDURE and CREATE FUNCTION statements to re-create the routines. However, these statements do not
# include attributes such as the routine creation and modification timestamps. This means that when the routines
# are reloaded, they will be created with the timestamps equal to the reload time.
#
# If you require routines to be re-created with their original timestamp attributes, do not use --routines. Instead,
# dump and reload the contents of the mysql.proc table directly, using a MySQL account that has appropriate privileges
# for the mysql database.
#
# This option was added in MySQL 5.0.13. Before that, stored routines are not dumped. Routine DEFINER values are not
# dumped until MySQL 5.0.20. This means that before 5.0.20, when routines are reloaded, they will be created with the
# definer set to the reloading user. If you require routines to be re-created with their original definer, dump and
# load the contents of the mysql.proc table directly as described earlier.
#
CONFIG_mysql_dump_full_schema='yes'

# Backup status of table(s) in textfile. This is very helpful when restoring backups, since it gives an idea, what changed
# in the meantime.
CONFIG_mysql_dump_dbstatus='yes'

# Backup dump settings

# Include CREATE DATABASE in backup?
CONFIG_mysql_dump_create_database='no'

# Separate backup directory and file for each DB? (yes or no)
CONFIG_mysql_dump_use_separate_dirs='yes'

# Choose Compression type. (gzip or bzip2)
CONFIG_mysql_dump_compression='bzip2'

# Store an additional copy of the latest backup to a standard
# location so it can be downloaded by third party scripts.
CONFIG_mysql_dump_latest='yes'

# Remove all date and time information from the filenames in the latest folder.
# Runs, if activated, once after the backups are completed. Practically it just finds all files in the latest folder
# and removes the date and time information from the filenames (if present).
CONFIG_mysql_dump_latest_clean_filenames='no'

# Create differential backups. Master backups are created weekly at #$CONFIG_do_weekly weekday. Between master backups,
# diff is used to create differential backups relative to the latest master backup. In the Manifest file, you find the
# following structure
# $filename     md5sum  $md5sum diff_id $diff_id        rel_id  $rel_id
# where each field is separated by the tabular character '\t'. The entries with $ at the beginning mean the actual values,
# while the others are just for readability. The diff_id is the id of the differential or master backup which is also in
# the filename after the last _ and before the suffixes begin, i.e. .diff, .sql and extensions. It is used to relate
# differential backups to master backups. The master backups have 0 as $rel_id and are thereby identifiable. Differential
# backups have the id of the corresponding master backup as $rel_id.
#
# To ensure that master backups are kept long enough, the value of $CONFIG_rotation_daily is set to a minimum of 21 days.
#
CONFIG_mysql_dump_differential='no'

# Notification setup

# What would you like to be mailed to you?
# - log   : send only log file
# - files : send log file and sql files as attachments (see docs)
# - stdout : will simply output the log to the screen if run manually.
# - quiet : Only send logs if an error occurs to the MAILADDR.
CONFIG_mailcontent='stdout'

# Set the maximum allowed email size in k. (4000 = approx 5MB email [see docs])
CONFIG_mail_maxattsize=4000

# Allow packing of files with tar and splitting it in pieces of CONFIG_mail_maxattsize.
#CONFIG_mail_splitandtar='yes'

# Use uuencode instead of mutt. WARNING: Not all email clients work well with uuencoded attachments.
#CONFIG_mail_use_uuencoded_attachments='no'

# Email Address to send mail to? (user@domain.com)
CONFIG_mail_address='luzem@luzem.com'

# Encryption

# Do you wish to encrypt your backups using openssl?
#CONFIG_encrypt='no'

# Choose a password to encrypt the backups.
#CONFIG_encrypt_password='password0123'

# Other

# Backup local files, i.e. maybe you would like to backup your my.cnf (mysql server configuration), etc.
# These files will be tar'ed, depending on your compression option CONFIG_mysql_dump_compression compressed and
# depending on the option CONFIG_encrypt encrypted.
#
# Note: This could also have been accomplished with CONFIG_prebackup or CONFIG_postbackup.
#CONFIG_backup_local_files=()

# Command to run before backups (uncomment to use)
#CONFIG_prebackup=&amp;amp;quot;/etc/mysql-backup-pre&amp;amp;quot;

# Command run after backups (uncomment to use)
#CONFIG_postbackup=&amp;amp;quot;/etc/mysql-backup-post&amp;amp;quot;

# Uncomment to activate! This will give folders rwx------
# and files rw------- permissions.
#umask 0077

# dry-run, i.e. show what you are gonna do without actually doing it
# inactive: =0 or commented out
# active: uncommented AND =1
#CONFIG_dryrun=1

at next step we add a cron line to run our backup every day


vim /etc/cron.daily/runmysqlbackup

the content should be like these


#!/bin/sh
/usr/local/bin/automysqlbackup /etc/automysqlbackup/myserver.conf
chown root.root /var/backup/db* -R
find /var/backup/db* -type f -exec chmod 400 {} \;
find /var/backup/db* -type d -exec chmod 700 {} \;

you should make your script executable


chmod +x /etc/cron.daily/runmysqlbackup

if you wanna try just execute


/etc/cron.daily/runmysqlbackup

and check /var/backup/db directory

and now you will have a daily backup 😛

Step 4: Install  zabbix server

 

yum install zabbix-server-mysql zabbix-web-mysql zabbix-agent
service zabbix-server start
service zabbix-agent start
chkconfig zabbix-agent on

 

 

we need to create a zabbix database user and a zabbix database

mysql -uroot -p

 

execute these sentences

create database zabbix character set utf8 collate utf8_bin;
grant all privileges on zabbix.* to zabbix@localhost identified by 'zabbixdatabasepasword';
flush privileges;
exit

 

next step is populate table structures

note: sql commands should changue check a should be in /usr/share/doc/zabbix-server-mysql-<version>/create


 mysql -uroot -p zabbix &amp;amp;lt; /usr/share/doc/zabbix-server-mysql-2.4.2/create/schema.sql
 mysql -uroot -p zabbix &amp;amp;lt; /usr/share/doc/zabbix-server-mysql-2.4.2/create/images.sql
 mysql -uroot -p zabbix &amp;amp;lt; /usr/share/doc/zabbix-server-mysql-2.4.2/create/data.sql

 

at this point we have out zabbix database its time to link zabbix and database


vim /etc/zabbix/zabbix_server.conf

 

your config file shoul be like these


# This is a configuration file for Zabbix Server process
# To get more information about Zabbix,
# visit http://www.zabbix.com

############ GENERAL PARAMETERS #################

### Option: ListenPort
#       Listen port for trapper.
#
# Mandatory: no
# Range: 1024-32767
# Default:
# ListenPort=10051

### Option: SourceIP
#       Source IP address for outgoing connections.
#
# Mandatory: no
# Default:
# SourceIP=

### Option: LogFile
#       Name of log file.
#       If not set, syslog is used.
#
# Mandatory: no
# Default:
# LogFile=

LogFile=/var/log/zabbix/zabbix_server.log

### Option: LogFileSize
#       Maximum size of log file in MB.
#       0 - disable automatic log rotation.
#
# Mandatory: no
# Range: 0-1024
# Default:
# LogFileSize=1

LogFileSize=0

### Option: DebugLevel
#       Specifies debug level
#       0 - basic information about starting and stopping of Zabbix processes
#       1 - critical information
#       2 - error information
#       3 - warnings
#       4 - for debugging (produces lots of information)
#
# Mandatory: no
# Range: 0-4
# Default:
# DebugLevel=3

### Option: PidFile
#       Name of PID file.
#
# Mandatory: no
# Default:
# PidFile=/tmp/zabbix_server.pid

PidFile=/var/run/zabbix/zabbix_server.pid

### Option: DBHost
#       Database host name.
#       If set to localhost, socket is used for MySQL.
#       If set to empty string, socket is used for PostgreSQL.
#
# Mandatory: no
# Default:
DBHost=localhost

### Option: DBName
#       Database name.
#       For SQLite3 path to database file must be provided. DBUser and DBPassword are ignored.
#
# Mandatory: yes
# Default:
# DBName=

DBName=zabbix

### Option: DBSchema
#       Schema name. Used for IBM DB2 and PostgreSQL.
#
# Mandatory: no
# Default:
# DBSchema=

### Option: DBUser
#       Database user. Ignored for SQLite.
#
# Mandatory: no
# Default:
# DBUser=

DBUser=zabbix

### Option: DBPassword
#       Database password. Ignored for SQLite.
#       Comment this line if no password is used.
#
# Mandatory: no
# Default:
DBPassword=zabbixdatabasepasword

### Option: DBSocket
#       Path to MySQL socket.
#
# Mandatory: no
# Default:
# DBSocket=/tmp/mysql.sock

DBSocket=/var/lib/mysql/mysql.sock

### Option: DBPort
#       Database port when not using local socket. Ignored for SQLite.
#
# Mandatory: no
# Range: 1024-65535
# Default (for MySQL):
# DBPort=3306

############ ADVANCED PARAMETERS ################

### Option: StartPollers
#       Number of pre-forked instances of pollers.
#
# Mandatory: no
# Range: 0-1000
# Default:
# StartPollers=5

### Option: StartIPMIPollers
#       Number of pre-forked instances of IPMI pollers.
#
# Mandatory: no
# Range: 0-1000
# Default:
# StartIPMIPollers=0

### Option: StartPollersUnreachable
#       Number of pre-forked instances of pollers for unreachable hosts (including IPMI and Java).
#       At least one poller for unreachable hosts must be running if regular, IPMI or Java pollers
#       are started.
#
# Mandatory: no
# Range: 0-1000
# Default:
# StartPollersUnreachable=1

### Option: StartTrappers
#       Number of pre-forked instances of trappers.
#       Trappers accept incoming connections from Zabbix sender, active agents and active proxies.
#       At least one trapper process must be running to display server availability and view queue
#       in the frontend.
#
# Mandatory: no
# Range: 0-1000
# Default:
# StartTrappers=5

### Option: StartPingers
#       Number of pre-forked instances of ICMP pingers.
#
# Mandatory: no
# Range: 0-1000
# Default:
# StartPingers=1

### Option: StartDiscoverers
#       Number of pre-forked instances of discoverers.
#
# Mandatory: no
# Range: 0-250
# Default:
# StartDiscoverers=1

### Option: StartHTTPPollers
#       Number of pre-forked instances of HTTP pollers.
#
# Mandatory: no
# Range: 0-1000
# Default:
# StartHTTPPollers=1

### Option: StartTimers
#       Number of pre-forked instances of timers.
#       Timers process time-based trigger functions and maintenance periods.
#       Only the first timer process handles the maintenance periods.
#
# Mandatory: no
# Range: 1-1000
# Default:
# StartTimers=1

### Option: JavaGateway
#       IP address (or hostname) of Zabbix Java gateway.
#       Only required if Java pollers are started.
#
# Mandatory: no
# Default:
# JavaGateway=

### Option: JavaGatewayPort
#       Port that Zabbix Java gateway listens on.
#
# Mandatory: no
# Range: 1024-32767
# Default:
# JavaGatewayPort=10052

### Option: StartJavaPollers
#       Number of pre-forked instances of Java pollers.
#
# Mandatory: no
# Range: 0-1000
# Default:
# StartJavaPollers=0

### Option: StartVMwareCollectors
#       Number of pre-forked vmware collector instances.
#
# Mandatory: no
# Range: 0-250
# Default:
# StartVMwareCollectors=0

### Option: VMwareFrequency
#       How often Zabbix will connect to VMware service to obtain a new data.
#
# Mandatory: no
# Range: 10-86400
# Default:
# VMwareFrequency=60

### Option: VMwareCacheSize
#       Size of VMware cache, in bytes.
#       Shared memory size for storing VMware data.
#       Only used if VMware collectors are started.
#
# Mandatory: no
# Range: 256K-2G
# Default:
# VMwareCacheSize=8M

### Option: SNMPTrapperFile
#       Temporary file used for passing data from SNMP trap daemon to the server.
#       Must be the same as in zabbix_trap_receiver.pl or SNMPTT configuration file.
#
# Mandatory: no
# Default:
# SNMPTrapperFile=/tmp/zabbix_traps.tmp

SNMPTrapperFile=/var/log/snmptt/snmptt.log

### Option: StartSNMPTrapper
#       If 1, SNMP trapper process is started.
#
# Mandatory: no
# Range: 0-1
# Default:
# StartSNMPTrapper=0

### Option: ListenIP
#       List of comma delimited IP addresses that the trapper should listen on.
#       Trapper will listen on all network interfaces if this parameter is missing.
#
# Mandatory: no
# Default:
# ListenIP=0.0.0.0

# ListenIP=127.0.0.1

### Option: HousekeepingFrequency
#       How often Zabbix will perform housekeeping procedure (in hours).
#       Housekeeping is removing outdated information from the database.
#       To prevent Housekeeper from being overloaded, no more than 4 times HousekeepingFrequency
#       hours of outdated information are deleted in one housekeeping cycle, for each item.
#       To lower load on server startup housekeeping is postponed for 30 minutes after server start.
#
# Mandatory: no
# Range: 1-24
# Default:
# HousekeepingFrequency=1

### Option: MaxHousekeeperDelete
#       The table &amp;amp;quot;housekeeper&amp;amp;quot; contains &amp;amp;quot;tasks&amp;amp;quot; for housekeeping procedure in the format:
#       [housekeeperid], [tablename], [field], [value].
#       No more than 'MaxHousekeeperDelete' rows (corresponding to [tablename], [field], [value])
#       will be deleted per one task in one housekeeping cycle.
#       SQLite3 does not use this parameter, deletes all corresponding rows without a limit.
#       If set to 0 then no limit is used at all. In this case you must know what you are doing!
#
# Mandatory: no
# Range: 0-1000000
# Default:
# MaxHousekeeperDelete=500

### Option: SenderFrequency
#       How often Zabbix will try to send unsent alerts (in seconds).
#
# Mandatory: no
# Range: 5-3600
# Default:
# SenderFrequency=30

### Option: CacheSize
#       Size of configuration cache, in bytes.
#       Shared memory size for storing host, item and trigger data.
#
# Mandatory: no
# Range: 128K-8G
# Default:
# CacheSize=8M

### Option: CacheUpdateFrequency
#       How often Zabbix will perform update of configuration cache, in seconds.
#
# Mandatory: no
# Range: 1-3600
# Default:
# CacheUpdateFrequency=60

### Option: StartDBSyncers
#       Number of pre-forked instances of DB Syncers
#
# Mandatory: no
# Range: 1-100
# Default:
# StartDBSyncers=4

### Option: HistoryCacheSize
#       Size of history cache, in bytes.
#       Shared memory size for storing history data.
#
# Mandatory: no
# Range: 128K-2G
# Default:
# HistoryCacheSize=8M

### Option: TrendCacheSize
#       Size of trend cache, in bytes.
#       Shared memory size for storing trends data.
#
# Mandatory: no
# Range: 128K-2G
# Default:
# TrendCacheSize=4M

### Option: HistoryTextCacheSize
#       Size of text history cache, in bytes.
#       Shared memory size for storing character, text or log history data.
#
# Mandatory: no
# Range: 128K-2G
# Default:
# HistoryTextCacheSize=16M

### Option: ValueCacheSize
#       Size of history value cache, in bytes.
#       Shared memory size for caching item history data requests.
#       Setting to 0 disables value cache.
#
# Mandatory: no
# Range: 0,128K-64G
# Default:
# ValueCacheSize=8M

### Option: Timeout
#       Specifies how long we wait for agent, SNMP device or external check (in seconds).
#
# Mandatory: no
# Range: 1-30
# Default:
# Timeout=3

### Option: TrapperTimeout
#       Specifies how many seconds trapper may spend processing new data.
#
# Mandatory: no
# Range: 1-300
# Default:
# TrapperTimeout=300

### Option: UnreachablePeriod
#       After how many seconds of unreachability treat a host as unavailable.
#
# Mandatory: no
# Range: 1-3600
# Default:
# UnreachablePeriod=45

### Option: UnavailableDelay
#       How often host is checked for availability during the unavailability period, in seconds.
#
# Mandatory: no
# Range: 1-3600
# Default:
# UnavailableDelay=60

### Option: UnreachableDelay
#       How often host is checked for availability during the unreachability period, in seconds.
#
# Mandatory: no
# Range: 1-3600
# Default:
# UnreachableDelay=15

### Option: AlertScriptsPath
#       Full path to location of custom alert scripts.
#       Default depends on compilation options.
#
# Mandatory: no
# Default:
# AlertScriptsPath=${datadir}/zabbix/alertscripts

AlertScriptsPath=/usr/lib/zabbix/alertscripts

### Option: ExternalScripts
#       Full path to location of external scripts.
#       Default depends on compilation options.
#
# Mandatory: no
# Default:
# ExternalScripts=${datadir}/zabbix/externalscripts

ExternalScripts=/usr/lib/zabbix/externalscripts

### Option: FpingLocation
#       Location of fping.
#       Make sure that fping binary has root ownership and SUID flag set.
#
# Mandatory: no
# Default:
# FpingLocation=/usr/sbin/fping

### Option: Fping6Location
#       Location of fping6.
#       Make sure that fping6 binary has root ownership and SUID flag set.
#       Make empty if your fping utility is capable to process IPv6 addresses.
#
# Mandatory: no
# Default:
# Fping6Location=/usr/sbin/fping6

### Option: SSHKeyLocation
#       Location of public and private keys for SSH checks and actions.
#
# Mandatory: no
# Default:
# SSHKeyLocation=

### Option: LogSlowQueries
#       How long a database query may take before being logged (in milliseconds).
#       Only works if DebugLevel set to 3 or 4.
#       0 - don't log slow queries.
#
# Mandatory: no
# Range: 1-3600000
# Default:
# LogSlowQueries=0

### Option: TmpDir
#       Temporary directory.
#
# Mandatory: no
# Default:
# TmpDir=/tmp

### Option: StartProxyPollers
#       Number of pre-forked instances of pollers for passive proxies.
#
# Mandatory: no
# Range: 0-250
# Default:
# StartProxyPollers=1

### Option: ProxyConfigFrequency
#       How often Zabbix Server sends configuration data to a Zabbix Proxy in seconds.
#       This parameter is used only for proxies in the passive mode.
#
# Mandatory: no
# Range: 1-3600*24*7
# Default:
# ProxyConfigFrequency=3600

### Option: ProxyDataFrequency
#       How often Zabbix Server requests history data from a Zabbix Proxy in seconds.
#       This parameter is used only for proxies in the passive mode.
#
# Mandatory: no
# Range: 1-3600
# Default:
# ProxyDataFrequency=1

### Option: AllowRoot
#       Allow the server to run as 'root'. If disabled and the server is started by 'root', the server
#       will try to switch to the user specified by the User configuration option instead.
#       Has no effect if started under a regular user.
#       0 - do not allow
#       1 - allow
#
# Mandatory: no
# Default:
# AllowRoot=0

### Option: User
#       Drop privileges to a specific, existing user on the system.
#       Only has effect if run as 'root' and AllowRoot is disabled.
#
# Mandatory: no
# Default:
# User=zabbix

### Option: Include
#       You may include individual files or all files in a directory in the configuration file.
#       Installing Zabbix will create include directory in /usr/local/etc, unless modified during the compile time.
#
# Mandatory: no
# Default:
# Include=

# Include=/usr/local/etc/zabbix_server.general.conf
# Include=/usr/local/etc/zabbix_server.conf.d/
# Include=/usr/local/etc/zabbix_server.conf.d/*.conf

### Option: SSLCertLocation
#       Location of SSL client certificates.
#       This parameter is used only in web monitoring.
#
# Mandatory: no
# Default:
# SSLCertLocation=${datadir}/zabbix/ssl/certs

### Option: SSLKeyLocation
#       Location of private keys for SSL client certificates.
#       This parameter is used only in web monitoring.
#
# Mandatory: no
# Default:
# SSLKeyLocation=${datadir}/zabbix/ssl/keys

### Option: SSLCALocation
#       Override the location of certificate authority (CA) files for SSL server certificate verification.
#       If not set, system-wide directory will be used.
#       This parameter is used only in web monitoring.
#
# Mandatory: no
# Default:
# SSLCALocation=

####### LOADABLE MODULES #######

### Option: LoadModulePath
#       Full path to location of server modules.
#       Default depends on compilation options.
#
# Mandatory: no
# Default:
# LoadModulePath=${libdir}/modules

### Option: LoadModule
#       Module to load at server startup. Modules are used to extend functionality of the server.
#       Format: LoadModule=&amp;amp;lt;module.so&amp;amp;gt;
#       The modules must be located in directory specified by LoadModulePath.
#       It is allowed to include multiple LoadModule parameters.
#
# Mandatory: no
# Default:
# LoadModule=

 

its time to start our service and let it enabled


service zabbix-server start
chkconfig  zabbix-server on
setsebool -P zabbix_can_network 1

Step 4: Configure nginx and php-fpm server

We need to install several packages and open port 80 (http)


yum -y install nginx php-common php-fpm
/sbin/iptables -A INPUT -i eth0 -p tcp --destination-port 80 -j ACCEPT
service iptables save
chkconfig nginx on
chkconfig php-fpm  on
service nginx start
service php-fpm start

open a web browser and put your zabbix ip on it you should view a page like these

welcome nginx

we need to adjust some php values


vim /etc/php.ini

changue these values


max_execution_time = 300

max_input_time = 300
post_max_size = 16M

date.timezone = Europe/Madrid

cgi.fix_pathinfo=1

if you don’t live in Spain here you have a list of timezones http://php.net/manual/en/timezones.php

next step is add zabbix domain to nginx


vim /etc/nginx/conf.d/zabbix.conf

file should look like these


server {
server_name zabbix.example.org;

root        /var/www/zabbix;
index       index.html index.php;
access_log  /var/log/nginx/access_zabbix.log main;
error_log   /var/log/nginx/error_zabbix.log error

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

}

next step is configure zabbix in php-fpm pool


 mkdir /var/lib/php/zabbix_php-fpm

chmod 770 /var/lib/php/zabbix_php-fpm/

chown root:nginx /var/lib/php/zabbix_php-fpm/

 vim /etc/php-fpm.d/zabbix.conf

 

config file should be like these


; Start a new pool named 'zabbix'.
[zabbix]

; The address on which to accept FastCGI requests.
; Valid syntaxes are:
;   'ip.add.re.ss:port'    - to listen on a TCP socket to a specific address on
;                            a specific port;
;   'port'                 - to listen on a TCP socket to all addresses on a
;                            specific port;
;   '/path/to/unix/socket' - to listen on a unix socket.
; Note: This value is mandatory.
listen = /var/run/php-zabbix.socket

; Set listen(2) backlog. A value of '-1' means unlimited.
; Default Value: -1
;listen.backlog = -1

; List of ipv4 addresses of FastCGI clients which are allowed to connect.
; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original
; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address
; must be separated by a comma. If this value is left blank, connections will be
; accepted from any ip address.
; Default Value: any
;listen.allowed_clients = 127.0.0.1

; Set permissions for unix socket, if one is used. In Linux, read/write
; permissions must be set in order to allow connections from a web server. Many
; BSD-derived systems allow connections regardless of permissions.
; Default Values: user and group are set as the running user
;                 mode is set to 0666
listen.owner = nginx
listen.group = nginx
listen.mode = 0666

; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
;       will be used.
; RPM: apache Choosed to be able to access some dir as httpd
user = nginx
; RPM: Keep a group allowed to write in log dir.
group = nginx

; Choose how the process manager will control the number of child processes.
; Possible Values:
;   static  - a fixed number (pm.max_children) of child processes;
;   dynamic - the number of child processes are set dynamically based on the
;             following directives:
;             pm.max_children      - the maximum number of children that can
;                                    be alive at the same time.
;             pm.start_servers     - the number of children created on startup.
;             pm.min_spare_servers - the minimum number of children in 'idle'
;                                    state (waiting to process). If the number
;                                    of 'idle' processes is less than this
;                                    number then some children will be created.
;             pm.max_spare_servers - the maximum number of children in 'idle'
;                                    state (waiting to process). If the number
;                                    of 'idle' processes is greater than this
;                                    number then some children will be killed.
; Note: This value is mandatory.
pm = dynamic

; The number of child processes to be created when pm is set to 'static' and the
; maximum number of child processes to be created when pm is set to 'dynamic'.
; This value sets the limit on the number of simultaneous requests that will be
; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP
; CGI.
; Note: Used when pm is set to either 'static' or 'dynamic'
; Note: This value is mandatory.
pm.max_children = 50

; The number of child processes created on startup.
; Note: Used only when pm is set to 'dynamic'
; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2
pm.start_servers = 5

; The desired minimum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
pm.min_spare_servers = 5

; The desired maximum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
pm.max_spare_servers = 35

; The number of requests each child process should execute before respawning.
; This can be useful to work around memory leaks in 3rd party libraries. For
; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS.
; Default Value: 0
;pm.max_requests = 500

; The URI to view the FPM status page. If this value is not set, no URI will be
; recognized as a status page. By default, the status page shows the following
; information:
;   accepted conn    - the number of request accepted by the pool;
;   pool             - the name of the pool;
;   process manager  - static or dynamic;
;   idle processes   - the number of idle processes;
;   active processes - the number of active processes;
;   total processes  - the number of idle + active processes.
; The values of 'idle processes', 'active processes' and 'total processes' are
; updated each second. The value of 'accepted conn' is updated in real time.
; Example output:
;   accepted conn:   12073
;   pool:             www
;   process manager:  static
;   idle processes:   35
;   active processes: 65
;   total processes:  100
; By default the status page output is formatted as text/plain. Passing either
; 'html' or 'json' as a query string will return the corresponding output
; syntax. Example:
;  
;  
;  
; Note: The value must start with a leading slash (/). The value can be
;       anything, but it may not be a good idea to use the .php extension or it
;       may conflict with a real PHP file.
; Default Value: not set
;pm.status_path = /status

; The ping URI to call the monitoring page of FPM. If this value is not set, no
; URI will be recognized as a ping page. This could be used to test from outside
; that FPM is alive and responding, or to
; - create a graph of FPM availability (rrd or such);
; - remove a server from a group if it is not responding (load balancing);
; - trigger alerts for the operating team (24/7).
; Note: The value must start with a leading slash (/). The value can be
;       anything, but it may not be a good idea to use the .php extension or it
;       may conflict with a real PHP file.
; Default Value: not set
;ping.path = /ping

; This directive may be used to customize the response of a ping request. The
; response is formatted as text/plain with a 200 response code.
; Default Value: pong
;ping.response = pong

; The timeout for serving a single request after which the worker process will
; be killed. This option should be used when the 'max_execution_time' ini option
; does not stop script execution for some reason. A value of '0' means 'off'.
; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
; Default Value: 0
;request_terminate_timeout = 0

; The timeout for serving a single request after which a PHP backtrace will be
; dumped to the 'slowlog' file. A value of '0s' means 'off'.
; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
; Default Value: 0
;request_slowlog_timeout = 0

; The log file for slow requests
; Default Value: not set
; Note: slowlog is mandatory if request_slowlog_timeout is set
slowlog = /var/log/php-fpm/zabbix-slow.log

; Set open file descriptor rlimit.
; Default Value: system defined value
;rlimit_files = 1024

; Set max core size rlimit.
; Possible Values: 'unlimited' or an integer greater or equal to 0
; Default Value: system defined value
;rlimit_core = 0

; Chroot to this directory at the start. This value must be defined as an
; absolute path. When this value is not set, chroot is not used.
; Note: chrooting is a great security feature and should be used whenever
;       possible. However, all PHP paths will be relative to the chroot
;       (error_log, sessions.save_path, ...).
; Default Value: not set
;chroot =

; Chdir to this directory at the start. This value must be an absolute path.
; Default Value: current directory or / when chroot
;chdir = /var/www

; Redirect worker stdout and stderr into main error log. If not set, stdout and
; stderr will be redirected to /dev/null according to FastCGI specs.
; Default Value: no
catch_workers_output = yes

; Limits the extensions of the main script FPM will allow to parse. This can
; prevent configuration mistakes on the web server side. You should only limit
; FPM to .php extensions to prevent malicious users to use other extensions to
; exectute php code.
; Note: set an empty value to allow all extensions.
; Default Value: .php
security.limit_extensions = .php .php3 .php4 .php5

; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from
; the current environment.
; Default Value: clean env
;env[HOSTNAME] = $HOSTNAME
;env[PATH] = /usr/local/bin:/usr/bin:/bin
;env[TMP] = /tmp
;env[TMPDIR] = /tmp
;env[TEMP] = /tmp

; Additional php.ini defines, specific to this pool of workers. These settings
; overwrite the values previously defined in the php.ini. The directives are the
; same as the PHP SAPI:
;   php_value/php_flag             - you can set classic ini defines which can
;                                    be overwritten from PHP call 'ini_set'.
;   php_admin_value/php_admin_flag - these directives won't be overwritten by
;                                     PHP call 'ini_set'
; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no.

; Defining 'extension' will load the corresponding shared extension from
; extension_dir. Defining 'disable_functions' or 'disable_classes' will not
; overwrite previously defined php.ini values, but will append the new value
; instead.

; Default Value: nothing is defined by default except the values in php.ini and
;                specified at startup with the -d argument
;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com
;php_flag[display_errors] = off
php_admin_value[error_log] = /var/log/php-fpm/zabbix-error.log
php_admin_flag[log_errors] = on
;php_admin_value[memory_limit] = 128M

; Set session path to a directory owned by process user
php_value[session.save_handler] = files
php_value[session.save_path] =  /var/lib/php/zabbix_php-fpm/

 

its time to changue permissions allowing nginx

chown nginx:nginx /etc/zabbix/web/
ln -s /usr/share/zabbix /var/www/
service php-fpm restart
service nginx restart
setsebool -P httpd_can_network_connect  on

 

Open a web browser pointing to your domain and you should can view these screen

zabbix instalation screen

follow screen instructions and enjoy your new motorization service

And advice restart your server for check that everything will work ok if a power outage or another problem appears

webs from where i take info

creating a mysql  backup user — http://bencane.com/2011/12/12/creating-a-read-only-backup-user-for-mysqldump/

Zabbix with nginx  — http://qiita.com/ksworks/items/911561ef22687a13a70c

Nginx php-fpm secure — https://nealpoole.com/blog/2011/04/setting-up-php-fastcgi-and-nginx-dont-trust-the-tutorials-check-your-configuration/

 

Enable ssh access on a Iomega ix4-200d

If you need to enable ssh access in your nas device is easy.

For example if your nas ip is 192.168.0.24 open a web browser with  https://192.168.0.24/supportaccess.html

ix4-200d enable sshmark Allow remote access for support (SSH and SFTP)

click apply and iomega ix4-200d will reboot

to access over ssh your need to add soho prefix in your password. For example if your admin password  is peter your ssh password will be sohopeter