콘텐츠로 이동

NetFUNNEL PHP 에이전트는 웹 서버에서 요청 단위로 유입을 제어합니다. run()의 결과에 따라 아래와 같이 처리합니다.

반환 값 후속 처리
true 원래 페이지를 그대로 응답합니다.
false getRedirectUrl()로 대기실 URL을 받아 302로 리다이렉트합니다.
  • PHP 7.4 이상
  • PHP 확장: ext-json, ext-curl
  • NetFUNNEL 서버와 HTTPS(443) 통신 가능

에이전트는 프로젝트 안, DocumentRoot 밖에 설치합니다.

구성 설치 위치
Composer 사용 vendor/netfunnel/php-agent/ (자동)
Zend Framework 1 등 library/netfunnel-php-agent/
CodeIgniter 3 application/third_party/netfunnel-php-agent/
CodeIgniter 4 app/ThirdParty/netfunnel-php-agent/
프레임워크 없음 lib/netfunnel-php-agent/

프로젝트의 composer.json에 아래 내용을 추가한 뒤 composer install을 실행합니다.

composer.json
{
"require": {
"netfunnel/php-agent": "4.6.0"
},
"repositories": [
{
"type": "package",
"package": {
"name": "netfunnel/php-agent",
"version": "4.6.0",
"dist": {
"url": "https://agent-lib.stclab.com/agents/was/php/netfunnel-php-agent-4.6.0.tar.gz",
"type": "tar"
},
"autoload": {
"psr-4": { "NetfunnelAgent\\": "src/" }
},
"require": {
"php": "^7.4 || ^8.0",
"ext-json": "*"
}
}
}
]
}

애플리케이션 구성에 맞춰 하나를 선택합니다.

구성 적용 방법
Pure PHP auto_prepend_file
Zend Framework 1 프론트 컨트롤러 플러그인
Laravel 글로벌 미들웨어
CodeIgniter 3 / 4 진입점 index.php

코드의 {CLIENT_ID}는 콘솔에서 발급받은 값으로 바꿉니다. timeoutMs는 NetFUNNEL 서버 응답을 기다리는 최대 시간(ms)이며, 이 시간을 넘기면 제어 없이 통과합니다.

auto_prepend_file을 사용하면 기존 PHP 파일을 수정하지 않고 적용할 수 있습니다. 프로젝트 루트(DocumentRoot 밖)에 netfunnel-prepend.php를 만듭니다.

netfunnel-prepend.php
<?php
/**
* NetFUNNEL 유입 제어. auto_prepend_file 로 모든 PHP 진입점 앞에서 실행된다.
*/
if (PHP_SAPI === 'cli') {
return;
}
require_once __DIR__ . '/lib/netfunnel-php-agent/autoload.php';
if (!class_exists('NetfunnelAgent\Netfunnel')) {
return;
}
try {
$netfunnel = new NetfunnelAgent\Netfunnel(array(
'clientId' => '{CLIENT_ID}',
'timeoutMs' => 1500,
));
$allowed = $netfunnel->run();
} catch (Throwable $error) {
error_log('[netfunnel] fail-open: ' . $error->getMessage());
return;
}
if ($allowed) {
return;
}
$redirectUrl = $netfunnel->getRedirectUrl();
if ($redirectUrl !== '') {
header('Location: ' . $redirectUrl, true, 302);
exit;
}

실행 방식에 맞춰 아래 중 하나로 auto_prepend_file을 설정합니다. 경로는 절대경로로 지정합니다.

실행 방식 설정 위치 설정 값
mod_php .htaccess php_value auto_prepend_file <프로젝트루트>/netfunnel-prepend.php
mod_php php.ini auto_prepend_file = <프로젝트루트>/netfunnel-prepend.php
php-fpm pool 설정 php_value[auto_prepend_file] = <프로젝트루트>/netfunnel-prepend.php

프론트 컨트롤러 플러그인으로 라우팅 전에 유입을 제어합니다.

1) 오토로더 추가 — public/index.php에서 프레임워크 부트스트랩보다 앞에 넣습니다.

public/index.php
// NetFUNNEL 에이전트 오토로더
require_once __DIR__ . '/../library/netfunnel-php-agent/autoload.php';
require_once 'Zend/Application.php';

2) 플러그인 작성 — library/Netfunnel/Plugin.php를 새로 만듭니다.

library/Netfunnel/Plugin.php
<?php
/**
* NetFUNNEL 유입 제어 플러그인. 라우팅 전에 동작한다.
*/
class Netfunnel_Plugin extends Zend_Controller_Plugin_Abstract
{
public function routeStartup(Zend_Controller_Request_Abstract $request)
{
if (PHP_SAPI === 'cli') {
return;
}
if (!class_exists('NetfunnelAgent\Netfunnel')) {
return;
}
try {
$netfunnel = new NetfunnelAgent\Netfunnel(array(
'clientId' => '{CLIENT_ID}',
'timeoutMs' => 1500,
));
if ($netfunnel->run()) {
return;
}
$redirectUrl = $netfunnel->getRedirectUrl();
} catch (Throwable $error) {
error_log('[netfunnel] fail-open: ' . $error->getMessage());
return;
}
if ($redirectUrl === '') {
return;
}
$this->getResponse()
->setRedirect($redirectUrl, 302)
->sendResponse();
exit;
}
}

3) 플러그인 등록 — application/Bootstrap.php에서 플러그인 스택 맨 앞(작은 stackIndex)에 등록합니다.

application/Bootstrap.php
protected function _initNetfunnel()
{
Zend_Controller_Front::getInstance()->registerPlugin(new Netfunnel_Plugin(), 1);
}

글로벌 미들웨어로 모든 요청에 대기열 제어를 적용합니다.

app/Http/Middleware/NetfunnelMiddleware.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use NetfunnelAgent\Netfunnel;
use Throwable;
class NetfunnelMiddleware
{
public function handle(Request $request, Closure $next)
{
try {
$netfunnel = new Netfunnel(['clientId' => '{CLIENT_ID}']);
$allowed = $netfunnel->run();
} catch (Throwable $error) {
return $next($request); // fail-open
}
return $allowed || $netfunnel->getRedirectUrl() === ''
? $next($request)
: redirect()->away($netfunnel->getRedirectUrl(), 302);
}
}

미들웨어는 글로벌 미들웨어 맨 앞에 등록합니다.

bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
$middleware->prepend(\App\Http\Middleware\NetfunnelMiddleware::class);
})

에이전트를 설치한 디렉터리 옆에 netfunnel.php를 만들고, 진입점에서 프레임워크 부트스트랩보다 앞에 불러옵니다.

1) 제어 파일 작성 — CodeIgniter 3은 application/third_party/, CodeIgniter 4는 app/ThirdParty/에 netfunnel.php를 새로 만듭니다.

netfunnel.php
<?php
/**
* NetFUNNEL 유입 제어. 진입점 index.php 에서 프레임워크 부트스트랩보다 앞에 실행된다.
*/
if (PHP_SAPI === 'cli') {
return;
}
require_once __DIR__ . '/netfunnel-php-agent/autoload.php';
if (!class_exists('NetfunnelAgent\Netfunnel')) {
return;
}
try {
$netfunnel = new NetfunnelAgent\Netfunnel(array(
'clientId' => '{CLIENT_ID}',
'timeoutMs' => 1500,
));
$allowed = $netfunnel->run();
} catch (Throwable $error) {
error_log('[netfunnel] fail-open: ' . $error->getMessage());
return;
}
if ($allowed) {
return;
}
$redirectUrl = $netfunnel->getRedirectUrl();
if ($redirectUrl !== '') {
header('Location: ' . $redirectUrl, true, 302);
exit;
}

2) 진입점에 추가 — 버전에 맞는 위치에 한 줄을 추가합니다.

index.php에서 BASEPATH.'core/CodeIgniter.php'를 불러오는 줄 바로 위에 추가합니다.

index.php
// NetFUNNEL 유입 제어
require_once APPPATH . 'third_party/netfunnel.php';
require_once BASEPATH.'core/CodeIgniter.php';

new NetfunnelAgent\Netfunnel(...)에 넘기는 배열의 키입니다.

필드 타입 기본값 필수 설명 에이전트 버전
clientId STRING N/A O 콘솔에서 발급받은 클라이언트 아이디를 입력합니다. 4.6.0 이상
timeoutMs INTEGER 3000 X NetFUNNEL 서버 응답을 기다리는 최대 시간(ms)입니다. 시간을 넘기면 제어 없이 통과합니다. 4.6.0 이상
returnKey BOOLEAN true X 사용자가 대기열을 통과해 페이지에 진입하면 즉시 다음 사용자가 입장할 수 있습니다. 비활성화하면 진입 후에도 일정 시간 다음 사용자가 대기합니다. (타임아웃은 콘솔의 세그먼트 설정 > 고급설정에서 가능합니다.) 4.6.0 이상
goodBots ARRAY N/A X 선의의 봇(검색엔진 등)을 진입 요청에서 제외합니다. User-Agent에 해당 문자열이 포함되는지로 판단하며, 대소문자를 구분합니다. 예시: ['Googlebot', 'Bingbot'] 4.6.0 이상
vwrPageDomain STRING N/A X CNAME 도메인만으로 VWR Page URL을 구성할 때 사용합니다. 예시: https://vwr.example.com 4.6.0 이상
cookieDomain STRING N/A X 발급되는 NetFUNNEL 쿠키의 도메인(Domain) 값을 직접 지정합니다. 4.6.0 이상

아래 명령으로 에이전트가 정상 적용되었는지 확인합니다. <고객사도메인>과 <제어대상URL>은 실제 값으로 바꿉니다.

터미널 창
# 에이전트 탑재 확인
curl -si https://<고객사도메인>/ | grep -i x-nf-ver
# 제어 대상 URL 확인
curl -si -H 'Accept: text/html' 'https://<고객사도메인>/<제어대상URL>'
확인 항목 기대 결과
에이전트 탑재 응답에 x-nf-ver: 4.6.0 헤더가 포함됩니다.
제어 대상 URL _nf_key로 시작하는 쿠키가 발급됩니다. 대기가 발생하면 302 응답과 함께 대기실 URL이 Location으로 내려옵니다.