強制 Postfix 使用 TLS 進行 MySQL 連接?
問題
我不知道如何強制 Postfix 使用與 MySQL 的 TLS 連接。我可以使用 TLS 作為 postfix 使用者從 Postfix 伺服器手動連接到 MySQL 伺服器,因此 MySQL 身份驗證沒有任何問題。問題很明顯:Postfix 沒有為 MySQL 連接請求 TLS。
版本:
- 作業系統:CentOS 7
- 後綴:2:2.10.1-6.el7 和 2:3.2.4-1.gf.el7
- MySQL (MariaDB):5.5.56
我是怎麼來的
我一直在整個網路上搜尋,包括各種 StackExchange 站點,以尋找這個問題的答案。我已經反复閱讀了大量的 Postfix 和 MySQL 文件。我找到的最好的答案是我拒絕的一個不必要的複雜:“在你的 Postfix 和 MySQL 伺服器之間建立一個 SSH 隧道,然後通過它連接。 ”必須有一種方法來指示 Postfix 使用 TLS (SSL) 加密與 MySQL 客戶端。
在我們探索設置之前,讓我確定一下: 我的郵件伺服器設置在沒有 MySQL TLS 的情況下執行良好。我成功地將 TLS 用於 SMTPS 和 IMAPS,這與我的問題無關。除了 Postfix 和 MySQL 伺服器之間的 MySQL 連接未加密外,郵件正在安全地進出我的網路。除了暴露的 Postfix-MySQL 連結外,我的郵件基礎設施沒有任何問題。
然而,由於不斷變化的安全要求,我必須更新我現有的基礎設施來加密所有 MySQL 連接。為 MySQL 連接設置 TLS 很簡單。 手動測試表明 MySQL 客戶端可以通過 TLS 加密的連結從所有允許的主機成功連接。因此,MySQL TLS 設置也很可靠,適用於除 Postfix 之外的所有內容。
我試過的
Postfix Server上的相關配置:
/etc/postfix/main.cf 減少到只是幾個連接之一,以保持材料盡可能具體。
virtual_alias_maps = proxy:mysql:/etc/postfix/lookup_aliases.cf proxy_read_maps = $virtual_alias_maps
/etc/postfix/lookup_aliases.cf 憑證和主機名被混淆。
hosts = mysql-server.domain.tld user = postfix password = ***** dbname = mail option_file = /etc/my.cnf.d/client.cnf option_group = client tls_verify_cert = yes query = SELECT goto FROM alias WHERE address = '%s' AND active = '1'
/etc/my.cnf 此文件未動。我包含它只是為了表明下一個配置文件已正確包含在 MySQL 客戶端配置中。
!includedir /etc/my.cnf.d
/etc/my.cnf.d/client.cnf
[client] ssl = true
成功 – 手動 – 從 Postfix 伺服器作為 postfix 使用者輸出 MySQL TLS 連接
請特別注意 TLS 已成功使用:
# hostname -f mail.domain.tld # sudo -u postfix mysql -h mysql-server.domain.tld -u postfix -p mail Enter password: Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 72 Server version: 5.5.56-MariaDB MariaDB Server Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [mail]> \s -------------- mysql Ver 15.1 Distrib 5.5.56-MariaDB, for Linux (x86_64) using readline 5.1 Connection id: 72 Current database: mail Current user: postfix@mail.domain.tld SSL: Cipher in use is DHE-RSA-AES256-GCM-SHA384 Current pager: stdout Using outfile: '' Using delimiter: ; Server: MariaDB Server version: 5.5.56-MariaDB MariaDB Server Protocol version: 10 Connection: mysql-server.domain.tld via TCP/IP Server characterset: latin1 Db characterset: utf8 Client characterset: utf8 Conn. characterset: utf8 TCP port: 3306 Uptime: 1 hour 27 min 23 sec Threads: 1 Questions: 271 Slow queries: 0 Opens: 13 Flush tables: 2 Open tables: 39 Queries per second avg: 0.051 -------------- MariaDB [mail]> \q Bye
MySQL伺服器上的相關配置:
MySQL 贈款
請注意,TLS(SSL)是必需的,但在我解決這個 TLS 連接問題之前,權限相對寬鬆:
MariaDB [(none)]> SHOW GRANTS FOR 'postfix'@'10.0.101.%'; +-----------------------------------------------------------------------------------------------------+ | Grants for postfix@10.0.101.% | +-----------------------------------------------------------------------------------------------------+ | GRANT USAGE ON *.* TO 'postfix'@'10.0.101.%' IDENTIFIED BY PASSWORD '*SOMEPASSWORDHASH' REQUIRE SSL | | GRANT SELECT ON `mail`.* TO 'postfix'@'10.0.101.%' | +-----------------------------------------------------------------------------------------------------+ 2 rows in set (0.00 sec)
日誌
當 REQUIRE SSL 時 Postfix 連接失敗 即使這裡 MySQL TLS 連接的手動命令行測試成功,Postfix 仍然不會使用 MySQL TLS。
MySQL 正常日誌:
180217 14:45:15 16 Connect postfix@mail.domain.tld as anonymous on mail 16 Connect Access denied for user 'postfix'@'mail.domain.tld' (using password: YES)
後綴日誌:
Feb 19 19:22:55 mail postfix/cleanup[11951]: warning: proxy:mysql:/etc/postfix/lookup_aliases.cf lookup error for "root@mail.domain.tld" Feb 19 19:22:55 mail postfix/cleanup[11951]: warning: E2CCA2069823: virtual_alias_maps map lookup problem for root@mail.domain.tld -- message not accepted, try again later
刪除 REQUIRE SSL 後,後綴連接成功 這是 Postfix 在將權限從 REQUIRE SSL 更改為 REQUIRE NONE 後成功連接。但是,連接未加密。
180217 15:17:21 26 Connect postfix@mail.domain.tld as anonymous on mail 26 Query show databases 26 Query show tables 26 Field List admin 26 Field List alias 26 Field List alias_domain 26 Field List config 26 Field List domain 26 Field List domain_admins 26 Field List fetchmail 26 Field List log 26 Field List mailbox 26 Field List quota 26 Field List quota2 26 Field List vacation 26 Field List vacation_notification 26 Query select @@version_comment limit 1
結論
我所需要的只是讓 Postfix 尊重
ssl = true
其 MySQL 客戶端連接。如果您需要任何進一步的資訊,請告訴我。更新:
發布此問題後,我通過更仔細的閱讀發現,2.11 之前的 Postfix 版本根本不支持讀取 MySQL 配置文件。因此,不可能將供應商提供的 Postfix 版本(2.10 版)配置為使用 MySQL TLS。我覺得 Postfix 文件中的措辭選擇不佳,其中MySQL 配置的 Postfix 文件的上半部分如下:
Postfix 3.1 and earlier don't read [client] option group settings unless a non-empty option_file or option_group value are specified. To enable this, specify, for example "option_group = client".
作者沒有說明:
These options are ignored for Postfix 2.10 and earlier. Postfix 2.11 through 3.1 don't read [client] option group settings unless a non-empty option_file or option_group value are specified. To enable this, specify, for example "option_group = client".
因此,我將 CentOS 7 上的 Postfix 從供應商提供的 2.10 版升級到GhettoForge Plus 提供的3.2 版。我確實安裝了附加
postfix3-mysql
軟體包。我寄予厚望,但這些都破滅了。現在,即使使用 Postfix 3.2,它仍然無法通過 TLS 連結連接到 MySQL。我都嘗試過
option_file = /etc/my.cnf
(應該是預設的和不必要的)option_file = /etc/my.cnf.d/client.cnf
但無濟於事。我什至試圖通過添加
tls_verify_cert = yes
. 這也沒有效果。請注意,證書名稱確實匹配,因此如果實際嘗試過,此驗證將通過。
概要
為了從 Postfix 建立 MySQL TLS 連接,您需要:
Postfix 2.11 或更新版本。CentOS 7 只提供Postfix 版本 2.10。您必須通過非 CentOS 方式獲得 Postfix 的升級。我選擇使用GhettoForge Plus
postfix3
的和postfix3-mysql
軟體包,因為它似乎受到 CentOS 社區的大力推薦。在您的
mysql_table
配置文件中設置:至少一種允許的
tls_ciphers
設置;客戶端 TLS 證書及其匹配的私鑰,由 MySQL 伺服器和 Postfix 客戶端通用的證書頒發機構簽名;或者
兩個都。
不要依賴在 /etc/my.cnf 或 /etc/my.cnf.d/ 文件中設置這些!* Postfix MySQL 程式碼不會讀取這些文件來確定是否建立 MySQL TLS 連接;他們被解析得太晚了。促使 Postfix 打開 MySQL TLS 連接的唯一
mysql_table
方法是在配置文件中指定 TLS 設置。時期。我是怎麼來的
我終於求助於閱讀 Postfix 3.2 原始碼。src/global/dict_mysql.c 的第 653-658 行特別有用。
最終解決方案
如果要模擬 的行為
ssl = true
,只需在mysql_table
配置文件中添加類似於以下內容的行:tls_ciphers = TLSv1.2
我們的配置要求只使用 TLS 1.2——並且早已在我們的 MySQL 伺服器的配置中強制執行,所以我並沒有自動想到在客戶端上也強制執行它——但是您可以自由添加其他如果您的組織允許使用較舊的密碼,則使用密碼。
請注意,我們很高興不使用客戶端證書。我們使用其他方式來保護和主動監控我們的數據庫連接;我們只是不想要額外的複雜性。
替代解決方案
如果您希望強制僅已知的、受信任的客戶端連接到您的 MySQL 伺服器——而您不能通過其他策略強制機制(如嚴格的防火牆、嚴格的密碼複雜性、密碼輪換週期性、連接審計等)來做到這一點——那麼您可以還可以通過
mysql_table
配置文件中的這些附加設置使用客戶端證書:tls_key_file = /path/to/private.key tls_cert_file = /path/to/public.certificate tls_CAfile = /path/to/common.CA.certificate # OR tls_CApath = /path/to/CA-and-intermediate-chain-certificates/
同樣,在 /etc/my.cnf 或 /etc/my.cnf.d/* 中設置這些也無濟於事。直到已經確定了連接類型(TLS 或非 TLS)之後,才會解析這些文件。
如果您選擇使用客戶端證書,請在伺服器上強制執行它們!當您只想加密 MySQL 流量時,您不需要客戶端證書**;相反,只需使用
tls_ciphers
上面的替代方法。添加客戶端證書使 MySQL 能夠驗證連接的客戶端是否已知且受信任,但前提是您告訴 MySQL 如何這樣做**!它不會猜測並且僅依賴於客戶端和伺服器之間存在的公共 CA 只是這個強大工具的部分實現。如果您對這個 MySQL 安全模型感興趣,我發現至少有一個How To guide 提供瞭如何使用客戶端證書驗證的好例子。