php_在线判断来源IP是否为国内IP(筛选国内国外ip办法)

php_在线判断来源IP是否为国内IP(筛选国内国外ip办法)

一朋友需要这个功能。我在我所熟悉的编写语言中想到了个办法

1.java 搭建麻烦

2.python 环境不好搭配 不适合给小白新手朋友用

3.易语言 (速度太慢)

4.php (毫秒级别 就它了)

环境:

宝塔

Redis

1.在宝塔面板中安装Redis

 

2.配置Redis(不需要改)

3. 在安装的PHP中安装Redis扩展。

4.在面板的安全配置里,开放相应的Redis端口(Redis使用的是6379端口,就开放6379端口)。(如果你是腾讯云什么还要去 控制后台修改 百度下开放端口就知道了)

 

5.测试是否成功配置好环境源码(php)

<?php
$redis = new \Redis();
$redis->connect('127.0.0.1', 6379);//serverip port
$redis ->set( "test" , "Hello World ");  
echo $redis ->get( "test");
echo "Server is running: " .$redis->ping();

没问题的话。那么现在其他源码:

#!/bin/bash
#variables

ip_txt_path=/www/wwwroot/isipchina/china_ip.txt;
ip_url='http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest';
php_path=/www/server/php/72/bin/php
script_path=/www/wwwroot/isipchina/putip2redis.php

#mv old txt

cur_time=$(date +"%Y%m%d%H%M%S");
if [ -f ${ip_txt_path} ];then
       mv ${ip_txt_path} ${ip_txt_path}_${cur_time};
fi

#download

/usr/bin/curl ${ip_url} | grep ipv4 | grep CN | awk -F\| '{ printf("%s/%d\n", $4, 32-log($5)/log(2)) }' >${ip_txt_path}

#parse 2 redis

echo "begin parse ip\n";
${php_path} ${script_path}

ip_txt_path=/www/wwwroot/isipchina/china_ip.txt; //存放国内字段IP文本的地址记得看路径
ip_url=’http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest’;//不需要改
php_path=/www/server/php/72/bin/php      //宝塔php72
script_path=/www/wwwroot/isipchina/putip2redis.php //把txt的内容 redis存进去数据库

${php_path} ${script_path}//运行php文件


putip2redis.php 

修改地址:define(“IP_FILE”, “/www/wwwroot/isipchina/china_ip.txt”);

<?php
/*

解析国内ip地址列表,以ip地址的第一段为索引,
保存到redis中的一个hash中

by 刘宏缔
2020.04.02

*/
//------------------------------------------------settings
ini_set("display_errors","On");
error_reporting(E_ALL);
//------------------------------------------------constant
define("REDIS_SERVER", "127.0.0.1");
define("REDIS_PORT", "6379");
define("IP_FILE", "/www/wwwroot/isipchina/china_ip.txt");
define("IP_HASH_NAME", "china_ip_hash");
//------------------------------------------------link 4 redis
$redis_link = new \Redis();
$redis_link->connect(REDIS_SERVER,REDIS_PORT);

//------------------------------------------------main
set_ip_list(IP_FILE);

//------------------------------------------------function
//处理所有的ip范围到redis
function set_ip_list($ip_file) {
    //从文件中得到所有的国内ip
    $arr_all = file($ip_file);

    //遍历,得到所有的第一段
    $arr_first = array();
    foreach ($arr_all as $k => $rangeone) {
        $rangeone = trim($rangeone);
        if ($rangeone == "") {
            continue;
        }
        
        $first = explode(".", $rangeone);
        if (isset($first[0]) && $first[0]!='') {
    	      $arr_first[] = $first[0];
        }
    }

    //对所有的第一段去除重复
    $arr_first = array_unique($arr_first);

    //得到线上hash的所有key
    $arr_hkeys = hash_keys(IP_HASH_NAME);

    //如果一个线上已存在的key不再存在于新ip的第一段的数组中
    //需要从线上hash中删除
    if (is_array($arr_hkeys) && sizeof($arr_hkeys)>0) {
        foreach($arr_hkeys as $k => $hkey_one) {
           if (!in_array($hkey_one, $arr_first)) {
                echo "will delete :".$hkey_one."\n";
                hash_delete_hkey(IP_HASH_NAME,$hkey_one);
            }
        }
    }

    //得到每个第一段下面对应的所有ip地址段,保存到redis
    foreach ($arr_first as $k => $first) {
    	  add_a_list_by_first($first,$arr_all);  
    }

}


//把所有的第一段为指定数字的ip,添加到redis
function add_a_list_by_first($first,$arr) {

     $arr_line = array();
     foreach ($arr as $k => $rangeone) {
          $rangeone = trim($rangeone);
          $first_a = explode(".", $rangeone);
          if (!isset($first_a[0]) || $first_a[0] == "") {
          	  continue;
          }
          $cur_first = $first_a[0];
          if ($cur_first == $first) {

              $line = get_line_by_rangeone($rangeone);
              //echo "line:".$line."\n";
              $arr_line[] = $line;
          } else {
          	  continue;
          }
      }


      if (sizeof($arr_line) >0) {
      	   $key_name = $first;
      	   hash_set(IP_HASH_NAME,$key_name,$arr_line);
      }
}


//得到一个ip地址段的起始范围
function get_line_by_rangeone($networkRange) {

        $s = explode('/', $networkRange);
        $network_start = (double) (sprintf("%u", ip2long($s[0])));
        $network_len = pow(2, 32 - $s[1]);
        $network_end = $network_start + $network_len - 1;

        $line = $network_start."--".$network_end;
        return $line;
}


//redis set 一个数组到hash
function hash_set($hash_name,$key_name,$arr_value){
      global $redis_link;
      $str_value = json_encode($arr_value);
      $b = $redis_link->hset($hash_name, $key_name, $str_value);
}

//返回redis hash中
function hash_keys($hash_name) {
      global $redis_link;
      $arr = $redis_link->hKeys($hash_name);
      return $arr;
}

//删除一个hash的hkey
function hash_delete_hkey($hash_name,$key_name) {
      global $redis_link;
      $redis_link->hdel($hash_name, $key_name);
}

?>

ipchina.php 用来判断ip是否为国内ip( 无需修改)

<?php
/*
判断一个ip是否国内的ip
需要连接到redis服务器进行判断
*/
//------------------------------------------------settings
ini_set("display_errors","On");
error_reporting(E_ALL);
$t1 = microtime(true);
//------------------------------------------------constant
define("REDIS_SERVER", "127.0.0.1");
define("REDIS_PORT", "6379");
define("IP_HASH_NAME", "china_ip_hash");
//------------------------------------------------link 2 redis
$redis_link = new \Redis();
$redis_link->connect(REDIS_SERVER,REDIS_PORT);
//------------------------------------------------main

//$ip = getRealIp();
$ip = getRealIp();//在线获取用户IP
$is_in = is_ip_in_china($ip);//判断一个ip是否国内的ip
echo "ip:".getRealIp().PHP_EOL;


if ($is_in == true) {
  echo "china";
} else {
  echo "foreign";
}

//------------------------------------------------function
function getRealIp()//判断来源IP
{
    $ip=false;
    if(!empty($_SERVER["HTTP_CLIENT_IP"])){
        $ip = $_SERVER["HTTP_CLIENT_IP"];
    }
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ips = explode (", ", $_SERVER['HTTP_X_FORWARDED_FOR']);
        if ($ip) { array_unshift($ips, $ip); $ip = FALSE; }
        for ($i = 0; $i < count($ips); $i++) {
            if (!eregi ("^(10│172.16│192.168).", $ips[$i])) {
                $ip = $ips[$i];
                break;
            }
        }
    }
    return ($ip ? $ip : $_SERVER['REMOTE_ADDR']);
}


//判断一个ip是否属于china
function is_ip_in_china($ip) {
  $ip = trim($ip);
    $first_a = explode(".", $ip);
    if (!isset($first_a[0]) || $first_a[0] == "") {
    	//ip有误,按国外算
    	return false;
    }
    $first = $first_a[0];
    
    $arr_range = hash_get(IP_HASH_NAME,$first);
    if (!is_array($arr_range) || sizeof($arr_range) == 0) {
    	  return false;
    }

    if (is_ip_in_arr_range($ip,$arr_range) == true) {
          return true;
    } else {
    	  return false;
    }
}

//判断一个ip是否属于ip的range数组
function is_ip_in_arr_range($ip,$arr_range) {
    $ip_long = (double) (sprintf("%u", ip2long($ip)));

  
  foreach ($arr_range as $k => $one) {
    $one = trim($one);
        //echo $one.":\n";
        $arr_one = explode("--", $one);

        if (!isset($arr_one[0]) || !isset($arr_one[1])) {
        	 continue;
        }

        $begin = $arr_one[0];
        $end = $arr_one[1];

        if ($ip_long >= $begin && $ip_long <= $end) {
            return true;
        }
  }
  return false;
}


//得到一个hash中对应key的value
function hash_get($hash_name,$key_name){

       global $redis_link;
         $str = $redis_link->hget($hash_name, $key_name);
         $arr = json_decode($str,true);
         return $arr;
}
$t2 = microtime(true);//计算时间

echo '耗时'.round($t2-$t1,6).'s /by:老马 ';
?>

第一次使用
记得采用宝塔定时

脚本格式:

任务名字:更新中国IP库

任务代码:

sh /www/wwwroot/isipchina/downchinaip.sh >> /www/wwwroot/isipchina/downchinaiplogs.log 2>&1

如果你们路径有改记得 对应改下

赞 (0)