Debian + Postfix + Dovecot + Multidomain + SSL + IPv6 + OpenVPN + Multi-interfaces + SpamAssassin-learn + Bind

Cet article explique comment configurer un serveur de messagerie moderne.
Postfix + Dovecot. SPF + DKIM + rDNS. Avec IPv6.
Avec un chiffrement TSL. Avec prise en charge de plusieurs domaines — partie avec un vĂ©ritable certificat SSL.
Avec une protection anti-spam et un score anti-spam élevé par rapport à d'autres serveurs de messagerie.
Avec prise en charge de plusieurs interfaces physiques.
Avec OpenVPN, auquel on se connecte via IPv4, et qui fournit de l'IPv6.

Si vous ne souhaitez pas Ă©tudier toutes ces technologies, mais voulez configurer un tel serveur — alors cet article est fait pour vous.

L'article n'essaie pas d'expliquer chaque détail. L'explication concerne les configurations non standards ou celles importantes du point de vue de l'utilisateur.

La motivation pour configurer un serveur de messagerie — un vieux rĂȘve. Cela peut sembler stupide, mais Ă  mon avis, c'est bien mieux que de rĂȘver d'une nouvelle voiture de marque prĂ©fĂ©rĂ©e.

La motivation pour configurer l'IPv6 — double. Un professionnel de l'IT doit constamment apprendre de nouvelles technologies pour survivre. Je veux apporter ma contribution à la lutte contre la censure.

La motivation pour configurer OpenVPN — uniquement pour que l'IPv6 fonctionne sur ma machine locale.
La motivation pour configurer plusieurs interfaces physiques — j'ai sur mon serveur une interface « lente mais illimitĂ©e » et une autre « rapide mais avec un tarif ».

La motivation pour configurer Bind — mon fournisseur propose un serveur DNS instable, et Google peut Ă©galement rencontrer des pannes. Je veux un serveur DNS stable pour un usage personnel.

La motivation Ă  Ă©crire cet article — le brouillon a Ă©tĂ© Ă©crit il y a 10 mois, et je l'ai dĂ©jĂ  consultĂ© deux fois. Si mĂȘme l'auteur en a rĂ©guliĂšrement besoin, il y a de fortes chances que d'autres en aient aussi besoin.

Il n'y a pas de solution universelle pour un serveur de messagerie. Mais je vais essayer d'Ă©crire quelque chose comme « faites ceci et ensuite, quand tout fonctionnera comme il faut — jetez le superflu ».

Il y a un serveur de colocation chez tech.ru. Il est possible de comparer avec OVH, Hetzner, AWS. Pour relever ce défi, il sera beaucoup plus efficace de collaborer avec tech.ru.

Le serveur fonctionne sous Debian 9.

Le serveur a 2 interfaces `eno1` et `eno2`. La premiÚre est illimitée, et la seconde est rapide.

Il y a 3 adresses IP statiques, XX.XX.XX.X0 et XX.XX.XX.X1 et XX.XX.XX.X2 sur l'interface `eno1` et XX.XX.XX.X5 sur l'interface `eno2`.

Il y a un pool d'adresses IPv6 XXXX:XXXX:XXXX:XXXX::/64, qui sont attribuées à l'interface `eno1` et de laquelle XXXX:XXXX:XXXX:XXXX:1:2::/96 a été attribuée à `eno2` à ma demande.

Il y a 3 domaines `domain1.com`, `domain2.com`, `domain3.com`. Pour `domain1.com` et `domain3.com`, il existe un certificat SSL.

Il y a un compte Google que je veux lier à la boßte mail `vasya.pupkin@domain1.com` (réception et envoi d'emails directement depuis l'interface gmail).
Il doit y avoir une boßte mail `support@domain2.com`, dont je souhaite recevoir une copie des emails dans ma boßte gmail. Et avoir la possibilité d'envoyer occasionnellement des emails au nom de `support@domain2.com` via l'interface web.

Il doit y avoir une boßte mail `ivanov@domain3.com`, utilisée par Ivanov sur son iPhone.

Les emails envoyés doivent répondre à toutes les exigences modernes en matiÚre de lutte contre le spam.
Il doit y avoir le plus haut niveau de chiffrement prévu pour les réseaux publics.
Il doit y avoir un support IPv6 pour l'envoi et la réception des emails.
Il doit y avoir SpamAssassin, qui ne supprimera jamais d'emails. Il devra soit les faire rebondir, soit les laisser passer, soit les envoyer dans le dossier IMAP 'Spam'.
L'auto-apprentissage de SpamAssassin doit ĂȘtre configurĂ© : si je dĂ©place un email dans le dossier 'Spam', il doit s'entraĂźner lĂ -dessus ; si je dĂ©place un email hors du dossier 'Spam', il doit Ă©galement s'entraĂźner. Les rĂ©sultats de l'apprentissage de SpamAssassin doivent influencer la classification des emails dans le dossier 'Spam'.
Les scripts php doivent pouvoir envoyer des emails au nom de n'importe quel domaine sur ce serveur.
Il doit y avoir un service openvpn, avec la possibilité d'utiliser IPv6 sur un client qui n'a pas IPv6.

Tout d'abord, il faut configurer les interfaces et le routage, y compris IPv6.
Ensuite, il faudra configurer OpenVPN, qui se connectera via IPv4 et fournira à un client une adresse IPv6 réelle statique. Ce client aura accÚs à tous les services IPv6 sur le serveur et à toute ressource IPv6 sur Internet.
Ensuite, il faudra configurer Postfix pour l'envoi d'emails + SPF + DKIM + rDNS et d'autres petites choses similaires.
Ensuite, il faudra configurer Dovecot et configurer le multidomaine.
Puis, il faudra configurer SpamAssassin et paramétrer l'apprentissage.
Enfin, installer Bind.

============= Multi-interfaces =============

Pour configurer les interfaces, il faut écrire ce qui suit dans '"/etc/network/interfaces'.

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
allow-hotplug eno1
iface eno1 inet static
        address XX.XX.XX.X0/24
        gateway XX.XX.XX.1
        dns-nameservers 127.0.0.1 213.248.1.6
        post-up ip route add XX.XX.XX.0/24 dev eno1 src XX.XX.XX.X0 table eno1t
        post-up ip route add default via XX.XX.XX.1 table eno1t
        post-up ip rule add table eno1t from XX.XX.XX.X0
        post-up ip rule add table eno1t to XX.XX.XX.X0

auto eno1:1
iface eno1:1 inet static
address XX.XX.XX.X1
netmask 255.255.255.0
        post-up ip rule add table eno1t from XX.XX.XX.X1
        post-up ip rule add table eno1t to XX.XX.XX.X1
        post-up   ip route add 10.8.0.0/24 dev tun0 src XX.XX.XX.X1 table eno1t
        post-down ip route del 10.8.0.0/24 dev tun0 src XX.XX.XX.X1 table eno1t

auto eno1:2
iface eno1:2 inet static
address XX.XX.XX.X2
netmask 255.255.255.0
        post-up ip rule add table eno1t from XX.XX.XX.X2
        post-up ip rule add table eno1t to XX.XX.XX.X2

iface eno1 inet6 static
        address XXXX:XXXX:XXXX:XXXX:1:1::/64
        gateway XXXX:XXXX:XXXX:XXXX::1
        up   ip -6 addr add XXXX:XXXX:XXXX:XXXX:1:1:1:1/64 dev $IFACE
        up   ip -6 addr add XXXX:XXXX:XXXX:XXXX:1:1:1:2/64 dev $IFACE
        down ip -6 addr del XXXX:XXXX:XXXX:XXXX:1:1:1:1/64 dev $IFACE
        down ip -6 addr del XXXX:XXXX:XXXX:XXXX:1:1:1:2/64 dev $IFACE

# The secondary network interface
allow-hotplug eno2
iface eno2 inet static
        address XX.XX.XX.X5
        netmask 255.255.255.0
        post-up   ip route add XX.XX.XX.0/24 dev eno2 src XX.XX.XX.X5 table eno2t
        post-up   ip route add default via XX.XX.XX.1 table eno2t
        post-up   ip rule add table eno2t from XX.XX.XX.X5
        post-up   ip rule add table eno2t to XX.XX.XX.X5
        post-up   ip route add 10.8.0.0/24 dev tun0 src XX.XX.XX.X5 table eno2t
        post-down ip route del 10.8.0.0/24 dev tun0 src XX.XX.XX.X5 table eno2t

iface eno2 inet6 static
        address XXXX:XXXX:XXXX:XXXX:1:2::/96
        up   ip -6 addr add XXXX:XXXX:XXXX:XXXX:1:2:1:1/64 dev $IFACE
        up   ip -6 addr add XXXX:XXXX:XXXX:XXXX:1:2:1:2/64 dev $IFACE
        down ip -6 addr del XXXX:XXXX:XXXX:XXXX:1:2:1:1/64 dev $IFACE
        down ip -6 addr del XXXX:XXXX:XXXX:XXXX:1:2:1:2/64 dev $IFACE

# OpenVPN network
iface tun0 inet6 static
        address XXXX:XXXX:XXXX:XXXX:1:3::/80

Ces paramĂštres peuvent ĂȘtre appliquĂ©s sur n'importe quel serveur dans tech.ru (avec un petit accord avec le support) et cela fonctionnera immĂ©diatement comme prĂ©vu.

Si vous avez de l'expĂ©rience dans la configuration de choses similaires pour Hetzner, OVH — c'est diffĂ©rent lĂ -bas. Plus compliquĂ©.

