Haproxy load balance smtp round-robin style (4 Responses)

Dans ce billet: la mise en place d’un proxy smtp qui fera du load balancing entre plusieurs serveurs (smtp…).

Le schéma: Un proxy SMTP qui redistribuera les mails reçus sur le port 587 (interface publique) à cinq (dont le serveur haproxy lui même…) autres serveurs SMTP, en faisant du round robin (chacun son tour) et en appliquant un poids (que vous définirez en fonction de la capacité de chaque serveur) à chaque serveur.

Avec un dessin peut-être ?

J’ai opté pour haproxy, très simple à mettre en place et peu consommateur de ressources.

# apt-cache policy haproxy
haproxy:
Installed: 1.5.8-2~bpo70+1
Candidate: 1.5.8-2~bpo70+1
Package pin: 1.5.8-2~bpo70+1
Version table:
1.5.8-3 999
500 http://debian.mirrors.ovh.net/debian/ jessie/main amd64 Packages
*** 1.5.8-2~bpo70+1 999
100 http://http.debian.net/debian/ wheezy-backports/main amd64 Packages
100 /var/lib/dpkg/status

N’installez pas la version Jessie de Haproxy, elle est buguée…

# service haproxy restart
[….] Restarting haproxy: haproxy[ALERT] 103/092622 (25184) : Starting proxy stats: cannot bind socket [0.0.0.0:PORT_WEBUI]
[ALERT] 103/092622 (25184) : Starting frontend Proxy_SMTP: cannot bind socket [xxx.xxx.xxx.xxx:587]
failed!

En fait Haproxy ne s’arrête pas…

# ps ax | grep haproxy
12097 ? Ss 0:00 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -D -p /var/run/haproxy.pid
12205 ? Ss 0:00 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -D -p /var/run/haproxy.pid
12239 ? Ss 0:00 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -D -p /var/run/haproxy.pid
12258 pts/1 S+ 0:00 grep haproxy

Le seul moyen de redémarrer Haproxy:

# killall haproxy
# service haproxy start

Donc on installe la version des Backports de Wheezy!

Ajout des backports:

deb http://http.debian.net/debian wheezy-backports main

Finalement installation:

# apt-get install haproxy

Ou si vous êtes en Jessie:

# apt-get install haproxy/wheezy-backports

Avec le fichier « preferences » qui va bien pour ne pas passer sur la version Jessie par inadvertance:

# cat /etc/apt/preferences.d/haproxy
Package: haproxy
Pin: release a=wheezy-backports
Pin-Priority: 999

# apt-cache policy haproxy
haproxy:
Installed: 1.5.8-2~bpo70+1
Candidate: 1.5.8-2~bpo70+1
Package pin: 1.5.8-2~bpo70+1
Version table:
1.5.8-3 999
500 http://debian.mirrors.ovh.net/debian/ jessie/main amd64 Packages
*** 1.5.8-2~bpo70+1 999
100 http://http.debian.net/debian/ wheezy-backports/main amd64 Packages
100 /var/lib/dpkg/status


Configuration: Toute la conf se passe dans le fichier /etc/haproxy/haproxy.cfg

Nous allons commencer par la section « global » à laquelle nous ne touchons pas…

global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL).
ssl-default-bind-ciphers kEECDH+aRSA+AES:kRSA+AES:+AES256:RC4-SHA:!kEDH:!LOW:!EXP:!MD5:!aNULL:!eNULL
ssl-default-bind-options no-sslv3

Mais nous modifions par contre la façon dont les logs sont gérés:

Dans /etc/rsyslog.d/49-haproxy.conf

$ModLoad imudp
$UDPServerAddress 127.0.0.1
$UDPServerRun 514
local0.* -/var/log/haproxy-info.log
local1.* -/var/log/haproxy-allbutinfo.log
& ~

Ne pas oublier le log rotate (notez l’ajout du wildcard… haproxy*.log)

/var/log/haproxy*.log {
daily
rotate 52
missingok
notifempty
compress
delaycompress
postrotate
invoke-rc.d rsyslog rotate >/dev/null 2>&1 || true
endscript
}

# /etc/init.d/rsyslog restart && /etc/init.d/haproxy restart && vdir /var/log/haproxy*
[ ok ] Stopping enhanced syslogd: rsyslogd.
[ ok ] Starting enhanced syslogd: rsyslogd.
[ ok ] Restarting haproxy: haproxy.
-rw-r—– 1 root adm 639 Apr 14 12:02 /var/log/haproxy-allbutinfo.log
-rw-r—– 1 root adm 639 Apr 14 12:02 /var/log/haproxy-info.log


Vient ensuite la section « defaults »

