
問題
我不知道如何強制 Postfix 使用 TLS 連線到 MySQL。我能作為 postfix 用戶,使用 TLS 手動從 Postfix 伺服器連接到 MySQL 伺服器,因此 MySQL 驗證不會出現任何問題。問題很明顯:Postfix 沒有為 MySQL 連線請求 TLS。
版本:
- 作業系統:CentOS 7
- 字尾:2:2.10.1-6.el7 和 2:3.2.4-1.gf.el7
- MySQL(瑪麗亞資料庫):56 年 5 月 5 日
我是怎麼到這裡的
我一直在整個網路上搜索,包括各個 StackExchange 站點,以尋找這個問題的答案。我已經反覆閱讀了大量的 Postfix 和 MySQL 文件。我發現的最佳答案是我拒絕的,因為它過於複雜:“在 Postfix 和 MySQL 伺服器之間設定 SSH 隧道,然後透過它進行連線。「 必須有一種方法來指示 Postfix 對 MySQL 用戶端使用 TLS (SSL) 加密。
在我們探討設定之前,讓我先介紹一下這個公司: 我的郵件伺服器設定在沒有 MySQL TLS 的情況下運作良好。我成功地將 TLS 用於 SMTPS 和 IMAPS,並且已經成功與我的問題無關。除了 Postfix 和 MySQL 伺服器之間的 MySQL 連線未加密之外,郵件在我的網路中安全傳輸。除了暴露的 Postfix-MySQL 連結之外,我的郵件基礎架構沒有任何問題。
但是,由於安全需求不斷變化,我必須更新現有基礎架構以加密所有 MySQL 連線。為 MySQL 連線設定 TLS 非常簡單。 手動測試表明 MySQL 用戶端可以透過 TLS 加密的連結從所有允許的主機成功連接。因此,MySQL TLS 設定也很可靠且適用於所有情況除了後綴。
我嘗試過的
Postfix伺服器上的相關設定:
/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: [email protected]
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 [email protected].% |
+-----------------------------------------------------------------------------------------------------+
| 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)
紀錄
需要 SSL 時 Postfix 連線失敗即使 MySQL TLS 連線的手動命令列測試成功,Postfix 仍然不會使用 MySQL TLS。
MySQL 常規日誌:
180217 14:45:15 16 Connect [email protected] 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 "[email protected]"
Feb 19 19:22:55 mail postfix/cleanup[11951]: warning: E2CCA2069823: virtual_alias_maps map lookup problem for [email protected] -- message not accepted, try again later
刪除 REQUIRE SSL 後 Postfix 連線成功
這是將權限從 REQUIRE SSL 變更為 REQUIRE NONE 後 Postfix 成功連線。然而,連接是未加密。
180217 15:17:21 26 Connect [email protected] 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
.這也沒有效果。請注意,證書名稱確實匹配,因此如果實際嘗試的話,此驗證將會通過。
答案1
概要
為了從 Postfix 建立 MySQL TLS 連接,您需要:
- Postfix 版本 2.11 或更高版本。 CentOS 7僅提供後綴版本 2.10。您必須透過非 CentOS 方式取得 Postfix 升級。我選擇使用
postfix3
和postfix3-mysql
包GhettoForge Plus因為看起來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 安全模型有興趣,我至少找到了一個如何指南為如何使用客戶端憑證驗證提供了很好的範例。