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

Дадзены артыкул аб тым як наладзіць сучасны паштовы сервер.
Postfix + Dovecot. SPF + DKIM + rDNS. З IPv6.
З шыфраваннем TSL. З падтрымкай некалькіх даменаў – частка з сапраўдным SSL сертыфікатам.
З антыспам-абаронай і высокім антыспам-рэйтынгам у іншых паштовых сервераў.
З падтрымкай некалькіх фізічных інтэрфейсаў.
З OpenVPN, падлучэнне да якога праз IPv4, і якое дае IPv6.

Калі вы не жадаеце вывучаць гэтыя ўсе тэхналогіі, але жадаеце наладзіць такі сервер - тады гэты артыкул для вас.

У артыкуле адсутнічаюць спробы патлумачыць кожную дэталь. Тлумачэнне ідзе да таго, што наладжана не стандартна ці важна з пункта гледжання спажыўца.

Матывацыя наладзіць паштовы сервер - мая даўняя мара. Можа гэта гучыць дурное, але ИМХО, гэта значна лепш, чым марыць аб новай машыне каханай маркі.

Матывацыя наладзіць IPv6 – дзве. ІТ спецыялісту неабходна вывучаць новыя тэхналогіі ўвесь час, каб выжыць. Жадаецца ўнесці свой сціплы фундуш у дужанне з цэнзурай.

Матывацыя налады OpenVPN – толькі для таго, каб IPv6 працаваў на лакальнай машыне.
Матывацыя наладкі некалькіх фізічных інтэрфейсаў - у мяне на серверы адзін інтэрфейс "павольны, але безлімітны", а іншы "хуткі, але з тарыфам".

Матывацыя налады налады Bind - мой правайдэр дае нестабільны DNS сервер, а google бывае таксама дае збоі. Жадаю стабільны DNS сервер для асабістага выкарыстання.

Матывацыя напісаць артыкул - чарнавік быў напісаў 10 месяцаў таму, і я ў яго ўжо два разы зазіраў. Калі нават аўтару гэта рэгулярна трэба - то вялікая верагоднасць, што і іншым спатрэбіцца.

Універсальнага рашэння для паштовага сервера няма. Але я пастараюся напісаць тыпу "зрабіце вось так і потым, калі ўсё будзе працаваць як трэба - выкіньце лішняе".

Маецца сервер Colocation у кампаніі tech.ru. Ёсць магчымасць параўнаць з OVH, Hetzner, AWS. Для рашэння дадзенай задачы значна больш эфектыўна будзе супрацоўніцтва менавіта з tech.ru.

На сэрвэры ўсталяваны Debian 9.

На серверы 2 інтэрфейсу `eno1` і `eno2`. Першы безлімітны, а другі хуткі адпаведна.

Маецца 3 статычных IP адрасы, XX.XX.XX.X0 і XX.XX.XX.X1 і XX.XX.XX.X2 на інтэрфейсе `eno1` і XX.XX.XX.X5 на інтэрфейсе `eno2`.

Маецца XXXX:XXXX:XXXX:XXXX::/64 пул IPv6 адрасоў, якія прызначаны на інтэрфейс `eno1` і з яго XXXX:XXXX:XXXX:XXXX:1:2::/96 па маёй просьбе прызначылі на `eno2`.

Маецца 3 дамена `domain1.com`, `domain2.com`, `domain3.com`. Для `domain1.com` і `domain3.com` ёсць SSL сертыфікат.

Маецца google рахунак, на які жадаецца прывязаць паштовую скрыню `[электронная пошта абаронена]` (атрыманне пошты і адпраўка пошты прама з gmail інтэрфейсу).
Павінна быць паштовая скрыня `[электронная пошта абаронена]`, копію пошты з якога я жадаю бачыць у сябе ў gmail. І ў рэдка мець магчымасць адправіць чагосьці ад імя `[электронная пошта абаронена]` праз web-інтэрфейс.

Павінна быць паштовая скрыня `[электронная пошта абаронена]`, якім будзе карыстацца Іваноў са свайго iPhone.

Адпраўляемыя лісты павінны адпавядаць усім сучасным патрабаванням да антыспаму.
Павінен быць найвышэйшы ўзровень шыфраваньня, прадугледжаны ў публічных сетках.
Павінна быць падтрымка IPv6 і для адпраўкі і для атрымання лістоў.
Павінен быць SpamAssassin, які ніколі не будзе выдаляць лісты. А будзе ці bounce рабіць ці прапускаць ці адпраўляць у IMAP тэчку «Спам».
Павінна быць наладжана аўта-навучанне SpamAssassin: калі я перамяшчаю ліст у тэчку «Спам» - навучыцца на гэтым; калі я перамяшчаю ліст з тэчкі «Спам» - навучыцца на гэтым. Вынікі навучання SpamAssassin - павінны ўплываць на траплянне ліста ў тэчку "Спам".
Скрыпты php павінны ўмець адпраўляць пошту ад імя любога дамена на дадзеным серверы.
Павінен быць openvpn сэрвіс, з магчымасцю выкарыстоўваць IPv6 на кліенце, у якога няма IPv6.