eno1 — c'est le nom de l'interface rĂ©seau #1 (lent, mais illimitĂ©).
eno2 — c'est le nom de l'interface rĂ©seau #2 (rapide, mais avec un tarif).
tun0 — est le nom de la carte rĂ©seau virtuelle d'OpenVPN.
XX.XX.XX.X0 — IPv4 #1 sur eno1.
XX.XX.XX.X1 — IPv4 #2 sur eno1.
XX.XX.XX.X2 — IPv4 #3 sur eno1.
XX.XX.XX.X5 — IPv4 #1 sur eno2.
XX.XX.XX.1 — passerelle IPv4.
XXXX:XXXX:XXXX:XXXX::/64 — IPv6 pour tout le serveur.
XXXX:XXXX:XXXX:XXXX:1:2::/96 — IPv6 pour eno2, tout le reste passe par eno1.
XXXX:XXXX:XXXX:XXXX::1 — passerelle IPv6 (il convient de noter qu'il est possible/nĂ©cessaire de procĂ©der diffĂ©remment ici. SpĂ©cifier l'IPv6 du switch).
dns-nameservers — sont indiquĂ©s 127.0.0.1 (car bind est installĂ© localement) et 213.248.1.6 (c'est de tech.ru).

«table eno1t» et «table eno2t» — le but de ces rĂšgles de routage est que le trafic entrant par eno1 sorte par celui-ci, tandis que le trafic entrant par eno2 sorte par celui-ci. De plus, les connexions initier par le serveur doivent Ă©galement sortir par eno1.

ip route add default via XX.XX.XX.1 table eno1t

Cette commande indique que tout trafic indĂ©fini, correspondant Ă  une rĂšgle marquĂ©e «table eno1t» — doit ĂȘtre dirigĂ© vers l'interface eno1.

ip route add XX.XX.XX.0/24 dev eno1 src XX.XX.XX.X0 table eno1t

Cette commande indique que tout le trafic initiĂ© par le serveur doit ĂȘtre dirigĂ© vers l'interface eno1.

ip rule add table eno1t from XX.XX.XX.X0
ip rule add table eno1t to XX.XX.XX.X0

Cette commande définit les rÚgles de marquage du trafic.

auto eno1:2
iface eno1:2 inet static
address XX.XX.XX.X2
netmask 255.255.255.0
        post-up ip rule add table eno1t from XX.XX.XX.X2
        post-up ip rule add table eno1t to XX.XX.XX.X2

Ce bloc définit un second IPv4 pour l'interface eno1.

ip route add 10.8.0.0/24 dev tun0 src XX.XX.XX.X1 table eno1t

Cette commande définit la route des clients OpenVPN vers les IPv4 locaux, sauf XX.XX.XX.X0.
Pourquoi cette commande suffit-elle pour tous les IPv4 — je ne comprends toujours pas.

iface eno1 inet6 static
        address XXXX:XXXX:XXXX:XXXX:1:1::/64
        gateway XXXX:XXXX:XXXX:XXXX::1

Nous dĂ©finissons ainsi l'adresse pour l'interface elle-mĂȘme. Le serveur l'utilisera comme adresse «sortante». Elle ne sera pas utilisĂ©e autrement.

Pourquoi l'indication «:1:1::» est-elle si complexe ? Pour que l'OpenVPN fonctionne correctement et uniquement pour cela. Nous en reparlerons plus tard.

Concernant la passerelle — cela fonctionne et c'est tout. Mais de maniĂšre correcte — ici, il faut spĂ©cifier l'IPv6 du switch auquel le serveur est connectĂ©.

Cependant, pour une raison quelconque, l'IPv6 cesse de fonctionner si je fais cela. C'est probablement un problĂšme de tech.ru.

ip -6 addr add XXXX:XXXX:XXXX:XXXX:1:1:1:1/64 dev $IFACE

Cela ajoute une adresse IPv6 Ă  l'interface. Si une centaine d'adresses sont nĂ©cessaires — alors il faudra une centaine de lignes dans ce fichier.

iface eno1 inet6 static
        address XXXX:XXXX:XXXX:XXXX:1:1::/64
...
iface eno2 inet6 static
        address XXXX:XXXX:XXXX:XXXX:1:2::/96
...
iface tun0 inet6 static
        address XXXX:XXXX:XXXX:XXXX:1:3::/80

J'ai noté les adresses et sous-réseaux de toutes les interfaces pour que cela soit clair.
eno1 — doit nĂ©cessairement ĂȘtre «/64» — car c'est l'ensemble de notre pool d'adresses.
tun0 — les sous-rĂ©seaux doivent ĂȘtre nĂ©cessairement plus grands que eno1. Sinon, il ne sera pas possible de configurer la passerelle IPv6 pour les clients OpenVPN.
eno2 — les sous-rĂ©seaux doivent ĂȘtre nĂ©cessairement plus grands que tun0. Sinon, les clients OpenVPN ne pourront pas accĂ©der aux adresses IPv6 locales.
Pour plus de clartĂ©, j'ai choisi un pas de sous-rĂ©seau de 16, mais il est mĂȘme possible de faire un pas de «1» si souhaitĂ©.
Par conséquent, 64 + 16 = 80, et 80 + 16 = 96.

Pour une visualisation encore plus claire :
XXXX:XXXX:XXXX:XXXX:1:1:YYYY:YYYY — ce sont les adresses qui doivent ĂȘtre assignĂ©es Ă  des sites ou services spĂ©cifiques sur l'interface eno1.
XXXX:XXXX:XXXX:XXXX:1:2:YYYY:YYYY — ce sont les adresses qui doivent ĂȘtre assignĂ©es Ă  des sites ou services spĂ©cifiques sur l'interface eno2.
XXXX:XXXX:XXXX:XXXX:1:3:YYYY:YYYY — ce sont les adresses qui doivent ĂȘtre assignĂ©es aux clients OpenVPN ou utilisĂ©es comme adresses de service OpenVPN.

Pour configurer le rĂ©seau — il doit ĂȘtre possible de redĂ©marrer le serveur.
Les modifications IPv4 sont prises en compte lors de l'exĂ©cution (il faut absolument exĂ©cuter dans screen — sinon, cette commande arrĂȘtera simplement le rĂ©seau sur le serveur) :

/etc/init.d/networking restart

Ajouter à la fin du fichier «/etc/iproute2/rt_tables» :

100 eno1t
101 eno2t

Sans cela, il n'est pas possible d'utiliser des tables personnalisées dans le fichier «/etc/network/interfaces».
Les chiffres doivent ĂȘtre uniques et infĂ©rieurs Ă  65535.

Les modifications IPv6 se changent facilement sans redémarrage, mais pour cela, il faut apprendre au moins trois commandes :

ip -6 addr ...
ip -6 route ...
ip -6 neigh ...

Configuration de «/etc/sysctl.conf»

# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward = 1

# Do not accept ICMP redirects (prevent MITM attacks)
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0

# Do not send ICMP redirects (we are not a router)
net.ipv4.conf.all.send_redirects = 0

# For receiving ARP replies
net.ipv4.conf.all.arp_filter = 0
net.ipv4.conf.default.arp_filter = 0

# For sending ARP
net.ipv4.conf.all.arp_announce = 0
net.ipv4.conf.default.arp_announce = 0

# Enable IPv6
net.ipv6.conf.all.disable_ipv6 = 0
net.ipv6.conf.default.disable_ipv6 = 0
net.ipv6.conf.lo.disable_ipv6 = 0

# IPv6 configuration
net.ipv6.conf.all.autoconf = 1
net.ipv6.conf.all.accept_ra = 0

# For OpenVPN
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.all.proxy_ndp = 1

# For nginx on boot
net.ipv6.ip_nonlocal_bind = 1

Voici les paramÚtres «sysctl» de mon serveur. Je souligne l'importance.

net.ipv4.ip_forward = 1

Sans cela, OpenVPN ne fonctionnera pas du tout.

net.ipv6.ip_nonlocal_bind = 1

Quiconque essaiera de faire un bind IPv6 (par exemple nginx) juste aprĂšs que l'interface ait Ă©tĂ© rĂ©initialisĂ©e — obtiendra une erreur indiquant que cette adresse n'est pas disponible.

Pour éviter cette situation, cette configuration est mise en place.

net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.all.proxy_ndp = 1

Sans ces paramĂštres, le trafic IPv6 des clients OpenVPN ne sort pas vers le monde.

Les autres paramĂštres ne se rapportent pas Ă  la question ou je ne me souviens pas Ă  quoi ils servent.
Mais au cas oĂč, je les laisse «tels quels».

Pour que les modifications de ce fichier soient prises en compte sans redĂ©marrer le serveur — il faut exĂ©cuter la commande :

sysctl -p

Plus de détails sur les rÚgles «table» : habr.com/post/108690

============= OpenVPN =============

OpenVPN IPv4 ne fonctionne pas sans iptables.

Voici mes iptables pour le VPN :

iptables -A INPUT -p udp -s YY.YY.YY.YY --dport 1194 -j ACCEPT
iptables -A FORWARD -i tun0 -o eno1 -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eno1 -j SNAT --to-source XX.XX.XX.X0
##iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eno1 -j MASQUERADE
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -p udp --dport 1194 -j DROP
iptables -A FORWARD -p udp --dport 1194 -j DROP

YY.YY.YY.YY est mon adresse IPv4 statique de la machine locale.
10.8.0.0/24 est le réseau IPv4 d'OpenVPN. Les adresses IPv4 des clients OpenVPN.
L'ordre des rĂšgles est important.

iptables -A INPUT -p udp -s YY.YY.YY.YY --dport 1194 -j ACCEPT
iptables -A FORWARD -i tun0 -o eno1 -j ACCEPT
...
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -p udp --dport 1194 -j DROP
iptables -A FORWARD -p udp --dport 1194 -j DROP

C'est une restriction pour que seul moi, avec mon IP statique, puisse utiliser OpenVPN.

iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eno1 -j SNAT --to-source XX.XX.XX.X0
  -- ou --
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eno1 -j MASQUERADE

Pour faire passer les paquets IPv4 entre les clients OpenVPN et Internet, il faut exécuter l'une de ces commandes.

Pour différents cas, l'une des options ne convient pas.
Dans mon cas, les deux commandes conviennent.
AprĂšs avoir lu la documentation, j'ai choisi la premiĂšre option, car elle consomme moins de CPU.

Pour que tous les réglages d'iptables soient pris en compte aprÚs un redémarrage, il faut les sauvegarder quelque part.

iptables-save > /etc/iptables/rules.v4
ip6tables-save > /etc/iptables/rules.v6

Ces noms ne sont pas choisis au hasard. Ils sont utilisés par le paquet « iptables-persistent ».

apt-get install iptables-persistent

Installation du paquet principal OpenVPN :

apt-get install openvpn easy-rsa

Configurons le modÚle pour les certificats (insérer vos propres valeurs) :

make-cadir ~/openvpn-ca
cd ~/openvpn-ca
ln -s openssl-1.0.0.cnf openssl.cnf

Modifions les paramĂštres du modĂšle de certificat :

mcedit vars

...
# Ces valeurs par défaut seront placées dans le certificat.
# Ne laissez aucun de ces champs vides.
export KEY_COUNTRY="FR"
export KEY_PROVINCE="Krasnodar"
export KEY_CITY="Dinskaya"
export KEY_ORG="Propre"
export KEY_EMAIL="admin@domain1.com"
export KEY_OU="VPN"

# Champ Sujet X509
export KEY_NAME="serveur"
...

Créons le certificat serveur :

cd ~/openvpn-ca
source vars
./clean-all
./build-ca
./build-key-server serveur
./build-dh
openvpn --genkey --secret keys/ta.key

Préparons la possibilité de créer les fichiers finaux « client-name.opvn » :

mkdir -p ~/client-configs/files
chmod 700 ~/client-configs/files
cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf ~/client-configs/base.conf
mcedit ~/client-configs/base.conf

# Client mode
client

# Interface tunnel type
dev tun

# TCP protocol
proto tcp-client

# Address/Port of VPN server
remote XX.XX.XX.X0 1194

# Don't bind to local port/address
nobind

# Don't need to re-read keys and re-create tun at restart
persist-key
persist-tun

# Remote peer must have a signed certificate
remote-cert-tls server
ns-cert-type server

# Enable compression
comp-lzo

# Custom
ns-cert-type server
tls-auth ta.key 1
cipher DES-EDE3-CBC

Préparons un script qui fusionnera tous les fichiers en un fichier opvn unique.

mcedit ~/client-configs/make_config.sh
chmod 700 ~/client-configs/make_config.sh

#!/bin/bash

# First argument: Client identifier

KEY_DIR=~/openvpn-ca/keys
OUTPUT_DIR=~/client-configs/files
BASE_CONFIG=~/client-configs/base.conf

cat ${BASE_CONFIG} 
    <(echo -e '<ca>') 
    ${KEY_DIR}/ca.crt 
    <(echo -e '</ca>n<cert>') 
    ${KEY_DIR}/${1}.crt 
    <(echo -e '</cert>n<key>') 
    ${KEY_DIR}/${1}.key 
    <(echo -e '</key>n<tls-auth>') 
    ${KEY_DIR}/ta.key 
    <(echo -e '</tls-auth>') 
    > ${OUTPUT_DIR}/${1}.ovpn

Créons le premier client OpenVPN :

cd ~/openvpn-ca
source vars
./build-key client-name
cd ~/client-configs
./make_config.sh client-name

Le fichier « ~/client-configs/files/client-name.ovpn » est envoyé sur l'appareil du client.

Pour les clients iOS, il faudra faire une astuce :
Le contenu de la balise «tls-auth» doit ĂȘtre sans commentaires.
Et aussi mettre «key-direction 1» juste avant la balise «tls-auth».

Configurons le fichier de configuration du serveur OpenVPN :

cd ~/openvpn-ca/keys
cp ca.crt ca.key server.crt server.key ta.key dh2048.pem /etc/openvpn
gunzip -c /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz | tee /etc/openvpn/server.conf
mcedit /etc/openvpn/server.conf

# Listen port
port 1194

# Protocol
proto tcp-server

# IP tunnel
dev tun0
tun-ipv6
push tun-ipv6

# Master certificate
ca ca.crt

# Server certificate
cert server.crt

# Server private key
key server.key

# Diffie-Hellman parameters
dh dh2048.pem

# Allow clients to communicate with each other
client-to-client

# Client config dir
client-config-dir /etc/openvpn/ccd

# Run client-specific script on connection and disconnection
script-security 2
client-connect "/usr/bin/sudo -u root /etc/openvpn/server-clientconnect.sh"
client-disconnect "/usr/bin/sudo -u root /etc/openvpn/server-clientdisconnect.sh"

# Server mode and client subnets
server 10.8.0.0 255.255.255.0
server-ipv6 XXXX:XXXX:XXXX:XXXX:1:3::/80
topology subnet

# IPv6 routes
push "route-ipv6 XXXX:XXXX:XXXX:XXXX::/64"
push "route-ipv6 2000::/3"

# DNS (for Windows)
# These are OpenDNS
push "dhcp-option DNS 208.67.222.222"
push "dhcp-option DNS 208.67.220.220"

# Configure all clients to redirect their default network gateway through the VPN
push "redirect-gateway def1 bypass-dhcp"
push "redirect-gateway ipv6" #For iOS

# Don't need to re-read keys and re-create tun at restart
persist-key
persist-tun

# Ping every 10s. Timeout of 120s.
keepalive 10 120

# Enable compression
comp-lzo

# User and group
user vpn
group vpn

# Log a short status
status openvpn-status.log

# Logging verbosity
##verb 4

# Custom config
tls-auth ta.key 0
cipher DES-EDE3-CBC

C'est nécessaire pour attribuer une adresse statique à chaque client (pas obligatoire, mais j'utilise) :

# Client config dir
client-config-dir /etc/openvpn/ccd

Le détail le plus complexe et crucial.

Malheureusement, OpenVPN ne sait pas encore configurer automatiquement la passerelle IPv6 pour les clients.
Il faut le faire «manuellement» pour chaque client.

# Run client-specific script on connection and disconnection
script-security 2
client-connect "/usr/bin/sudo -u root /etc/openvpn/server-clientconnect.sh"
client-disconnect "/usr/bin/sudo -u root /etc/openvpn/server-clientdisconnect.sh"

Fichier «/etc/openvpn/server-clientconnect.sh» :

#!/bin/sh

# Check client variables
if [ -z "$ifconfig_pool_remote_ip" ] || [ -z "$common_name" ]; then
        echo "Missing environment variable."
        exit 1
fi

# Load server variables
. /etc/openvpn/variables

ipv6=""

# Find out if there is a specific config with fixed IPv6 for this client
if [ -f "/etc/openvpn/ccd/$common_name" ]; then
        # Get fixed IPv6 from client config file
        ipv6=$(sed -nr 's/^.*ifconfig-ipv6-push[ t]+([0-9a-fA-F:]+).*$/1/p' "/etc/openvpn/ccd/$common_name")
        echo $ipv6
fi

# Get IPv6 from IPv4
if [ -z "$ipv6" ]; then
        ipp=$(echo "$ifconfig_pool_remote_ip" | cut -d. -f4)
        if ! [ "$ipp" -ge 2 -a "$ipp" -le 254 ] 2>/dev/null; then
                echo "Invalid IPv4 part."
                exit 1
        fi
        hexipp=$(printf '%x' $ipp)
        ipv6="$prefix$hexipp"
fi

# Create proxy rule
/sbin/ip -6 neigh add proxy $ipv6 dev eno1

Fichier «/etc/openvpn/server-clientdisconnect.sh» :

#!/bin/sh

# Check client variables
if [ -z "$ifconfig_pool_remote_ip" ] || [ -z "$common_name" ]; then
        echo "Missing environment variable."
        exit 1
fi

# Load server variables
. /etc/openvpn/variables

ipv6=""

# Find out if there is a specific config with fixed IPv6 for this client
if [ -f "/etc/openvpn/ccd/$common_name" ]; then
        # Get fixed IPv6 from client config file
        ipv6=$(sed -nr 's/^.*ifconfig-ipv6-push[ t]+([0-9a-fA-F:]+).*$/1/p' "/etc/openvpn/ccd/$common_name")
fi

# Get IPv6 from IPv4
if [ -z "$ipv6" ]; then
        ipp=$(echo "$ifconfig_pool_remote_ip" | cut -d. -f4)
        if ! [ "$ipp" -ge 2 -a "$ipp" -le 254 ] 2>/dev/null; then
                echo "Invalid IPv4 part."
                exit 1
        fi
        hexipp=$(printf '%x' $ipp)
        ipv6="$prefix$hexipp"
fi

# Delete proxy rule
/sbin/ip -6 neigh del proxy $ipv6 dev eno1

Les deux scripts utilisent le fichier «/etc/openvpn/variables» :

# Subnet
prefix=XXXX:XXXX:XXXX:XXXX:2:
# netmask
prefixlen=112

Pourquoi est-ce écrit ainsi, je ne me souviens pas.

Ça a l'air Ă©trange maintenant netmask = 112 (ici, ça devrait ĂȘtre 96).
Et le prefix est étrange, il ne correspond pas au réseau tun0.
Mais bon, je laisse «tel quel».

cipher DES-EDE3-CBC

C'est selon les goĂ»ts — j'ai choisi ce type de chiffrement de connexion.

Plus de détails sur la configuration d'OpenVPN IPv4.

Plus de détails sur la configuration d'OpenVPN IPv6.

============= Postfix =============

Installation du paquet principal :

apt-get install postfix

Lors de l'installation, choisir «internet-site».

Mon «/etc/postfix/main.cf» ressemble à ça :

smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no

# L'ajout de .domain est le travail du MUA.
append_dot_mydomain = no

readme_directory = no

# Voir http://www.postfix.org/COMPATIBILITY_README.html -- par défaut 2 sur
# les nouvelles installations.
compatibility_level = 2

# ParamĂštres TLS
smtpd_tls_cert_file=/etc/ssl/domain1.com.2018.chained.crt
smtpd_tls_key_file=/etc/ssl/domain1.com.2018.key
smtpd_use_tls=yes
smtpd_tls_auth_only = yes
smtp_bind_address = XX.XX.XX.X0
smtp_bind_address6 = XXXX:XXXX:XXXX:XXXX:1:1:1:1

smtp_tls_security_level = may
smtp_tls_ciphers = export
smtp_tls_protocols = !SSLv2, !SSLv3
smtp_tls_loglevel = 1

smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
myhostname = domain1.com
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = domain1.com
mydestination = localhost
relayhost =
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = ipv4

internal_mail_filter_classes = bounce

# Type de stockage
virtual_transport = lmtp:unix:private/dovecot-lmtp
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf

# ParamĂštres SMTP-Auth
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_recipient_restrictions =
        permit_sasl_authenticated,
        permit_mynetworks,
        #reject_invalid_hostname,
        #reject_unknown_recipient_domain,
        reject_unauth_destination,
        reject_rbl_client sbl.spamhaus.org,
        check_policy_service unix:private/policyd-spf

