feat: initial commit
This commit is contained in:
Executable
+63
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/**
|
||||
* 流量判定主流水线
|
||||
*
|
||||
* 阶段顺序(不可调换):
|
||||
* 1. Session 快速路径 → 2. 黑白名单 → 3. 广告来源限制 → 4. 临时链接 → 5. API/指纹
|
||||
*/
|
||||
class CheckPipeline
|
||||
{
|
||||
/**
|
||||
* 在调用方(ip_check 顶层)作用域执行完整判定链。
|
||||
* 依赖全局:$v_info, $config_name, $__cloak_debug_on, $reason
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function run()
|
||||
{
|
||||
global $v_info, $config_name, $__cloak_debug_on, $__cloak_debug_started, $reason;
|
||||
|
||||
if (!isset($reason)) {
|
||||
$reason = '';
|
||||
}
|
||||
|
||||
CloakPipelineTimer::init();
|
||||
|
||||
CloakPipelineTimer::stage('Session快速路径');
|
||||
if (self::resolveSessionFastPath()) {
|
||||
include __DIR__ . '/stages/resolve_session_fast_path_hit.inc.php';
|
||||
CloakPipelineTimer::finish();
|
||||
return;
|
||||
}
|
||||
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__, 'Session 快速路径', 'skip', '未命中缓存,进入完整判定流程(DEBUG 已重置 visit_to_*)');
|
||||
}
|
||||
|
||||
CloakPipelineTimer::stage('黑白名单');
|
||||
include __DIR__ . '/stages/apply_whitelist_blacklist.inc.php';
|
||||
CloakPipelineTimer::stage('广告来源限制');
|
||||
include __DIR__ . '/stages/run_ad_source_guard.inc.php';
|
||||
CloakPipelineTimer::stage('临时链接参数');
|
||||
include __DIR__ . '/stages/check_url_args_timeout.inc.php';
|
||||
include __DIR__ . '/stages/run_main_api_fingerprint.inc.php';
|
||||
CloakPipelineTimer::finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否命中 session 缓存结果(true = 跳过完整判定)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function resolveSessionFastPath()
|
||||
{
|
||||
global $__cloak_debug_on;
|
||||
|
||||
return (
|
||||
!$__cloak_debug_on
|
||||
&& SHOW_SITE_MODE_SWITCH === 'ip_check'
|
||||
&& isset($_SESSION['check_result'])
|
||||
&& ($_SESSION['check_result'] === 'true' || $_SESSION['check_result'] === 'false')
|
||||
);
|
||||
}
|
||||
}
|
||||
Executable
+137
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../Page/FpPageRenderer.php';
|
||||
require_once __DIR__ . '/../Page/RiskPageRenderer.php';
|
||||
require_once __DIR__ . '/../FpUrlHelper.php';
|
||||
|
||||
/**
|
||||
* 判定完成后的路由输出(真实页 / 安全页 / 二次风控)
|
||||
*/
|
||||
class RouteResolver
|
||||
{
|
||||
/**
|
||||
* @param array $ctx 需含 v_info, logs, config_name, reason, model
|
||||
*/
|
||||
public static function dispatch(array $ctx)
|
||||
{
|
||||
extract($ctx, EXTR_SKIP);
|
||||
|
||||
// 正品模式:始终走安全页逻辑
|
||||
if (SHOW_SITE_MODE_SWITCH == 'zp') {
|
||||
self::renderSafePage($logs, $v_info);
|
||||
return;
|
||||
}
|
||||
|
||||
$showFp = (SHOW_SITE_MODE_SWITCH == 'ip_check' && $_SESSION['check_result'] != 'false')
|
||||
|| SHOW_SITE_MODE_SWITCH == 'fp';
|
||||
|
||||
if ($showFp) {
|
||||
self::renderFpOrRisk($logs, $v_info);
|
||||
return;
|
||||
}
|
||||
|
||||
self::renderSafePage($logs, $v_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $logs
|
||||
*/
|
||||
private static function renderSafePage(array $logs, $v_info)
|
||||
{
|
||||
if (SHOW_SITE_MODE_SWITCH == 'zp') {
|
||||
$logs['result'] = 'false';
|
||||
$logs['reason'] = '正品模式';
|
||||
}
|
||||
|
||||
$zp_url = DB_ZP;
|
||||
$logs['fp_url'] = $zp_url;
|
||||
write_log_db($logs);
|
||||
|
||||
if (empty($zp_url)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$redirect_method = CLOAK_REDIRECT_METHOD;
|
||||
if ($redirect_method == 'curl') {
|
||||
$html = file_get_content_sstr($zp_url);
|
||||
$_html = caiji_lujing_buquan($html, $zp_url, $_SERVER['HTTP_HOST']);
|
||||
echo $_html;
|
||||
exit;
|
||||
}
|
||||
if ($redirect_method == '302') {
|
||||
header('Location: ' . $zp_url);
|
||||
exit;
|
||||
}
|
||||
if ($redirect_method == 'js') {
|
||||
self::echoJsRedirect($zp_url);
|
||||
}
|
||||
}
|
||||
|
||||
private static function renderFpOrRisk(array $logs, $v_info)
|
||||
{
|
||||
if (AUTO_BLACK == 'ON') {
|
||||
$times = howmanytimesbyip($v_info->v_ip);
|
||||
if ($times + 1 >= AUTO_BLACK_TIMES) {
|
||||
write_black_list($v_info->v_ip);
|
||||
}
|
||||
}
|
||||
if (!isset($_SESSION['visit_to_3'])) {
|
||||
$_SESSION['visit_to_3'] = '1';
|
||||
}
|
||||
if (($_SESSION['visit_to_3'] ?? '1') != '3'
|
||||
&& (CLOAK_RISK_NUMBER > 0 && CLOAK_RISK_NUMBER <= 90)) {
|
||||
// 二次风控:先写 wait 状态,f_check 完成后再更新 result / fp_url(避免 true+空跳转)
|
||||
$logs['result'] = 'wait';
|
||||
$logs['reason'] = '二次风控检测中';
|
||||
$logs['fp_url'] = '';
|
||||
$log_id = write_log_db($logs);
|
||||
$riskCtx = [
|
||||
'logs' => $logs,
|
||||
'v_info' => $v_info,
|
||||
'log_id' => $log_id,
|
||||
];
|
||||
if (CLOAK_REDIRECT_METHOD == 'curl') {
|
||||
self::renderRiskCurlInject($riskCtx);
|
||||
return;
|
||||
}
|
||||
RiskPageRenderer::render($riskCtx);
|
||||
return;
|
||||
}
|
||||
|
||||
$logs['result'] = 'true';
|
||||
$logs['reason'] = '';
|
||||
FpPageRenderer::render(['logs' => $logs]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $ctx 需含 v_info, log_id
|
||||
*/
|
||||
private static function renderRiskCurlInject(array $ctx)
|
||||
{
|
||||
extract($ctx, EXTR_SKIP);
|
||||
$zp_url = DB_ZP;
|
||||
$html = file_get_content_sstr($zp_url);
|
||||
$_html = caiji_lujing_buquan($html, $zp_url, $_SERVER['HTTP_HOST']);
|
||||
ob_start();
|
||||
require dirname(__DIR__, 3) . '/cloakjs.php';
|
||||
$js_to_inject = ob_get_clean();
|
||||
if (hasHeadTag($_html)) {
|
||||
$new_html = preg_replace('/(<head[^>]*>)/i', "$1\n" . $js_to_inject, $_html);
|
||||
} else {
|
||||
$new_html = $js_to_inject . $_html;
|
||||
}
|
||||
echo $new_html;
|
||||
exit;
|
||||
}
|
||||
|
||||
private static function echoJsRedirect($zp_url)
|
||||
{
|
||||
$zp_url_js = htmlspecialchars($zp_url, ENT_QUOTES, 'UTF-8');
|
||||
echo '<SCRIPT LANGUAGE="JavaScript">'
|
||||
. 'var time = 1;var timelong = 0;'
|
||||
. 'function diplaytime(){document.all.his.innerHTML = time -timelong ;timelong ++;}'
|
||||
. 'function redirect(){window.location.href="' . $zp_url_js . '";}'
|
||||
. "timer=setInterval('diplaytime()', 30);"
|
||||
. "timer=setTimeout('redirect()',time * 30);"
|
||||
. '</SCRIPT>';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
//指定ip显示仿品(优先数据库白名单组,其次兼容旧版 SHOW_SITE_IP 逗号列表)
|
||||
if (defined('WHITELIST_GROUP_ID') && (int) WHITELIST_GROUP_ID > 0) {
|
||||
$ips_fp_ary = ip_group_list_addresses((int) WHITELIST_GROUP_ID);
|
||||
} else {
|
||||
$ips_fp_ary = array_filter(array_map('trim', explode(',', SHOW_SITE_IP)), static function ($v) {
|
||||
return $v !== '';
|
||||
});
|
||||
}
|
||||
$reason = ""; // 判断理由
|
||||
|
||||
$whiteParamsMatched = false;
|
||||
if( !empty(WHITE_PARAMS) ) {
|
||||
$wparams = explode('=', WHITE_PARAMS, 2);
|
||||
|
||||
if(count($wparams) == 2) {
|
||||
$pk = $wparams[0];
|
||||
$pv = $wparams[1];
|
||||
}
|
||||
|
||||
if(isset($_GET[$pk]) && strip_tags($_GET[$pk]) == $pv) {
|
||||
$whiteParamsMatched = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$match = false;
|
||||
if (defined('BLACKLIST_GROUP_ID') && (int) BLACKLIST_GROUP_ID > 0) {
|
||||
$blEntries = ip_group_list_addresses((int) BLACKLIST_GROUP_ID);
|
||||
$match = ip_visitor_in_blacklist_entries($v_info->v_ip, $blEntries);
|
||||
}
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__,'黑名单检查', $match ? 'fail' : 'pass', $match ? 'IP 在黑名单组内' : '未命中黑名单', [
|
||||
'ip' => $v_info->v_ip,
|
||||
'group_id' => defined('BLACKLIST_GROUP_ID') ? BLACKLIST_GROUP_ID : 0,
|
||||
]);
|
||||
}
|
||||
if ($match) {
|
||||
$_SESSION["check_result"] = "false";
|
||||
$reason = "黑名单";
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_record(__LINE__,'false', $reason, ['stage' => 'blacklist']);
|
||||
}
|
||||
}
|
||||
|
||||
if(in_array($v_info->v_ip, $ips_fp_ary) ) {
|
||||
$_SESSION["check_result"] = "true";
|
||||
$reason = "白名单";
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__,'IP 白名单', 'pass', 'IP 在白名单组/列表中');
|
||||
cloak_dbg_record(__LINE__,'true', $reason, ['stage' => 'whitelist_ip']);
|
||||
}
|
||||
} elseif( !empty(WHITE_PARAMS) ) {
|
||||
$wparams = explode('=', WHITE_PARAMS, 2);
|
||||
if(count($wparams) == 2) {
|
||||
$pk = $wparams[0];
|
||||
$pv = $wparams[1];
|
||||
}
|
||||
if(isset($_GET[$pk]) && strip_tags($_GET[$pk]) == $pv) {
|
||||
$_SESSION["check_result"] = "true";
|
||||
$reason = "白名单链接参数";
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__,'链接参数白名单', 'pass', WHITE_PARAMS);
|
||||
cloak_dbg_record(__LINE__,'true', $reason, ['stage' => 'whitelist_params']);
|
||||
}
|
||||
}
|
||||
} elseif ($__cloak_debug_on && !empty(WHITE_PARAMS)) {
|
||||
cloak_dbg_step(__LINE__,'链接参数白名单', 'skip', '参数不匹配: ' . WHITE_PARAMS);
|
||||
}
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
//判断临时链接参数(Guard 之后、API/指纹 之前)
|
||||
if(empty($_SESSION["check_result"]) && !$whiteParamsMatched && SHOW_SITE_MODE_SWITCH == 'ip_check' && CLOAK_URL_ARGS_TIMEOUT > 0) {
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__,'临时链接参数', 'info', 'CLOAK_URL_ARGS_TIMEOUT=' . CLOAK_URL_ARGS_TIMEOUT . ' 分钟,开始检查');
|
||||
}
|
||||
$dir = dirname(__DIR__, 4) . '/args';
|
||||
$pattern = '/^' . preg_quote($config_name, '/') . '_\d{10}\.txt$/i';
|
||||
$matchedFile = "";
|
||||
|
||||
if (is_dir($dir)) {
|
||||
$iterator = new DirectoryIterator($dir);
|
||||
foreach ($iterator as $file) {
|
||||
if ($file->isFile() && preg_match($pattern, $file->getFilename())) {
|
||||
$matchedFile = $file->getFilename();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$__url_args_cfg = CloakAdSourceGuard::configFromDefines();
|
||||
$__url_args_ctx = CloakAdSourceGuard::buildRequestContext();
|
||||
$__url_args_qualifies = CloakAdSourceGuard::shouldStartUrlArgsTimer($__url_args_cfg, $__url_args_ctx);
|
||||
|
||||
if ($__url_args_qualifies) {
|
||||
if(!$matchedFile) {
|
||||
$filename = $config_name . '_' . time() . '.txt';
|
||||
if(touch($dir . '/' . $filename)) {
|
||||
$matchedFile = $filename;
|
||||
}
|
||||
}
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__, '临时链接参数', 'info', '命中广告来源规则,开始/续期有效时长', [
|
||||
'platforms_enabled' => CloakAdSourceGuard::anyPlatformEnabled($__url_args_cfg),
|
||||
]);
|
||||
}
|
||||
} elseif ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__, '临时链接参数', 'skip', '未通过广告来源规则,不启动计时');
|
||||
}
|
||||
|
||||
unset($__url_args_cfg, $__url_args_ctx, $__url_args_qualifies);
|
||||
|
||||
if($matchedFile) {
|
||||
if (preg_match('/_(\d{10})\.txt$/', $matchedFile, $matches)) {
|
||||
$fileTimestamp = $matches[1];
|
||||
$diffMinutes = floor((time() - $fileTimestamp) / 60);
|
||||
|
||||
if ($diffMinutes < CLOAK_URL_ARGS_TIMEOUT) {
|
||||
$check_result = false;
|
||||
$reason = "临时链接参数:距离第一次访问过去了" . $diffMinutes . " 分钟";
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__,'临时链接参数', 'fail', $reason, ['diff_minutes' => $diffMinutes]);
|
||||
}
|
||||
} else {
|
||||
$check_result = true;
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__,'临时链接参数', 'pass', '已超过 ' . CLOAK_URL_ARGS_TIMEOUT . ' 分钟,继续后续判定');
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$check_result = false;
|
||||
$reason = "临时链接参数:尚未有效访问";
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__,'临时链接参数', 'fail', $reason);
|
||||
}
|
||||
}
|
||||
|
||||
if(!$check_result) {
|
||||
$reason = cloak_reason_or($reason, '临时链接参数拦截');
|
||||
if (class_exists('CloakPipelineTimer', false)) {
|
||||
CloakPipelineTimer::finish();
|
||||
}
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_record(__LINE__,'false', $reason, ['stage' => 'url_args_timeout']);
|
||||
CloakDebugPage::setExitPoint(__LINE__, '临时链接参数拦截 → 安全页(DEBUG 提前截停)');
|
||||
CloakDebugPage::renderAndExit([
|
||||
'config_name' => $config_name,
|
||||
'check_result' => 'false',
|
||||
'reason' => $reason,
|
||||
'visitor' => $v_info,
|
||||
'logs' => [],
|
||||
'device' => '',
|
||||
'mode' => SHOW_SITE_MODE_SWITCH,
|
||||
'fp_urls' => defined('DB_FP') ? DB_FP : [],
|
||||
'zp_url' => defined('DB_ZP') ? DB_ZP : '',
|
||||
'started_at' => $__cloak_debug_started,
|
||||
]);
|
||||
}
|
||||
$logs = array();
|
||||
$zp_url = DB_ZP;
|
||||
$logs['site_name'] = str_replace("www.", "", $_SERVER['HTTP_HOST']);
|
||||
$logs['customers_ip'] = $v_info->v_ip;
|
||||
$logs['country'] = substr($v_info->v_country, 0, 2);
|
||||
$logs['v_Browser'] = $v_info->v_Browser;
|
||||
$logs['v_referer'] = $v_info->v_referer;
|
||||
$logs['Client'] = $v_info->v_Client;
|
||||
$logs['v_PageURL'] = $v_info->v_curPageURL;
|
||||
$logs['v_site_server'] = $v_info->v_site_server;
|
||||
$logs['accept_language'] = $v_info->accept_language;
|
||||
$logs['visit_md5_code'] = $v_info->visit_md5_code;
|
||||
$logs['campagin_id'] = $v_info->costm_ip_score;
|
||||
$logs['result'] = "false";
|
||||
$logs['device'] = "";
|
||||
$logs['reason'] = $reason;
|
||||
$logs['fp_url'] = $zp_url;
|
||||
write_log_db($logs);
|
||||
|
||||
$redirect_method = CLOAK_REDIRECT_METHOD;
|
||||
if(!empty($zp_url)) {
|
||||
if($redirect_method == 'curl') {
|
||||
$html = file_get_content_sstr($zp_url);
|
||||
$_html = caiji_lujing_buquan($html, $zp_url, $_SERVER['HTTP_HOST']);
|
||||
echo $_html;
|
||||
exit;
|
||||
} elseif($redirect_method == '302') {
|
||||
header('Location: ' . $zp_url);
|
||||
exit;
|
||||
} elseif ($redirect_method == 'js') {
|
||||
$zp_url_js = htmlspecialchars($zp_url, ENT_QUOTES, 'UTF-8');
|
||||
echo '<SCRIPT LANGUAGE="JavaScript">'
|
||||
. 'var time = 1;var timelong = 0;'
|
||||
. 'function diplaytime(){document.all.his.innerHTML = time -timelong ;timelong ++;}'
|
||||
. 'function redirect(){window.location.href="' . $zp_url_js . '";}'
|
||||
. "timer=setInterval('diplaytime()', 30);"
|
||||
. "timer=setTimeout('redirect()',time * 30);"
|
||||
. '</SCRIPT>';
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif ($__cloak_debug_on && CLOAK_URL_ARGS_TIMEOUT <= 0) {
|
||||
cloak_dbg_step(__LINE__,'临时链接参数', 'skip', 'CLOAK_URL_ARGS_TIMEOUT=0,已关闭');
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
// ── SESSION 快速路径命中 ──────────────────────────────────────────────
|
||||
// session 中已有缓存结果,跳过所有判断,直接进入路由输出
|
||||
$reason = '缓存';
|
||||
if ($__cloak_debug_on) {
|
||||
CloakDebugPage::setFlag('session_cached', true);
|
||||
cloak_dbg_step(__LINE__,'Session 快速路径', 'pass', '命中缓存 check_result=' . ($_SESSION['check_result'] ?? ''));
|
||||
cloak_dbg_record(__LINE__, $_SESSION['check_result'] ?? 'false', $reason, ['stage' => 'session_fast_path']);
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
// 广告来源限制(黑白名单之后、临时链接 / API 之前)
|
||||
if (empty($_SESSION['check_result'])) {
|
||||
$__ad_guard_cfg = [
|
||||
'ad_fb' => defined('CLOAK_AD_FB') && strtoupper(CLOAK_AD_FB) === 'ON',
|
||||
'ad_google' => defined('CLOAK_AD_GOOGLE') && strtoupper(CLOAK_AD_GOOGLE) === 'ON',
|
||||
'ad_tiktok' => defined('CLOAK_AD_TIKTOK') && strtoupper(CLOAK_AD_TIKTOK) === 'ON',
|
||||
'ad_strict' => defined('CLOAK_AD_STRICT') && strtoupper(CLOAK_AD_STRICT) === 'ON',
|
||||
'ad_spm_id' => defined('CLOAK_AD_SPM_ID') ? (string) CLOAK_AD_SPM_ID : '',
|
||||
];
|
||||
|
||||
if (CloakAdSourceGuard::anyPlatformEnabled($__ad_guard_cfg)) {
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__, '广告来源限制', 'info', '已启用平台检测,开始 evaluate()');
|
||||
}
|
||||
|
||||
$__ad_ref_raw = isset($_SERVER['HTTP_REFERER']) ? (string) $_SERVER['HTTP_REFERER'] : '';
|
||||
$__ad_ref_parts = parse_url($__ad_ref_raw);
|
||||
$__ad_ref_q = [];
|
||||
if (!empty($__ad_ref_parts['query'])) {
|
||||
parse_str($__ad_ref_parts['query'], $__ad_ref_q);
|
||||
}
|
||||
$__ad_query = array_merge($__ad_ref_q, $_GET);
|
||||
|
||||
$__ad_result = CloakAdSourceGuard::evaluate($__ad_guard_cfg, [
|
||||
'referer' => $__ad_ref_raw,
|
||||
'query' => $__ad_query,
|
||||
'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? (string) $_SERVER['HTTP_USER_AGENT'] : '',
|
||||
]);
|
||||
|
||||
if ($__ad_result['passed']) {
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__, '广告来源限制', 'pass', 'matched_by=' . $__ad_result['matched_by']);
|
||||
cloak_dbg_record(__LINE__, null, '', [
|
||||
'stage' => 'ad_source_guard',
|
||||
'matched_by' => $__ad_result['matched_by'],
|
||||
]);
|
||||
}
|
||||
} elseif ($__ad_guard_cfg['ad_strict']) {
|
||||
$_SESSION['check_result'] = 'false';
|
||||
$reason = $__ad_result['reason'];
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_record(__LINE__, 'false', $reason, [
|
||||
'stage' => 'ad_source_guard',
|
||||
'matched_by' => $__ad_result['matched_by'],
|
||||
'strict' => true,
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
$reason = cloak_reason_append($reason, $__ad_result['reason']);
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__, '广告来源限制', 'warn', $reason, [
|
||||
'matched_by' => $__ad_result['matched_by'],
|
||||
'strict' => false,
|
||||
]);
|
||||
cloak_dbg_record(__LINE__, null, $reason, [
|
||||
'stage' => 'ad_source_guard_uncertain',
|
||||
'matched_by' => $__ad_result['matched_by'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
unset($__ad_ref_raw, $__ad_ref_parts, $__ad_ref_q, $__ad_query, $__ad_result);
|
||||
} elseif ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__, '广告来源限制', 'skip', '未开启任何广告平台');
|
||||
}
|
||||
|
||||
unset($__ad_guard_cfg);
|
||||
} elseif ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__, '广告来源限制', 'skip', 'check_result 已由前置步骤写入: ' . ($_SESSION['check_result'] ?? ''));
|
||||
}
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
<?php
|
||||
// 主判定块:API 远程判定 + 前端指纹(Guard 之后执行)
|
||||
if(empty($_SESSION["check_result"]) ) // 缓存里没有判断结果或者判断结果是跳转安全站
|
||||
{
|
||||
if (class_exists('CloakPipelineTimer', false)) {
|
||||
CloakPipelineTimer::stage('API与指纹准备');
|
||||
}
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__,'主判定块 (API+指纹)', 'info', 'check_result 为空,进入 API/指纹 判定块');
|
||||
}
|
||||
if(empty($_SESSION['visit_to_1'])) // 重置session信息
|
||||
{
|
||||
$_SESSION['visit_to_1'] = '1';
|
||||
$_SESSION['visit_to_2'] = '1';
|
||||
$_SESSION['visit_to_3'] = '1';
|
||||
$_SESSION["gcu_country"] = ''; // IP国家
|
||||
$_SESSION["gcu_Client"] = '';
|
||||
$_SESSION["gcu_ip"] = '';
|
||||
$_SESSION["gcu_Browser"] = '';
|
||||
}
|
||||
|
||||
if($_SESSION['visit_to_1'] == '1' && $_SESSION['visit_to_2'] != '2') // $_SESSION['visit_to_2'] 为2时表示已经判断过所有规则。
|
||||
{
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__,'主判定块 (API)', 'info', 'visit_to_1=1 且 visit_to_2!=2,执行 API 调用条件满足');
|
||||
}
|
||||
if(CLOAK_V_REFERER == "OFF" && $v_info->v_referer == "") {
|
||||
$v_info->v_referer = 'off';
|
||||
}
|
||||
|
||||
if(isset($_COOKIE['vbrowser']) && $_COOKIE['vbrowser'] == 'mobile') {
|
||||
$_SESSION["gcu_Browser"] = 'mobile';
|
||||
} else {
|
||||
$_SESSION["gcu_Browser"] = 'pc';
|
||||
}
|
||||
|
||||
if($v_info->v_referer != "") //排除机器访问,赋值给 _COOKIE , _SESSION
|
||||
{
|
||||
//echo $v_info->v_referer;
|
||||
$v_info->get_visit_md5_code(); //生成客户信息md5
|
||||
$v_referer_str = $v_info->v_referer; /* && $v_info->accept_language != "Chinese"*/
|
||||
if(!empty($v_referer_str) && !empty($v_info->accept_language) /* && $v_info->v_Browser != "unknown" && ( strpos($v_referer_str,"google") || strpos($v_referer_str,"bing") || strpos($v_referer_str,"yahoo") || strpos($v_referer_str,"facebook") || strpos($v_referer_str,"yandex")) */)
|
||||
{
|
||||
setCrossDomainCookie("gfuid", $v_info->visit_md5_code, time()+3600*24);
|
||||
$_SESSION["gcu_country"] = $v_info->v_country;
|
||||
$_SESSION["gcu_Client"] = $v_info->v_Client;
|
||||
$_SESSION["gcu_ip"] = $v_info->v_ip;
|
||||
$_SESSION["gcu_Browser"] = empty($_SESSION["gcu_Browser"])?$v_info->v_Browser:$_SESSION["gcu_Browser"];
|
||||
}
|
||||
$_SESSION["gcuid"] = $v_info->visit_md5_code;
|
||||
} elseif( !empty($_COOKIE["gfuid"]) ) {
|
||||
$_SESSION["gcuid"] = $_COOKIE["gfuid"];
|
||||
$v_info->v_referer = "COOKIE: " . cloak_current_request_url();
|
||||
$v_info->set_visit_md5_code($_COOKIE["gfuid"]); //赋值客户信息md5
|
||||
}
|
||||
|
||||
if(!empty($_SESSION["gcuid"]) && !empty($v_info->v_referer))
|
||||
{
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__,'Referer / gcuid', 'pass', 'gcuid 与 referer 均存在,可进入指纹/API 判定', [
|
||||
'gcuid' => $_SESSION['gcuid'],
|
||||
'referer' => $v_info->v_referer,
|
||||
]);
|
||||
}
|
||||
if(strtoupper(CLOAK_ZH_ON) == "ON" || strtoupper(CLOAK_MOBILE_ON) == "ON" || strtoupper(CLOAK_OS_ON) == "ON" || intval(IPHONE_MODEL) > 0 || intval(IS_VIRTUAL) > 0) {
|
||||
if (class_exists('CloakPipelineTimer', false)) {
|
||||
CloakPipelineTimer::stage('指纹检测');
|
||||
}
|
||||
|
||||
if (cloak_fingerprint_cookies_ready()) {
|
||||
if ($_COOKIE['cl'] == 'uklot' && is_numeric($_COOKIE['ctime'])) {
|
||||
$v_info->check_result = 'false';
|
||||
$mmr = cloak_fingerprint_mmr_reason();
|
||||
$reason = '可疑访客:' . $mmr;
|
||||
$_SESSION['check_result'] = trim($v_info->check_result);
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_record(__LINE__, trim($v_info->check_result), $reason, ['stage' => 'fingerprint_cookie', 'mmr' => $mmr]);
|
||||
}
|
||||
} else {
|
||||
$v_info->check_result = 'true';
|
||||
}
|
||||
} elseif (cloak_fingerprint_time_param_present()) {
|
||||
// 已完成指纹跳转(URL 含 time),但 Cookie 未写入:终止再次重定向
|
||||
$v_info->check_result = 'false';
|
||||
|
||||
$reason = cloak_reason_or($reason, '指纹Cookie未写入(已完成前端检测)');
|
||||
$_SESSION['check_result'] = 'false';
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__, 'JS 指纹检测', 'fail', 'URL 含 time 但指纹 Cookie 缺失,停止重定向');
|
||||
cloak_dbg_record(__LINE__, 'false', $reason, ['stage' => 'fingerprint_cookie_missing']);
|
||||
}
|
||||
} else {
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__, 'JS 指纹检测', 'skip', 'DEBUG 跳过指纹 JS 跳转,直接进入 API 判定');
|
||||
CloakDebugPage::setFlag('skipped_fingerprint', true);
|
||||
$v_info->check_result = 'true';
|
||||
} else {
|
||||
FingerprintRedirectRenderer::renderAndExit($config_name);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$v_info->check_result = 'true';
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__,'JS 指纹检测', 'skip', 'ZH/Mobile/OS/机型检测均为 OFF,跳过指纹');
|
||||
}
|
||||
}
|
||||
|
||||
if($v_info->check_result == 'true') {
|
||||
if (class_exists('CloakPipelineTimer', false)) {
|
||||
CloakPipelineTimer::stage('API远程判定');
|
||||
}
|
||||
$__api_return = $v_info->send_visitor_Info_xyz(); // 使用CLOAK判断接口
|
||||
if ($__cloak_debug_on) {
|
||||
if ($__api_return !== null) {
|
||||
CloakDebugPage::setApiResponse([
|
||||
'called' => true,
|
||||
'check_result'=> $v_info->check_result,
|
||||
'reason' => $v_info->v_reason,
|
||||
'country' => $v_info->v_country,
|
||||
'result_raw' => isset($__api_return['result']) ? ($__api_return['result'] ? 'true' : 'false') : '',
|
||||
'raw' => $__api_return,
|
||||
]);
|
||||
cloak_dbg_step(__LINE__,'API 远程判定', 'decide', 'API 已返回', [
|
||||
'api_result' => $v_info->check_result,
|
||||
'api_reason' => $v_info->v_reason !== '' ? $v_info->v_reason : '(空)',
|
||||
]);
|
||||
} else {
|
||||
CloakDebugPage::setApiResponse([
|
||||
'called' => false,
|
||||
'skip_reason' => '无法获取IP,未调用 API判断IP信息是否安全',
|
||||
]);
|
||||
cloak_dbg_step(__LINE__,'API 远程判定', 'skip', '前置条件不满足,未调用 API', [
|
||||
'v_ip' => $v_info->v_ip,
|
||||
'v_Browser' => $v_info->v_Browser,
|
||||
'accept_language' => $v_info->accept_language,
|
||||
]);
|
||||
}
|
||||
}
|
||||
//echo "<br />获取到结果:".$v_info->check_result."<br />";
|
||||
$_SESSION["gcu_referer"] = $v_info->v_referer;
|
||||
$_SESSION["gcu_country"] = $v_info->v_country;
|
||||
$_SESSION['visit_to_2'] = '2'; // 记录接口调用结果缓存
|
||||
|
||||
if ($__api_return !== null) {
|
||||
$_SESSION["check_result"] = trim($v_info->check_result);
|
||||
$reason = cloak_api_reason($__api_return, $_SESSION["check_result"]);
|
||||
} else {
|
||||
$_SESSION["check_result"] = "false";
|
||||
$reason = cloak_reason_or($reason, 'API未调用:缺少访客信息(ip/Browser/Accept-Language)');
|
||||
}
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_record(__LINE__,$_SESSION['check_result'], $reason, [
|
||||
'stage' => 'api_cloak',
|
||||
'api_reason' => $v_info->v_reason,
|
||||
]);
|
||||
}
|
||||
} elseif ($v_info->check_result == 'false') {
|
||||
$_SESSION["check_result"] = "false";
|
||||
$reason = cloak_reason_or($reason, '指纹检测未通过,未调用API');
|
||||
}
|
||||
} else {
|
||||
$_SESSION["check_result"] = "false";
|
||||
$reason = "爬虫";
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__,'Referer / gcuid', 'fail', 'gcuid 或 referer 为空,判定为爬虫', [
|
||||
'gcuid' => $_SESSION['gcuid'] ?? '',
|
||||
'referer' => $v_info->v_referer,
|
||||
]);
|
||||
cloak_dbg_record(__LINE__,'false', $reason, ['stage' => 'no_referer_or_gcuid']);
|
||||
}
|
||||
}
|
||||
} elseif (($_SESSION['visit_to_2'] ?? '') == '2') {
|
||||
if (!empty($_SESSION["check_result"])) {
|
||||
if ($reason === '') {
|
||||
$reason = ($_SESSION['check_result'] === 'true')
|
||||
? 'Session API缓存:判定通过'
|
||||
: 'Session API缓存:判定拒绝';
|
||||
}
|
||||
} else {
|
||||
$_SESSION["check_result"] = 'false';
|
||||
$reason = cloak_reason_or($reason, 'Session状态异常(visit_to_2=2但无缓存结果),默认安全页');
|
||||
}
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__,'主判定块 (API)', 'skip', 'visit_to_2=2,本块已跳过(' . $reason . ')');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($reason === '') {
|
||||
$reason = ($_SESSION['check_result'] === 'true')
|
||||
? '前置规则判定通过(主判定块已跳过)'
|
||||
: '前置规则判定拒绝(主判定块已跳过)';
|
||||
}
|
||||
if ($__cloak_debug_on) {
|
||||
cloak_dbg_step(__LINE__,'主判定块 (API)', 'skip', 'check_result 已有值,跳过主判定块');
|
||||
cloak_dbg_record(__LINE__,$_SESSION['check_result'] ?? 'false', $reason, ['stage' => 'session_partial']);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user