11
$domain = 'abasdfasdfac.comlkjljkl';  // Yes, an ugly invalid domain

$start_time = microtime(true);
echo "<p>MX "; 
var_dump(checkdnsrr($domain, 'MX'));
echo "</p>";
$end_time = microtime(true);
echo "<p>run time: " . ($end_time - $start_time) . "</p>";

これを私の開発システム (住宅用 DSL w/AT&T での Win+XAMPP) で実行すると、60ミリ秒程度の時間がかかります。

ただし、ライブ サーバーにアップロードしてそこから実行すると、実行時間は 20台まで上がります。

@dns_get_record($domain, DNS_MX)代わりに使用しても結果は同じです。

何が原因でしょうか? AT&T の DNS サーバーが、実動サーバーが指しているよりも速く結果を返す問題ですか? それでも、20秒は長すぎるようです。

さらに重要なことは、どのように修正するのですか?

これを電子メール検証の最終段階として使用しています。ただし、DNS ルックアップが返されるまでユーザーを 20 秒間待機させることはできません。

編集:

私はこれをもう少し詳しく調べました。コンソールからの使用digは、無効なドメインの DNS チェックを行うのに 20 ~ 30 秒かかる同じサーバーで高速です。そこが重要なポイントかもしれません。有効なドメインは、 または のいずれcheckdnsrr()かですぐに返されます@dns_get_record

暫定的な措置として@dns_get_record、メールの有効性チェックを、dig私が書いたベースの関数に置き換えることを検討しています:

// Use "dig" command to get DNS record data
// $type    ANY = Complete record
//          A   = Address Record
//          MX  = Mail Exchange Record
//          CNAME = Canonical Name Record  (http://en.wikipedia.org/wiki/Canonical_name_record)
//
//          more types: http://en.wikipedia.org/wiki/List_of_DNS_record_types
//
// $host    Domain to investigate
//
function dig_get_dns_record($type, $host) 
{ 
    $cleaned_host = escapeshellcmd($host);
    ob_start(); 
        // Note: for this to work on Windows/XAMPP "dig" has to be installed and the search path
        passthru("dig $type $cleaned_host"); 
        $lookup = ob_get_contents(); 
    ob_end_clean(); 
    //echo "<pre>" . $lookup . "</pre>";  // Remove comment to see dig output
    return $lookup; 
}   


// For the purposes of deciding if a domain is real, this checks, the MX, A and CNAME
// and returns FALSE if none are found.  If only one of the three exists we give it
// the benefit of the doubt.
//
// $host    Domain to investigate
//
function has_valid_dns($host)
{
    $result  = dig_get_dns_record("MX", $host);
    $result .= dig_get_dns_record("A", $host);
    $result .= dig_get_dns_record("CNAME", $host);
    return strpos($result, "ANSWER SECTION:") > 0;
}

これで森から抜け出すことができますが、実際には答えではありません。本当の問題は、Linux サーバーの構成設定にあると確信しています。

遅延をテストすることに興味がある場合は、いくつかのテストを含むページを次に示します (サイトのフォームは現在、この遅延に悩まされています。実際にサインアップしたいだけでない限り、フォームをいじらないでください)。

編集:リンクは関連性がなくなったため削除され、ページは削除されます

テストの提案:

apple.com
apple.commmmmmmmmmm
example.com
asdfasdfasdf

注意

AndreKR の回答により、これらの関数を末尾のピリオドでテストするようになり、それだけで応答時間が数十秒からミリ秒に短縮されました。

これで問題は解決しましたが、実際には新しい質問には答えませんでした: なぜ? 完全を期すために、このNota Beneを追加し、私の調査に基づいてその質問に答えることが重要だと思います。

ソースに戻ってRFC-1034RFC-1035のほとんどを読みました。

DNS に関する限り、完全修飾ドメイン名 (FQDN) は実際にはピリオドで終わることが判明しました。FQDN への言及のほとんどは、DNS に絶対ドメイン名と相対ドメイン名の概念があることを説明していません。DNS がそれらを区別する方法は、まさにこの末尾のピリオドによるものです。

DNS リゾルバは、DNS スタイルの FQDN (末尾にピリオドがある) を検出すると、その DNS FQDN (絶対ドメイン名の指定) に対して要求されたレコードを探し出します。これには、数回の再試行が必要になる場合があります。たとえば、MX レコードを探していて、それが FQDN レコードに存在しない場合、代わりに CNAME が存在する可能性があります。DNS リゾルバーは CNAME を取得し、新しい DNS 照会を開始して MX レコードを見つけようとします。

DNS リゾルバーが相対ドメイン名の指定に遭遇するとどうなりますか? つまり、末尾にピリオドがないもの。例: 「テスト」。DNS リゾルバーは、提供された相対ドメイン名に一連の DNS サフィックスを追加することで、実際にこれを絶対 FQDN に変換しようとします。例えば:

@dns_get_record("abceabce.gov", DNS_MX);  // No trailing period === relative

たとえば、ホストで実行すると、www.example.com少なくとも次の一連のクエリが生成されます。

@dns_get_record("abceabce.gov.www.example.com", DNS_MX);
@dns_get_record("abceabce.gov.example.com", DNS_MX);
@dns_get_record("abceabce.gov.com", DNS_MX);

これらはいずれも失敗する可能性が高く、プロセス全体に時間がかかります。

プロセス全体は、RFC のA Security Problem and Proposed Correction With Widely Deployed DNS Softwareで実際にカバーされていることが判明しました。読む価値があります。

4

1 に答える 1

15

どうやら、PHP DNS関数にはタイムアウトがありませんが、デフォルトのタイムアウトdig5秒です(数回の試行で)。

さらに、開発サーバーと本番サーバーは、名前を解決するために異なるDNSサーバーを使用している可能性があります。現在、一部のDNSサーバーは無効なドメインに対して空の応答を送信し、一部のDNSサーバー( djbdnsなど)はまったく応答を送信しません(仕様によれば、これは問題ありません)。

.また、resolv.conf / Windowsネットワーク設定からの潜在的な検索ドメインを追加したくない場合は、ドメイン名に最後の(ドット)を含める必要があることに注意してください。ワイルドカードがある場合は、おそらく常に解決可能です。

于 2012-12-29T01:25:27.247 に答える