
클라이언트 측 봇 탐지 라이브러리로, 28개의 가중치 모듈, 행동 분석, 브라우저 지문 인식, 허니팟, 서버 측 검증을 제공합니다. 헤드리스 브라우저, Selenium, Puppeteer, Playwright 및 은밀 자동화 프레임워크를 탐지합니다.
클라이언트 측 봇 및 자동화 탐지 라이브러리로, 가중치 기반 점수 산정, 행동 분석, 브라우저 지문 인식, 설정 가능한 임계값을 제공합니다. 헤드리스 브라우저, Selenium, Puppeteer, Playwright, CDP 기반 도구, 스텔스 자동화 프레임워크를 탐지합니다.
v2.1.0 — 탐지 방지 허니팟, GPU 안정적 캔버스 지문 인식, 향상된 행동 분석, 지연 초기화, 서버 측 변조 탐지, 요청 지문 바인딩, 속도 제한.
human, suspicious, bot 및 해당 마찰 조치 (monitor, challenge, block)Browser Your Server
┌──────────────────────────┐ ┌──────────────────────┐
│ Collector (singleton) │ POST │ Express Middleware │
│ ├─ 28 detection modules│ signals │ ├─ NonceManager │
│ ├─ BehaviorTracker │ + nonce │ ├─ RateLimiter │
│ ├─ HoneypotTraps │───────────▶│ ├─ TamperDetector │
│ ├─ Stack trace traps │ │ ├─ computeVerdict() │
│ └─ IframeContext │ │ └─ Proof-of-Work │
│ │ verdict │ │
│ ↓ collect() → │ + proof │ Returns: │
│ DetectionResult[] │◀───────────│ { verdict, score, │
└──────────────────────────┘ │ confidence, proof, │
│ tamperScore } │
└──────────────────────┘
│
▼
Session-gated endpoint
(login, checkout, etc.)
validates proof before
granting access
핵심 원칙: 브라우저는 원시 DetectionResult[] 신호만 수집합니다. 서버는 비밀 가중치 테이블을 사용하여 최종 판정을 계산합니다. 클라이언트가 계산한 판정은 절대 신뢰하지 않습니다.
npm install
npm run build
dist/에 출력:
botdetect.min.js (폴리필 포함, ~151 KB)botdetect-clean.min.js (최신 브라우저 전용, ~74 KB)<script src="/path/to/botdetect.min.js"></script>
<script>
BotDetect.collector.enableTraps();
BotDetect.collector.enableBehavioralTracking();
BotDetect.collector.enableHoneypots();
</script>
cd server
npm install express cors express-session
node example-integration.js
async function onLogin() {
const { nonce } = await (await fetch('/api/botdetect/nonce')).json();
BotDetect.collector.setNonce(nonce);
const signals = await BotDetect.collector.collect();
const resp = await fetch('/api/botdetect/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ signals, nonce })
});
const { verdict, score, proof, friction } = await resp.json();
document.getElementById('botdetect-proof').value = proof;
document.getElementById('login-form').submit();
}
app.post('/api/login', (req, res) => {
const bd = req.session.botdetect;
if (!bd) return res.status(403).json({ error: 'no_verification' });
if (bd.verdict === 'bot') return res.status(403).json({ error: 'access_denied' });
if (bd.verdict === 'suspicious') return challengeCaptcha(req, res);
res.json({ success: true });
});
import Collector from './collector/Collector';
// 또는 전역: BotDetect.collector
| 메서드 | 반환값 | 설명 |
|---|---|---|
getInstance(config?) | Collector | 싱글턴 접근자 |
configure(config) | void | 런타임 설정 업데이트 |
getConfig() | CollectorConfig | 현재 설정 |
init() | void | 지연 초기화: 트랩, 추적, 허니팟 |
enableTraps() | void | DOM API에 스택 트레이스 트랩 설치 |
enableBehavioralTracking() | void | 마우스/키보드/스크롤 모니터링 시작 |
enableHoneypots(container?) | void | 허니팟 필드 설치 |
collect() | Promise<DetectionResult[]> | 모든 탐지 실행 |
setNonce(nonce) | void | 서버 발급 논스 저장 |
getSessionId() | string | 고유 세션 식별자 |
getFingerprint() | string | 세션 지문 해시 |
resetBehavioralData() | void | 행동 데이터 초기화 |
destroy() | void | 모든 리스너와 DOM 요소 정리 |
import Detector from './detector/Detector';
| 메서드 | 반환값 | 설명 |
|---|---|---|
getInstance(config?) | Detector | 싱글턴 접근자 |
configure(config) | void | 설정 업데이트 |
analyze(results) | DetectionVerdict | 점수 + 분류 (로컬 디버그 전용) |
handleError(error) | DetectionVerdict | 실패 시 폴백 판정 |
경고:
analyze()는 브라우저에서 전적으로 실행됩니다. 프로덕션 결정에 절대 사용하지 마십시오.
interface DetectionResult {
name: string; // 모듈 이름
score: number; // 0.0 – 1.0
weight: number; // 1 – 10 (중요도)
detail?: string; // 사람이 읽을 수 있는 설명
}
interface DetectionVerdict {
verdict: 'bot' | 'suspicious' | 'human';
score: number; // 0.0 – 1.0
confidence: number; // 0.0 – 1.0
signals: DetectionResult[];
threshold: number;
friction: 'monitor' | 'challenge' | 'block';
}
interface CollectorConfig {
detectionTimeoutMs: number; // 모듈당 타임아웃 (기본값: 3000)
enableTraps: boolean;
enableBehavioralTracking: boolean;
enableHoneypots: boolean;
thresholds: { strict: number; balanced: number; relaxed: number };
}
const { createBotDetectEndpoint } = require('./server');
const { router, generateProofOfWork, cleanup } = createBotDetectEndpoint({
secretSalt: process.env.BOTDETECT_SALT,
scoring: {
threshold: 'balanced', // 'strict' | 'balanced' | 'relaxed' | number
minSignals: 2,
signalBoostThreshold: 0.8,
frictionThresholds: { monitor: 0.2, challenge: 0.5, block: 0.8 }
},
nonce: { ttl: 300000 }, // 5분 논스 만료
noScript: { timeout: 10000 }, // 10초 스크립트 미지원 윈도우
rateLimit: { maxRequests: 10, windowMs: 60000 },
noScriptPaths: ['/api/login', '/api/checkout', '/api/register']
});
app.use('/api', router);
| 엔드포인트 | 메서드 | 목적 |
|---|---|---|
/api/botdetect/nonce | GET | 일회용 논스 발급 |
/api/botdetect/verify | POST | 신호 제출, 서명된 판정 수신 |
/api/botdetect/midcycle | POST | 세션 중 재검증 |
{
"verdict": "human",
"score": 0.125,
"confidence": 0.85,
"tamperScore": 0,
"friction": "monitor",
"threshold": 0.5,
"proof": "a1b2c3d4e5f6..."
}
const { computeVerdict, RateLimiter, NonceManager } = require('./scoring');
const verdict = computeVerdict(signals, {
threshold: 'balanced',
minSignals: 2,
signalBoostThreshold: 0.8,
frictionThresholds: { monitor: 0.2, challenge: 0.5, block: 0.8 }
});
// verdict.tamperScore > 0 이면 신호 변조 감지