smtpd_helo_restrictions =
        #reject_invalid_helo_hostname,
        #reject_non_fqdn_helo_hostname,
        reject_unknown_helo_hostname

smtpd_client_restrictions =
        permit_mynetworks,
        permit_sasl_authenticated,
        reject_non_fqdn_helo_hostname,
        permit

# SPF
policyd-spf_time_limit = 3600

# OpenDKIM
milter_default_action = accept
milter_protocol = 6
smtpd_milters = unix:var/run/opendkim/opendkim.sock
non_smtpd_milters = unix:var/run/opendkim/opendkim.sock

# Adresse IP par domaine
sender_dependent_default_transport_maps = pcre:/etc/postfix/sdd_transport.pcre

Examinons les détails de cette configuration.

smtpd_tls_cert_file=/etc/ssl/domain1.com.2018.chained.crt
smtpd_tls_key_file=/etc/ssl/domain1.com.2018.key

Selon les membres de Habr, ce bloc contient `de la désinformation et des thÚses erronées`.Ce n'est qu'aprÚs 8 ans au début de ma carriÚre que j'ai commencé à comprendre comment fonctionne SSL.

Je vais donc m'efforcer de décrire comment utiliser SSL (sans répondre aux questions «Comment ça marche ?» et «Pourquoi ça marche ?»).

La base du chiffrement moderne est la création d'une paire de clés (deux trÚs longues chaßnes de caractÚres).

Une clĂ© est privĂ©e, l'autre est publique. La clĂ© privĂ©e doit ĂȘtre conservĂ©e trĂšs secrĂštement, tandis que la clĂ© publique peut ĂȘtre distribuĂ©e Ă  tous.

Avec la clé publique, on peut chiffrer une chaßne de texte de sorte que seul le propriétaire de la clé privée puisse la déchiffrer.
VoilĂ  donc les bases de la technologie.

Étape n°1 — sites HTTPS.
Lorsque le navigateur accÚde à un site, il apprend du serveur web que le site est en HTTPS et demande donc la clé publique.
Le serveur web transmet la clĂ© publique. Le navigateur utilise cette clĂ© publique pour chiffrer la requĂȘte http et l'envoie.
Le contenu de la requĂȘte http ne peut ĂȘtre lu que par celui qui possĂšde la clĂ© privĂ©e, c'est-Ă -dire uniquement le serveur auquel la requĂȘte est adressĂ©e.
La requĂȘte http contient au moins un URI. Ainsi, si un pays tente de restreindre l'accĂšs non pas Ă  tout le site, mais Ă  une page spĂ©cifique, cela est impossible pour les sites https.

Étape n°2 — la rĂ©ponse chiffrĂ©e.
Le serveur web fournit une rĂ©ponse qui peut ĂȘtre facilement lue en chemin.
La solution est trÚs simple : le navigateur génÚre localement une paire de clés privée-publique pour chaque site https.
Et avec la requĂȘte de la clĂ© publique du site, il envoie sa propre clĂ© publique locale.
Le serveur web la mémorise et lors de l'envoi de la réponse http, il chiffre celle-ci avec la clé publique de ce client spécifique.
Maintenant, la rĂ©ponse http ne peut ĂȘtre dĂ©chiffrĂ©e que par le dĂ©tenteur de la clĂ© privĂ©e du navigateur du client (c'est-Ă -dire le client lui-mĂȘme).

Étape n°3 — Ă©tablir une connexion sĂ©curisĂ©e par un canal public.
Dans l'exemple n°2, il y a une vulnĂ©rabilitĂ© : rien n'empĂȘche un attaquant d'intercepter la requĂȘte http et de modifier l'information sur la clĂ© publique.
Ainsi, l'intermédiaire pourra voir tout le contenu des messages envoyés et reçus tant que le canal de communication ne sera pas changé.
Pour y remédier, il suffit d'envoyer la clé publique du navigateur comme message chiffré avec la clé publique du serveur web.
Le serveur web commence alors par envoyer une rĂ©ponse du type « ta clĂ© publique est celle-ci » et chiffre ce message avec cette mĂȘme clĂ© publique.
Le navigateur regarde la réponse : si le message « ta clé publique est celle-ci » est reçu, cela garantit à 100 % que ce canal de communication est sécurisé.
À quel point est-il sĂ©curisĂ© ?
La création d'un tel canal de communication sécurisée se fait à la vitesse de ping*2. Par exemple, 20 ms.
Un attaquant doit soit avoir en avance la clé privée de l'une des parties, soit trouver la clé privée en quelques millisecondes.
Casser une clé privée moderne prendra des décennies sur un superordinateur.

Étape n°4 — base de donnĂ©es publique des clĂ©s publiques.
Il est évident qu'il existe une possibilité pour un attaquant se trouvant sur le canal de communication entre le client et le serveur.
La possibilité pour le client de se faire passer pour le serveur, et le serveur de se faire passer pour le client. Et de simuler une paire de clés dans les deux sens.
Ainsi, l'assaillant pourra voir tout le trafic et aura la possibilité de « modifier » ce trafic.
Par exemple, changer l'adresse à laquelle envoyer de l'argent ou copier le mot de passe d'une banque en ligne ou bloquer un contenu « indésirable ».
Pour lutter contre de tels assaillants, une base de données publique avec des clés publiques a été conçue pour chaque site https.
Chaque navigateur « sait » qu'il existe environ 200 de telles bases de données. Cela est préconfiguré dans chaque navigateur.
Cette « connaissance » est corroborée par la clé publique de chaque certificat. Ainsi, il est impossible de contrefaire la connexion à un centre de certification spécifique.

Il est maintenant facile de comprendre comment utiliser SSL pour https.
Si l'on utilise un peu son esprit, il devient évident comment les agences de renseignement pourraient exploiter cette configuration. Mais cela leur coûtera des efforts colossaux.
Et pour les organisations moins consĂ©quentes que la NSA ou la CIA, il est pratiquement impossible de percer le niveau de sĂ©curitĂ© existant, mĂȘme pour des cibles VIP.

J'ajouterai encore un mot sur les connexions ssh. Il n'y a pas de clés publiques, que faire alors ? La question se résout de deux maniÚres.
Option ssh par mot de passe :
Lors de la premiÚre connexion, le client ssh doit avertir qu'il s'agit d'une nouvelle clé publique du serveur ssh.
Et lors des connexions suivantes, si un avertissement « nouvelle clĂ© publique du serveur ssh » apparaĂźt, cela signifiera que vous ĂȘtes en train d'ĂȘtre espionnĂ©.
Ou que lors de la premiÚre connexion vous avez été espionné, et maintenant vous communiquez avec le serveur sans intermédiaires.
En fait, parce que le fait d’ĂȘtre espionnĂ© est facilement, rapidement et sans effort dĂ©tectable, cette attaque n'est utilisĂ©e que dans des cas particuliers ciblant un client spĂ©cifique.

Option ssh par clé :
Prenez une clé USB, enregistrez-y la clé privée pour le serveur ssh (il y a des termes et de nombreuses nuances à cela, mais j'écris pour l'éducation, pas un guide d'utilisation).
La clĂ© publique reste sur la machine oĂč sera le client ssh et elle est Ă©galement tenue secrĂšte.
Apportez la clé USB au serveur, branchez-la, copiez la clé privée, puis brûlez la clé USB et dispersez les cendres au vent (ou au moins formatez-la en remplissant de zéros).
C'est tout — aprĂšs cette opĂ©ration, il sera impossible de pirater une telle connexion SSH. Évidemment, dans 10 ans, un superordinateur pourra analyser le trafic — mais c'est une autre histoire.

Je m'excuse pour ce hors-sujet.

Donc, maintenant que la théorie est claire, je vais parler du processus de création d'un certificat SSL.

Nous créons une clé privée et des "gabarits" pour la clé publique avec "openssl genrsa".
Nous envoyons les "gabarits" Ă  une entreprise tierce, Ă  laquelle nous payons environ 9 $ pour le certificat le plus simple.

Au bout de quelques heures, nous recevons de cette entreprise notre "clé publique" ainsi qu'un ensemble de plusieurs clés publiques.

Pourquoi payer une entreprise tierce pour obtenir ma clĂ© publique — c'est une question Ă  part, que nous n'allons pas aborder ici.

Maintenant, il est clair ce que signifie l'inscription :

smtpd_tls_key_file=/etc/ssl/domain1.com.2018.key

Le dossier "/etc/ssl" contient tous les fichiers concernant SSL.
domain1.com — le nom de domaine.
2018 — l'annĂ©e de crĂ©ation des clĂ©s.
"key" — signifie que le fichier contient une clĂ© privĂ©e.

Et la signification de ce fichier :

smtpd_tls_cert_file=/etc/ssl/domain1.com.2018.chained.crt
domain1.com — le nom de domaine.
2018 — l'annĂ©e de crĂ©ation des clĂ©s.
chained — signifie qu'il s'agit d'une chaĂźne de clĂ©s publiques (la premiĂšre est notre clĂ© publique et les autres sont celles fournies par l'entreprise qui a Ă©mis la clĂ© publique).
crt — signifie qu'il s'agit d'un certificat prĂȘt (une clĂ© publique avec des explications techniques).

smtp_bind_address = XX.XX.XX.X0
smtp_bind_address6 = XXXX:XXXX:XXXX:XXXX:1:1:1:1

Cette configuration n'est pas utilisée dans ce cas, mais elle est mentionnée à titre d'exemple.

Parce qu'une erreur dans ce paramĂštre entraĂźnera l'envoi de spam depuis votre serveur (sans votre consentement).

Ensuite, il faudra prouver Ă  tout le monde que vous n'ĂȘtes pas en faute.

recipient_delimiter = +

Beaucoup de gens ne le savent peut-ĂȘtre pas, mais c'est le symbole standard pour le filtrage des emails, et cela est supportĂ© par la plupart des serveurs de mail modernes.

Par exemple, si vous avez une boĂźte mail "username@gmail.com", essayez d'envoyer Ă  "username+spam@gmail.com" — regardez ce qui en rĂ©sulte.

inet_protocols = ipv4

Cela peut prĂȘter Ă  confusion.

Mais ce n'est pas sans raison. Chaque nouveau domaine, par défaut, utilise uniquement IPv4, puis je m'assure d'activer IPv6 pour chacun individuellement.

virtual_transport = lmtp:unix:private/dovecot-lmtp
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf

Ici, nous définissons que tout le courrier entrant va dans dovecot.
Les rÚgles pour les domaines, les boßtes aux lettres et les alias sont à consulter dans la base de données.

/etc/postfix/mysql-virtual-mailbox-domains.cf

utilisateur = usermail
motdepasse = mailpassword
hĂŽtes = 127.0.0.1
derniernom = servermail
requĂȘte = SELECT 1 FROM virtual_domains WHERE name='%s'

/etc/postfix/mysql-virtual-mailbox-maps.cf

utilisateur = usermail
motdepasse = mailpassword
hĂŽtes = 127.0.0.1
derniernom = servermail
requĂȘte = SELECT 1 FROM virtual_users WHERE email='%s'

/etc/postfix/mysql-virtual-alias-maps.cf

utilisateur = usermail
motdepasse = mailpassword
hĂŽtes = 127.0.0.1
derniernom = servermail
requĂȘte = SELECT destination FROM virtual_aliases WHERE source='%s'

# SMTP-Auth settings
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes

Maintenant, postfix sait qu'il peut accepter des courriers Ă  envoyer uniquement avec une authentification de dovecot.

Je ne comprends vraiment pas pourquoi il faut le dupliquer ici. Nous avons déjà indiqué dans «virtual_transport» tout ce qu'il faut.

Mais le systùme postfix est trùs ancien — c'est probablement des rustines des temps anciens.

smtpd_recipient_restrictions =
        ...

smtpd_helo_restrictions =
        ...

smtpd_client_restrictions =
        ...

C'est à configurer différemment pour chaque serveur de messagerie.

Je dispose de 3 serveurs de messagerie et ces configurations sont trÚs différentes en raison de différentes exigences d'utilisation.

Il faut configurer cela attentivement — sinon le spam va inonder votre serveur ou, pire, vous serez l'origine du spam.

# SPF
policyd-spf_time_limit = 3600

Configuration pour un plugin lié à la vérification des courriers entrants SPF.

# OpenDKIM
milter_default_action = accept
milter_protocol = 6
smtpd_milters = unix:var/run/opendkim/opendkim.sock
non_smtpd_milters = unix:var/run/opendkim/opendkim.sock

Configuration stipulant que tous les courriers sortants doivent ĂȘtre accompagnĂ©s d'une signature DKIM.

# IP address per domain
sender_dependent_default_transport_maps = pcre:/etc/postfix/sdd_transport.pcre

C'est un détail clé dans la routage des courriers lors de l'envoi à partir de scripts PHP.

Fichier «/etc/postfix/sdd_transport.pcre»:

/^www-domain1@domain1.com$/ domain1:
/^www-domain2@domain1.com$/ domain2:
/^www-domain3@domain1.com$/ domain3:
/@domain1.com$/             domain1:
/@domain2.com$/             domain2:
/@domain3.com$/             domain3:

À gauche — expressions rĂ©guliĂšres. À droite — l'Ă©tiquette qui est associe Ă  l'email.
Postfix, conformément à l'étiquette, prendra en compte plusieurs autres lignes de configuration pour un courriel spécifique.

Comment exactement postfix sera reconfiguré pour un email spécifique sera indiqué dans «master.cf».

Les lignes 4, 5, 6 — elles sont principales. Au nom de quel domaine nous envoyons le message — telle Ă©tiquette nous mettons.
Mais il n'est pas toujours spécifié dans les anciens scripts PHP le champ «from». Alors le nom d'utilisateur entre en jeu.

L'article est dĂ©jĂ  assez vaste — je ne voudrais pas me dĂ©tourner sur la configuration nginx+fpm.

En rĂ©sumĂ© — pour chaque site, nous dĂ©finissons notre propre utilisateur linux propriĂ©taire. Et par consĂ©quent, notre propre pool fpm.

Le pool fpm utilise n'importe quelle version de php (c'est formidable car sur un mĂȘme serveur, il est possible d'utiliser diffĂ©rentes versions de php et mĂȘme diffĂ©rents php.ini sans problĂšme pour les sites voisins).

Ainsi, pour l'utilisateur linux spécifique «www-domain2», il y a un site domain2.com. Sur ce site, il y a du code d'envoi de courriers sans spécifier le champ from.

Ainsi, mĂȘme dans ce cas, les courriers seront envoyĂ©s correctement et ne tomberont jamais dans le spam.

Mon «/etc/postfix/master.cf» ressemble à cela :

...
smtp      inet  n       -       y       -       -       smtpd
  -o content_filter=spamassassin
...
submission inet n       -       y       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
...
policyd-spf  unix  -       n       n       -       0       spawn
    user=policyd-spf argv=/usr/bin/policyd-spf

spamassassin unix -     n       n       -       -       pipe
    user=spamd argv=/usr/bin/spamc -f -e
    /usr/sbin/sendmail -oi -f ${sender} ${recipient}
...
domain1  unix -       -       n       -       -       smtp
   -o smtp_bind_address=XX.XX.XX.X1
   -o smtp_helo_name=domain1.com
   -o inet_protocols=all
   -o smtp_bind_address6=XXXX:XXXX:XXXX:XXXX:1:1:1:1
   -o syslog_name=postfix-domain1

domain2  unix -       -       n       -       -       smtp
   -o smtp_bind_address=XX.XX.XX.X5
   -o smtp_helo_name=domain2.com
   -o inet_protocols=all
   -o smtp_bind_address6=XXXX:XXXX:XXXX:XXXX:1:2:1:1
   -o syslog_name=postfix-domain2

domain3  unix -       -       n       -       -       smtp
   -o smtp_bind_address=XX.XX.XX.X2
   -o smtp_helo_name=domain3
   -o inet_protocols=all
   -o smtp_bind_address6=XXXX:XXXX:XXXX:XXXX:1:1:5:1
   -o syslog_name=postfix-domain3

Le fichier n'est pas totalement inclus — il est dĂ©jĂ  trĂšs gros.
J'ai uniquement marqué ce qui a été modifié.

smtp      inet  n       -       y       -       -       smtpd
  -o content_filter=spamassassin
...
spamassassin unix -     n       n       -       -       pipe
    user=spamd argv=/usr/bin/spamc -f -e
    /usr/sbin/sendmail -oi -f ${sender} ${recipient}

Ce sont les paramÚtres liés à spamassassin, que nous aborderons plus tard.

submission inet n       -       y       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject

Nous autorisons la connexion au serveur de messagerie via le port 587.
Pour cela, une authentification est nécessaire.

policyd-spf  unix  -       n       n       -       0       spawn
    user=policyd-spf argv=/usr/bin/policyd-spf

Nous activons la vérification SPF.

apt-get install postfix-policyd-spf-python

Nous allons installer le paquet pour les vérifications SPF mentionnées ci-dessus.

domain1  unix -       -       n       -       -       smtp
   -o smtp_bind_address=XX.XX.XX.X1
   -o smtp_helo_name=domain1.com
   -o inet_protocols=all
   -o smtp_bind_address6=XXXX:XXXX:XXXX:XXXX:1:1:1:1
   -o syslog_name=postfix-domain1

C'est la partie la plus intéressante. C'est la possibilité d'envoyer des e-mails pour un domaine spécifique à partir d'une adresse IPv4/IPv6 spécifique.

Ceci est fait pour le rDNS. Le rDNS est l'obtention d'une chaĂźne par adresse IP.
Et pour les e-mails, cette possibilité est utilisée pour confirmer que le helo correspond exactement au rDNS de l'adresse à partir de laquelle l'e-mail a été envoyé.

Si le helo ne correspond pas au domaine de l'e-mail au nom duquel l'e-mail a été envoyé, des points de spam sont attribués.

Helo ne correspondant pas au rDNS — beaucoup de points de spam sont attribuĂ©s.
Par conséquent, chaque domaine doit avoir sa propre adresse IP.
Pour OVH — dans le tableau de bord, il est possible de spĂ©cifier le rDNS.
Pour tech.ru — la question est rĂ©solue par le support.
Pour AWS — la question est rĂ©solue par le support.
«inet_protocols» et «smtp_bind_address6» — cela active la prise en charge de l'IPv6.
Il faut aussi configurer le rDNS pour l'IPv6.
«syslog_name» — cela est pour faciliter la lecture des logs.

Acheter des certificats je recommande ici.

Configuration de la combinaison postfix+dovecot ici.

Configuration SPF.

============= Dovecot =============

apt-get install dovecot-imapd dovecot-pop3d dovecot-lmtpd dovecot-mysql dovecot-antispam

Configuration de mysql, nous installons nous-mĂȘmes les paquets.

Fichier «/etc/dovecot/conf.d/10-auth.conf»

disable_plaintext_auth = yes
auth_mechanisms = plain login

Autorisation uniquement sous forme chiffrée.

Fichier «/etc/dovecot/conf.d/10-mail.conf»

mail_location = maildir:/var/mail/vhosts/%d/%n

Ici nous indiquerons l'emplacement de stockage des mails.

Je veux qu'ils soient stockés dans des fichiers et groupés par domaines.

Fichier «/etc/dovecot/conf.d/10-master.conf»

service imap-login {
  inet_listener imap {
    port = 0
  }
  inet_listener imaps {
    address = XX.XX.XX.X1, XX.XX.XX.X2, XX.XX.XX.X5, [XXXX:XXXX:XXXX:XXXX:1:1:1:1], [XXXX:XXXX:XXXX:XXXX:1:2:1:1], [XXXX:XXXX:XXXX:XXXX:1:1:5:1]
    port = 993
    ssl = yes
  }
}
service pop3-login {
  inet_listener pop3 {
    port = 0
  }
  inet_listener pop3s {
    address = XX.XX.XX.X1, XX.XX.XX.X2, XX.XX.XX.X5, [XXXX:XXXX:XXXX:XXXX:1:1:1:1], [XXXX:XXXX:XXXX:XXXX:1:2:1:1], [XXXX:XXXX:XXXX:XXXX:1:1:5:1]
    port = 995
    ssl = yes
  }
}
service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0600
    user = postfix
    group = postfix
  }
}
service imap {
}
service pop3 {
}
service auth {
  unix_listener auth-userdb {
    mode = 0600
    user = vmail
  }

  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }
  user = dovecot
}
service auth-worker {
  user = vmail
}
service dict {
  unix_listener dict {
  }
}