Спачатку трэба наладзіць інтэрфейсы і маршрутызацыю, у тым ліку IPv6.
Потым трэба будзе наладзіць OpenVPN, які будзе злучацца па IPv4 і падаваць кліенту статычны-рэальны IPv6 адрас. У гэтага кліента будзе доступ да ўсіх IPv6 сэрвісаў на серверы і доступ да любых рэсурсаў IPv6 у інтэрнэце.
Потым трэба будзе наладзіць Postfix на адпраўку лістоў + SPF + DKIM + rDNS і іншыя таму падобныя дробязі.
Потым трэба будзе наладзіць Dovecot і наладзіць Multidomain.
Потым трэба будзе настроіць SpamAssassin і наладзіць навучанне.
У завяршэнне ўсталяваць Bind.

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

Для налады інтэрфейсаў трэба прапісаць вось такое ў "/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

Дадзеныя налады можна ўжываць на любым серверы ў tech.ru (з невялікім узгадненнем з падтрымкай) і яно адразу запрацуе як трэба.

Калі вопыт налады аналагічных рэчаў для Hetzner, OVH - там па-іншаму. Больш складана.

eno1 - гэта назва сеткавай карты # 1 (павольны, але безлімітны).
eno2 - гэта назва сеткавай карты # 2 (хуткі, але з тарыфам).
tun0 - гэта назва віртуальнай сеткавай карты ад OpenVPN.
XX.XX.XX.X0 - IPv4 #1 на eno1.
XX.XX.XX.X1 - IPv4 #2 на eno1.
XX.XX.XX.X2 - IPv4 #3 на eno1.
XX.XX.XX.X5 - IPv4 #1 на eno2.
XX.XX.XX.1 - IPv4 gateway.
XXXX:XXXX:XXXX:XXXX::/64 - IPv6 на ўвесь сервер.
XXXX:XXXX:XXXX:XXXX:1:2::/96 — IPv6 для eno2, усё астатняе звонку заходзіць у eno1.
XXXX:XXXX:XXXX:XXXX::1 — IPv6 gateway (варта адзначыць, што тут можна/трэба зрабіць па-іншаму. Указаць IPv6 свіча).
dns-nameservers - пазначаны 127.0.0.1 (таму што ўсталяваны bind лакальна) і 213.248.1.6 (гэта ад tech.ru ).

"table eno1t" і "table eno2t" - сэнс гэтых route-rule у тым, каб трафік які ўвайшоў праз eno1 -> сышоў бы праз яго ж, а трафік які ўвайшоў праз eno2 -> сышоў бы праз яго ж. А таксама злучэнні па ініцыятыве сервера сыходзілі б праз eno1.

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

Гэтай камандай мы задаём, што любы незразумелы трафік, які патрапіў пад любое rule у якога адзначана "table eno1t" -> накіраваць у інтэрфейс eno1.

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

Гэтай камандай мы задаём, што любы трафік па ініцыятыве сервера накіраваць у інтэрфейс eno1.

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

Гэтай камандай мы задаем самі правілы маркіроўкі трафіку.

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

Гэты блок задае другі IPv4 для інтэрфейсу eno1.

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

Гэтай камандай мы задаём route ад кліентаў OpenVPN да лакальных IPv4 акрамя XX.XX.XX.X0.
Чаму гэтай каманды дастаткова для ўсіх IPv4 – я да гэтага часу не разумею.

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

Гэта мы задаем адрас для самога інтэрфейсу. Сервер яго будзе выкарыстоўваць як "зыходны" адрас. Больш ніяк выкарыстоўвацца не будзе.

Чаму пазначана «:1:1::» так складана? Каб OpenVPN працавала правільна і толькі для гэтага. Пра гэта падрабязней пазней.

На тэму gateway так працуе і добра. Але па правільным - сюды трэба паказаць IPv6 свіча да якога падлучаны сервер.

Аднак чамусьці IPv6 перастае працаваць, калі я так раблю. Мусіць гэта замарочкі tech.ru нейкія.

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

Гэта даданне IPv6 адрасы на інтэрфейс. Калі трэба сотню адрасоў - значыць сотню радкоў у гэтым файле.

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

Адзначыў адрасы і падсеткі ўсіх інтэрфейсаў, каб было наглядна.
eno1 - абавязкова павінна быць/64» - таму што гэта ўвесь наш pool адрасоў.
tun0 - падсетка павінна быць абавязкова больш eno1. Інакш нельга будзе наладзіць IPv6 gateway для кліентаў OpenVPN.
eno2 - падсетка павінна быць абавязкова больш tun0. Інакш кліенты OpenVPN не змогуць патрапіць на IPv6 адрасы лакальныя.
Для навочнасці я абраў крок падсеткі 16, але пры жаданні можна нават "1" крок рабіць.
Адпаведна 64+16 = 80, а 80+16 = 96.

