만족

[PHP] 아이피 정보 조회 및 해외 아이피 차단 본문

[PHP] 아이피 정보 조회 및 해외 아이피 차단

Backend/PHP Satisfaction 2022. 1. 13. 18:42

현재 운영중인 서비스에서 VPN으로 아이피를 해외로 돌려 악성 댓글을 작성하는 경우가 포착되었다.

 

따라서 요청 아이피를 확인해 해외 아이피인 경우 일부 기능을 사용할 수 없도록 할 것이다.

 

클라이언트 아이피 가져오기

    function getClientIP() {
        $ipaddress = '';

        if ($_SERVER['HTTP_CLIENT_IP']) {
            $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
        } else if ($_SERVER['HTTP_X_FORWARDED_FOR']) {
            $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
        } else if ($_SERVER['HTTP_X_FORWARDED']) {
            $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
        } else if ($_SERVER['HTTP_FORWARDED_FOR']) {
            $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
        } else if ($_SERVER['HTTP_FORWARDED']) {
            $ipaddress = $_SERVER['HTTP_FORWARDED'];
        } else if ($_SERVER['REMOTE_ADDR']) {
            $ipaddress = $_SERVER['REMOTE_ADDR'];
        }
        return $ipaddress;
    }

이 코드는 요청 헤더에서 요청 클라이언트의 IP를 리턴하는 코드이다.

 

IP 정보 조회하기

https://ipinfo.io/account/home

 

Log in - IPinfo.io

Need an IPinfo account? Sign up © IPinfo · Privacy & Terms

ipinfo.io

ipinfo에서 해당 기능을 무료로 제공한다. (월 50,000건까지)

 

회원가입을 완료하면(결제 수단 등록이 필요하지 않다), 토큰을 발급받는다.

 

별도 로직 작성 없이 모듈을 다운로드하여 사용할 수도 있다.

 

https://github.com/ipinfo/php

 

GitHub - ipinfo/php: Official PHP library for IPinfo (IP geolocation and other types of IP data)

Official PHP library for IPinfo (IP geolocation and other types of IP data) - GitHub - ipinfo/php: Official PHP library for IPinfo (IP geolocation and other types of IP data)

github.com

다만 이 포스트에서는 사용하지 않고, 직접 curl 코드를 작성해 사용할 것이다.

 

class HTTPResponse {
    public $code;
    public $response;
    public $url;
    public $info;
    public $raw;

    public function __construct($ch) {
        $temp = curl_exec($ch);

        $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);

        // $header = substr($data, 0, $headerSize);
        $this->response = substr($temp, $headerSize);
        $this->code     = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $this->url      = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
        $this->info     = curl_getinfo($ch);
        $this->raw      = $temp;

        curl_close($ch);
    }
    public function printInfo() {
        var_dump($this->info);
        // echo $this->code;
        // echo $this->url;
        // echo $this->response;
        // echo $this->info;
    }
}
class Curl {
    public static function get($url, $params, $header = array('Accept: application/json', 'Content-Type: application/json')) {
        //$query= http_build_query(Curl::parseParams($params));

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url . '?' . $params);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        //echo curl_errno($ch);
        return new HTTPResponse($ch);
    }
}

Curl 실행 시 위 코드를 사용할 것이다.

 

이제 발급받은 토큰과, 가이드를 참조하여 IP의 정보를 조회해 보자.

 

//...
$response= Curl::get('https://ipinfo.io/'.$ip,"token=YOUR_TOKEN");
if($response->code!= 200){
    //요청 횟수 초과 및 검증 서버 다운 
}
$response= json_decode($response->response);
var_dump($response);
//...

결과는 아래와 같다.

 

array(9) { ["ip"]=> string(15) "221.146.186.213" ["city"]=> string(5) "Seoul" ["region"]=> string(5) "Seoul" ["country"]=> string(2) "KR" ["loc"]=> string(16) "37.5783,127.0946" ["org"]=> string(20) "AS4766 Korea Telecom" ["postal"]=> string(5) "02260" ["timezone"]=> string(10) "Asia/Seoul" }

 

여기에서 country값이 KR이면 한국이고, 다른 값이면 해외로 취급한다.

 

따라서 아래 로직을 추가하여 해외 아이피일 경우 요청을 드랍시킬 수 있다.

 

//...
$response= Curl::get('https://ipinfo.io/'.$ip,"token=YOUR_TOKEN");
if($response->code!= 200){
    //요청 횟수 초과 및 검증 서버 다운 
}
$response= json_decode($response->response);
if($response['country'] != 'KR'){
    //해외 아이피
}else{
    //한국 아이피
}
//...

 

이 로직을 모듈화 시켜보자.

 

function isAllowedCountryIP($ip){
    $response= Curl::get('https://ipinfo.io/'.$ip,"token=YOUR_TOKEN");
    if($response->code!= 200){
        //요청 횟수 초과 및 검증 서버 다운 
        return true;
    }
    $response= json_decode($response->response);
    if($response['country'] != 'KR'){
        return false;
    }
    return true;
}

이렇게 하면 isAllowedCountryIP에 아이피를 전달했을 때,

아이피 정보를 조회할 수 없거나 한국 아이피인 경우 true, 이외에는 false를 리턴하게 된다.

 

이제 해외 아이피가 사용하지 못하게 할 엔드포인트로 이동해, 

isAllowedCountryIP(getClientIP()) 를 사용하여 false일 경우 

403으로 응답하여 해당 엔드포인트를 사용할 수 없게 만들 수 있다.

 

//해외 아이피를 차단할 엔트포인트 로직

//...

if(!$isAllowedCountryIP(getClientIP())){
	//해외 아이피 감지
    http_response_code(403);
    exit();
}
//원래의 로직 실행

//...

 



Comments