C'est le fichier principal de configuration de dovecot.
Ici nous désactivons les connexions non sécurisées.
Et nous activons les connexions sécurisées.

Fichier «/etc/dovecot/conf.d/10-ssl.conf»

ssl = required
ssl_cert = </etc/nginx/ssl/domain1.com.2018.chained.crt
ssl_key = </etc/nginx/ssl/domain1.com.2018.key
local XX.XX.XX.X5 {
  ssl_cert = </etc/nginx/ssl/domain2.com.2018.chained.crt
  ssl_key =  </etc/nginx/ssl/domain2.com.2018.key
}

Nous configurons ssl. Indiquons que ssl est obligatoire.
Et le certificat lui-mĂȘme. Et un dĂ©tail important — la directive «local». Indique, pour quelle connexion Ă  quel IPv4 local — quel certificat ssl utiliser.

Au fait, l'IPv6 n'est pas configuré ici, je corrigerai cette omission un de ces jours.
XX.XX.XX.X5 (domain2) — pas de certificat. Pour la connexion des clients, il faut indiquer domain1.com.
XX.XX.XX.X2 (domain3) — il y a un certificat, pour la connexion des clients on peut indiquer domain1.com ou domain3.com.

Fichier «/etc/dovecot/conf.d/15-lda.conf»

protocol lda {
  mail_plugins = $mail_plugins sieve
}

Cela sera nécessaire plus tard pour spamassassin.

Fichier «/etc/dovecot/conf.d/20-imap.conf»

protocol imap {
  mail_plugins = $mail_plugins antispam
}

C'est le plugin antispam. Il est nécessaire pour former spamassassin lors du déplacement vers / depuis le dossier «Spam».

Fichier «/etc/dovecot/conf.d/20-pop3.conf»

protocol pop3 {
}

C'est simplement un fichier.

Fichier «/etc/dovecot/conf.d/20-lmtp.conf»

protocole lmtp {
  mail_plugins = $mail_plugins sieve
  postmaster_address = admin@domain1.com
}

Configuration de l'lmtp.

Fichier «/etc/dovecot/conf.d/90-antispam.conf»

plugin {
  antispam_backend = pipe
  antispam_trash = Trash;trash
  antispam_spam = Junk;Spam;SPAM
  antispam_pipe_program_spam_arg = --spam
  antispam_pipe_program_notspam_arg = --ham
  antispam_pipe_program = /usr/bin/sa-learn
  antispam_pipe_program_args = --username=%Lu
}