Для яшчэ большай навочнасці:
XXXX:XXXX:XXXX:XXXX:1:1:YYYY:YYYY — гэта адрасы, якія павінны быць прызначаны канкрэтным сайтам або сэрвісам на інтэрфейсе eno1.
XXXX:XXXX:XXXX:XXXX:1:2:YYYY:YYYY — гэта адрасы, якія павінны быць прызначаны канкрэтным сайтам або сэрвісам на інтэрфейсе eno2.
XXXX:XXXX:XXXX:XXXX:1:3:YYYY:YYYY - гэта адрасы, якія павінны быць прызначаны кліентам OpenVPN або выкарыстоўвацца як службовыя адрасы OpenVPN.

Для настройкі сеткі - павінна быць магчымасць перазагружаць сервер.
IPv4 змены падхапляюцца пры выкананні (абавязкова загарнуць у screen — інакш гэтая каманда проста выпусціць сетку на серверы):

/etc/init.d/networking restart

У файл "/etc/iproute2/rt_tables" дадаць у канец:

100 eno1t
101 eno2t

Без гэтага нельга выкарыстоўваць кастамныя table у файле "/etc/network/interfaces".
Лічбы павінны быць унікальныя і менш за 65535.

IPv6 змены змяняюцца лёгка без перазагрузкі, але для гэтага трэба навучыцца прынамсі тром камандам:

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

Настройка "/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

Гэта налады "sysctl" майго сервера. Адзначу важнае.

net.ipv4.ip_forward = 1

Без гэтага OpenVPN не будзе працаваць ніяк.

net.ipv6.ip_nonlocal_bind = 1

Любы, хто паспрабуе зрабіць bind IPv6 (напрыклад nginx) адразу пасля таго, як інтэрфейс падаўся - атрымае памылку. Што такі адрас недаступны.

Каб пазбегнуць такой сітуацыі і робіцца такая настройка.

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

Без гэтых настроек IPv6 трафік ад кліента OpenVPN не выходзіць у свет.

Іншыя налады ці не адносяцца да справы ці я не памятаю навошта яны.
Але на ўсякі выпадак пакідаю "як ёсць".

Для таго, каб змены гэтага файла падхапіліся без перазагрузкі сервера - трэба выканаць каманду:

sysctl -p

Больш дэталёва пра «table» правілы: habr.com/post/108690

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

OpenVPN IPv4 не працуе без iptables.

У мяне iptables вось такія для 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 - гэта мой статычны IPv4 адрас лакальнай машыны.
10.8.0.0/24 - IPv4 сетка openvpn. IPv4 адрасы для кліентаў openvpn.
Паслядоўнасць правіл важная.

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

Гэтае абмежаванне, каб толькі я са свайго статычнага IP мог бы скарыстацца OpenVPN.

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

Для прабівання IPv4 пакетаў паміж кліентамі OpenVPN і інтэрнэтам - трэба прапісаць адну з гэтых каманд.

Для розных выпадкаў адзін з варыянтаў не падыходзіць.
Для майго выпадку падыходзяць абедзве каманды.
Пачытаўшы дакументацыю я абраў першы варыянт, таму што ён есць менш CPU.

Каб усе налады iptables падхапляліся пасля reboot – трэба захаваць іх кудысьці.

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

Такія імёны выбраны не выпадкова. Іх выкарыстоўвае пакет "iptables-persistent".

apt-get install iptables-persistent

Устаноўка асноўнага пакета OpenVPN:

apt-get install openvpn easy-rsa

Наладзім шаблон для сертыфікатаў (падставіць свае значэнні):

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

Адрэдагуем наладкі шаблону сертыфікатаў:

mcedit vars

...
# These are the default values for fields
# which will be placed in the certificate.
# Don't leave any of these fields blank.
export KEY_COUNTRY="RU"
export KEY_PROVINCE="Krasnodar"
export KEY_CITY="Dinskaya"
export KEY_ORG="Own"
export KEY_EMAIL="[email protected]"
export KEY_OU="VPN"

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

Ствараем серверны сертыфікат:

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

Падрыхтуем магчымасць ствараць выніковыя "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

Прыгатуем скрыпт, які будзе сшываць усе файлы ў адзіны opvn файл.

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}/.crt 
    <(echo -e '</cert>n<key>') 
    ${KEY_DIR}/.key 
    <(echo -e '</key>n<tls-auth>') 
    ${KEY_DIR}/ta.key 
    <(echo -e '</tls-auth>') 
    > ${OUTPUT_DIR}/.ovpn

Ствараем першага кліента OpenVPN:

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

Файл "~/client-configs/files/client-name.ovpn" адпраўляем на ўтройства кліенту.

Для iOS кліентаў трэба будзе зрабіць трук:
Змесціва тэга "tls-auth" павінна быць без каментароў.
А таксама паставіць "key-direction 1" адразу перад тэгам "tls-auth".

Наладзім канфіг 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

Гэта трэба для таго, каб задаць статычны адрас кожнаму кліенту (не абавязкова, але я выкарыстоўваю):

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

Самая складаная і ключавая дэталь.

Нажаль OpenVPN яшчэ не ўмее самастойна наладжваць IPv6 gateway для кліентаў.
Даводзіцца "ўручную" прабіваць гэта для кожнага кліента.

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

Файл "/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

Файл "/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

Абодва скрыпту выкарыстоўваюць файл "/etc/openvpn/variables":

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

Чаму тут так напісана - цяжка ўспомніць.

Цяпер выглядае дзіўным netmask = 112 (тут жа 96 павінен быць).
І prefix дзіўны, не адпавядае сетцы tun0.
Але добра, пакідаю "як ёсць".

cipher DES-EDE3-CBC

Гэта на аматара - я абраў такі спосаб шыфравання злучэння.

Больш дэталёва пра настройку OpenVPN IPv4.

Больш дэталёва пра настройку OpenVPN IPv6.

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

Устаноўка асноўнага пакета:

apt-get install postfix

Пры ўсталёўцы абраць "internet-site".

Мой "/etc/postfix/main.cf" выглядае так:

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

# appending .domain is the MUA's job.
append_dot_mydomain = no

readme_directory = no

# See http://www.postfix.org/COMPATIBILITY_README.html -- default to 2 on
# fresh installs.
compatibility_level = 2

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

# Storage type
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 settings
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 address per domain
sender_dependent_default_transport_maps = pcre:/etc/postfix/sdd_transport.pcre

Разгледзім дэталі гэтага канфіга.

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

На думку хабраўчан дадзены блок змяшчае "дэзінфармацыю і няправільныя тэзісы".Толькі праз 8 гадоў пасля пачатку маёй кар'еры я пачаў разумець, як працуе SSL.

Таму я вазьму на сябе смеласць апісаць як карыстацца SSL (не адказваючы на ​​пытанні "Як гэта працуе?" і "Чаму гэта працуе?").

Аснова сучаснага шыфравання - гэта стварэнне пары ключоў (два вельмі доўгія радкі сімвалаў).

Адзін ключ прыватны, іншы ключ публічны . Прыватны ключ захоўваем вельмі старанна ў сакрэце. Публічны ключ раздаём усім жадаючым.

Пры дапамозе публічнага ключа можна зашыфраваць радок тэксту так, што расшыфраваць зможа толькі ўладальнік прыватнага ключа.
Ну вось і ўся аснова тэхналогіі.

Крок №1 - https сайты.
Браўзэр пры звароце да сайта даведаецца ад вэб сервера, што сайт https і таму запытвае публічны ключ.
Вэб сервер аддае публічны ключ. Браўзэр выкарыстоўваючы публічны ключ зашыфроўвае http-request і адпраўляе яго.
Кантэнт http-request можа прачытаць толькі той у каго ёсць прыватны ключ, то бок толькі сервер да якога выконваецца зварот.
Http-request утрымоўвае ў сабе прынамсі URI. Таму калі ў краіне спрабуюць абмежаваць доступ не да ўсяго сайта, а да канкрэтнай старонкі - то для https сайтаў гэта зрабіць немагчыма.

Крок №2 - зашыфраваны адказ.
Вэб сервер дае адказ, які лёгка могуць прачытаць па дарозе.
Рашэнне лімітава простае - браўзэр у сябе лакальна фармуе такую ​​ж пару прыватны-публічны ключ для кожнага https сайта.
І разам з запытам публічнага ключа сайта дасылае свой лакальны публічны ключ.
Вэб сервер запамінае яго і пры адпраўцы http-response шыфруе гэтым вось публічным ключом пэўнага кліента.
Цяпер http-response можа расшыфраваць толькі ўладальнік прыватнага ключа браўзэра кліента (гэта значыць сам кліент).

Крок №3 - усталёўка абароненага злучэння па публічным канале.
У прыкладзе №2 ёсць уразлівасць - нічога не мяшае добразычліўцам перахапіць http-request і падрэдагаваць інфармацыю аб публічным ключы.
Такім чынам пасярэднік будзе выдатна бачыць увесь кантэнт якія адпраўляюцца-атрымліваюцца паведамленняў пакуль не зменіцца канал сувязі.
Дужацца з гэтым лімітава проста - досыць адправіць публічны ключ браўзэра як паведамленне зашыфраванае публічным ключом вэб сервера.
Вэб сервер тады перш за ўсё адпраўляе адказ тыпу «твой публічны ключ вось такі вось» і шыфруе гэтае паведамленне гэтым жа публічным ключом.
Браўзэр глядзіць адказ - калі прыйшло паведамленне "твой публічны ключ вось такі вось" - то гэта 100% гарантыя, што дадзены канал сувязі бяспечны.
Наколькі ў бясьпецы?
Само стварэнне такога бяспечнага канала сувязі адбываецца са хуткасцю ping*2. Напрыклад 20мс.
Зламыснік павінен або загадзя мець прыватны ключ аднаго з бакоў. Або падабраць прыватны ключ за пару мілісекунд.
Узлом аднаго сучаснага прыватнага ключа зоймь дзесяцігоддзі на суперкампутары.

Крок №4 - публічная БД публічных ключоў.
Відавочна, што ва ўсёй гэтай гісторыі існуе магчымасць для зламысніка які сядзіць на канале сувязі паміж кліентам і серверам.
Магчымасць кліенту прадбачыцца серверам, а серверу прадставіцца кліентам. І сэмуляваць пару ключоў у абодва бакі.
Тады зламыснік будзе бачыць увесь трафік і будзе мець магчымасць "падрэдагаваць" трафік.
Напрыклад змяніць адрас куды адпраўляць грошы ці скапіяваць пароль ад анлайн-банка ці заблакаваць «непажаданы» кантэнт.
Для барацьбы з такімі зламыснікамі прыдумалі публічную БД з публічнымі ключамі для кожнага https сайта.
Кожны браўзэр "ведае" аб існаванні каля 200 такіх БД. Гэта прадусталяванае ў кожны браўзэр.
"Веды" падмацавана публічным ключом ад кожнага сертыфіката. Гэта значыць злучэнне з кожным пэўным цэнтрам сертыфікацыі падрабіць немагчыма.

Цяпер ёсць простае разуменне як карыстацца SSL для https.
Калі паварушыць мазгамі - тое стане зразумела, як спец-службы могуць у гэтай канструкцыі чагосьці ўзламаць. Але гэта ім будзе каштаваць жахлівых намаганняў.
А арганізацыям менш АНБ або ЦРУ - практычна немагчыма ўзламаць існуючы ўзровень абароны нават для vip.

Яшчэ дадам пра ssh злучэнні. Там ніякіх публічных ключоў няма, як жа быць. Пытанне вырашаецца двума спосабамі.
Варыянт ssh-па-паролю:
Пры першым злучэнні ssh-кліент павінен папярэдзіць, што тут у нас новы публічны ключ ад ssh-сервера.
І пры далейшых злучэннях калі з'явілася папярэджанне "новы публічны ключ ад ssh-сервера" - будзе азначаць, што вас спрабуюць праслухаць.
Або пры першым злучэнні вас праслухоўвалі, а зараз вы маеце зносіны з серверам без пасярэднікаў.
Уласна з-за таго, што факт праслухоўвання лёгка, хутка і без намаганняў выкрываецца - гэтай атакай карыстаюцца толькі ў асаблівых выпадках пад канкрэтнага кліента.

Варыянт ssh-па-ключу:
Бярэм флэшку, запісваем на яе прыватны ключ для ssh-сервера (для гэтага ёсць тэрміны і куча нюансаў істотных, але я пішу лікбез, а не інструкцыю па ўжыванні).
Публічны ключ пакідаем на машыне дзе будзе ssh-кліент і яго таксама трымаем у сакрэце.
Прыносім флэшку да сервера, устаўляемы, які капіюецца прыватны ключ, а флэшку спальваем і развейваем прах па ветры (ці хоць бы фарматуем з запаўненнем нулямі).
Вось і ўсё - пасля такой аперацыі будзе немагчыма ўзламаць такое ssh злучэнне. Зразумела гадоў за 10 на суперкампутары можна будзе паглядзець трафік - але гэта асобная гісторыя.

Прашу прабачэння за афтоп.

Такім чынам, зараз калі вядомая тэорыя. Раскажу пра flow стварэння SSL сертыфіката.

Пры дапамозе openssl genrsa мы ствараем прыватны ключ і нарыхтовак для публічнага ключа.
"нарыхтовак" адпраўляем іншай кампаніі, якой мы плацім прыкладна $9 за самы просты сертыфікат.

Праз пару гадзін мы атрымліваем ад гэтай іншай кампаніі наш "публічны" ключ і яшчэ набор некалькіх публічных ключоў.

Навошта іншай кампаніі плаціць за афармленне майго публічнага ключа - пытанне асобнае, тут разглядаць не будзем.

Цяпер зразумела ў чым сэнс надпісу:

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

У тэчцы "/etc/ssl" складзены ўсе файлы для ssl пытанняў.
domain1.com - назва дамена.
2018 - год стварэння ключоў.
"key" - абазначэнне, што файл прыватны-ключ.

І сэнс гэтага файла:

smtpd_tls_cert_file=/etc/ssl/domain1.com.2018.chained.crt
domain1.com - назва дамена.
2018 - год стварэння ключоў.
chained – пазначэнне, што тут ланцужок грамадскіх ключоў (першы – наш грамадскі і іншыя – што прыйшло ад кампаніі якая аформіла публічны ключ).
crt - абазначэнне, што тут гатовы сертыфікат (публічны ключ з тлумачэннямі тэхнічнымі).

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

Гэтая ўстаноўка ў дадзеным выпадку не выкарыстоўваецца, але напісана для прыкладу.

Бо памылка ў дадзеным параметры прывядзе да адпраўкі ад вашага сервера спаму (без вашай волі).

Потым даказвайце ўсім, што вы не вінаватыя.

recipient_delimiter = +

Магчыма многія не ведаюць, дык вось гэта стандартны сімвал для ранжыравання пасем, і гэта падтрымліваецца большасцю сучасных паштовых сервераў.

Напрыклад калі ў вас ёсць паштовая скрыня[электронная пошта абаронена]» паспрабуйце адправіць на «[электронная пошта абаронена]» - Паглядзіце што з гэтага атрымаецца.

inet_protocols = ipv4

Магчыма гэта будзе збіваць з панталыку.

Але гэта ня проста так. Кожны новы дамен - па змаўчанні толькі IPv4, потым уключаю IPv6 для кожнага ў асобнасці.

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

Тут мы задаём, што ўся ўваходная пошта сыходзіць у dovecot.
А правілы для domain, mailbox, alias - глядзець у БД.

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

user = usermail
password = mailpassword
hosts = 127.0.0.1
dbname = servermail
query = SELECT 1 FROM virtual_domains WHERE name='%s'

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

user = usermail
password = mailpassword
hosts = 127.0.0.1
dbname = servermail
query = SELECT 1 FROM virtual_users WHERE email='%s'

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

user = usermail
password = mailpassword
hosts = 127.0.0.1
dbname = servermail
query = 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

Цяпер postfix ведае, што прымаць пошту для далейшай адпраўкі можна толькі па аўтарызацыі з dovecot.

Мне праўда не вельмі зразумела, навошта гэта тут дубліраваць. Мы ж ужо паказалі ў "virtual_transport" усё што трэба.

Але postfix сістэма вельмі старая - напэўна гэта кастылі ад старых часоў.

smtpd_recipient_restrictions =
        ...

smtpd_helo_restrictions =
        ...

smtpd_client_restrictions =
        ...

Гэта наладжваць для кожнага паштовага сервера па-свойму.

У маім распараджэнні ёсць 3 паштовыя серверы і гэтыя налады вельмі розныя з-за розных патрабаванняў да выкарыстання.

Наладжваць трэба ўважліва - інакш спам хлыне да вас ці яшчэ горш - спам хлыне ад вас.

# SPF
policyd-spf_time_limit = 3600

Настройка для нейкага плагіна звязанага з праверкай 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

Настройка, што ўсе выходныя лісты мы павінны забяспечваць подпісам DKIM.

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

Гэта ключавая дэталь у маршрутызацыі лістоў пры адпраўкі лістоў ад php скрыптоў.

Файл "/etc/postfix/sdd_transport.pcre":

/^[email protected]$/ domain1:
/^[email protected]$/ domain2:
/^[email protected]$/ domain3:
/@domain1.com$/             domain1:
/@domain2.com$/             domain2:
/@domain3.com$/             domain3:

Злева - рэгулярныя выразы. Справа - пазнака, якой адзначаецца ліст.
Postfix у адпаведнасці з пазнакай - улічыць яшчэ некалькі радкоў канфігурацыі для канкрэтнага ліста.

Як менавіта будзе пераканфігураваны postfix для канкрэтнага ліста - будзе паказана ў «master.cf».

Радкі 4, 5, 6 - яны галоўныя. Ад імя якога дамена адпраўляем ліст - такую ​​пазнаку і ставім.
Але не заўсёды ў php скрыптах у старым кодзе паказваецца поле "from". Тады на дапамогу прыходзіць імя карыстальніка.

Артыкул і так шырокая - не хацелася б адцягвацца на наладу nginx + fpm.

Коратка - мы для кожнага сайта задаём свайго linux-user уладальніка. І адпаведна свой fpm-pool.

Fpm-pool выкарыстоўвае любую версію php (гэта цудоўна калі на адным серверы без праблем для суседніх сайтаў можна выкарыстоўваць розную версію php і нават розны php.ini).

Дык вось у канкрэтнага linux-user "www-domain2" ёсць сайт domain2.com. На гэтым сайце ёсць код адпраўкі лістоў без указання поля from.

Дык вось нават у такім выпадку лісты будуць сыходзіць карэктна і ніколі не патрапяць у спам.

Мой "/etc/postfix/master.cf" выглядае так:

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

Файл прыведзены не цалкам - ён і так вельмі вялікі.
Адзначыў толькі тое, што зменена.

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}

Гэта наладкі звязаныя са spamassasin, пра яго пазней.

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

Дазваляем далучацца да паштовага сервера праз 587 порт.
Для гэтага абавязкова аўтарызавацца.

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

Уключаем праверку SPF.

apt-get install postfix-policyd-spf-python

Усталюем пакет для SPF праверак вышэй.

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

А гэта самае цікавае. Гэта магчымасць адпраўляць лісты для канкрэтнага дамена з канкрэтнага IPv4/IPv6 адраса.

Робіцца гэта дзеля rDNS. rDNS - гэта атрыманне нейкага радка па IP адрасе.
І для пошты гэтая магчымасць выкарыстоўваецца для пацверджання таго, што helo сапраўды адпавядае rDNS таго адраса, з якога адправілі email.

Калі helo не адпавядае дамену пошты, ад імя каго адправілі ліст - налічваюцца спам акуляры.

Helo не адпавядае rDNS - налічваецца шмат спам ачкоў.
Адпаведна для кожнага дамена павінен быць свой IP адрас.
Для OVH - у кансольцы ёсць магчымасць паказваць rDNS.
Для tech.ru - праз саппорт пытанне вырашаецца.
Для AWS - праз саппорт пытанне вырашаецца.
"inet_protocols" і "smtp_bind_address6" - гэта мы ўключаем падтрымку IPv6.
Для IPv6 таксама трэба rDNS прапісваць.
"syslog_name" - а гэта для зручнасці чытання логаў.

Купляць сертыфікаты рэкамендую тут.

Настройка звязкі postfix+dovecot тут.

Настройка SPF.

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

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

Налада mysql, які ўсталёўваецца самі пакеты.

Файл "/etc/dovecot/conf.d/10-auth.conf"

disable_plaintext_auth = yes
auth_mechanisms = plain login

Аўтарызацыя толькі ў зашыфраваным выглядзе.

Файл "/etc/dovecot/conf.d/10-mail.conf"

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

Тут пакажам месца захоўвання лістоў.

Я хачу, каб яны захоўваліся ў файлах і былі згрупаваны па даменах.

Файл "/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 {
  }
}

Гэта галоўны файл налад dovecot.
Тут мы адключаем не абароненыя злучэнні.
І ўключаем абароненыя злучэнні.

Файл "/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
}

Наладжваем ssl. Паказваем, што ssl - абавязкова.
І сам сертыфікат. І важная дэталь - дырэктыва "local". Паказвае, пры злучэнні да якога лакальнага IPv4 - які ssl сертыфікат выкарыстоўваць.

Дарэчы IPv6 тут не наладжаны, выпраўлю гэты недагляд як-нітку потым.
XX.XX.XX.X5 (domain2) - сертыфіката няма. Для злучэння кліентаў трэба ўказваць domain1.com.
XX.XX.XX.X2 (domain3) — сертыфікат ёсць, для злучэння кліентаў можна ўказваць domain1.com або domain3.com .

Файл "/etc/dovecot/conf.d/15-lda.conf"

protocol lda {
  mail_plugins = $mail_plugins sieve
}

Гэта ў далейшым трэба будзе для spamassassin.

Файл "/etc/dovecot/conf.d/20-imap.conf"

protocol imap {
  mail_plugins = $mail_plugins antispam
}

Гэта antispam убудова. Патрэбен для навучання spamassasin у момант пераносу ў/з папкі "Spam".

Файл "/etc/dovecot/conf.d/20-pop3.conf"

protocol pop3 {
}

Проста такі файл ёсць.

Файл "/etc/dovecot/conf.d/20-lmtp.conf"

protocol lmtp {
  mail_plugins = $mail_plugins sieve
  postmaster_address = [email protected]
}

Настройка lmtp.

Файл "/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
}

Налады навучання spamassasin у момант пераносу ў/з папкі "Spam".

Файл "/etc/dovecot/conf.d/90-sieve.conf"

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

Файл у якім паказана што рабіць з уваходнымі лістамі.

Файл "/var/lib/dovecot/sieve/default.sieve"

require ["fileinto", "mailbox"];

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

Трэба скампіляваць файл: "sievec default.sieve".

Файл "/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
}

Указанне sql файлаў для аўтарызацыі.
А сам файл - як спосаб аўтарызацыі.

Файл "/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';

Гэта адпавядае аналагічным наладам для postfix.

Файл "/etc/dovecot/dovecot.conf"

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

Асноўны файл канфігурацыі.
Важна тое, што мы тут паказваем-дадаем пратаколы.

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

apt-get install spamassassin spamc

Усталюем пакеты.

adduser spamd --disabled-login

Дадамо карыстальніка ад імя якога.

systemctl enable spamassassin.service

Уключаем аўта-загрузку spamassassin сэрвіс пры загрузцы.

Файл "/etc/default/spamassassin":

CRON=1

Уключаўшы аўтаматычнае абнаўленне правілаў "па змаўчанні".

Файл "/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

Трэба зрабіць у mysql БД "sa" з карыстачом "sa" з паролем "password" (замяніць на нешта адэкватнае).

report_safe - гэта замест ліста будзе дасылацца справаздача аб лісце-спаме.
use_bayes - гэта налады машыннага навучання spamassassin.

Астатнія налады spamassassin ужываліся раней па артыкуле.

Агульная настройка spamassassin.
Пра перамяшчэнне новых Спам-лістоў у IMAP тэчку «Spam».
Пра простую звязак Dovecot + SpamAssassin.
Рэкамендую да чытання тэорыя навучання spamassasin пры руху лістоў у imap тэчках (і не рэкамендую да ўжывання).

============= Зварот да супольнасці =============

Яшчэ хацелася б закінуць ідэю ў супольнасць пра тое, як павысіць узровень абароненасці лістоў, якія перасылаюцца. Калі ўжо я так глыбока пагрузіўся ў тэму пошты.

Каб карыстач мог бы ў сябе на кліенце (outlook, thunderbird, browser-plugin, …) стварыць пару ключоў. Публічны і прыватны. Публічны - адправіць у DNS. Прыватны - захоўваць на кліенце. Паштовыя серверы б умелі прымяняць публічны ключ для адпраўкі канкрэтнаму адрасату.

І для абароны ад спаму пры такіх лістах (так, паштовы сервер жы не зможа паглядзець кантэнт) — трэба будзе ўвесці 3 правілы:

  1. Абавязковы сапраўдны подпіс DKIM, абавязковы SPF, абавязковы rDNS.
  2. Нейронавая сетка на тэму навучання антыспаму + БД да яе на баку кліента.
  3. Алгарытм шыфравання павінен быць такім, што які адпраўляе бок павінна выдаткаваць на шыфраванні ў 100 раз больш магутнасцяў CPU, чым прымаючы бок.

Акрамя публічных лістоў - распрацаваць стандарт ліста-прапановы «пачаць абароненую перапіску». Адзін з карыстальнікаў (паштовая скрыня) шле іншай паштовай скрыні ліст з атачам. У лісце тэкст-прапанова пачаць абаронены канал сувязі для перапіскі і публічны ключ уладальніка паштовай скрыні (пры гэтым прыватны ключ на баку кліента).

Можна нават пару ключоў рабіць спецыяльна для кожнай перапіскі. Карыстальнік-атрымальнік можа прыняць гэтую прапанову і адправіць свой публічны ключ (таксама зроблены спецыяльна для дадзенай перапіскі). Далей першы карыстач адпраўляе службовы кантрольны ліст (зашыфраваны публічным ключом другога карыстача) — пры атрыманні якога другі карыстач можа лічыць сфармаваны канал сувязі надзейным. Далей другі карыстач адпраўляе кантрольны ліст - і тады першы карыстач таксама можа лічыць сфармаваны канал абароненым.

Для барацьбы з перахопам ключоў па дарозе – трэба ў пратаколе прадугледзець магчымасць перадачы хаця б аднаго публічнага ключа пры дапамозе флэшкі.

І самае галоўнае - каб гэта ўсё працавала (пытанне «а хто за гэта заплаціць?»):
Увесці паштовыя сертыфікаты коштам ад 10 $ за 3 гады. Якія будуць дазваляць адпраўніку ўказаць у dns, што «мае публічныя ключы знаходзяцца вон-там». І будуць даваць магчымасць пачынаць абароненае злучэнне. Пры гэтым - прымаць такія злучэнні бясплатна.
gmail нарэшце манетызуе сваіх карыстальнікаў. За 10 $ у 3 гады - права ствараць абароненыя каналы перапіскі.

============= Заключэнне =============

Для тэставання ўсяго артыкула я збіраўся арандаваць выдзелены сервер на месяц і купіць дамен з ssl сертыфікатам.

Але жыццёвыя абставіны склаліся так гэтае пытанне зацягнулася на 2 месяцы.
І вось калі з'явіўся зноў вольны час - вырашыў публікаваць артыкул як ёсць, а не рызыкаваць тым, што публікацыя зацягнецца яшчэ на год.

Калі будзе дастаткова шмат пытанняў тыпу "а вось тут мала падрабязна апісана" – тады напэўна знойдуцца сілы ўзяць выдзелены сервер з новым даменам і новым SSL сертыфікатам і яшчэ падрабязней апісаць і галоўнае – выявіць усе выпушчаныя важныя дэталі.

Таксама хацелася б атрымаць водгукі на тэму ідэі пра паштовыя сертыфікаты. Калі ідэя спадабаецца - пастараюся знайсці сілы напісаць чарнавік для rfc.

Пры капіяванні вялікіх кавалкаў артыкула - паказваць спасылку на гэты артыкул.
Пры перакладзе на любую іншую мову — указваць спасылку на гэты артыкул.
На англійскую мову я сам пастараюся перавесці і пакіну крыжаваныя спасылкі.


Крыніца: habr.com

Дадаць каментар