한줄공지
  • 등록된 공지내용이 없습니다.

Ubuntu 20.04에서 PHP와 함께 Redis®를 사용하여 Rate Limiter로 사용하기

2024년 7월 5일
조회수 52
코멘트 0

목차

소개

Rate limiting은 서버에서 자원 사용을 제한하는 방법입니다. 예를 들어, API (응용 프로그램 프로그래밍 인터페이스)를 실행하는 경우, 특정 시간 내에 사용자가 서버에 요청 할 수있는 횟수를 제한하는 캡을 설정할 수 있습니다. 웹 애플리케이션의 요청 속도를 제어하면 DoS (서비스 거부) 공격의 위험을 줄일 수 있습니다. 이를 통해 애플리케이션에 공정한 사용 정책을 적용할 수 있습니다. 대규모 웹 애플리케이션에서 특정 제약을 초과하지 않도록 작업을 제한하면 대역폭 및 리소스 사용에 대한 큰 비용을 절약할 수 있습니다.

이 가이드에서는 Vultr Ubuntu 20.04 서버에서 PHP를 사용하여 웹 리소스에 대한 요청을 제한하는 데 Redis® 서버를 사용합니다.

사전요구사항

이 가이드를 따르려면 다음 사항이 필요합니다:

  • Ubuntu 20.04 서버
  • sudo 사용자
  • Lamp Stack
  • Redis® 서버

Redis® 확장 설치

Vultr Ubuntu 클라우드 서버에 로그인하고 php-redis 확장을 설치하세요. 이 모듈을 사용하면 PHP 코드에서 Redis® 라이브러리를 사용할 수 있습니다.

 $ sudo apt install -y php-redis

새 구성을 로드하기 위해 Apache 서버를 다시 시작하세요.

 $ sudo systemctl restart apache2

PHP 리소스 생성

서버의 루트 디렉토리에 PHP 리소스를 만드세요.

 $ sudo nano /var/www/html/resource.php

그런 다음 아래 정보를 파일에 추가하세요.

 <?php 
    try {             
            $redis = new Redis(); 
            $redis->connect('127.0.0.1', 6379); 

            $username = $_SERVER['PHP_AUTH_USER']; 
            $password = $_SERVER['PHP_AUTH_PW'];

            $key = $username;

            $allowed_requests_per_period = 3;
            $time_frame_in_seconds       = 10;

            $total_requests = 0;

            if ($redis->exists($key)) {
                $redis->INCR($key);                  
                $total_requests = $redis->get($key);                    

                if ($total_requests > $allowed_requests_per_period) {
                   echo "Hey, " . $username . ", You've already reached your requests limit. Total requests " 
                         . $total_requests . " Allowed requests " . $allowed_requests_per_period;
                   exit();                   
                }                

            } else {               
                $redis->set($key, 1); 
                $redis->expire($key, $time_frame_in_seconds); 
                $total_requests = 1;       
            } 

            echo "ok, total requests " . $total_requests;            

        } catch (Exception $e) {
            echo $e->getMessage();
        }
?>

파일 편집을 마치면 Ctrl + X, Y를 누르고 Enter를 눌러 저장하고 닫으세요.

/var/www/html/resource.php 코드 설명:

$redis = new Redis(); 
$redis->connect('127.0.0.1', 6379); 

위의 코드를 사용하여 로컬호스트의 포트 6379를 통해 Redis® 서버에 연결합니다.

$username = $_SERVER['PHP_AUTH_USER']; 
$password = $_SERVER['PHP_AUTH_PW'];

PHP를 Apache 모듈로 실행하도록 구성한 경우, $_SERVER['PHP_AUTH_USER']$_SERVER['PHP_AUTH_PW'] 변수는 HTTP 기본 인증 자격 증명을 각각 $username$password 변수에 할당합니다.

$key = $username;

웹 리소스에 액세스하는 여러 사용자가 있을 수 있으므로 $_SERVER['PHP_AUTH_USER'] 변수에서 검색한 $username 변수로 Redis® 키를 생성하여 각 사용자의 트래픽을 독립적으로 추적할 수 있습니다.

$allowed_requests_per_period = 3;
$time_frame_in_seconds       = 10;

위의 두 변수는 애플리케이션의 설정 사용 정책에 따라 웹 리소스 요청을 제한할 수 있게합니다. 이 예제에서는 사용자를 10초 동안 3회로 제한합니다. 필요에 따라 이 값을 조정하세요.

$total_requests = 0;

$total_requests 변수를 사용하여 사용자가 요청한 총 횟수를 초기화합니다.

if ($redis->exists($key)) {
     $redis->INCR($key);                  
     $total_requests = $redis->get($key);                    

     if ($total_requests > $allowed_requests_per_period) {
         echo "You've already reached your requests limit. Total requests " 
         . $total_requests . " Allowed requests " . $allowed_requests_per_period;
         exit();                   
     }                

 } else {               
     $redis->set($key, 1); 
     $redis->expire($key, $time_frame_in_seconds); 
     $total_requests = 1;       
 }