ParamÚtres d'apprentissage de spamassassin lors du déplacement vers/depuis le dossier «Spam».

Fichier «/etc/dovecot/conf.d/90-sieve.conf»

plugin {
  sieve = ~/\.dovecot.sieve
  sieve_dir = ~/sieve
  sieve_after = /var/lib/dovecot/sieve/default.sieve
}

Fichier indiquant quoi faire avec les emails entrants.

Fichier «/var/lib/dovecot/sieve/default.sieve»

require ["fileinto", "mailbox"];

if header :contains "X-Spam-Flag" "YES" {
        fileinto :create "Spam";
}

Il faut compiler le fichier : «sievec default.sieve».

Fichier «/etc/dovecot/conf.d/auth-sql.conf.ext»

passdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}
userdb {
  driver = static
  args = uid=vmail gid=vmail home=/var/mail/vhosts/%d/%n
}

Indication des fichiers sql pour l'autorisation.
Le fichier lui-mĂȘme — comme mĂ©thode d'autorisation.

Fichier «/etc/dovecot/dovecot-sql.conf.ext»

driver = mysql
connect = host=127.0.0.1 dbname=servermail user=usermail password=password
default_pass_scheme = SHA512-CRYPT
password_query = SELECT email as user, password FROM virtual_users WHERE email='%u';

Cela correspond aux paramĂštres similaires pour postfix.

Fichier «/etc/dovecot/dovecot.conf»

protocols = imap lmtp pop3
listen = *, ::
dict {
}
!include conf.d/*.conf
!include_try local.conf

Fichier de configuration principal.
Il est important que nous spécifiions ajoutons les protocoles.

============= SpamAssassin =============

apt-get install spamassassin spamc

Installer les paquets.

adduser spamd --disabled-login

Ajoutons un utilisateur au nom de celui-ci.

systemctl enable spamassassin.service

Activer le démarrage automatique du service spamassassin au démarrage.

Fichier «/etc/default/spamassassin» :

CRON=1

Activer la mise à jour automatique des rÚgles «par défaut».

Fichier «/etc/spamassassin/local.cf» :

report_safe 0

use_bayes          1
bayes_auto_learn   1
bayes_auto_expire  1
bayes_store_module Mail::SpamAssassin::BayesStore::MySQL
bayes_sql_dsn      DBI:mysql:sa:localhost:3306
bayes_sql_username sa
bayes_sql_password password

Il faut créer la base de données mysql «sa» avec l'utilisateur «sa» et le mot de passe «password» (remplacer par quelque chose de plus approprié).

report_safe — c'est au lieu d'un email, un rapport sur l'email spam sera envoyĂ©.
use_bayes — ce sont les paramùtres d'apprentissage automatique de spamassassin.

Les autres paramÚtres de spamassassin ont été appliqués précédemment selon l'article.

Configuration générale de «spamassassin».
Concernant le déplacement des nouveaux emails de spam dans le dossier IMAP «Spam».
Concernant la simple combinaison Dovecot + SpamAssassin.
Je recommande la lecture de la théorie de l'apprentissage de spamassassin lors du déplacement des emails dans les dossiers imap (et je ne recommande pas son application).

============= Appel à la communauté =============

J'aimerais Ă©galement soumettre une idĂ©e Ă  la communautĂ© sur comment amĂ©liorer la sĂ©curitĂ© des e-mails envoyĂ©s. Étant donnĂ© que je me suis profondĂ©ment plongĂ© dans le sujet de la messagerie.

Pour que l'utilisateur puisse créer une paire de clés sur son client (Outlook, Thunderbird, plugin de navigateur, etc.). Une clé publique à envoyer dans le DNS. Une clé privée à conserver sur le client. Les serveurs de messagerie devraient pouvoir utiliser la clé publique pour l'envoi vers un destinataire spécifique.

Et pour se protéger contre le spam dans le cadre de tels e-mails (oui, le serveur de messagerie ne pourra pas vérifier le contenu) - il sera nécessaire d'introduire 3 rÚgles :

  1. Signature DKIM authentique obligatoire, SPF obligatoire, rDNS obligatoire.
  2. Un réseau neuronal pour l'apprentissage contre le spam + base de données associée cÎté client.
  3. L'algorithme de chiffrement doit ĂȘtre tel que la partie Ă©mettrice dĂ©pense 100 fois plus de puissance CPU pour le chiffrement que la partie rĂ©ceptrice.

En plus des e-mails publics - développer une norme pour les e-mails de proposition de "commencer une correspondance sécurisée". Un utilisateur (boßte aux lettres) envoie à une autre boßte aux lettres un e-mail avec une piÚce jointe. Dans l'e-mail, il y a un texte proposant de commencer un canal de communication sécurisé et la clé publique du propriétaire de la boßte aux lettres (la clé privée étant conservée cÎté client).

On peut mĂȘme crĂ©er une paire de clĂ©s spĂ©cialement pour chaque correspondance. L'utilisateur destinataire peut accepter cette proposition et envoyer sa clĂ© publique (Ă©galement créée spĂ©cialement pour cette correspondance). Ensuite, le premier utilisateur envoie un e-mail de contrĂŽle (chiffrĂ© avec la clĂ© publique du deuxiĂšme utilisateur) — Ă  la rĂ©ception duquel le deuxiĂšme utilisateur peut considĂ©rer le canal de communication Ă©tabli comme fiable. Ensuite, le deuxiĂšme utilisateur envoie un e-mail de contrĂŽle — et alors le premier utilisateur peut Ă©galement considĂ©rer le canal Ă©tabli comme sĂ©curisĂ©.

Pour lutter contre l'interception des clés en cours de route - il faut prévoir dans le protocole la possibilité de transmettre au moins une clé publique à l'aide d'une clé USB.

Et surtout — que tout cela fonctionne (la question "qui va payer pour cela ?") :
Introduire des certificats de messagerie à partir de 10 $ pour 3 ans. Cela permettra à l'expéditeur d'indiquer dans le DNS que « mes clés publiques se trouvent là-bas ». Et cela offrira la possibilité de commencer une connexion sécurisée, tout en acceptant ces connexions gratuitement.
Gmail monétise enfin ses utilisateurs. Pour 10 $ sur 3 ans, le droit de créer des canaux de communication sécurisés.

============= Conclusion =============

Pour tester l'ensemble de l'article, je prévoyais de louer un serveur dédié pendant un mois et d'acheter un domaine avec un certificat SSL.

Mais les circonstances de la vie ont fait que cette question a été reportée de 2 mois.
Et voilà, quand j'ai de nouveau eu du temps libre, j'ai décidé de publier l'article tel quel, plutÎt que de risquer que la publication prenne encore un an.

S'il y a suffisamment de questions du type « ici, ce n'est pas assez dĂ©taillĂ© » — alors je trouverai probablement les ressources nĂ©cessaires pour louer un serveur dĂ©diĂ© avec un nouveau domaine et un nouveau certificat SSL, et dĂ©crire tout cela plus en dĂ©tail, tout en mettant en lumiĂšre toutes les dĂ©tails importants omis.

J'aimerais également recevoir des avis sur l'idée des certificats de messagerie. Si l'idée plaßt, j'essaierai de trouver les moyens d'écrire un brouillon pour le RFC.

Lors de la copie de larges morceaux d'article, veuillez indiquer le lien vers cet article.
Lors de la traduction dans une autre langue, veuillez indiquer le lien vers cet article.
Je m'occuperai moi-mĂȘme de la traduction en anglais et laisserai des liens croisĂ©s.


Source : habr.com

Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS đŸ”„ Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster