Bash

OpenBSD 6.0 chrooted httpd 與 php 7.0 mail() 工作,但沒有郵件出去?

  • December 13, 2016

我從全新安裝的 OpenBSD 6.0 開始,它在他們的 httpd 伺服器(不是 Apache)上有一個 chroot(/var/www)。我安裝了 PHP 7.0 並使用二進制安裝設置了 php-fpm。在 web 根目錄中同時存在 sendmail 和 femail 對象。我將一個網站移動到適當的位置,php 執行良好,php 查詢 postgresql 數據庫(也從二進制安裝)並且一切執行良好 - 除了 mail()。

我在 /var/www/logs/php.mail.log 中設置了一個日誌文件,它看到郵件被 php 辨識,日誌條目如下:

[09-Dec-2016 15:04:34 UTC] mail() on [/do_quick_mail_test.php:23]: To: myemail@domain.com -- Headers: From: support@domain.com (domain.com Robot)

/var/www/logs/error.log 和系統消息中都沒有錯誤發生。

系統郵件日誌中沒有電子郵件指示。

當我像這樣從命令行執行命令時,它可以正常工作並且郵件正常傳遞,沒有問題:

echo 'Subject: test' | chroot /var/www /usr/sbin/sendmail -v myemail@domain.com

我用瀏覽器訪問的 php 程序是一個非常簡單的程序:

<?php
session_start();

header( "Content-Type: text/plain" );

echo( 'Configuration Tests:'."\n" );

echo('Testing DNS:'."\n" );
print_r( dns_get_record("trialtoaster.com") );
echo( 'localhost lookup: '.gethostbyname( "localhost" )."\n" );

echo('Testing DateTime:'."\n" );
print_r( getdate() );

echo('Sending test email:'."\n" );
if ( mail("myemail@domain.com", "PHP Test mail", "PHP email - test message.", "From: support@domain.com (domain.com Robot)") ) {
       echo '- PHP thinks the email went normally.';
} else {
       echo '- PHP thinks the email failed.';
}
?>

該程序不會產生任何失敗,除了 mail() 死亡。DNS 測試返回所有記錄,包括 MX 記錄,並且日期準確。儘管正確記錄在 php 郵件日誌中。

顯示時, phpinfo() 正確反映了配置:

sendmail_path:  /usr/sbin/sendmail -t
SMTP:  localhost
smtp_port: 25

當我檢查數據包過濾器時,它允許 lo0 上的任何東西去任何地方,當我執行命令時,我可以在 pftop 上看到它,但是當我從瀏覽器執行 mail() 時沒有任何顯示。

我已將 sendmail.ini 安裝在與 chrooted sendmail 相同的目錄中,這沒有任何區別。

它開始看起來像 OpenBSD chrooted httpd 安裝不完整,因為為了使用 php mail() 命令,有些東西完全失去了,我擔心它可能是 bash shell 和庫,因為郵件從命令發送得很好線。這對我來說似乎不合時宜,因為 chroot 的目的是監禁黑客,並為被監禁的系統提供 bash shell 和庫似乎有很多表面區域可以進行攻擊。

我只是覺得這不是問題,因為否則,您不妨放棄 chroot 並在沒有監獄的情況下執行它(看起來)。

有沒有人看到我缺少的東西 - 如果沒有,我在 shell 和庫中進行複制,那麼在不編寫自定義包裝器的情況下,最安全的方法是什麼?

我相信這可以通過以下兩種方式之一解決:

(1) 您可以通過在 chroot 中安裝可執行 shell 來解決此問題,以便 sendmail 二進製文件可以執行。如果你這樣做了,即使你將它安裝在一個包裝器中,​​你也增加了攻擊的表面積,你還不如放棄 chroot。包裝器可以重新包裝,您需要做的就是執行重新啟動,您的系統就會被破解。我的投票是不這樣做。

(2) 最好的選擇是放棄郵件並直接通過套接字使用 SMTP——這與 PHP 和 Web 伺服器本身已經在執行的方式幾乎相同。chroot 上沒有 shell,您所做的只是安裝更多 php 程式碼並讓該程式碼在 localhost 上打開一個套接字到埠 25,您的 MTA 已經在該埠上偵聽並傳遞到外部世界,但不執行任何任意程式碼。

以下是它的工作原理:

如果尚未安裝 Pear,請安裝它,然後安裝郵件腳本。您可以像這樣輕鬆地做到這一點:

pkg_add install Pear
pear install Mail_smtp
pear install Net_SMTP

根據您的系統 - 第一個 pear 安裝可能會為您執行第二個安裝作為依賴項。

從那裡我在自己的 php 程序中添加了一個 php 函式:

<?php
/**
* Sends an email using SMTP directly rather than using the sendmail binary (which requires
* a shell environment to run).  This allows the chrooted server to run with less exposure.
*/
require_once "Mail.php";

function SMTP_mail($recipients, $subjectHeader, $message, $fromHeader)
{
   $headers['From']    = $fromHeader;
   $headers['Subject'] = $subjectHeader;

   $smtpinfo["host"] = "localhost";
   $smtpinfo["port"] = "25";
   $smtpinfo["auth"] = false;

   // Create the mail object using the Mail::factory method
   $mail_object = Mail::factory("smtp", $smtpinfo);

   $mail_object->send($recipients, $headers, $message);
}

剩下要做的就是檢查我正在遷移的程式碼並將郵件說明轉換為使用此功能:

SMTP_mail($sendToEmailAddr, $subjectLine, $messageBody, 'From: Support@domain.com (Domain.com Robot)');

如果您還沒有這樣做,那麼在 chroot 之外發送郵件的能力應該已經可以工作了。重要但對我們來說是在 /etc/mail/smtp.conf 文件中:

listen on lo0

# Since we are only listening on the lo0 (local) we can safely use
# commands that are "accept from any" or bare "accept" commands.

# accept from any for domain "example.org" alias <aliases> deliver to mbox
accept for local alias <aliases> deliver to mbox

# accept from the lo0 (local) interface anything and relay it out
accept for any relay

# This was the original command - use it if you ever open up
# the external interface by doing a "listen on any" rather than
# the above command - that will keep us from being an open relay:
#accept from local for any relay

給它一個很好的重啟,它應該可以工作 - 假設你有我在我的問題中所做的相同設置。PHP 將通過 chroot 中的 localhost 打開與 chroot 外部 localhost 的 SMTP 連接,發送您程式發送的電子郵件,然後關閉連接。OpenBSD 的 mailer.conf 將確保“真正的”sendmail (smtpctl) 獲取它並根據該電子郵件地址的郵件主機的 DNS 中的 MX 條目將其路由到外部世界。您需要通過在 /etc/rc.conf.local 系統文件中設置 smtpd_flags 來確保 SMTP 正在執行。

全部由惡魔執行,與您的程式碼一樣安全。我希望這有幫助!

引用自:https://serverfault.com/questions/819845