위의 코드는 Redis® 서버에서 $key 변수의 존재 여부를 확인합니다. 키가 존재하는 경우 $redis->INCR($key) 명령을 사용하여 1을 증가시킵니다. 키가 존재하지 않는 경우 $key 값을 1로 설정하고 $time_frame_in_seconds 변수로 정의된 만료 기간으로 새 키를 설정합니다. 그런 다음 $redis->get($key)를 사용하여 $key 키의 현재 수를 가져옵니다. 값을 가져온 후, $total_requests 변수에 할당합니다.

다음으로 PHP의 if...else 구문을 사용하여 클라이언트가 정의된 기간 동안 허용된 총 요청을 초과하는지 평가합니다. 제한을 초과하면 사용자에게 오류를 반환합니다.

echo "ok, total requests " . $total_requests;

파일 아래쪽에는 사용자가 제한을 초과하지 않은 경우 사용자가 한 요청의 수를 출력합니다.

Redis® Rate Limiter 테스트

서버의 명령 프롬프트를 열고, curl 명령을 사용하여 위에서 생성한 /var/www/html/resource.php 웹 리소스를 조회합니다. 'http://localhost/resource.php?[1-20]'의 더미 쿼리 문자열은 스크립트가 Redis® 서버에 의해 제한되는지 확인하기 위해 리소스에 20번 액세스할 수 있도록 합니다.

$ curl --user john:SAMPLE_PASSWORD 
  -H "Accept: text/plain" 
  -H "Content-Type: text/plain" 
  -X GET http://localhost/resource.php?[1-20]

위 코드를 실행한후, 아래 출력을 받을 수 있어야 합니다.

[1/20]: http://localhost/resource.php?1 --> stdout
--_curl_--http://localhost/resource.php?1
    ok, total requests 1
[2/20]: http://localhost/resource.php?2 --> stdout
--_curl_--http://localhost/resource.php?2
    ok, total requests 2
[3/20]: http://localhost/resource.php?3 --> stdout
--_curl_--http://localhost/resource.php?3
    ok, total requests 3
[4/20]: http://localhost/resource.php?4 --> stdout
--_curl_--http://localhost/resource.php?4
    Hey, john, You've already reached your requests limit. Total requests 4 Allowed requests 3
[5/20]: http://localhost/resource.php?5 --> stdout
--_curl_--http://localhost/resource.php?5
    Hey, john, You've already reached your requests limit. Total requests 5 Allowed requests 3
[6/20]: http://localhost/resource.php?6 --> stdout
...

첫 세 개의 요청이 수락되는 것을 확인할 수 있습니다. 그러나 네 번째 요청부터 PHP 스크립트가 비율 제한 오류를 발생시키기 시작했습니다.

결론

이 튜토리얼에서 Redis® 서버를 사용하여 Ubuntu 20.04에서 PHP로 리소스 사용을 제한하는 방법을 알아보았습니다. 이 가이드는 Redis®와 함께 소비자가 리소스를 제한하는 방법의 예시에 불과합니다. 이를 확장하여 웹 애플리케이션의 요구 사항에 맞게 조정 할 수 있습니다.

 

출처: https://docs.vultr.com/use-redis-as-a-rate-limiter-with-php-on-ubuntu-20-04

안정적이고 저렴한 가상 서버(VPS) 안내

안정적인 서버 호스팅을 찾고 계신가요? 지금 Vultr 호스팅을 한번 이용 해 보세요. 지금 보고 계신 HaruLogs 사이트도 Vultr에서 VPS 호스팅 하고 있습니다. 한국, 일본, 미국등 다양한 국가에 클릭 몇번으로 안정적이고 저렴한 VPS를 운영 할 수 있습니다.

아래 배너를 통해 회원 가입을 하시면 100달러의 무료 크레딧을 받을 수 있습니다. 100달러의 무료 크레딧은 Vultr의 최소 사양 VPS를 20대 동시 운영가능한 크레딧입니다.

지금 무료로 Vultr $100 크레딧 선물 받기

 

Vultr 서비스 요약

  • VPS
    • 인스턴스
      • AMD 또는 Intel High Performance 인스턴스 최저 $6 - 1vCPU, 1GB Memory, 2TB Bandwidth, 25GB NVMe
    • 엣지
  • Block Storage
  • Object Storage (AWS S3 호환)
  • Firewall
  • Network
  • Load Balancers
  • Kubernetes
  • Databases
포스트 통계
지금 보고있는 포스트의 통계 데이터를 확인 해 보세요.
  • 총 조회수
    53
  • 최근 30일 조회수
    19
연관 포스트
코멘트 작성