2012-03-06 5 views
2

新しいアプリケーションで再利用したい古いプロジェクトのホワイトリストのIPフィルタがあります。IPv6で動作するPHPベースのIPフィルタをリファクタリングする

edit for clarification;

ホワイトリストには、以下に指定された形式のエントリが含まれています。 foreach ($whitelist as $listed)を使用して、現在のエントリ($listed)のタイプを確認してから、このエントリを$ipと比較します。一致するものが見つからなかった場合は、falseを返す場合は、指定されたIPに一致するエントリが見つかるとすぐにtrueを返します。今のところ

、IPv4のみをサポートし、フィルタが続くようなホワイトリストエントリを可能にする:BEGIN指定して

  1. IPレンジ - END(192.168.0.1-192.168.0.5
  2. 単一のIPアドレス(例えば192.168.0.2これらのケースのそれぞれを確認する方法は次のようになり、*の-wildcard(例えば192.168.0.*

を使用して)

  • IP-範囲は、クライアントのIPであると$listedは、上記のいずれかの形式に一致するホワイトリスト/ブラックリストからエントリです:

    public function checkAgainstRange($ip, $listed) 
    { 
        list($begin, $end) = explode('-', $listed); 
        $begin = ip2long($begin); 
        $end = ip2long($end); 
        $ip = ip2long($ip); 
        return ($ip >= $begin && $ip <= $end); 
    } 
    
    public function checkAgainstSingle($ip, $listed) 
    { 
        return long2ip(ip2long($ip)) === long2ip(ip2long($listed)); 
    } 
    
    public function checkAgainstWildcard($ip, $listed) 
    { 
        $listedSegment = explode('.', $listed); 
        $ipSegment = explode('.', $ip); 
    
        for ($i = 0; $i < count($listedSegment); $i++) { 
         // We're finished when the wildcarded block is reached 
         // Important: Check for wildcard first, as it won't match the client IP! 
         if ($listedSegment[$i] == '*') { 
          return true; 
         } 
         if ($listedSegment[$i] != $ipSegment[$i]) { 
          return false; 
         } 
        } 
        // Just to be safe: If we reach this, something went wrong 
        return false; 
    } 
    

    Iは、IPv6-アドレスでこれらの作業を作成する方法についてのいくつかの方向性を必要とします。

    必要な変更のいくつかの

    は明白です:私はcheckAgainstWildcard()で可能な区切り文字として:をチェックする必要があり* * ip2long()は、IPv4のみ、アドレス で動作します。

    php-docsにはinet_ntop()inet_pton()が見つかりました。私はちょうど次の2つの単一のIPアドレスを比較するために使用できますか?

    public function checkAgainstSingle($ip, $listed) 
    { 
        $ip = inet_ntop($ip); 
        $listed = inet_ntop($listed); 
        if ($ip === false || $listed === false) { 
         throw new \Exception; 
        } 
        return $ip === $false; 
    } 
    

    使用例:

    $filter = new IpFilter(); 
    $ip = $_SERVER['REMOTE_ADDR']; 
    
    $result = $filter->checkAgainstSingle($ip, '192.168.0.1'); 
    $result = $filter->checkAgainstRange($ip, '192.168.0.1-192.168.0.10'); 
    $result = $filter->checkAgainstWildcard($ip, '192.168.0.*'); 
    

    checkAgainstRange()のようなものを維持することにも役立ちますか?もしそうなら、どうすれば同様の方法でIPv6範囲を調べることができますか?明らかに私は変更できませんip2long()ここにinet_ntop() ...

    ワイルドカード範囲と同じです。私はそれらを保持し、:をセグメント区切り文字としてチェックし、それが見つからなければ、区切り文字として.にフォールバックすればよいでしょうか?

  • +0

    フィルタは正確に何をする必要がありますか?私は期待される結果がここにあるのではない。いくつかのデモを提供できますか?与えられたIPが与えられたpaternと一致するかどうかを調べる。 –

    +0

    はい、 '$ filtered == $ filtered'をチェックすることで、IPをホワイトリストと照合するIpフィルタです。ここで、' $ filtered'はホワイトリストの1つのエントリです。基本的に私はホワイトリストをループし、私のIPと一致するエントリを見つけるとすぐに停止します。私は質問を編集して、より明確にします。 – dbrumann

    答えて

    2

    IPアドレスが人間が読める形式または印刷可能な形式の場合、inet_pton()を使用してバイナリ形式に変換できます。次に、bin2hex()を使用してバイナリデータを16進形式で表示することができます。

    例:

    $address = inet_pton("2a00:8640:1::1"); 
    echo bin2hex($address); 
    

    はあなたが表示されます:

    2a008640000100000000000000000001 
    

    あなたがして、サブネット上の代わりに、別のアドレスを確認したい場合は、最初の16進数の文字を比較することができます。 IPv6サブネットはほぼ常に/ 64ネットワークで、各16進文字は4ビットなので、最初の(64/4 =)16文字はサブネットを示します。 IPv6では、複数のIPv6アドレスを持つことができ、最近のWindowsおよびMac OS Xシステムではデフォルトで有効になっているプラ​​イバシー拡張機能を使用すると、定期的に送信元アドレスが変更されます。サブネット上でのマッチングは、IPv6にとって最も有用かもしれません。

    関連する問題