Skip to content

thanos-studio/kanadi

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Kanadi - Multi-Layer CAPTCHA Framework

Kanadi Logo

여러 검증 레이어를 지원하는 유연하고 확장 가능한 CAPTCHA 프레임워크입니다. 기존 캡차와 달리, Kanadi는 번들에 있는 모든 챌린지를 완료해야 검증이 완료됩니다.

English | 한국어


한국어

주요 기능

  • 멀티 레이어 검증: 여러 validator를 번들로 묶어서 체인 형태로 검증
  • 커스텀 Validator: @Validator 데코레이터로 직접 validator 제작 가능
  • 내장 Validator: Proof of Work (PoW), 브라우저 검증 등 기본 제공
  • 강력한 Ban 시스템: IP/CIDR/ASN/Device/User 단위 차단, Redis 캐싱
  • NestJS 통합: NestJS 애플리케이션과 완벽하게 통합
  • 데이터베이스 지원: Redis와 PostgreSQL을 이용한 세션 관리
  • 유연한 아키텍처: 모듈화된 설계로 쉬운 커스터마이징

설치

npm install kanadi
# 또는
bun add kanadi

빠른 시작

1. Gateway 생성

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에 등록

import { Module } from '@nestjs/common';
import { CaptchaGateway } from './kanadi.gateway';

@Module({
    imports: [CaptchaGateway],  // 그냥 직접 import하면 됩니다!
})
export class AppModule {}

주의: @KanadiGateway 데코레이터가 자동으로 NestJS Module로 변환하므로, forRoot()나 다른 설정 없이 바로 imports에 추가할 수 있습니다.

3. 커스텀 Validator 만들기

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

새로운 챌린지 세션을 생성합니다.

응답:

{
    "status": "Challenge created successfully",
    "sessionId": "session-id",
    "challenge": {
        "id": "challenge-id"
    },
    "timeout": 10000
}

POST /{namespace}/siteverify

챌린지 응답을 검증합니다.

요청 본문:

{
    "sessionId": "session-id",
    "challengeId": "challenge-id",
    "response": {}
}

응답:

{
    "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입니다.

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 캐싱: 밀리초 단위 조회 성능
  • 자동 만료: 임시/영구 차단 지원

빠른 시작

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 도구를 제공합니다:

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 시스템 가이드를 참고하세요.

데이터베이스 스키마

프레임워크는 Redis(빠른 인메모리 캐싱)와 PostgreSQL(영구 저장소)을 함께 사용합니다.

Redis 모델

  • KanadiContext
  • KanadiBundleSession
  • KanadiValidatorSession
  • KanadiUser
  • KanadiDevice
  • KanadiHistory

PostgreSQL 테이블

  • Redis 모델과 동일하며, 적절한 관계 설정 포함

데이터는 주기적으로 Redis에서 PostgreSQL로 동기화됩니다.

문서

자세한 사용법은 한국어 문서를 참고하세요:

예제

완전한 예제는 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

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

About

Multi-Layer CAPTCHA Framework

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published