Ici nous changeons le mode http par le tcp, nous enlevons le httplog et les différents fichiers d’erreur:

defaults
log global
mode tcp
option dontlognull
option redispatch
maxconn 2048
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms


Nous configurons maintenant le WEBUI qui nous permettra de surveiller que tout se déroule bien ((tout du moins au début, je déconseille de laisser l’interface Web en prod, ou de bien la protéger avec iptables).

Ajoutez le bloc suivant au fichier de configuration: PORT au choix, CHEMIN au choix, IDENTIFIANT et MOTDEPASSE au choix.

listen stats :PORT
mode http
stats enable
stats hide-version
stats realm Haproxy\ Statistics
stats uri /CHEMIN?stats
stats auth IDENTIFIANT:MOTDEPASSE

N’oubliez pas la règle iptables pour que le port soit accessible
-A INPUT -p tcp -m tcp --dport PORT -j ACCEPT

On redémarre haproxy et on se rend sur l’interface Web:
http://serveur.domaine.tld:PORT/CHEMIN?stats

Il vous demandera vos identifiants évidemment…

Haproxy WebUI

Haproxy WebUI


Maintenant la partie « amusante »:
Nous allons séparer le « frontend » (la partie qui écoute) et le backend (la définition des serveurs à qui nous dispatchons les mails)

1) Le Frontend

Toujours dans /etc/haproxy.bak/haproxy.cfg

Ajoutez ceci:

frontend Proxy_SMTP
bind IP_PUBLIQUE_DE_HAPROXY:587
acl white_list src 127.0.0.1 IP_CLIENT1 IP_CLIENT2
mode tcp
rate-limit sessions 5000
no option http-server-close
timeout client 1m
log global
option tcplog
default_backend Serveurs_Postfix

Explications:
Nous donnons un nom au Frontend: Proxy_SMTP
Haproxy est lié au port 587 sur l’IP publique (Attention, il faut désactiver le port 587 dans postfix)
Nous mettons en liste blanche les IP qui se connecterons au Proxy pour envoyer des mails (seules ces IP ont le droit de se connecter à haproxy).
Nous définissons une limite de sessions concomitantes maximum.
Un « timeout » de 1 minute.
Nous définissons le backend (Serveurs_Postfix).


2) Le Backend

backend Serveurs_Postfix
mode tcp
log global
option tcplog
#option smtpchk HELO hostname
timeout server 1m
timeout connect 5s
balance roundrobin

server smtp0 127.0.0.1:25 weight 256 check inter 8000
server smtp1 IP_SMTP1:25 weight 128 check inter 8000
server smtp2 IP_SMTP2:25 weight 64 check inter 8000
server smtp2 IP_SMTP3:25 weight 32 check inter 8000
server smtp2 IP_SMTP4:25 weight 16 check inter 8000

haproxy 02

Make a Comment

Your email address will not be published.

You can make the comment area bigger by pulling the arrow. If you are techie, you can use basic HTML tags and attributes to format your comment.

(required)

*

