Debian + Postfix + Dovecot + Više domena + SSL + IPv6 + OpenVPN + Više sučelja + SpamAssassin-učenje + Bind

Ovaj članak objašnjava kako postaviti moderni mail server.
Postfix + Dovecot. SPF + DKIM + rDNS. Uz IPv6.
S TSL enkripcijom. Uz podršku za više domena — deo sa pravim SSL certifikatom.
Sa zaštitom od spam-a i visokim spam ratingom u poredjenju s drugim mail serverima.
Uz podršku za više fizičkih interfejsa.
Sa OpenVPN-om, povezanost putem IPv4, pružajući IPv6.

Ako ne želite učiti sve ove tehnologije, ali želite postaviti takav server — ovaj članak je za vas.

Članak ne pokušava da objasni svaku pojedinost. Objašnjenja nisu standardna ili su važna iz perspektive korisnika.

Motivacija za postavljanje mail servera — moj dugogodišnji san. Možda zvuči glupo, ali po mom mišljenju, to je mnogo bolje nego sanjati o novom automobilu omiljenog brenda.

Motivacija za postavljanje IPv6 — dve. IT stručnjaku je potrebno stalno učiti nove tehnologije kako bi preživeo. Želim da dam svoj skromni doprinos borbi protiv cenzure.

Motivacija za postavljanje OpenVPN — samo da bi IPv6 radio na lokalnoj mašini.
Motivacija za postavljanje više fizičkih interfejsa — na mom serveru imam jedan ‘spori, ali neograničen’ interfejs, i drugi ‘brzi, ali sa tarifom’.

Motivacija za postavljanje Binda — moj provajder pruža nestabilan DNS server, a Google takođe može da ima probleme. Želim stabilan DNS server za ličnu upotrebu.

Motivacija za pisanje članka — nacrt je napisan pre 10 meseci, već sam ga dva puta pregledao. Ako je to potrebno autoru, velika je verovatnoća da će biti potrebno i drugima.

Ne postoji univerzalno rešenje za mail servere. Ali trudiću se da napišem nešto poput ‘uradite to, a kada sve bude funkcionisalo kako treba — izbacite suvišne stvari’.

Imam Colocation server kod kompanije tech.ru. Ima mogućnost poređenja sa OVH, Hetzner, AWS. Za rešenje ovog zadatka, mnogo efikasnije bi bilo saraditi upravo sa tech.ru.

Na serveru je instaliran Debian 9.

Na serveru su 2 interfejsa `eno1` i `eno2`. Prvi je neograničen, a drugi brz.

Imam 3 statičke IP adrese, XX.XX.XX.X0 i XX.XX.XX.X1 i XX.XX.XX.X2 na interfejsu `eno1` i XX.XX.XX.X5 na interfejsu `eno2`.

Imam XXXX:XXXX:XXXX:XXXX::/64 IPv6 adresni opseg dodeljen interfejsu `eno1` i od njega XXXX:XXXX:XXXX:XXXX:1:2::/96 po mojoj molbi dodeljen je `eno2`.

Postoje 3 domene `domain1.com`, `domain2.com`, `domain3.com`. Za `domain1.com` i `domain3.com` postoji SSL certifikat.

Imam Google račun, na koji želim povezati e-mail adresu `vasya.pupkin@domain1.com` (primanje i slanje e-pošte iz sučelja Gmail).
Trebam e-mail adresu `support@domain2.com`, čiju kopiju e-pošte želim vidjeti u svom Gmailu. Također bih rijetko mogao slati nešto u ime `support@domain2.com` putem web sučelja.

Trebam e-mail adresu `ivanov@domain3.com`, koju će koristiti Ivanov sa svog iPhonea.

Poslane poruke moraju ispunjavati sve moderne zahtjeve protiv neželjene pošte.
Mora postojati najviši nivo šifriranja predviđen u javnim mrežama.
Mora biti podrška za IPv6 i za slanje i za primanje e-pošte.
Mora postojati SpamAssassin koji nikada neće brisati poruke. Umjesto toga će ih ili odbacivati, ili propuštati ili slati u IMAP mapu 'Neželjena pošta'.
SpamAssassin treba imati podešeno automatsko učenje: ako premjestim poruku u mapu 'Neželjena pošta' — treba se obučiti na tome; ako premjestim poruku iz mape 'Neželjena pošta' — treba se obučiti na tome. Rezultati učenja SpamAssassina trebaju utjecati na to hoće li poruka završiti u mapi 'Neželjena pošta'.
PHP skripte trebaju moći slati e-poštu u ime bilo koje domene na ovom poslužitelju.
Mora postojati OpenVPN servis, s mogućnošću korištenja IPv6 na klijentu koji nema IPv6.

