如何限制从PHP发送的出站SMTP邮件


How to limit outbound SMTP mail sent from PHP

我们有共享托管服务器,它们为多个客户端(共享托管)使用PHP fastcgi(在IIS上)。客户端经常使用旧的可利用代码,这会在其应用程序中造成漏洞,最终被黑客用来安装恶意代码。大多数时候,这些代码被用来从我们的服务器发送垃圾邮件。

我们无法控制客户的代码,因此修补漏洞是完全不可能的。

然而,一旦客户在Y时间内发送超过X封电子邮件,我们希望阻止他们发送垃圾邮件。

设置是基于fastcgi的,因此php和Web服务器之间几乎没有关系。PHP通过本地主机上的SMTP发送邮件。邮件服务器允许中继所有本地主机连接(显然)。

我想到的一件事是在fastcgi环境中设置一个包含标识符的环境变量,并使用php的prepend file选项为php的mailer发送的所有邮件添加一个标头。之后,我们可以使用该邮件头来识别垃圾邮件的罪魁祸首。

上面的选项仍然无法处理发送电子邮件时使用常规telnet(telnet localhost、HELO、MAIL FROM等)的垃圾邮件脚本。

我想问你的是:我提到的这个想法是处理我们问题的最佳选择,也许也是唯一的选择吗?或者有更好的解决方案吗?如果是,请解释一下你将如何处理这个问题。

您可以在MTA(邮件传输代理)上进行筛选。例如,允许Exim中每个用户在1小时内发送不超过50封电子邮件(http://www.exim.org)配置文件(/etc/exim/exim.conf):

begin acl
acl_check_not_smtp:
warn ratelimit = 0 / 1h / strict / $sender_address_local_part
log_message = Sender rate $sender_rate / $sender_rate_perio
acl_not_smtp = acl_not_smtp
begin acl
acl_not_smtp:
        deny message = Sender rate overlimit - $sender_rate / $sender_rate_period
        ratelimit = 50 / 1h / strict
        accept

无论他们如何发送,都可以通过php-mail()或其他方法。

大多数共享主机都会阻止使用PHP的mail()函数,因为这很容易被利用。相反,他们建议使用sendmail或类似的脚本,这些脚本在发送之前需要SMTP身份验证。假设你还没有这样做,一旦实现,你应该能够跟踪从特定域/电子邮件帐户发送的电子邮件数量,并对其进行限制。

好吧,在这个问题上跟我一起。我还没有实施,但看起来不错。

这里的概念是,你可以

  1. 在客户网站上的每个页面之前运行一个php文件
  2. 在该php文件中,将mail函数重命名为mail_internal()
  3. 在这个php中,创建了一个名为mail的新函数来检查/验证您的客户是否被允许发送邮件,如果他们被允许,则使用相同的参数调用mailinternal()函数

您必须安装runkit PECL扩展http://us.php.net/manual/en/runkit.installation.php

更改

在php.ini 中

auto_prepend_file /var/www/allclients_forcedfile.php

在/var/www/allclients_forcedfile.php 中

runkit_function_rename ( "mail" , "mail_internal" );
function mail (   $to ,   $subject ,   $message, $additional_headers = "",   $additional_parameters ="" )
{
     $args = func_get_args();
     error_log("mail_internal : $_SERVER[HTTP_HOST] : ".implode(" : ",$args));
     //lookup whether you want to send more mail for this client  maybe by keeping a counter in some file in the $SERVER[DOCUMENT_ROOT]
     if($sendmoremail)
            return mail_internal (   $args[0],   $args[1] ,   $args[2], $args[3]  ,   $args[4]   );
     return false;
}

不出所料,Stack Overflow似乎不是这个问题的正确答案。提供的答案没有公开一些明确的方法来识别FastCGI会话与MTA(SMTP)服务器的连接。

我将继续我最初的概念,即向php的环境中添加一个标识符。可以使用getenv()函数在PHP的prepend文件中读取此标识符。然后可以将此标识符添加到传出邮件的邮件头中。

此外,我还启用了mail.add_x_headerini设置,这将有助于确定是哪个脚本导致了垃圾邮件的运行。

我把这个问题留给赏金持续时间,希望其他选项能神奇地出现:)