@kanadi/core
Version:
Multi-Layer CAPTCHA Framework with customizable validators and challenge bundles
363 lines (270 loc) • 9.46 kB
Markdown
# Kanadi - Multi-Layer CAPTCHA Framework
<div align="center">
<img src="images/kanadi.webp" alt="Kanadi Logo" width="400" />
</div>
<br />
여러 검증 레이어를 지원하는 유연하고 확장 가능한 CAPTCHA 프레임워크입니다. 기존 캡차와 달리, Kanadi는 번들에 있는 모든 챌린지를 완료해야 검증이 완료됩니다.
> [English](#english) | [한국어](#한국어)
---
## 한국어
### 주요 기능
- **멀티 레이어 검증**: 여러 validator를 번들로 묶어서 체인 형태로 검증
- **커스텀 Validator**: `@Validator` 데코레이터로 직접 validator 제작 가능
- **내장 Validator**: Proof of Work (PoW), 브라우저 검증 등 기본 제공
- **강력한 Ban 시스템**: IP/CIDR/ASN/Device/User 단위 차단, Redis 캐싱
- **NestJS 통합**: NestJS 애플리케이션과 완벽하게 통합
- **데이터베이스 지원**: Redis와 PostgreSQL을 이용한 세션 관리
- **유연한 아키텍처**: 모듈화된 설계로 쉬운 커스터마이징
### 설치
```bash
npm install kanadi
# 또는
bun add kanadi
```
### 빠른 시작
#### 1. Gateway 생성
```typescript
import { KanadiGateway, KanadiClient, KanadiContext } from 'kanadi/gateway';
import { PSQLDatabaseConfig, RedisDatabaseConfig } from 'kanadi/database';
import { PowV2Validator } from 'kanadi/validators';
@KanadiGateway({
namespace: "captcha",
config: [
PSQLDatabaseConfig.forRoot({
url: "postgres://user:password@localhost:5432/captcha"
}),
RedisDatabaseConfig.forRoot({
host: "localhost",
password: "your-password",
port: 6379
})
],
validators: [
PowV2Validator
]
})
export class CaptchaGateway {
constructor(private readonly client: KanadiClient) {}
async handleOnChallengeCreated(context: KanadiContext) {
// 챌린지 번들 생성
const bundle = await context.createBundle('my-bundle-id');
// 번들에 middleware 추가
await bundle.add('pow_v2', {
difficulty: 5,
data: 'challenge-data'
});
// 번들 발행
await bundle.publish();
// 챌린지 발급
return await context.challenge({
bundleId: bundle,
timeout: 10000
});
}
async handleOnChallengeValidated(context: KanadiContext) {
return await context.validate();
}
}
```
#### 2. AppModule에 등록
```typescript
import { Module } from '@nestjs/common';
import { CaptchaGateway } from './kanadi.gateway';
@Module({
imports: [CaptchaGateway], // 그냥 직접 import하면 됩니다!
})
export class AppModule {}
```
> **주의**: `@KanadiGateway` 데코레이터가 자동으로 NestJS Module로 변환하므로, `forRoot()`나 다른 설정 없이 바로 imports에 추가할 수 있습니다.
#### 3. 커스텀 Validator 만들기
```typescript
import { Validator, IChallengeValidator, ChallengeContext, ChallengeStep, StepValidationResult, ChallengeResult } from 'kanadi/middleware';
import { Injectable } from '@nestjs/common';
@Injectable()
@Validator({
id: 'my_validator',
name: '내 커스텀 Validator',
priority: 5,
required: true,
category: 'custom',
description: '커스텀 검증 로직'
})
export class MyValidator implements IChallengeValidator {
generateChallenge(context: ChallengeContext): ChallengeStep {
return {
solveId: 'unique-solve-id',
validatorId: 'my_validator',
validatorName: '내 커스텀 Validator',
data: {
// 클라이언트에게 전달할 챌린지 데이터
},
timeout: 30
};
}
async validate(
context: ChallengeContext,
solveId: string,
submittedData: any
): Promise<StepValidationResult> {
// 검증 로직
return {
solveId,
validatorId: 'my_validator',
validatorName: '내 커스텀 Validator',
result: ChallengeResult.PASS,
score: 100,
confidence: 0.95,
processingTime: 10,
evidence: {},
timestamp: new Date()
};
}
canExecute(context: ChallengeContext): boolean {
return true;
}
calculateDifficulty(context: ChallengeContext): number {
return 5;
}
}
```
### API 엔드포인트
프레임워크가 자동으로 다음 엔드포인트를 생성합니다:
#### POST `/{namespace}/challenge`
새로운 챌린지 세션을 생성합니다.
**응답:**
```json
{
"status": "Challenge created successfully",
"sessionId": "session-id",
"challenge": {
"id": "challenge-id"
},
"timeout": 10000
}
```
#### POST `/{namespace}/siteverify`
챌린지 응답을 검증합니다.
**요청 본문:**
```json
{
"sessionId": "session-id",
"challengeId": "challenge-id",
"response": {}
}
```
**응답:**
```json
{
"status": "success"
}
```
### 아키텍처
#### 핵심 컴포넌트
- **kanadi/validator**: Validator 데코레이터와 인터페이스
- **kanadi/gateway**: Gateway 데코레이터와 클라이언트 관리
- **kanadi/database**: 데이터베이스 설정 (Redis, PostgreSQL)
- **kanadi/models**: Redis OM과 Prisma를 위한 데이터 모델
- **kanadi/validators**: 내장 validator들
#### 데이터 흐름
1. 클라이언트가 챌린지 요청
2. Gateway가 지정된 validator들로 번들 생성
3. 각 validator가 챌린지 생성
4. 클라이언트가 모든 챌린지 해결
5. Gateway가 모든 응답 검증
6. 모든 validator를 통과하면 캡차 완료
### 내장 Validators
#### PowV2Validator
계산 작업을 요구하는 Proof of Work validator입니다.
```typescript
await bundle.add('pow_v2', {
difficulty: 5, // 0-10, 높을수록 어려움
data: 'challenge-data'
});
```
### Ban 시스템
강력한 차단 시스템으로 악의적인 요청을 효과적으로 차단할 수 있습니다.
#### 주요 기능
- **IP/CIDR 차단**: 단일 IP 또는 IP 대역 차단 (`192.168.1.0/24`)
- **ASN 차단**: 전체 네트워크 차단 (`AS54115`)
- **Device/User 차단**: 디바이스 및 사용자 단위 차단
- **Session 차단**: 세션과 연관된 모든 엔티티 차단
- **Redis 캐싱**: 밀리초 단위 조회 성능
- **자동 만료**: 임시/영구 차단 지원
#### 빠른 시작
```typescript
import { Ban } from 'kanadi/ban';
await Ban.IP('192.168.1.100', {
reason: 'Spam attack',
durationMinutes: 60
});
await Ban.IP('192.168.1.0/24', {
reason: 'Spam network'
});
await Ban.ASN('AS54115', {
reason: 'Datacenter abuse',
durationMinutes: 1440
});
const result = await Ban.Check('ip', '192.168.1.100');
if (result.banned) {
console.log('IP is banned:', result.database?.reason);
}
await Ban.Remove('ip', '192.168.1.100');
const bans = await Ban.List(20);
const stats = await Ban.Stats();
```
#### CLI 도구
Ban 시스템을 쉽게 관리할 수 있는 CLI 도구를 제공합니다:
```bash
bun scripts/ban-test.ts ban-ip 192.168.1.0/24 "Spam network" 60
bun scripts/ban-test.ts ban-asn AS54115 "Datacenter abuse"
bun scripts/ban-test.ts check ip 192.168.1.100
bun scripts/ban-test.ts list
bun scripts/ban-test.ts stats
```
자세한 내용은 [Ban 시스템 가이드](./docs/ko/ban-system.md)를 참고하세요.
### 데이터베이스 스키마
프레임워크는 Redis(빠른 인메모리 캐싱)와 PostgreSQL(영구 저장소)을 함께 사용합니다.
#### Redis 모델
- KanadiContext
- KanadiBundleSession
- KanadiValidatorSession
- KanadiUser
- KanadiDevice
- KanadiHistory
#### PostgreSQL 테이블
- Redis 모델과 동일하며, 적절한 관계 설정 포함
데이터는 주기적으로 Redis에서 PostgreSQL로 동기화됩니다.
### 문서
자세한 사용법은 한국어 문서를 참고하세요:
- **[시작하기](./docs/ko/tutorial.md)**: 설치 및 기본 설정
- **[커스텀 Validator 만들기](./docs/ko/creating-validators.md)**: Validator 제작 가이드
- **[Ban 시스템](./docs/ko/ban-system.md)**: 차단 시스템 완벽 가이드
### 예제
완전한 예제는 `examples/` 디렉토리를 참고하세요:
- **kanadi.gateway.ts**: 전체 gateway 구현
- **validators/browser.validator.ts**: 커스텀 브라우저 검증 예제
- **scripts/ban-test.ts**: Ban 시스템 CLI 도구
- **scripts/ban-cron.ts**: 자동 Ban 정리 스크립트
---
## English
A flexible and extensible CAPTCHA framework that supports multiple validation layers. Unlike traditional CAPTCHAs, Kanadi requires completing all challenges in a bundle before verification is complete.
### Features
- **Multi-Layer Validation**: Chain multiple validators together in a bundle
- **Custom Validators**: Create your own validators with the `@Validator` decorator
- **Built-in Validators**: Includes Proof of Work (PoW) and browser validation
- **NestJS Integration**: Seamlessly integrates with NestJS applications
- **Database Support**: Redis and PostgreSQL support for session management
- **Flexible Architecture**: Modular design allows for easy customization
### Installation
```bash
npm install kanadi
# or
bun add kanadi
```
### Quick Start
See the Korean documentation above for detailed examples.
### Examples
See the `examples/` directory for complete working examples.
---
## License
MIT