Prvo treba postaviti sučelja i rutiranje, uključujući IPv6.
Zatim treba postaviti OpenVPN koji će se povezivati putem IPv4 i davati klijentu statičku pravu IPv6 adresu. Ovaj klijent će imati pristup svim IPv6 servisima na poslužitelju i pristup bilo kojim IPv6 resursima na internetu.
Zatim treba postaviti Postfix za slanje e-pošte + SPF + DKIM + rDNS i druge slične sitnice.
Zatim treba postaviti Dovecot i konfigurirati Multidomain.
Zatim treba postaviti SpamAssassin i konfigurirati učenje.
Na kraju treba instalirati Bind.

============= Više sučelja =============

Za konfiguriranje sučelja treba upisati ovo u '"/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

Ove postavke se mogu primijeniti na bilo kojem poslužitelju u tech.ru (uz malo usklađivanja s podrškom) i odmah će raditi kako treba.

Ako imate iskustva s konfiguriranjem sličnih stvari za Hetzner, OVH — to je drugačije. Složenije.

eno1 — to je naziv mrežne kartice #1 (spora, ali bez ograničenja).
eno2 — to je naziv mrežne kartice #2 (brza, ali s tarifom).
tun0 — naziv virtualne mrežne kartice od OpenVPN.
XX.XX.XX.X0 — IPv4 #1 na eno1.
XX.XX.XX.X1 — IPv4 #2 na eno1.
XX.XX.XX.X2 — IPv4 #3 na eno1.
XX.XX.XX.X5 — IPv4 #1 na eno2.
XX.XX.XX.1 — IPv4 gateway.
XXXX:XXXX:XXXX:XXXX::/64 — IPv6 za cijeli server.
XXXX:XXXX:XXXX:XXXX:1:2::/96 — IPv6 za eno2, dok sve ostalo ulazi u eno1.
XXXX:XXXX:XXXX:XXXX::1 — IPv6 gateway (važno je napomenuti da se ovdje može/nadamo drugačije. Treba navesti IPv6 switch-a).
dns-nameservers — navedeni su 127.0.0.1 (jer je bind instaliran lokalno) i 213.248.1.6 (to je od tech.ru).

«table eno1t» i «table eno2t» — svrha ovih route-rule je da promet koji ulazi kroz eno1 -> ide kroz njega, a promet koji ulazi kroz eno2 -> ide kroz njega. Također, veze po inicijativi servera odlaze kroz eno1.

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

Ovom naredbom postavljamo da sav nepoznati promet koji ulazi pod bilo kojeg pravila označeno kao «table eno1t» -> bude usmjeren na sučelje eno1.

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

Ovom naredbom postavljamo da sav promet po inicijativi servera bude usmjeren na sučelje eno1.

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

Ovom naredbom postavljamo same pravila za označavanje prometa.

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

Ovaj blok postavlja drugi IPv4 za sučelje eno1.

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

Ovom naredbom postavljamo rutu od OpenVPN klijenata do lokalnih IPv4 osim XX.XX.XX.X0.
Zašto je ova naredba dovoljna za sve IPv4 — još uvijek ne razumijem.

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

Ovdje postavljamo adresu za samo sučelje. Server će je koristiti kao «izlaznu» adresu. Više se neće koristiti.

Zašto je navedeno «:1:1::» tako složeno? Da bi OpenVPN ispravno radio i samo zbog toga. O tome više detalja kasnije.

Što se tiče gateway-a — tako radi i to je u redu. No ispravno bi bilo — ovdje navesti IPv6 switch-a kojem je server povezan.

Ipak, zašto IPv6 prestaje raditi ako uradim tako. Vjerojatno neki problemi tech.ru.

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

Ovo je dodavanje IPv6 adrese na sučelje. Ako trebate stotinu adresa — znači stotinu redaka u ovoj datoteci.

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

Označio sam adrese i podmreže svih sučelja da bi bilo pregledno.
eno1 — mora imati «/64» — jer je to cijeli naš pool adresa.
tun0 — podmreža mora biti veća od eno1. Inače, nećemo moći postaviti IPv6 gateway za OpenVPN klijente.
eno2 — podmreža mora biti veća od tun0. Inače, OpenVPN klijenti neće moći pristupiti lokalnim IPv6 adresama.
Za ilustraciju izabrao sam korak podmreže 16, ali po želji može se koristiti čak i korak «1».
Prema tome, 64+16 = 80, a 80+16 = 96.

Za još veću jasnoću:
XXXX:XXXX:XXXX:XXXX:1:1:YYYY:YYYY — to su adrese koje trebaju biti dodijeljene određenim stranicama ili servisima na sučelju eno1.
XXXX:XXXX:XXXX:XXXX:1:2:YYYY:YYYY — to su adrese koje trebaju biti dodijeljene određenim stranicama ili servisima na sučelju eno2.
XXXX:XXXX:XXXX:XXXX:1:3:YYYY:YYYY — to su adrese koje trebaju biti dodijeljene OpenVPN klijentima ili korištene kao servisne adrese OpenVPN-a.

Za postavljanje mreže — mora biti mogućnost ponovnog pokretanja servera.
IPv4 promjene se primjenjuju pri izvršenju (obavezno omotajte u screen — inače će ova komanda jednostavno srušiti mrežu na serveru):

/etc/init.d/networking restart

U datoteku «/etc/iproute2/rt_tables» dodati na kraj:

100 eno1t
101 eno2t

Bez ovoga ne možemo koristiti prilagođene tablice u datoteci «/etc/network/interfaces».
Brojevi moraju biti jedinstveni i manji od 65535.

IPv6 promjene se lako primjenjuju bez ponovnog pokretanja, ali za to se treba naučiti najmanje tri komande:

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

Postavke «/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

Ovo su postavke «sysctl» mog servera. Istaknut ću važno.

net.ipv4.ip_forward = 1

Bez ovoga OpenVPN neće raditi nikako.

net.ipv6.ip_nonlocal_bind = 1

Svako ko pokuša napraviti bind IPv6 (na primjer nginx) odmah nakon što se sučelje podijeli — dobit će grešku. Takva adresa nije dostupna.

Kako bismo izbjegli takvu situaciju, napravljena je ovakva postavka.

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

Bez ovih postavki IPv6 promet od OpenVPN klijenta neće izaći u svijet.

Ostale postavke ili nisu važne ili se ne sjećam zašto su tamo.
Ali za svaki slučaj ostavljam «kako jest».

Da bi se promjene u ovoj datoteci primili bez ponovnog pokretanja servera — treba izvršiti komandu:

sysctl -p

Detaljnije o pravilima «table»: habr.com/post/108690

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

OpenVPN IPv4 ne radi bez iptables.

Moji iptables su ovakvi za 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 — moja statička IPv4 adresa lokalnog računala.
10.8.0.0/24 — IPv4 mreža openvpn. IPv4 adrese za openvpn klijente.
Redoslijed pravila je važan.

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

Ovo je ograničenje da samo ja sa svoje statičke IP adrese mogu koristiti OpenVPN.

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

Za prosljeđivanje IPv4 paketa između OpenVPN klijenata i interneta — trebate koristiti jednu od ovih naredbi.

Za različite slučajeve, jedna od opcija nije pogodna.
Za moj slučaj obje naredbe su odgovarajuće.
Nakon čitanja dokumentacije odabrao sam prvu opciju jer troši manje CPU-a.

Da bi sve postavke iptables bile učitane nakon ponovnog pokretanja — treba ih negdje spremiti.

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

Ova imena nisu izabrana slučajno. Koristi ih paket „iptables-persistent“.

apt-get install iptables-persistent

Instalacija glavnog paketa OpenVPN:

apt-get install openvpn easy-rsa

Postavimo predložak za certifikate (zamijeniti vlastitim vrijednostima):

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

Uredimo postavke predloška certifikata:

mcedit vars

...
# Ovo su zadane vrijednosti za polja
# koja će biti unesena u certifikat.
# Ne ostavljajte nijedno od ovih polja prazno.
export KEY_COUNTRY="HR"
export KEY_PROVINCE="Kvarner"
export KEY_CITY="Rijeka"
export KEY_ORG="Vlastito"
export KEY_EMAIL="admin@domain1.com"
export KEY_OU="VPN"

# X509 Subject Field
export KEY_NAME="server"
...

Kreiramo server certifikat:

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

Pripremimo mogućnost stvaranja konačnih „client-name.opvn“ datoteka:

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

Pripremimo skriptu koja će spojiti sve datoteke u jedan opvn datoteku.

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

Kreiramo prvog OpenVPN klijenta:

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

Datoteku „~/client-configs/files/client-name.ovpn“ šaljemo na uređaj klijentu.

Za iOS klijente treba napraviti trik:
Sadržaj taga «tls-auth» treba biti bez komentara.
Također treba postaviti «key-direction 1» odmah prije taga «tls-auth».

Postavljamo konfiguraciju OpenVPN servera:

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

To je potrebno kako bi se postavila statička adresa za svakog klijenta (nije obavezno, ali ja to koristim):

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

Najkompliciraniji i ključni detalj.

Nažalost, OpenVPN još ne može samostalno postaviti IPv6 gateway za klijente.
Moramo to «ručno» proslijediti za svakog klijenta.

# 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"

Datoteka «/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

Datoteka «/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

Oba skripta koriste datoteku «/etc/openvpn/variables»:

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

Zašto je ovdje to napisano — teško se sjetiti.

Trenutno izgleda čudno netmask = 112 (ovdje bi trebao biti 96).
I prefix je čudan, ne odgovara mreži tun0.
Ali dobro, ostavljam «kako jest».

cipher DES-EDE3-CBC

To je stvar ukusa — odabrao sam ovakav način šifriranja veze.

Detaljnije o postavkama OpenVPN IPv4.

Detaljnije o postavkama OpenVPN IPv6.

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

Instalacija glavnog paketa:

apt-get install postfix

Prilikom instalacije odabrati «internet-site».

Moj «/etc/postfix/main.cf» izgleda ovako:

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

# dodavanje .domain je zadatak MUA.
append_dot_mydomain = no

readme_directory = no

# Vidite http://www.postfix.org/COMPATIBILITY_README.html -- prema zadanim postavkama 2 za
# nova instalacija.
compatibility_level = 2

# TLS parametri
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

# Tip pohrane
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

# SMTP-Auth postavke
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

# IP adresa po domeni
sender_dependent_default_transport_maps = pcre:/etc/postfix/sdd_transport.pcre

Pogledajmo detalje ove konfiguracije.

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

Prema mišljenju članova Habr, ovaj blok sadrži `dezinformacije i netočne teze`.Tek nakon 8 godina od početka svoje karijere počeo sam razumjeti kako SSL radi.

Stoga ću se usuditi opisati kako koristiti SSL (ne odgovarajući na pitanja "Kako to radi?" i "Zašto to radi?").

Osnova suvremenog šifriranja je stvaranje para ključeva (dva vrlo dugačka niza znakova).

Jedan „ključ“ je privatni, a drugi ključ je „javna“. Privatni ključ čuvamo vrlo pažljivo u tajnosti. Javni ključ dodjeljujemo svima zainteresiranima.

Pomoću javnog ključa moguće je šifrirati niz teksta tako da ga može dešifrirati samo vlasnik privatnog ključa.
I to je osnova tehnologije.

Korak br. 1 — https stranice.
Kada se preglednik obrati web poslužitelju, saznaje od njega da je stranica https i stoga traži javni ključ.
Web poslužitelj pruža javni ključ. Preglednik koristi javni ključ za šifriranje http-zahtjeva i slanje istog.
Sadržaj http-zahtjeva može pročitati samo onaj tko ima privatni ključ, tj. samo server kojem se obraća.
Http-zahtjev sadrži barem URI. Stoga, ako se u zemlji pokušavaju ograničiti pristupi ne cijelom sajtu, nego određenoj stranici — to za https sajtove nije moguće.

Korak br. 2 — šifrirani odgovor.
Web poslužitelj daje odgovor koji se lako može pročitati tijekom puta.
Rješenje je izuzetno jednostavno — preglednik lokalno formira par privatni-javni ključ za svaki https sajt.
I zajedno s zahtjevom javnog ključa sajta šalje svoj lokalni javni ključ.
Web poslužitelj ga pamti i pri slanju http-odgovora šifrirati će ovim javnim ključem konkretnog klijenta.
Sada http-odgovor može dešifrirati samo vlasnik privatnog ključa preglednika klijenta (tj. sam klijent).

Korak br. 3 — uspostavljanje sigurnog spoja putem javnog kanala.
U primjeru br. 2 postoji ranjivost — ništa ne sprječava zlonamjernike da presretnu http-zahtjev i izmijene informacije o javnom ključu.
Tako će posrednik savršeno vidjeti sav sadržaj poslanih-primanih poruka sve dok se kanal veze ne promijeni.
Boriti se protiv toga je krajnje jednostavno — dovoljno je poslati javni ključ preglednika kao poruku šifriranu javnim ključem web poslužitelja.
Web poslužitelj tada prvo šalje odgovor tipa „tvoj javni ključ je ovakav” i šifrirati će ovu poruku tim istim javnim ključem.
Preglednik gleda odgovor — ako je stigla poruka „tvoj javni ključ je ovakav” — onda je to 100% garancija da je ovaj kanal veze siguran.
Koliko je siguran?
Samo stvaranje ovakvog sigurnog kanala veze događa se brzinom ping*2. Na primjer 20ms.
Napadač mora ili unaprijed imati privatni ključ jedne od strana. Ili odabrati privatni ključ u nekoliko milisekundi.
Hacking jednog modernog privatnog ključa bi trajao desetljećima na superračunalu.

Korak br. 4 — javna Baza podataka javnih ključeva.
Očigledno je da u cijeloj ovoj priči postoji mogućnost za napadača koji sjedi na kanalu veze između klijenta i servera.
Mogućnost klijentu da se predstavi kao server, a serveru da se predstavi kao klijent. I emulirati par ključeva u oba smjera.
Tada će napadač vidjeti sav promet i imati mogućnost 'urediti' promet.
Na primjer, promijeniti adresu na koju slati novac ili kopirati lozinku od online banke ili blokirati 'nepoželjni' sadržaj.
Za borbu protiv takvih napadača zamišljena je javna Baza podataka s javnim ključevima za svaki https sajt.
Svaki preglednik 'zna' o postojanju oko 200 takvih baza podataka. To je unaprijed postavljeno u svaki preglednik.
'Znanje' je potkrijepljeno javnim ključem svakog certifikata. To jest, povezivanje s svakim pojedinačnim centrom za certifikaciju nije moguće lažirati.

Sada imamo jednostavno razumijevanje kako koristiti SSL za https.
Ako malo razmislite, postat će jasno kako sigurnosne službe mogu u ovoj konstrukciji nešto hakirati. No, to će im zahtijevati monstruozne napore.
Organizacijama manjim od NSA ili CIA-e — praktički je nemoguće hakirati postojeći nivo zaštite čak i za VIP.

Još ću dodati o ssh vezama. Tamo nema javnih ključeva, pa kako onda biti. Pitanje se rješava na dva načina.
Opcija ssh-po-lozinki:
Prilikom prvog povezivanja, ssh-klijent treba upozoriti da imamo novi javni ključ od ssh-servera.
I prilikom daljnjih povezivanja, ako se pojavi upozorenje 'novi javni ključ od ssh-servera' — to će značiti da vas pokušavaju prisluškivati.
Ili ste prilikom prvog povezivanja bili prisluškivani, a sada razgovarate sa serverom bez posrednika.
Uglavnom, zbog toga što se činjenica prisluškivanja lako, brzo i bez napora otkriva — ovom napadu se koristi samo u posebnim slučajevima za konkretne klijente.

Opcija ssh-po-ključu:
Uzmem USB flash, snimim na nju privatni ključ za ssh-server (za to postoje termini i hrpa suptilnosti, ali pišem obrazovni tekst, a ne upute za primjenu).
Javni ključ ostavljamo na mašini gdje će biti ssh-klijent i njega također čuvamo u tajnosti.
Donosimo USB flash na server, umetnemo, kopiramo privatni ključ, a USB flash spaljujemo i raspršujemo pepeo po vjetru (ili bar formatiramo s popunjavanjem nulama).
I to je to — nakon takve operacije bit će nemoguće hakirati tako ssh veze. Naravno, za deset godina na superračunalu moći će se pogledati promet — ali to je posebna priča.

Ispričavam se zbog offtopa.

Dakle, sada kada je teorija poznata. Pričat ću o toku kreiranja ssl certifikata.

Pomoću „openssl genrsa“ kreiramo privatni ključ i „šablone“ za javni ključ.
„šablone“ šaljemo trećoj strani kojoj plaćamo oko $9 za najjednostavniji certifikat.

Nakon nekoliko sati dobivamo od te treće strane naš „javni“ ključ i još nekoliko javnih ključeva.

Zašto plaćati trećoj strani za obradu mog javnog ključa — to je pitanje o kojem nećemo raspravljati.

Sada je jasno što znači natpis:

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

U mapi „/etc/ssl“ pohranjeni su svi datoteke za ssl pitanja.
domain1.com — naziv domene.
2018 — godina kreiranja ključeva.
„key“ — oznaka koja pokazuje da je datoteka privatni ključ.

I smisao ove datoteke:

smtpd_tls_cert_file= /etc/ssl/domain1.com.2018.chained.crt
domain1.com — naziv domene.
2018 — godina kreiranja ključeva.
chained — oznaka koja ukazuje da se ovdje nalazi lanac javnih ključeva (prvi je naš javni, a ostali su oni koji su došli od kompanije koja je izradila javni ključ).
crt — oznaka koja označava da je ovdje gotov certifikat (javnog ključa s tehničkim pojašnjenjima).

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

Ova postavka se u ovom slučaju ne koristi, ali je navedena za primjer.

Jer pogreška u ovoj postavci dovest će do slanja spam poruka s vašeg servera (bez vaše volje).

Kasnije dokazujući svima da niste krivi.

recipient_delimiter = +

Možda mnogi ne znaju, ali ovo je standardni simbol za rangiranje poruka, a to podržava većina modernih mail servera.

Na primjer, ako imate email adresu „username@gmail.com“ pokušajte poslati na „username+spam@gmail.com“ — vidjet ćete što će se dogoditi.

inet_protocols = ipv4

Možda će vas to zbuniti.

Ali nije bez razloga. Svaki novi domen — prema zadanim postavkama samo IPv4, zatim uključujem IPv6 za svaki posebno.

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

Ovdje definiramo da će sva dolazna pošta ići u dovecot.
A pravila za domen, mailbox, alias — pogledajte u BDP.

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

korisnik = usermail
lozinka = mailpassword
hostovi = 127.0.0.1
dbime = servermail
upit = SELECT 1 FROM virtual_domains WHERE name='%s'

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

korisnik = usermail
lozinka = mailpassword
hostovi = 127.0.0.1
dbime = servermail
upit = SELECT 1 FROM virtual_users WHERE email='%s'

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

korisnik = usermail
lozinka = mailpassword
hostovi = 127.0.0.1
dbime = servermail
upit = 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

Sada postfix zna da može primati poštu za daljnje slanje samo uz autorizaciju s dovecot.

Stvarno mi nije jasno zašto to ovdje duplicirati. Već smo u 'virtual_transportu' naveli sve što je potrebno.

Ali postfix je jako stari sustav — vjerojatno su to improvizacije iz starih vremena.

smtpd_recipient_restrictions =
        ...

smtpd_helo_restrictions =
        ...

smtpd_client_restrictions =
        ...

To se mora konfigurirati za svaki mail server prema vlastitim potrebama.

Imam na raspolaganju 3 mail servera i te postavke su vrlo različite zbog različitih zahtjeva za korištenje.

Mora se pažljivo konfigurirati — inače će vam spam početi dolaziti ili, još gore, spam će odlaziti od vas.

# SPF
policyd-spf_time_limit = 3600

Konfiguracija za neki dodatak vezan uz provjeru SPF dolazne pošte.

# 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

Postavka da sve izlazne poruke trebamo označiti DKIM potpisom.

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

Ovo je ključna točka u usmjeravanju poruka prilikom slanja e-pošte iz php skripti.

Datoteka '/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:

S lijeva — regularni izrazi. S desna — oznaka kojom se označava poruka.
Postfix će, u skladu s oznakom, uzeti u obzir još nekoliko redaka konfiguracije za određenu poruku.

Kako će točno biti rekonfiguriran postfix za određenu poruku — bit će navedeno u 'master.cf'.

Redovi 4, 5, 6 — oni su glavni. Od kojeg domena šaljemo poruku — tu oznaku stavljamo.
Ali ne navodi se uvijek u php skriptama u starom kodu polje 'from'. Tada pomaže ime korisnika.

Članak je već obilna — ne bih želio odvući pažnju na konfiguraciju nginx+fpm.

Ukratko — za svaku web stranicu postavljujemo svog linux korisnika. I sukladno tome, svoj fpm-pool.

Fpm-pool koristi bilo koju verziju php-a (to je sjajno jer na jednom serveru bez problema možemo koristiti različite verzije php-a pa čak i različite php.ini za susjedne web stranice).

Dakle, konkretni linux korisnik 'www-domain2' ima stranicu domain2.com. Na toj stranici postoji kod za slanje poruka bez navođenja polja from.

Dakle, čak i u tom slučaju, poruke će odlaziti ispravno i nikada neće završiti u spamu.

Moj '/etc/postfix/master.cf' izgleda ovako:

...
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

Datoteka nije u potpunosti sadržana — već je vrlo velika.
Označio sam samo ono što je promijenjeno.

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}

Ovo su postavke povezane sa SpamAssassinom, o njemu kasnije.

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

Dopuštamo povezivanje na poštanski poslužitelj preko porta 587.
Za to je obavezna autentifikacija.

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

Aktiviramo provjeru SPF-a.

apt-get install postfix-policyd-spf-python

Instaliramo paket za SPF provjere iznad.

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

A ovo je najzanimljivije. Ovo je mogućnost slanja poruka za određenu domenu s određenom IPv4/IPv6 adresom.

To se radi zbog rDNS-a. rDNS je dobivanje nekog stringa prema IP adresi.
I za poštu se ova mogućnost koristi za potvrdu da helo točno odgovara rDNS-u te adrese s koje je poslan email.

Ako helo ne odgovara domeni pošte, u ime koje je poslano pismo — dodjeljuju se spam bodovi.

Helo ne odgovara rDNS-u — dodjeljuje se mnogo spam bodova.
Prema tome, za svaku domenu treba biti vlastita IP adresa.
Za OVH — u konzoli postoji mogućnost određivanja rDNS-a.
Za tech.ru — pitanje se rješava putem podrške.
Za AWS — pitanje se rješava putem podrške.
«inet_protocols» i «smtp_bind_address6» — ovime uključujemo podršku za IPv6.
Za IPv6 također je potrebno postaviti rDNS.
«syslog_name» — ovo je radi lakšeg čitanja logova.

Kupovina certifikata preporučujem ovdje.

Postavka veze postfix+dovecot ovdje.

Postavka SPF.

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

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

Postavka mysql, instaliramo pakete sami.

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

disable_plaintext_auth = yes
auth_mechanisms = plain login

Ovlaštenje samo u enkriptiranom obliku.

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

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

Ovdje ćemo navesti mjesto spremanja poruka.

Želim da se pohranjuju u datotekama i da budu grupirani po domenama.

Datoteka «/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 {
  }
}

Ovo je glavna datoteka postavki dovecota.
Ovdje isključujemo nezaštićene veze.
I uključujemo zaštićene veze.

Datoteka «/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
}

Konfiguriramo ssl. Navodimo da je ssl obavezan.
I sam certifikat. I važan detalj — direktiva «local». Određuje koji ssl certifikat koristiti pri spajanju na određeni lokalni IPv4.

Usput, IPv6 ovdje nije podešen, to ću ispraviti nekom prilikom.
XX.XX.XX.X5 (domain2) — certifikat nedostaje. Za spajanje klijenata treba navesti domain1.com.
XX.XX.XX.X2 (domain3) — certifikat postoji, za spajanje klijenata može se navesti domain1.com ili domain3.com.

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

protocol lda {
  mail_plugins = $mail_plugins sieve
}

To će kasnije biti potrebno za spamassassin.

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

protocol imap {
  mail_plugins = $mail_plugins antispam
}

Ovo je antispam dodatak. Potreban je za obuku spamassassina prilikom premještanja u/iz mape «Spam».

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

protocol pop3 {
}

Jednostavno taka datoteka postoji.

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

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

Postavka lmtp.

Datoteka «/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
}

Postavke obuke spamassassina prilikom premještanja u/iz mape „Spam“.

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

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

Datoteka koja određuje što učiniti s dolaznim porukama.

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

require ["fileinto", "mailbox"];

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

Treba iskompajlirati datoteku: «sievec default.sieve».

Datoteka «/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
}

Određivanje sql datoteka za autentifikaciju.
A sama datoteka — kao način autentifikacije.

Datoteka «/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';

To odgovara sličnim postavkama za postfix.

Datoteka «/etc/dovecot/dovecot.conf»

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

Glavna konfigurationska datoteka.
Važno je ono što ovdje navodimo-dodajemo protokole.

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

apt-get install spamassassin spamc

Instalirajmo pakete.

adduser spamd --disabled-login

Dodajmo korisnika pod kojim će se koristiti.

systemctl enable spamassassin.service

Uključujemo automatsko pokretanje spamassassin servisa prilikom podizanja sustava.

Datoteka «/etc/default/spamassassin»:

CRON=1

Omogućava automatsko ažuriranje pravila „prema zadanim postavkama“.

Datoteka «/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

Treba napraviti u mysql bazi „sa“ s korisnikom „sa“ i lozinkom „password“ (zamijeniti nečim adekvatnim).

report_safe — to umjesto e-pošte će biti poslan izvještaj o e-poruci-spamu.
use_bayes — to su postavke strojnog učenja spamassassina.

Ostale postavke spamassassina su primijenjene ranije prema članku.

Opća postavka „spamassassin“.
O premještanju novih spam poruka u IMAP mapu „Spam“.
O jednostavnom povezivanju Dovecot + SpamAssassin.
Preporučujem da pročitate teoriju učenja spamassassina prilikom kretanja poruka u imap mapama (i ne preporučujem korištenje).

============= Obraćanje zajednici =============

Također bih želio predložiti ideju zajednici o tome kako povećati razinu sigurnosti u poslanim e-mailovima. Budući da sam se toliko duboko zaronio u temu elektroničke pošte.

Kako bi korisnik mogao na svom klijentu (Outlook, Thunderbird, proširenje za preglednik, ...) stvoriti par ključeva. Javnog i privatnog. Javni — poslati u DNS. Privatni — čuvati na klijentu. E-mail poslužitelji bi trebali znati primijeniti javni ključ za slanje određenom primatelju.

I za zaštitu od spam poruka kod takvih e-mailova (da, e-mail poslužitelj ne može pregledati sadržaj) — potrebno je uvesti 3 pravila:

  1. Obavezni pravi DKIM potpis, obavezni SPF, obavezni rDNS.
  2. Neuronska mreža o temi obuke protiv spama + baza podataka koja joj pripada na strani klijenta.
  3. Algoritam šifriranja trebao bi biti takav da strana koja šalje mora potrošiti 100 puta više računalne snage nego strana koja prima.

Osim javnih e-mailova — razviti standard e-maila-ponude za "započinjanje zaštićene komunikacije". Jedan od korisnika (e-mail adresa) šalje drugom e-mail s privitkom. U e-mailu je tekst-ponuda za započinjanje sigurnog kanala za komunikaciju i javni ključ vlasnika e-mail adrese (pri čemu se privatni ključ čuva na strani klijenta).

Može se čak stvoriti par ključeva posebno za svaku komunikaciju. Korisnik-primatelj može prihvatiti tu ponudu i poslati svoj javni ključ (također izrađen posebno za ovu komunikaciju). Nakon toga, prvi korisnik šalje kontrolni e-mail (šifriran javnim ključem drugog korisnika) — čime drugi korisnik može smatrati da je formirani komunikacijski kanal pouzdan. Nakon toga, drugi korisnik šalje kontrolni e-mail — i tada prvi korisnik također može smatrati da je formirani kanal zaštićen.

Kako bi se borilo protiv presretanja ključeva na putu — potrebno je u protokolu predvidjeti mogućnost prijenosa barem jednogjavnog ključa putem USB stik.

I najvažnije — da to sve funkcionira (pitanje "tko će to platiti?"):
Unesite e-mail certifikate od 10 $ za 3 godine. Oni će omogućiti pošiljatelju da naznači u DNS-u da su „moji javni ključevi tamo”. Ovi certifikati će omogućiti pokretanje sigurnih veza, dok će prihvaćati takve veze besplatno.
Gmail konačno monetizira svoje korisnike. Za 10 $ u 3 godine — pravo na stvaranje sigurnih kanala komunikacije.

============= Zaključak =============

Za testiranje cijelog članka planirao sam unajmiti namjenski server na mjesec dana i kupiti domenu sa SSL certifikatom.

No, životne okolnosti su dovele do toga da je ovo pitanje oduženo 2 mjeseca.
I kada se ponovo pojavilo slobodno vrijeme — odlučio sam objaviti članak kakav je, a ne riskirati da objava bude odgođena još godinu dana.

Ako bude dovoljno pitanja tipa „ovdje nije dovoljno detaljno objašnjeno” — tada ću vjerojatno pronaći snage da uzmem namjenski server s novom domenom i novim SSL certifikatom te da još detaljnije opisujem i, što je najvažnije — otkrijem sve propuštene važne detalje.

Također bih volio dobiti povratne informacije o ideji o e-mail certifikatima. Ako se ideja svidi — potrudit ću se pronaći snage napisati nacrt za RFC.

Prilikom kopiranja velikih dijelova članka — navedite poveznicu na ovaj članak.
Prilikom prevođenja na bilo koji drugi jezik — navedite poveznicu na ovaj članak.
Na engleski jezik pokušat ću prevesti sam i ostaviti međusobne poveznice.


Izvor: habr.com

Kupite pouzdan hosting za web stranice s DDoS zaštitom, VPS VDS servere 🔥 Kupite pouzdan hosting za web stranice s DDoS zaštitom, VPS VDS servere | ProHoster