0

对我的服务器的分布式 smtp 身份验证攻击的不断浪潮促使我禁止非指定 IP 连接到我的服务器上的 smtp 并通过它发送邮件。非常有效。(说明:http ://sysadmintips.in/advanced/csf/exim )

但是,我现在无法使用 Google Mail (Gmail) 为新帐户“发送邮件”,而无需启用双因素身份验证(这很痛苦,因为我正在为我的客户远程设置此功能)或重新打开 smtp auth我的服务器。

我的另一个选择是将 Google Mail 的 IP 地址列入白名单。

谷歌搜索发现了这种方式来检索当前的谷歌 IP 范围,使用这些内容(我从这个页面复制:https ://support.google.com/a/answer/60764?hl=en ):

nslookup -q=TXT _spf.google.com 8.8.8.8

这将返回包含在 Google SPF 记录中的域列表,例如:_netblocks.google.com、_netblocks2.google.com、_netblocks3.google.com

现在查找与这些域关联的 DNS 记录,一次一个,如下所示:

nslookup -q=TXT _netblocks.google.com 8.8.8.8
nslookup -q=TXT _netblocks2.google.com 8.8.8.8
nslookup -q=TXT _netblocks3.google.com 8.8.8.8

这些命令的结果包含当前地址范围。

我可以使用这些输出为 /etc/csf/csf.smtpauth 生成有用的内容吗?

我可以在 PHP 中编写一些代码来执行此操作,并以 root 身份将其作为 cron 任务运行,但是什么格式是可以接受的?csf.smtpauth 是否接受 IP 范围声明?它是否可以处理 IPV6 IP?

在进行任何更改后,我还需要自动强制重启 csf 和 lfd,以便使用新的 IP。以root身份运行的PHP有可能吗?

谢谢!

4

1 回答 1

0

解决了。

我编写了以下 PHP 代码,它查询 Google 的 SPF 记录,然后,只有在需要时,才会用新的 SMTP Auth 块替换现有的 SMTP Auth 块。然后它会创建一个文件,该文件用作 bash 脚本重新启动防火墙的标志。

请注意,/etc/csf/csf.smtpauth 接受 IPV4 和 IPV6 地址以及 CIDR 地址范围。

// Grab current Google SPF IPs...
$dns = dns_get_record('_spf.google.com', DNS_TXT);
if (!$dns)
{
    echo "FAILED TO RETRIEVE DNS RECORD<br />\n";
    exit;
}

// The variable in which to store the results
$ranges = array();

// Of interest in particular to us is...
$val = $dns[0]['txt'];

preg_match_all("/include:[^\s]+\s/", $val, $matches);

if (sizeof($matches[0]) <= 0)
{
    echo "BAD DATA RECEIVED OR FAILED TO DECODE DATA<br />\n";
    exit;
}

foreach ($matches[0] as $match)
{
    $match = trim($match);
    $domain = trim(preg_replace("/include\:/", "", $match));

    // Now do it all again for this domain to get the IP range
    $dns = dns_get_record($domain, DNS_TXT);

    if (!$dns)
    {
        echo "DNS LOOKUP FAILURE AT PASS 2<br />\n";
        exit;
    }

    $val = $dns[0]['txt'];
    preg_match_all("/ip\d:[^\s]+\s/", $val, $ips);

    if (sizeof($ips[0])<=0)
    {
        // At time of writing this is entirely possible as _netblocks3.google.com
        // currently holds NO IP ranges
    }
    else
    {
        foreach ($ips[0] as $ip)
        {
            $ip = trim($ip);
            if ($ip <> '')
            {
                $ip = preg_replace("/ip\d\:/", "", $ip);
                $ranges[] = $ip;
            }
        }
    }
}

// To be here means we made it without a major problem. Form the new IP range for
// the smtp auth file (/etc/csf/csf.smtpauth) and compare with the existing. Update only if there has
// been a change. Also update only if there are at least N ranges found.
// When I wrote this there were 11 IPV4 ranges and 6 IPV6 ranges so setting 
// low limit to 10
$limit = 10;
$filename  = '/etc/csf/csf.smtpauth';

if (sizeof($ranges) < $limit)
{
    echo "NOT UPDATING RANGES, TOO FEW DISCOVERED, PROBLEM?";
    exit;
}

$filerange = "# GOOGLE SPF RESULTS START\n";
$filerange .= join("\n", $ranges);
$filerange .= "\n# GOOGLE SPF RESULTS END";

// Read in existing conf file 
$econf = file_get_contents($filename);
if (sizeof($econf)<=0)
{
    echo "FAILED TO READ $filename<br />\n";
    exit;
}

// Extract the block
if (!preg_match("/\# GOOGLE SPF RESULTS START.+\# GOOGLE SPF RESULTS END/s", $econf, $matches))
{
    echo "FAILED TO FIND EXISTING BLOCK. CORRUPT AUTH FILE?<br />\n";
    exit;
}

if ($filerange == $matches[0])
{
    // IT'S THE SAME DO NOT UPDATE IT!;
    exit;
}

// Replace the block entirely
$econf = preg_replace("/\# GOOGLE SPF RESULTS START.+\# GOOGLE SPF RESULTS END/s", $filerange, $econf);

// Write out the new file contents
file_put_contents($filename, $econf);

// Trigger a CSF/LFD restart by creating trigger file.
touch("restartcsflfd"); 

然后创建一个 CRON 任务以在每次运行上述内容之后不久运行此 shell 脚本:

#!/bin/bash
if [ -f /path-to-file/restartcsflfd ];
then
    csf -r
    /etc/init.d/lfd restart
    rm -f restartcsflfd
    echo "RE-STARTED CSF and LFD"
fi
于 2015-06-29T10:23:49.543 回答