PHP獲取IP地址的方法,防止偽造IP地址注入攻擊


PHP獲取IP地址的方法

/**
 * 獲取客戶端IP地址
 * <br />來源:ThinkPHP
 * <br />"X-FORWARDED-FOR" 是代理服務器通過 HTTP Headers 提供的客戶端IP。代理服務器可以偽造任何IP。
 * <br />要防止偽造,不要讀這個IP即可(同時告訴用戶不要用HTTP 代理)。
 * @param integer $type 返回類型 0 返回IP地址 1 返回IPV4地址數字
 * @param boolean $adv 是否進行高級模式獲取(有可能被偽裝) 
 * @return mixed
 */
function get_client_ip($type = 0, $adv = false) {
    $type = $type ? 1 : 0;
    static $ip = NULL;
    if ($ip !== NULL)
        return $ip[$type];
    if ($adv) {
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            $pos = array_search('unknown', $arr);
            if (false !== $pos)
                unset($arr[$pos]);
            $ip = trim($arr[0]);
        }elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
            $ip = $_SERVER['HTTP_CLIENT_IP'];
        } elseif (isset($_SERVER['REMOTE_ADDR'])) {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
    } elseif (isset($_SERVER['REMOTE_ADDR'])) {
        $ip = $_SERVER['REMOTE_ADDR'];
    }
    // IP地址合法驗證, 防止通過IP注入攻擊
    $long = sprintf("%u", ip2long($ip));
    $ip = $long ? array($ip, $long) : array('0.0.0.0', 0);
    return $ip[$type];
}

/**
 * 獲得用戶的真實IP地址
 * <br />來源:ecshop
 * <br />$_SERVER和getenv的區別,getenv不支持IIS的isapi方式運行的php
 * @access  public
 * @return  string
 */
function real_ip() {
    static $realip = NULL;
    if ($realip !== NULL) {
        return $realip;
    }
    if (isset($_SERVER)) {
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            /* 取X-Forwarded-For中第一個非unknown的有效IP字符串 */
            foreach ($arr AS $ip) {
                $ip = trim($ip);

                if ($ip != 'unknown') {
                    $realip = $ip;

                    break;
                }
            }
        } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
            $realip = $_SERVER['HTTP_CLIENT_IP'];
        } else {
            if (isset($_SERVER['REMOTE_ADDR'])) {
                $realip = $_SERVER['REMOTE_ADDR'];
            } else {
                $realip = '0.0.0.0';
            }
        }
    } else {
        if (getenv('HTTP_X_FORWARDED_FOR')) {
            $realip = getenv('HTTP_X_FORWARDED_FOR');
        } elseif (getenv('HTTP_CLIENT_IP')) {
            $realip = getenv('HTTP_CLIENT_IP');
        } else {
            $realip = getenv('REMOTE_ADDR');
        }
    }
    // 使用正則驗證IP地址的有效性,防止偽造IP地址進行SQL注入攻擊
    preg_match("/[\d\.]{7,15}/", $realip, $onlineip);
    $realip = !empty($onlineip[0]) ? $onlineip[0] : '0.0.0.0';
    return $realip;
}

X-Forwarded-For地址形式列舉:
unkonwn, unknown, 211.100.22.30
172.16.20.110, 202.116.64.196, 203.81.21.61
10.194.75.83, 10.194.73.11, 10.194.71.11, unknown
192.168.120.57, unknown, unknown, 211.10.10.195
unknown, 210.75.1.181
155.161.59.47, unknown

偽造IP地址進行注入攻擊:

IP偽造有幾種途徑,一種是通過是修改IP數據包,有興趣的可以去看看IP數據包的結構,還有一種就是利用修改http頭信息來實現IP偽造。涉及到“客戶端”IP的通常使用3個環境變量:$_SERVER['HTTP_CLIENT_IP']和$_SERVER['X_FORWARDED_FOR']還有$_SERVER['REMOTE_ADDR']實際上,這3個環境變量都有局限性。前兩個是可以隨意偽造。只要在發送的http頭里設置相應值就可以,任意字符都可以,而第3個環境變量,如果用戶使用了匿名代理,那這個變量顯示的就是代理IP。
一般獲取IP后更新到數據庫代碼如:$sql="update t_users set login_ip='".get_client_ip()."' where ...",而如果接收到的ip地址是:xxx.xxx.xxx.xxx';delete from t_users;-- ,代入參數SQL語句就變成了:"update t_users set login_ip='xxx.xxx.xxx.xxx';delete from t_users;-- where ...
所以獲取IP地址后,務必使用正則等對IP地址的有效性進行驗證,另外一定要使用參數化SQL命令!

總結:

"X-FORWARDED-FOR" 是代理服務器通過 HTTP Headers 提供的客戶端IP。代理服務器可以偽造任何IP。
要防止偽造,不要讀這個IP即可(同時告訴用戶不要用HTTP 代理)。
如果是PHP,$_SERVER['REMOTE_ADDR'] 就是跟你服務器直接連接的IP,用這個就可以了。

 

獲取服務器IP地址:

/**
 * 獲取服務端IP地址
 * @return string
 * @since 1.0 2016-7-1 SoChishun Added.
 */
function get_host_ip() {
    return isset($_SERVER['HTTP_X_FORWARDED_HOST']) ? $_SERVER['HTTP_X_FORWARDED_HOST'] : (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '');
}

 

參考文章:

http://www.cnblogs.com/skiplow/archive/2011/07/20/2111751.html (偽造IP地址進行SYN洪水攻擊)
http://www.feifeiboke.com/pcjishu/3391.html (你所不懂的火狐瀏覽器妙用之偽造IP地址)
https://segmentfault.com/q/1010000000095850#a-1020000000098537 (如何避免用戶訪問請求偽造ip)
http://blog.csdn.net/clh604/article/details/9234473 (PHP使用curl偽造IP地址和header信息)
http://www.cnblogs.com/lmule/archive/2010/10/15/1852020.html (REMOTE_ADDR,HTTP_CLIENT_IP,HTTP_X_FORWARDED_FOR)

 

版權聲明:本文采用署名-非商業性使用-相同方式共享(CC BY-NC-SA 3.0 CN)國際許可協議進行許可,轉載請注明作者及出處。
本文標題:PHP獲取IP地址的方法,防止偽造IP地址注入攻擊
本文鏈接:http://www.cnblogs.com/sochishun/p/7168860.html
本文作者:SoChishun (郵箱:14507247#qq.com | 博客:http://www.cnblogs.com/sochishun/)
發表日期:2017年7月14日


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM