9

$_SERVER['REMOTE_ADDR']を使用して自分のサイトにアクセスしようとしているユーザーのIPアドレスを取得しています。データベースには、ボックスごとにIDSとCIDRエントリが異なるさまざまなボックスがあります。特定のボックスのCIDRのいずれかにユーザーIPが存在するかどうかを確認したいと思います。それが存在する場合、彼はそれ以外の場合は入場できません。ユーザーIPが

127.0.0.1

ボックス12のCIDRエントリが

192.168.1.20/27
192.168.0.10/32

CIDRエントリは、データベースの列に格納されます

この範囲内のIPを持っている場合は、サイトへのアクセスを許可する必要があります。各CIDRエントリに対して彼のIPを確認したいと思います。

何かアイデアはありますか?

ありがとう

4

2 に答える 2

12

OK、この5つの簡単な手順に従ってみてください...

1. CIDRを配列に格納します(データベースからそれらを読み取ります。これを取得する方法を知っていると思います)

$cidrs = array(
  '192.168.1.20/27', 
  '192.168.0.10/32'
  );

2.ユーザーのIP(リモートアドレス)を取得します

$user_ip = $_SERVER['REMOTE_ADDR'];

3.この関数を追加します

function IPvsCIDR($user_ip, $cidr) {
  $parts = explode('/', $cidr);
  $ipc = explode('.', $parts[0]);
  foreach ($ipc as &$v)
    $v = str_pad(decbin($v), 8, '0', STR_PAD_LEFT);
  $ipc = substr(join('', $ipc), 0, $parts[1]);
  $ipu = explode('.', $user_ip);
  foreach ($ipu as &$v)
    $v = str_pad(decbin($v), 8, '0', STR_PAD_LEFT);
  $ipu = substr(join('', $ipu), 0, $parts[1]);
  return $ipu == $ipc;
  }

4.ユーザーのIPアドレスを$cidrsと比較します

$validaddr = false;
foreach ($cidrs as $addr)
  if (IPvsCIDR($user_ip, $addr)) {
    $validaddr = true;
    break;
    } 

5.ユーザーをどうするかを決める

if ($validaddr) {
  echo "CORRECT IP ADDRESS";
  }
else {
  echo "INCORRECT IP ADDRESS";
  }

それでおしまい!

この関数がどのように機能するか。CIDRアドレス部分(xxxx)をバイナリ文字列に変換し、最初のN桁を取ります。次に、ユーザーのIPで同じジョブを実行し、値が一致するかどうかを確認します。

例2(関数からの完全なジョブ)

function testUserIP($user_ip, $cidrs) {
  $ipu = explode('.', $user_ip);
  foreach ($ipu as &$v)
    $v = str_pad(decbin($v), 8, '0', STR_PAD_LEFT);
  $ipu = join('', $ipu);
  $res = false;
  foreach ($cidrs as $cidr) {
    $parts = explode('/', $cidr);
    $ipc = explode('.', $parts[0]);
    foreach ($ipc as &$v) $v = str_pad(decbin($v), 8, '0', STR_PAD_LEFT);
    $ipc = substr(join('', $ipc), 0, $parts[1]);
    $ipux = substr($ipu, 0, $parts[1]);
    $res = ($ipc === $ipux);
    if ($res) break;
    }
  return $res;
  }

使用法:

$user_ip = $_SERVER['REMOTE_ADDR'];
$cidrs = array('192.168.1.20/27', '192.168.0.10/32'); 
if (testUserIP($user_ip, $cidrs)) {
  // user ip is ok
  }
else {
  // access denied
  }
于 2012-04-20T09:37:28.200 に答える
3

私はしばらくの間この関数を使用しています:

<?php

/**
 * Returns TRUE if given IPv4 address belongs to given network, FALSE otherwhise
 *
 * @param string $str_ip IP address in '127.0.0.1' format
 * @param string $str_range Network and mask as '127.0.0.0/8', '127.0.0.0/255.0.0.0' or '127.0.0.1'
 * @return bool
 *
 * @version v2011-08-30
 */
function ip_belongs_to_network($str_ip, $str_range){
    // Extract mask
    list($str_network, $str_mask) = array_pad(explode('/', $str_range), 2, NULL);
    if( is_null($str_mask) ){
        // No mask specified: range is a single IP address
        $mask = 0xFFFFFFFF;
    }elseif( (int)$str_mask==$str_mask ){
        // Mask is an integer: it's a bit count
        $mask = 0xFFFFFFFF << (32 - (int)$str_mask);
    }else{
        // Mask is in x.x.x.x format
        $mask = ip2long($str_mask);
    }

    $ip = ip2long($str_ip);
    $network = ip2long($str_network);
    $lower = $network & $mask;
    $upper = $network | (~$mask & 0xFFFFFFFF);

    return $ip>=$lower && $ip<=$upper;
}

アップデート:

私の場合、実際にはすべてのCIDRエントリがデータベースにあります。foreachループが機能するすべてのTOSECIDRエントリを含むIPを確認するにはどうすればよいですか?

エントリの数によって異なります。PHPループは、いくつかの範囲で問題ありませんが、それらが50ある場合は、50のSQLクエリを起動することを意味します。その場合、おそらくデータベースアプローチに切り替える必要があります。たとえば、範囲を2つの列(下位IPアドレスと上位IPアドレス)に格納できます。そうすれば、あなたがする必要があるのはこれだけです:

$sql = 'SELECT COUNT(1) AS belongs_to_at_least_one_range
    FROM ranges
    WHERE :remote_address BETWEEN lower_address AND upper_address
    LIMIT 1';
$params = array(
    'remote_address' => ip2long($_SERVER['REMOTE_ADDR']),
);

(または、必要に応じてすべての一致をフェッチします。)

このコード行を説明していただけますかlist($str_network, $str_mask) = array_pad(explode('/', $str_range), 2, NULL);

explode('/', $str_range)
// Split the string at `/` characters

array_pad(explode('/', $str_range), 2, NULL);
// Fill with NULLs if we have less than 2 items

list($str_network, $str_mask) =
// Store first part in `$str_network` and second part in `$str_mask`
于 2012-04-20T09:35:46.987 に答える