code

    {"widget_type":"comment_query","include_string":71,"exclude_string":"","page":0,"query_type":"","supplemental_filter":""}

    Mailpile

    Découverte bien sympa aujourd’hui: Mailpile.
    100% Free & Open Source Software (j’en parlerais même pas sinon…), support gpg en dur pour crypter vos messages, rapide, et très simple à installer.
    Vivement que ce ne soit plus en Beta… Mailpile est vraiment différent de tout ce que vous connaissiez, et c’est agréable.

    Mailpile 1200x651

    Prérequis:
    gnupgp (preferably on the 1.x branch for now, as Mailpile doesn’t currently act as a GPG Agent)
    OpenSSL
    Python 2.7+

    Choppez le code avec git:

    laurent@ns1:~$ git clone https://github.com/mailpile/Mailpile.git

    Cloning into ‘Mailpile’…
    remote: Counting objects: 30553, done.
    remote: Total 30553 (delta 0), reused 0 (delta 0), pack-reused 30553
    Receiving objects: 100% (30553/30553), 16.69 MiB | 4.00 MiB/s, done.
    Resolving deltas: 100% (20114/20114), done.Installez deux/trois trucs en plus si nécessaire:

    root@ns1:~# apt-get install python-pip
    root@ns1:~# apt-get install python-dev
    root@ns1:~# pip install -r /home/laurent/Mailpile/requirements.txt
    Successfully installed lxml Jinja2 spambayes markupsafe pyDNS pgpdump lockfile

    laurent@tor:~$ cd Mailpile/

    Maintenant je vais gentiment demander à Mailpile d’écouter sur toutes les interfaces réseaux (le soft est sur un serveur, j’ai besoin d’y accéder à distance).
    Si vous l’installez sur votre desktop / laptop lancez simplement ./mp il sera alors accessible dans votre navigateur (qui devrait s’ouvrir tout seul au lancement de Mailpile) au lien suivant:

    http://127.0.0.1:33411.

    laurent@ns1:~/Mailpile$ ./mp –set sys.http_host=0.0.0.0
    Failed to configure i18n. Using fallback.
    Elapsed: 0.015s (set: Updated your settings)
    {
    « sys.http_host »: « 0.0.0.0 »
    }

    Au lancement suivant, inutile de repréciser l’interface, c’est enregistré automatiquement dans la conf.

    laurent@ns1:~/Mailpile$ ./mp
    Failed to configure i18n. Using fallback.
    Metadata index not found: /home/laurent/.local/share/Mailpile/default/mailpile.idx
    Elapsed: 0.001s (load: Loaded metadata index)
    Mailpile.py a tool Copyright 2013-2014, Mailpile ehf
    for searching and <https://www.mailpile.is/>
    organizing piles of e-mail

    This program is free software: you can redistribute it and/or modify it under
    the terms of either the GNU Affero General Public License as published by the
    Free Software Foundation or the Apache License 2.0 as published by the Apache
    Software Foundation. See the file COPYING.md for details.

    The Web interface address is: http://0.0.0.0:33411/

    * Type `help` for instructions or `quit` to quit.
    * Long running operations can be aborted by pressing: <CTRL-C>

    mailpile>

    La console: :-)

    mailpile> help
    Elapsed: 0.003s (tags: Listed 0 tags)

    Commands:
    setup [do_gpg_stuff] Enter setup flow
    load Load or reload the metadata index
    interact
    q|quit Exit Mailpile, normal shutdown
    rescan [full|vcards|vcards:<src>|both|mailboxes|sources|<msgs>]
    Add new messages to index
    wait
    optimize [harder] Optimize the keyword search index
    gpg <GPG arguments …> Interact with GPG directly
    browse_o Launch browser and exit, if already running
    cat </path/to/file> [>/path/to/output] Dump the contents of a file, decrypting if necessary
    cd <…/new/path/…> Change working directory
    login Authenticate a user (log in)
    logout [<session ID>] De-authenticate a user (log out)
    ls <…/new/path/…> Display working directory listing
    pidfile </path/to/pidfile> Write the PID to a file
    pipe [e@mail.com|command|>filename] — [<cmd> [args … ]]
    Pipe a command to a shell command, file or e-mail
    ps Display list of running threads, locks and outstanding events.
    www [<host:port>] Just run the web server
    vcards [–lines] [<terms>] Find vcards
    cached [<cache-id>] Fetch results from the command cache.
    output [json|text|html|<template>.html|…] Choose format for command results.
    crypto_p [<emailaddresses>] Retrieve the current crypto policy for a user
    eventlog [incomplete] [wait] [<count>] [<field>=<val> <f>!=<v> <f>=~<re> …]
    Display events from the event log
    hashcash <bits> <challenge> Try to collide a hash using the SMTorP algorithm
    u|undo [<Event ID>] Undo either the last action or one specified by Event ID

    append
    <section.variable> <value> Add a new value to a list (or ordered dict) setting
    S|set
    <section.variable> <value> Change a setting
    U|unset <var> Reset one or more settings to their defaults
    P|print [-short|-secrets|-flat] <var> Print one or more settings
    A|add
    <path/to/mailbox> Add one or more mailboxes
    h|help [<command-group>] Print help on Mailpile or individual commands.
    plugins [
    <plugins>] List the currently available plugins.

    s|search [@<start>] <terms> Search your mail!
    unthread Remove a message from a thread.
    n|next Display next page of results
    p|previous Display previous page of results
    o|order <how> Sort by: date, from, subject, random or index
    v|view [raw] <message> View one or more messages
    e|extract <msgs> <att> [><fn>] Extract attachment(s) to file(s)

    tag <[+|-]tags> <msgs> Add or remove tags on a set of messages
    tags [<wanted>|!<wanted>] […] List tags
    filter [new|read] [notag] [=<mid>] [<terms>] [+<tag>] [-<tag>] [<comment>]
    Add auto-tag rule for current search or terms
    contacts [–lines] [<terms>]
    profiles [–lines] [<terms>]
    groups [–lines] [<terms>] Find groups
    autotag <msgs>

    C|compose [ephemeral] Create a new blank e-mail for editing
    E|edit [<messages>] Edit an existing draft
    m|mail Update message from an HTTP upload and move to outbox.
    update <messages> <<filename> Update message from a file or HTTP upload.
    a|attach <messages> [
    <path/to/file>] Attach a file to a message
    unattach <mid> <atts> Remove an attachment from a message
    r|reply [all|ephemeral] <messages> Create reply(-all) drafts to one or more messages
    f|forward [att|ephemeral] <messages> Create forwarding drafts of one or more messages
    bounce <messages> [<emails>] Mail/bounce a message (to someone)
    sendmail Try to empty the outbox.

    export [-flat] [-notags] <msgs> [<fmt>:
    <path>] Export messages to an external mailbox

    Tags: (use a tag as a command to display tagged messages)

    mailpile>

    Je vous laisse faire la suite, vous êtes de grands garçons (et filles):
    Ajouter un Profile/Source et accès smtp pour envoyer vos messages.
    Et lisez vos mails…

    Mailpile 02

    Un p’tit truc si vous commencez avec une boite mail déjà bien pleine…

    Marquer tout comme lu:

    mailpile> search in:new
    Elapsed: 0.131s (search: Found 91271 results in 0.127s)


    7 WordPress *Nouveau site WordPress (Inbox)7 hours

    10 root *Postfix: Rapport quotidien (Inbox)8 hours
    11 lol ****UNCHECKED*** mailpile (Inbox[E]10 hours
    12 Karmaweb *Request for confirmation (Inbox)22 hours

    20 Karmaweb *WHMCS Automatic Setup Successful (Inbox)2 days

    mailpile> tag -new all
    Elapsed: 1.006s (tag: Tagged 91271 messages)

    Untagged New (91271 messages)

    mailpile>

    Et pour finir le script de démarrage qui va bien:

    https://github.com/coeusite/mailpile-debian-init-script/blob/master/mailpile
    (ne pas oublier le chmod +x et update-rc.d mailpile default qui vont bien)

    #!/bin/bash
    ### BEGIN INIT INFO
    # Provides: mailpile
    # Required-Start: $local_fs $remote_fs $network $syslog
    # Required-Stop: $local_fs $remote_fs $network $syslog
    # Default-Start: 2 3 4 5
    # Default-Stop: 0 1 6
    # Short-Description: Start/stop mailpile daemon
    ### END INIT INFO
    # ——————————————————————————
    # /etc/init.d/mailpile
    #
    # This script is an init script to run mailpile in the background, using a
    # screen. The script was designed and tested for Debian systems, but may work on
    # other systems. On Debian, enable it by moving the script to
    # « /etc/init.d/mailpile » and issuing the command
    # « update-rc.d mailpile defaults 99″
    # ——————————————————————————
    ## Username to run mailpile under
    USER= »mailpile »
    ## Absolute path to the mailpile binary.
    MAILPILE= »/home/mailpile/Mailpile/mp »
    ## Absolute path to the screen binary.
    SCREEN= »/usr/bin/screen »
    ## Name of the screen session, you can then « screen -r mailpile » to get it back
    ## to the forground and work with it on your shell.
    SCREEN_NAME= »mailpile »
    ## Absolute path to mailpile’s PID file.
    PIDFILE= »/var/run/mailpile.pid »
    case « $1 » in
    ## Start mailpile in the background.
    start)
    echo « Starting mailpile. »
    start-stop-daemon –start –background –oknodo \
    –pidfile « $PIDFILE » –make-pidfile \
    –chuid $USER \
    –exec $SCREEN — -DmUS $SCREEN_NAME $MAILPILE
    if [[ $? -ne 0 ]]; then
    echo « Error: mailpile failed to start. »
    exit 1
    fi
    echo « mailpile started successfully. »
    ;;
    ## Stop mailpile.
    stop)
    echo « Stopping mailpile. »
    start-stop-daemon –stop –oknodo –pidfile « $PIDFILE »
    if [[ $? -ne 0 ]]; then
    echo « Error: failed to stop mailpile process. »
    exit 1
    fi
    echo « mailpile stopped successfully. »
    ;;
    ## Restart mailpile.
    restart)
    « $0 » stop
    sleep 1
    « $0 » start || exit 1
    ;;
    ## Print usage information if the user gives an invalid option.
    *)
    echo « Usage: $0 [start|stop|restart] »
    exit 1
    ;;
    esac

     

    Ce site et le serveur qui l'héberge utilisent UNIQUEMENT des LOGICIELS LIBRES.

    Serveur propulsé par Debian Stable, site gracieusement hébergé par Karmaweb

    Ce site (évidemment) utilise des cookies (et vous savez pourquoi). Ces cookies ne sont pas (et ne seront jamais) utilisés à des fins commerciales. Je suppose que vous êtes d’accord ?
    okidoc
    x