Debian + Postfix + Dovecot + 多域 + SSL + IPv6 + OpenVPN + 多介面 + SpamAssassin-learn + 綁定

本文介紹如何設定現代郵件伺服器。
後綴+鴿舍。 SPF + DKIM + rDNS。 使用 IPv6。
採用 TSL 加密。 支援多個網域 - 包含真正的 SSL 憑證。
具有反垃圾郵件保護和來自其他郵件伺服器的高反垃圾郵件評級。
支援多種物理介面。
使用 OpenVPN,透過 IPv4 進行連接,並提供 IPv6。

如果您不想學習所有這些技術,但想建立這樣的伺服器,那麼這篇文章適合您。

本文並未嘗試解釋每一個細節。 解釋了哪些內容未配置為標準或從消費者的角度來看很重要。

建立郵件伺服器的動機是我長期以來的夢想。 這聽起來可能很愚蠢,但恕我直言,這比夢想擁有一輛你最喜歡的品牌的新車要好得多。

設定 IPv6 有兩個動機。 IT專家需要不斷學習新技術才能生存。 我願意為反對審查制度做出自己的微薄貢獻。

設定 OpenVPN 的動機只是為了讓 IPv6 在本機電腦上運作。
設定多個實體介面的動機是,在我的伺服器上,我有一個介面“慢但無限制”,另一個介面“快但有關稅”。

設定Bind設定的動機是我的ISP提供了不穩定的DNS伺服器,Google有時也會失敗。 我想要一個穩定的 DNS 伺服器供個人使用。

寫文章的動機——我10個月前寫了一篇草稿,我已經看了兩次了。 即使作者經常需要它,其他人也很可能需要它。

郵件伺服器沒有通用的解決方案。 但我會嘗試寫一些類似「這樣做,然後,當一切都按預期進行時,扔掉多餘的東西」。

tech.ru 公司擁有一台託管伺服器。 可以與OVH、Hetzner、AWS進行比較。 為了解決這個問題,與tech.ru的合作會更有效。

伺服器上安裝了 Debian 9。

伺服器有 2 個介面“eno1”和“eno2”。 第一個是無限的,第二個是快速的。

有 3 個靜態 IP 位址,「eno0」介面上有 XX.XX.XX.X1 和 XX.XX.XX.X2 和 XX.XX.XX.X1,「eno5」介面上有 XX.XX.XX.X2 。

可用 XXXX:XXXX:XXXX:XXXX::/64 分配給「eno6」介面的 IPv1 位址池,並根據我的要求將 XXXX:XXXX:XXXX:XXXX:1:2::/96 指派給「eno2」。

有 3 個網域「domain1.com」、「domain2.com」、「domain3.com」。 `domain1.com` 和 `domain3.com` 有一個 SSL 憑證。

我有一個 Google 帳戶,我想將其連結到我的郵箱[電子郵件保護]`(直接從 gmail 介面接收郵件和發送郵件)。
一定要有信箱`[電子郵件保護]`,我想在 Gmail 中查看的電子郵件副本。 而且能代發東西的也很少見`[電子郵件保護]` 透過網路介面。

一定要有信箱`[電子郵件保護]`,伊凡諾夫將在他的 iPhone 上使用它。

發送的電子郵件必須符合所有現代反垃圾郵件要求。
公共網路必須提供最高等級的加密。
發送和接收信件都應該支援 IPv6。
應該有一個永遠不會刪除電子郵件的 SpamAssassin。 它會退回、跳過或傳送到 IMAP「垃圾郵件」資料夾。
必須配置 SpamAssassin 自動學習:如果我將一封信移至 Spam 資料夾,它就會從中學習; 如果我從垃圾郵件資料夾中移動一封信,它就會從中學習。 SpamAssassin 訓練的結果應該會影響信件是否最終進入垃圾郵件資料夾。
PHP 腳本必須能夠代表給定伺服器上的任何網域發送郵件。
應該有一個 openvpn 服務,能夠在沒有 IPv6 的客戶端上使用 IPv6。

首先,您需要設定介面和路由,包括 IPv6。
然後,您需要設定 OpenVPN,它將透過 IPv4 連接並為用戶端提供靜態真實 IPv6 位址。 該用戶端將有權存取伺服器上的所有 IPv6 服務以及 Internet 上的任何 IPv6 資源。
然後你需要設定Postfix發送信件+SPF+DKIM+rDNS和其他類似的小東西。
然後您需要配置 Dovecot 並配置多域。
然後您需要配置 SpamAssassin 並配置訓練。
最後,安裝綁定。

============= 多介面==============

要配置接口,您需要將其寫入“/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 - eno4 上的 IPv1 #1。
XX.XX.XX.X1 - eno4 上的 IPv2 #1。
XX.XX.XX.X2 - eno4 上的 IPv3 #1。
XX.XX.XX.X5 - eno4 上的 IPv1 #2。
XX.XX.XX.1 - IPv4 網關。
XXXX:XXXX:XXXX:XXXX::/64 - 整個伺服器的 IPv6。
XXXX:XXXX:XXXX:XXXX:1:2::/96 - eno6 的 IPv2,來自外部的所有其他內容都進入 eno1。
XXXX:XXXX:XXXX:XXXX::1 — IPv6 閘道(值得注意的是,這可以/應該以不同的方式完成。指定 IPv6 交換器)。
dns-nameservers - 指示 127.0.0.1(因為 bind 是本地安裝的)和 213.248.1.6(來自 tech.ru)。

「table eno1t」和「table eno2t」 - 這些路由規則的含義是透過 eno1 進入 -> 的流量將通過它離開,通過 eno2 進入 -> 的流量將通過它離開。 伺服器發起的連線也會經過eno1。

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

使用此命令,我們指定將屬於任何標記為「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

此區塊指定 eno4 介面的第二個 IPv1。

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

使用此指令,我們設定從 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 才能正常運作並且僅用於此目的。 稍後會詳細介紹這一點。

關於網關的主題 - 這就是它的工作原理,這很好。 但正確的做法是在這裡指明伺服器所連接的交換器的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「 - 因為這是我們的整個地址池。
tun0 - 子網路必須大於 eno1。 否則,將無法為 OpenVPN 用戶端設定 IPv6 閘道。
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 變更(請務必將其包裹在螢幕中 - 否則此命令只會使伺服器上的網路崩潰):

/etc/init.d/networking restart

加到檔案“/etc/iproute2/rt_tables”的末尾:

100 eno1t
101 eno2t

如果沒有這個,您就無法使用「/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

介面啟動後立即嘗試綁定 IPv6(例如 nginx)的任何人都會收到錯誤。 該地址不可用。

為了避免這樣的情況,做了這樣的設定。

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

如果沒有這些 IPv6 設置,來自 OpenVPN 用戶端的流量將不會傳播到世界各地。

其他設定要么不相關,要么我不記得它們的用途。
但為了以防萬一,我「保持原樣」。

為了在不重新啟動伺服器的情況下拾取對此文件的更改,您需要執行以下命令:

sysctl -p

有關“表”規則的更多詳細資訊: habr.com/post/108690

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

如果沒有 iptables,OpenVPN IPv4 就無法運作。

我的 VPN iptables 是這樣的:

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 網路。 openvpn 用戶端的 IPv4 位址。
規則的一致性很重要。

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

要在 OpenVPN 用戶端和 Internet 之間轉送 IPv4 封包,您需要註冊這些命令之一。

對於不同的情況,其中一個選項並不適合。
這兩個命令都適合我的情況。
閱讀文件後,我選擇了第一個選項,因為它使用的 CPU 更少。

為了在重新啟動後拾取所有 iptables 設置,您需要將它們保存在某個地方。

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 閘道。
您必須為每位客戶「手動」轉發此訊息。

# 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)。
而且前綴很奇怪,它與tun0網路不符。
但好吧,我會保持原樣。

cipher DES-EDE3-CBC

這並不適合所有人 - 我選擇了這種加密連接的方法。

了解有關設定 OpenVPN IPv4 的更多資訊。

了解有關設定 OpenVPN IPv6 的更多資訊。

============= 後綴 =============

安裝主套件:

apt-get install postfix

安裝時選擇「互聯網站點」。

我的“/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 網站。
當造訪某個網站時,瀏覽器從 Web 伺服器獲知該網站是 https,因此會要求公鑰。
Web 伺服器給予公鑰。 瀏覽器使用公鑰加密http請求並發送。
http請求的內容只有擁有私鑰的人才能讀取,也就是只有發出請求的伺服器才能讀取。
Http-request 至少包含一個 URI。 因此,如果一個國家試圖限制存取的不是整個網站,而是特定頁面,那麼這對 https 網站來說是不可能做到的。

步驟#2 - 加密回應。
網路伺服器提供了可以在路上輕鬆閱讀的答案。
解決方案非常簡單 - 瀏覽器在本地為每個 https 網站產生相同的私鑰-公鑰對。
隨著對網站公鑰的請求,它會發送其本地公鑰。
Web 伺服器會記住它,並在發送 http 回應時使用特定客戶端的公鑰對其進行加密。
現在http-response只能由客戶端瀏覽器私鑰的擁有者(即客戶端本身)解密。

步驟 3 - 透過公共通道建立安全連線。
範例 2 中存在一個漏洞 - 沒有什麼可以阻止好心人攔截 http 請求並編輯有關公鑰的資訊。
因此,中間人將清楚地看到發送和接收的訊息的所有內容,直到通訊通道發生變化。
處理這個問題非常簡單 - 只需將瀏覽器的公鑰作為使用 Web 伺服器的公鑰加密的訊息發送即可。
然後,網路伺服器首先發送一個類似「你的公鑰是這樣的」的回應,並使用相同的公鑰加密該訊息。
瀏覽器查看回應 - 如果收到訊息「您的公鑰是這樣的」 - 那麼這就是 100% 保證該通訊通道是安全的。
安全性如何?
這種安全通訊通道的建立速度為 ping*2。 例如20毫秒。
攻擊者必須事先擁有其中一方的私鑰。 或在幾毫秒內找到私鑰。
在超級電腦上破解一個現代私鑰需要數十年的時間。

步驟#4 - 公鑰的公共資料庫。
顯然,在整個故事中,攻擊者有機會佔據客戶端和伺服器之間的通訊通道。
客戶端可以冒充伺服器,伺服器也可以冒充客戶端。 並在兩個方向上模擬一對按鍵。
然後攻擊者將看到所有流量並能夠「編輯」流量。
例如,變更匯款地址或複製網路銀行的密碼或封鎖「令人反感」的內容。
為了對抗此類攻擊者,他們提出了一個公共資料庫,其中包含每個 https 網站的公鑰。
每個瀏覽器都「知道」大約 200 個此類資料庫的存在。 每個瀏覽器中都預先安裝了它。
「知識」由每個憑證的公鑰支援。 也就是說,與每個特定證書頒發機構的連接無法偽造。

現在已經簡單了解如何使用SSL進行https。
如果你動動腦子,就會清楚特殊服務如何破解這個結構中的某些東西。 但這將讓他們付出巨大的努力。
對於小於 NSA 或 CIA 的組織來說,破解現有的保護等級幾乎是不可能的,即使對於 VIP 來說也是如此。

我還將添加有關 ssh 連接的內容。 那裡沒有公鑰,那你能做什麼呢? 該問題透過兩種方式解決。
選項 ssh-by-password:
在第一次連線期間,ssh 用戶端應該警告我們從 ssh 伺服器取得了新的公鑰。
在進一步的連線過程中,如果出現「來自 ssh 伺服器的新公鑰」警告,則表示他們正在試圖竊聽您。
或者您在第一次連接時被竊聽,但現在您無需中介即可與伺服器進行通訊。
實際上,由於竊聽的事實很容易、快速且毫不費力地被揭露,這種攻擊僅在針對特定客戶端的特殊情況下使用。

選項 ssh-by-key:
我們拿一個閃存驅動器,在上面寫入 ssh 伺服器的私鑰(這有一些術語和許多重要的細微差別,但我正在編寫一個教育程序,而不是使用說明)。
我們將公鑰留在 ssh 客戶端所在的電腦上,並對其保密。
我們把閃存驅動器帶到伺服器上,插入它,複製私鑰,然後燒掉閃存驅動器,將灰燼撒到風中(或至少用零格式化)。
就是這樣 - 在這樣的操作之後,將不可能破解這樣的 ssh 連接。 當然,十年後就可以在超級電腦上查看流量——但那是另一回事了。

我為題外話道歉。

現在這個理論已經眾所周知了。 我將向您介紹建立 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。
以及網域、郵箱、別名的規則 - 在資料庫中尋找。

/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 使用者擁有者。 相應地你的 fpm 池。

Fpm-pool 使用任何版本的 php(在同一台伺服器上,您可以使用不同版本的 php,甚至可以為相鄰網站使用不同的 php.ini,這很棒)。

因此,特定的 linux 使用者「www-domain2」有一個網站domain2.com。 該網站有一個用於發送電子郵件的程式碼,無需指定寄件者欄位。

因此,即使在這種情況下,信件也將被正確發送,並且永遠不會成為垃圾郵件。

我的“/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 完全相符。

如果 helo 與傳送信件的電子郵件網域不匹配,則會獎勵垃圾郵件積分。

Helo 與 rDNS 不符 - 授予大量垃圾郵件積分。
因此,每個網域必須有自己的 IP 位址。
對於 OVH - 在控制台中可以指定 rDNS。
對於 tech.ru - 問題已透過支援解決。
對於 AWS,該問題是透過支援解決的。
“inet_protocols”和“smtp_bind_address6” - 我們啟用 IPv6 支援。
對於 IPv6,您還需要註冊 rDNS。
“syslog_name” - 這是為了方便閱讀日誌。

購買證書 我在這裡推薦.

在這裡設定 postfix+dovecot 鏈接.

設定SPF。

============= 鴿舍 =============

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。
還有證書本身。 一個重要的細節是「本地」指令。 指示連接到哪個本機 IPv4 時要使用哪個 SSL 憑證。

順便說一句,這裡沒有配置IPv6,我稍後會修正這個遺漏。
XX.XX.XX.X5(網域2)- 無憑證。 若要連接客戶端,您需要指定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
}

這是一個反垃圾郵件插件。 在與「垃圾郵件」資料夾之間傳輸時需要訓練 spamassasin。

檔案“/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 訓練設定。

檔案“/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「垃圾郵件」資料夾.
關於Dovecot + SpamAssassin的簡單組合.
我建議在 imap 資料夾中移動字母時閱讀 spamassasin 學習理論(並且我不建議使用它).

============= 向社會呼籲=============

我還想向社區提出一個關於如何提高轉發信件的安全級別的想法。 因為我深深地沉浸在郵件這個話題中。

這樣使用者就可以在他的客戶端(outlook、thunderbird、瀏覽器外掛程式等)上建立一對金鑰。 公立和私立。 公共 - 發送到 DNS。 私密 - 為客戶節省費用。 郵件伺服器將能夠使用公鑰傳送給特定的收件者。

為了防止此類信件的垃圾郵件(是的,郵件伺服器將無法查看內容) - 您需要引入 3 條規則:

  1. 強制真實 DKIM 簽章、強制 SPF、強制 rDNS。
  2. 一個關於反垃圾郵件訓練的神經網路+一個客戶端資料庫。
  3. 加密演算法必須使得發送方在加密上花費的 CPU 能力必須是接收方的 100 倍。

除了公開信函之外,還應制定一封標準提案信「以開始安全通訊」。 其中一個使用者(郵箱)將一封帶有附件的信件發送到另一個郵箱。 這封信包含一個關於啟動一個用於通訊的安全通訊通道的文字建議以及郵箱所有者的公鑰(在客戶端有一個私鑰)。

您甚至可以為每封信件專門製作幾把鑰匙。 接收用戶可以接受此提議並發送他的公鑰(也是專門為此通信而製作的)。 接下來,第一用戶發送服務控制信函(用第二用戶的公鑰加密)——第二用戶收到該信函後可以認為所形成的通訊頻道是可靠的。 接下來,第二個使用者發送控制信-然後第一個使用者也可以認為所形成的通道是安全的。

為了防止在路上攔截金鑰,協定必須提供使用快閃磁碟機傳輸至少一個公鑰的可能性。

最重要的是這一切都有效(問題是「誰來付錢?」):
輸入郵政憑證,起價 10 美元,為期 3 年。 這將允許發送者在 dns 中表明「我的公鑰在那裡」。 他們將為您提供開始安全連接的機會。 同時,接受此類連線是免費的。
gmail 終於透過用戶獲利了。 每 10 年 3 美元 - 創建安全通訊管道的權利。

=============結論===============

為了測試整篇文章,我打算租用一個月的專用伺服器並購買帶有 SSL 憑證的網域。

但生活環境發生了變化,這個問題拖了兩個月。
因此,當我再次有空閒時間時,我決定按原樣發表這篇文章,而不是冒著出版又拖一年的風險。

如果有很多諸如“但這沒有描述得足夠詳細”之類的問題,那麼可能會有力量採用具有新網域和新 SSL 憑證的專用伺服器,並更詳細地描述它,並且大多數重要的是,找出所有缺失的重要細節。

我還想獲得有關郵政證書的想法的回饋。 如果你喜歡這個主意,我會盡力找到力量為 rfc 寫一份草稿。

複製文章的大部分內容時,請提供本文的連結。
翻譯成任何其他語言時,請提供本文的連結。
我會嘗試自己將其翻譯成英文並留下交叉引用。


來源: www.habr.com

添加評論