Initial commit: Add runbooks collection
- anvil-load-test-report.md - claude_communication_flow.md - incus-crowdsec-architecture.md - incus-meilisearch-manual.md - kitty-setup-guide.md - OpenAppSec_WAF_Operations_Guide.md - openappsec-setup-20250817.md - xray-proxy-guide.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
305
OpenAppSec_WAF_Operations_Guide.md
Normal file
305
OpenAppSec_WAF_Operations_Guide.md
Normal file
@@ -0,0 +1,305 @@
|
|||||||
|
# OpenAppSec WAF 운영 가이드
|
||||||
|
|
||||||
|
## 📋 시스템 개요
|
||||||
|
|
||||||
|
**구축 환경**: incus 컨테이너 기반
|
||||||
|
**구성**: Agent (보안 엔진) + OCI (프록시)
|
||||||
|
**IP 주소**:
|
||||||
|
- Agent: 10.90.135.243
|
||||||
|
- OCI: 10.90.135.233
|
||||||
|
|
||||||
|
**메모리 사용량**: Agent 184MB + OCI 58MB = 242MB
|
||||||
|
**성능**: 290+ RPS, 15-25ms 응답시간
|
||||||
|
|
||||||
|
## 🔧 핵심 설정 파일 위치
|
||||||
|
|
||||||
|
### Agent 컨테이너 (openappsec-agent)
|
||||||
|
```bash
|
||||||
|
# 정책 파일들
|
||||||
|
/etc/cp/conf/production_policy.yaml # 운영 정책 (현재 적용)
|
||||||
|
/etc/cp/conf/local_policy_learning.yaml # Learning 모드
|
||||||
|
/etc/cp/conf/local_policy_high_confidence.yaml # High Confidence
|
||||||
|
/etc/cp/conf/local_policy_with_exceptions.yaml # Exception 규칙 포함
|
||||||
|
|
||||||
|
# 제어 스크립트
|
||||||
|
/etc/cp/scripts/open-appsec-ctl.sh # 메인 제어 스크립트
|
||||||
|
/usr/local/bin/waf-monitor.sh # 모니터링 스크립트
|
||||||
|
/usr/local/bin/waf-emergency.sh # 비상 복구 스크립트
|
||||||
|
|
||||||
|
# 로그 파일
|
||||||
|
/var/log/nano_agent/cp-nano-http-transaction-handler.log*
|
||||||
|
/var/log/waf-monitor.log # 모니터링 로그
|
||||||
|
/var/log/waf-emergency.log # 비상 작업 로그
|
||||||
|
```
|
||||||
|
|
||||||
|
### OCI 컨테이너 (openappsec-oci)
|
||||||
|
```bash
|
||||||
|
# nginx 설정
|
||||||
|
/etc/nginx/conf.d/production.conf # 운영 환경 설정
|
||||||
|
/etc/nginx/conf.d/default.conf # 기본 설정 (백업)
|
||||||
|
|
||||||
|
# 로그 파일
|
||||||
|
/var/log/nginx/access.log
|
||||||
|
/var/log/nginx/error.log
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 일상 운영 명령어
|
||||||
|
|
||||||
|
### 상태 확인
|
||||||
|
```bash
|
||||||
|
# WAF 전체 상태 확인
|
||||||
|
incus exec openappsec-agent -- /etc/cp/scripts/open-appsec-ctl.sh --status
|
||||||
|
|
||||||
|
# 확장 상태 정보
|
||||||
|
incus exec openappsec-agent -- /etc/cp/scripts/open-appsec-ctl.sh --status --extended
|
||||||
|
|
||||||
|
# 현재 적용 정책 확인
|
||||||
|
incus exec openappsec-agent -- /etc/cp/scripts/open-appsec-ctl.sh --view-policy
|
||||||
|
|
||||||
|
# 컨테이너 리소스 사용량
|
||||||
|
incus info openappsec-agent | grep "Memory usage"
|
||||||
|
incus info openappsec-oci | grep "Memory usage"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 정책 관리
|
||||||
|
```bash
|
||||||
|
# 정책 변경 (Learning 모드)
|
||||||
|
incus exec openappsec-agent -- /etc/cp/scripts/open-appsec-ctl.sh --apply-policy /etc/cp/conf/local_policy_learning.yaml
|
||||||
|
|
||||||
|
# 정책 변경 (High Confidence)
|
||||||
|
incus exec openappsec-agent -- /etc/cp/scripts/open-appsec-ctl.sh --apply-policy /etc/cp/conf/local_policy_high_confidence.yaml
|
||||||
|
|
||||||
|
# 정책 변경 (운영 모드)
|
||||||
|
incus exec openappsec-agent -- /etc/cp/scripts/open-appsec-ctl.sh --apply-policy /etc/cp/conf/production_policy.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
### 로그 모니터링
|
||||||
|
```bash
|
||||||
|
# 실시간 보안 이벤트 확인
|
||||||
|
incus exec openappsec-agent -- tail -f /var/log/nano_agent/cp-nano-http-transaction-handler.log1
|
||||||
|
|
||||||
|
# 최근 차단/탐지 이벤트 분석
|
||||||
|
incus exec openappsec-agent -- grep "Web Request" /var/log/nano_agent/*.log* | tail -10 | jq '.eventData'
|
||||||
|
|
||||||
|
# 모니터링 로그 확인
|
||||||
|
incus exec openappsec-agent -- tail -20 /var/log/waf-monitor.log
|
||||||
|
|
||||||
|
# nginx 접근 로그
|
||||||
|
incus exec openappsec-oci -- tail -f /var/log/nginx/access.log
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🆘 비상 대응 절차
|
||||||
|
|
||||||
|
### 긴급 상황별 대응
|
||||||
|
```bash
|
||||||
|
# 1. 오탐으로 정상 사용자 차단 시 (즉시 실행)
|
||||||
|
incus exec openappsec-agent -- /usr/local/bin/waf-emergency.sh bypass
|
||||||
|
|
||||||
|
# 2. WAF 서비스 문제 시
|
||||||
|
incus exec openappsec-agent -- /usr/local/bin/waf-emergency.sh restart
|
||||||
|
|
||||||
|
# 3. 심각한 서비스 장애 시
|
||||||
|
incus exec openappsec-agent -- /usr/local/bin/waf-emergency.sh disable
|
||||||
|
|
||||||
|
# 4. 정상 상태로 복구
|
||||||
|
incus exec openappsec-agent -- /usr/local/bin/waf-emergency.sh restore
|
||||||
|
```
|
||||||
|
|
||||||
|
### 롤백 절차
|
||||||
|
1. **백업 정책 복원**: 이전 정책 파일로 복구
|
||||||
|
2. **서비스 재시작**: WAF 서비스 재시작
|
||||||
|
3. **상태 확인**: 정상 동작 검증
|
||||||
|
4. **모니터링 강화**: 24시간 집중 관찰
|
||||||
|
|
||||||
|
## 📊 성능 모니터링
|
||||||
|
|
||||||
|
### 일일 체크리스트
|
||||||
|
- [ ] WAF 서비스 상태 정상
|
||||||
|
- [ ] 메모리 사용량 < 300MB
|
||||||
|
- [ ] 응답 시간 < 50ms
|
||||||
|
- [ ] 오탐 이벤트 < 5건/일
|
||||||
|
|
||||||
|
### 성능 측정 명령어
|
||||||
|
```bash
|
||||||
|
# 응답 시간 테스트
|
||||||
|
for i in {1..5}; do curl -w "응답시간: %{time_total}s\n" -s -o /dev/null "http://10.90.135.233/health"; done
|
||||||
|
|
||||||
|
# 동시 연결 처리 테스트
|
||||||
|
time (seq 1 50 | xargs -n1 -P10 -I{} curl -s -o /dev/null "http://10.90.135.233/health" 2>/dev/null)
|
||||||
|
|
||||||
|
# 메모리 사용량 상세 확인
|
||||||
|
incus exec openappsec-agent -- ps -eo pid,rss,vsz,comm,args | grep cp-nano
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔄 정책 전환 가이드
|
||||||
|
|
||||||
|
### Phase 1: Learning Mode (1-2주)
|
||||||
|
**목적**: 정상 트래픽 패턴 학습
|
||||||
|
**설정**: `detect-learn` 모드, 모든 요청 로깅
|
||||||
|
**모니터링**: 일일 로그 분석, 학습 진행도 확인
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Learning 모드 적용
|
||||||
|
incus exec openappsec-agent -- /etc/cp/scripts/open-appsec-ctl.sh --apply-policy /etc/cp/conf/local_policy_learning.yaml
|
||||||
|
|
||||||
|
# 학습 데이터 확인
|
||||||
|
incus exec openappsec-agent -- wc -l /var/log/nano_agent/*handler*.log*
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 2: High Confidence (테스트)
|
||||||
|
**목적**: 고신뢰도 탐지만 차단, 오탐 최소화
|
||||||
|
**기준**: 일일 요청 1000+, 안정적 패턴 확립
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# High Confidence 모드 적용
|
||||||
|
incus exec openappsec-agent -- /etc/cp/scripts/open-appsec-ctl.sh --apply-policy /etc/cp/conf/local_policy_high_confidence.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
**전환 조건**:
|
||||||
|
- ✅ 7-14일간 안정적 학습 데이터 축적
|
||||||
|
- ✅ 일일 오탐률 < 1%
|
||||||
|
- ✅ 모든 핵심 기능 정상 접근 확인
|
||||||
|
- ✅ 사용자 컴플레인 없음
|
||||||
|
|
||||||
|
### Phase 3: Production (운영)
|
||||||
|
**목적**: 전체 보안 기능 활성화
|
||||||
|
**설정**: `prevent` 모드, Exception 규칙 적용
|
||||||
|
|
||||||
|
## 🔍 트러블슈팅
|
||||||
|
|
||||||
|
### 일반적인 문제
|
||||||
|
|
||||||
|
**1. WAF 서비스 응답 없음**
|
||||||
|
```bash
|
||||||
|
# 프로세스 확인
|
||||||
|
incus exec openappsec-agent -- ps aux | grep cp-nano
|
||||||
|
|
||||||
|
# 포트 확인
|
||||||
|
incus exec openappsec-agent -- netstat -tlnp | grep 1200
|
||||||
|
|
||||||
|
# 재시작
|
||||||
|
incus exec openappsec-agent -- /usr/local/bin/waf-emergency.sh restart
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. 높은 오탐률**
|
||||||
|
```bash
|
||||||
|
# 최근 차단 이벤트 분석
|
||||||
|
incus exec openappsec-agent -- grep "Prevent" /var/log/nano_agent/*.log* | tail -20
|
||||||
|
|
||||||
|
# Learning 모드로 임시 전환
|
||||||
|
incus exec openappsec-agent -- /usr/local/bin/waf-emergency.sh bypass
|
||||||
|
|
||||||
|
# Confidence 임계값 조정 (high로 변경)
|
||||||
|
incus exec openappsec-agent -- /etc/cp/scripts/open-appsec-ctl.sh --apply-policy /etc/cp/conf/local_policy_high_confidence.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
**3. 성능 저하**
|
||||||
|
```bash
|
||||||
|
# 메모리 사용량 확인
|
||||||
|
incus exec openappsec-agent -- free -h
|
||||||
|
incus exec openappsec-agent -- ps aux --sort=-%mem | head -10
|
||||||
|
|
||||||
|
# 로그 파일 크기 확인
|
||||||
|
incus exec openappsec-agent -- du -sh /var/log/nano_agent/
|
||||||
|
|
||||||
|
# 오래된 로그 정리
|
||||||
|
incus exec openappsec-agent -- find /var/log/nano_agent -name "*.log*" -mtime +3 -delete
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📈 보안 이벤트 분석
|
||||||
|
|
||||||
|
### 이벤트 타입별 분석
|
||||||
|
```bash
|
||||||
|
# XSS 공격 탐지 현황
|
||||||
|
incus exec openappsec-agent -- grep "Cross Site Scripting" /var/log/nano_agent/*.log* | wc -l
|
||||||
|
|
||||||
|
# SQL Injection 탐지 현황
|
||||||
|
incus exec openappsec-agent -- grep "SQL Injection" /var/log/nano_agent/*.log* | wc -l
|
||||||
|
|
||||||
|
# 신뢰도별 이벤트 분석
|
||||||
|
incus exec openappsec-agent -- grep "eventConfidence" /var/log/nano_agent/*.log* | jq -r '.eventData.eventConfidence' | sort | uniq -c
|
||||||
|
```
|
||||||
|
|
||||||
|
### 공격자 IP 분석
|
||||||
|
```bash
|
||||||
|
# 최다 차단 IP 확인
|
||||||
|
incus exec openappsec-agent -- grep "sourceIP" /var/log/nano_agent/*.log* | jq -r '.eventData.sourceIP' | sort | uniq -c | sort -nr | head -10
|
||||||
|
|
||||||
|
# 특정 IP 차단 이력
|
||||||
|
incus exec openappsec-agent -- grep "1.2.3.4" /var/log/nano_agent/*.log* | jq '.eventData'
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔐 보안 정책 튜닝
|
||||||
|
|
||||||
|
### Exception 규칙 추가
|
||||||
|
```yaml
|
||||||
|
# /etc/cp/conf/local_policy_with_exceptions.yaml 수정 예시
|
||||||
|
exceptions:
|
||||||
|
- rule-id: "admin-panel"
|
||||||
|
uri-prefix: "/admin"
|
||||||
|
source-ip: ["10.90.135.0/24", "192.168.1.0/24"]
|
||||||
|
- rule-id: "api-endpoints"
|
||||||
|
uri-prefix: "/api"
|
||||||
|
specific-protections: ["csrf-protection"]
|
||||||
|
- rule-id: "file-upload"
|
||||||
|
uri-prefix: "/upload"
|
||||||
|
specific-protections: ["open-redirect"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Confidence 임계값 조정
|
||||||
|
- `low`: 모든 의심 활동 탐지 (높은 오탐)
|
||||||
|
- `medium`: 균형잡힌 탐지 (권장)
|
||||||
|
- `high`: 고신뢰도만 탐지 (낮은 오탐)
|
||||||
|
- `critical`: 매우 확실한 공격만 탐지
|
||||||
|
|
||||||
|
## 📅 정기 점검 일정
|
||||||
|
|
||||||
|
### 일일 (평일 오전 9시)
|
||||||
|
- WAF 서비스 상태 확인
|
||||||
|
- 전날 보안 이벤트 검토
|
||||||
|
- 메모리/CPU 사용량 확인
|
||||||
|
|
||||||
|
### 주간 (매주 월요일)
|
||||||
|
- 오탐 패턴 분석
|
||||||
|
- 성능 지표 리뷰
|
||||||
|
- 로그 용량 관리
|
||||||
|
|
||||||
|
### 월간 (매월 첫째 주)
|
||||||
|
- 전체 보안 정책 검토
|
||||||
|
- Exception 규칙 업데이트
|
||||||
|
- 백업 및 복구 테스트
|
||||||
|
- 보안 이벤트 통계 리포트
|
||||||
|
|
||||||
|
## 📞 에스컬레이션 연락처
|
||||||
|
|
||||||
|
**Level 1**: 일반 운영 이슈
|
||||||
|
**Level 2**: 보안 이벤트 급증
|
||||||
|
**Level 3**: 서비스 전면 장애
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**문서 최종 업데이트**: 2025-08-17
|
||||||
|
**다음 검토 예정일**: 2025-09-17
|
||||||
|
|
||||||
|
## 🔖 빠른 참조
|
||||||
|
|
||||||
|
### 자주 사용하는 명령어
|
||||||
|
```bash
|
||||||
|
# 상태 확인
|
||||||
|
incus exec openappsec-agent -- /etc/cp/scripts/open-appsec-ctl.sh --status
|
||||||
|
|
||||||
|
# 비상 bypass
|
||||||
|
incus exec openappsec-agent -- /usr/local/bin/waf-emergency.sh bypass
|
||||||
|
|
||||||
|
# 로그 확인
|
||||||
|
incus exec openappsec-agent -- tail -f /var/log/nano_agent/cp-nano-http-transaction-handler.log1
|
||||||
|
|
||||||
|
# 성능 테스트
|
||||||
|
curl -w "응답시간: %{time_total}s\n" -s -o /dev/null "http://10.90.135.233/health"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 정책 파일 경로 요약
|
||||||
|
- Learning: `/etc/cp/conf/local_policy_learning.yaml`
|
||||||
|
- High Confidence: `/etc/cp/conf/local_policy_high_confidence.yaml`
|
||||||
|
- Production: `/etc/cp/conf/production_policy.yaml`
|
||||||
|
- With Exceptions: `/etc/cp/conf/local_policy_with_exceptions.yaml`
|
||||||
406
anvil-load-test-report.md
Normal file
406
anvil-load-test-report.md
Normal file
@@ -0,0 +1,406 @@
|
|||||||
|
# Anvil 부하테스트 및 성능 최적화 보고서
|
||||||
|
|
||||||
|
**작성일**: 2026-01-10
|
||||||
|
**환경**: Incus jp1 → k8s (k3s) → anvil namespace
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Part 1. 핵심 요약
|
||||||
|
|
||||||
|
## 1. 아키텍처
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────┐
|
||||||
|
│ k8s (k3s, max-pods=200) │
|
||||||
|
│ │
|
||||||
|
[Client] ──▶ Cloudflare ─┼─▶ Traefik (x3) │
|
||||||
|
(권장) │ │ │
|
||||||
|
│ ▼ │
|
||||||
|
│ Nginx (x2~15, HPA) │
|
||||||
|
│ │ │
|
||||||
|
│ ▼ │
|
||||||
|
│ PHP-FPM (x5~30, HPA) ─▶ Redis │
|
||||||
|
│ │ (Session) │
|
||||||
|
│ ▼ │
|
||||||
|
│ ProxySQL (Cache 256MB) │
|
||||||
|
│ │ │
|
||||||
|
└───────┼─────────────────────────────────┘
|
||||||
|
│
|
||||||
|
┌────────────┴────────────┐
|
||||||
|
▼ ▼
|
||||||
|
┌─────────────┐ ┌─────────────┐
|
||||||
|
│ MariaDB-1 │ │ MariaDB-2 │
|
||||||
|
│ (Primary) │──Repl───▶ │ (Replica) │
|
||||||
|
└─────────────┘ └─────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 최종 성능 결과
|
||||||
|
|
||||||
|
### 2.1 Gnuboard5 (실제 애플리케이션)
|
||||||
|
|
||||||
|
| 항목 | Origin Only | + Cloudflare (예상) |
|
||||||
|
|------|-------------|---------------------|
|
||||||
|
| **최대 RPS** | **505.9** | **2,000+** |
|
||||||
|
| 성공률 | 100% | 100% |
|
||||||
|
| 평균 응답 | 390ms | ~50ms (캐시 HIT) |
|
||||||
|
|
||||||
|
### 2.2 simple-db.php (단순 쿼리)
|
||||||
|
|
||||||
|
| 항목 | 값 |
|
||||||
|
|------|-----|
|
||||||
|
| **최대 RPS** | **3,466** |
|
||||||
|
| 성공률 | 100% |
|
||||||
|
| 평균 응답 | 56ms |
|
||||||
|
|
||||||
|
### 2.3 예상 동시 접속자
|
||||||
|
|
||||||
|
| 시나리오 | Gnuboard5 |
|
||||||
|
|----------|-----------|
|
||||||
|
| Origin Only | ~1,700명 |
|
||||||
|
| **Cloudflare 70% 캐시** | **~5,600명** |
|
||||||
|
| **Cloudflare 80% 캐시** | **~8,500명** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 최적화 적용 현황
|
||||||
|
|
||||||
|
| 영역 | 최적화 | 효과 | 상태 |
|
||||||
|
|------|--------|------|------|
|
||||||
|
| ProxySQL | Query Cache 256MB | DB 부하 99% 감소 | ✅ |
|
||||||
|
| ProxySQL | Read Replica 활용 | +21% RPS | ✅ |
|
||||||
|
| PHP | OPcache 256MB | PHP 컴파일 캐시 | ✅ |
|
||||||
|
| PHP | Redis 세션 | 세션 공유/속도 | ✅ |
|
||||||
|
| HPA | minReplicas 설정 | Cold Start 방지 | ✅ |
|
||||||
|
| MariaDB | Buffer Pool 512MB | 99.998% 히트율 | ✅ |
|
||||||
|
| **CDN** | **Cloudflare** | **+300% 예상** | ⏳ 권장 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 핵심 설정값
|
||||||
|
|
||||||
|
### 4.1 HPA 설정
|
||||||
|
|
||||||
|
| Deployment | Min | Max | CPU Target |
|
||||||
|
|------------|-----|-----|------------|
|
||||||
|
| nginx | 2 | 15 | 70% |
|
||||||
|
| php-fpm | 5 | 30 | 70% |
|
||||||
|
|
||||||
|
### 4.2 리소스 설정
|
||||||
|
|
||||||
|
| 구성요소 | 설정 | 값 |
|
||||||
|
|----------|------|-----|
|
||||||
|
| MariaDB | max_connections | 500 |
|
||||||
|
| ProxySQL | Query Cache | 256MB, TTL 5초 |
|
||||||
|
| ProxySQL | Read Replica | hostgroup 1 |
|
||||||
|
| PHP | OPcache | 256MB, 20K files |
|
||||||
|
| PHP | Session | Redis |
|
||||||
|
| k3s | max-pods | 200 |
|
||||||
|
|
||||||
|
### 4.3 업로드 제한
|
||||||
|
|
||||||
|
| 구성요소 | 값 |
|
||||||
|
|----------|-----|
|
||||||
|
| Nginx | 100MB |
|
||||||
|
| PHP | 100MB |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 운영 체크리스트
|
||||||
|
|
||||||
|
### 필수 확인 사항
|
||||||
|
|
||||||
|
- [ ] HPA minReplicas 설정 확인 (nginx: 2, php-fpm: 5)
|
||||||
|
- [ ] ProxySQL Read Replica 설정 확인 (hostgroup 1)
|
||||||
|
- [ ] ProxySQL PVC 마운트 확인 (설정 영구 저장)
|
||||||
|
- [ ] OPcache 활성화 확인
|
||||||
|
- [ ] Redis 세션 연결 확인
|
||||||
|
- [ ] Cloudflare 적용 (권장)
|
||||||
|
|
||||||
|
### 모니터링 명령어
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# k9s 실행
|
||||||
|
k9s
|
||||||
|
|
||||||
|
# HPA 상태
|
||||||
|
kubectl get hpa -n anvil
|
||||||
|
|
||||||
|
# Pod 리소스
|
||||||
|
kubectl top pods -n anvil
|
||||||
|
|
||||||
|
# ProxySQL 캐시 상태
|
||||||
|
kubectl exec -n anvil deploy/proxysql -- mysql -h127.0.0.1 -P6032 -uadmin -padmin \
|
||||||
|
-e "SELECT * FROM stats.stats_mysql_global WHERE Variable_Name LIKE '%Query_Cache%';"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 변경 이력
|
||||||
|
|
||||||
|
| 일시 | 변경 내용 | 효과 |
|
||||||
|
|------|----------|------|
|
||||||
|
| 2026-01-09 | MariaDB max_connections 151→500 | 연결 여유 확보 |
|
||||||
|
| 2026-01-09 | nginx/php-fpm CPU 2코어 | 처리량 증가 |
|
||||||
|
| 2026-01-09 | ProxySQL Query Cache 256MB | +17% RPS |
|
||||||
|
| 2026-01-09 | k3s max-pods 200 | Pod 확장성 |
|
||||||
|
| 2026-01-09 | OPcache 최적화 | PHP 성능 향상 |
|
||||||
|
| 2026-01-09 | HPA minReplicas 설정 | +6% RPS |
|
||||||
|
| 2026-01-09 | ProxySQL Read Replica | +21% RPS |
|
||||||
|
| 2026-01-09 | Real IP 설정 | 클라이언트 IP 추적 |
|
||||||
|
| 2026-01-09 | 파일 업로드 100MB | 대용량 파일 지원 |
|
||||||
|
| 2026-01-10 | 최종 문서 정리 | - |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Part 2. 상세 설정 (참고)
|
||||||
|
|
||||||
|
## A. ProxySQL 설정
|
||||||
|
|
||||||
|
### Query Cache 설정
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- ProxySQL Admin (포트 6032) 접속
|
||||||
|
SET mysql-query_cache_size_MB = 256;
|
||||||
|
LOAD MYSQL VARIABLES TO RUNTIME;
|
||||||
|
SAVE MYSQL VARIABLES TO DISK;
|
||||||
|
|
||||||
|
-- SELECT 쿼리 캐시 + Read Replica 라우팅
|
||||||
|
INSERT INTO mysql_query_rules
|
||||||
|
(rule_id, active, match_digest, cache_ttl, destination_hostgroup, apply)
|
||||||
|
VALUES
|
||||||
|
(100, 1, '^SELECT', 5000, 1, 1);
|
||||||
|
LOAD MYSQL QUERY RULES TO RUNTIME;
|
||||||
|
SAVE MYSQL QUERY RULES TO DISK;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Hostgroup 구성
|
||||||
|
|
||||||
|
| Hostgroup | 서버 | 용도 |
|
||||||
|
|-----------|------|------|
|
||||||
|
| 0 | Primary (10.253.101.133) | Write |
|
||||||
|
| 1 | Primary + Replica | Read (캐시 + 부하분산) |
|
||||||
|
|
||||||
|
### 캐시 동작 흐름
|
||||||
|
|
||||||
|
```
|
||||||
|
요청 ──▶ ProxySQL
|
||||||
|
│
|
||||||
|
├─ Cache HIT (99.5%) ──▶ 즉시 응답 (0.1ms)
|
||||||
|
│
|
||||||
|
└─ Cache MISS (0.5%) ──▶ MariaDB (Primary/Replica)
|
||||||
|
│
|
||||||
|
└──▶ 캐시 저장 ──▶ 응답
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## B. PHP 설정
|
||||||
|
|
||||||
|
### OPcache (opcache.ini)
|
||||||
|
|
||||||
|
```ini
|
||||||
|
opcache.enable=1
|
||||||
|
opcache.memory_consumption=256
|
||||||
|
opcache.max_accelerated_files=20000
|
||||||
|
opcache.validate_timestamps=0
|
||||||
|
opcache.revalidate_freq=0
|
||||||
|
opcache.fast_shutdown=1
|
||||||
|
opcache.interned_strings_buffer=16
|
||||||
|
```
|
||||||
|
|
||||||
|
### 세션 (session.ini)
|
||||||
|
|
||||||
|
```ini
|
||||||
|
session.save_handler = redis
|
||||||
|
session.save_path = "tcp://redis:6379"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 업로드 (upload.ini)
|
||||||
|
|
||||||
|
```ini
|
||||||
|
upload_max_filesize = 100M
|
||||||
|
post_max_size = 100M
|
||||||
|
max_file_uploads = 20
|
||||||
|
max_execution_time = 300
|
||||||
|
max_input_time = 300
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## C. Nginx 설정
|
||||||
|
|
||||||
|
### nginx.conf
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
worker_processes auto;
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
use epoll;
|
||||||
|
multi_accept on;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
sendfile on;
|
||||||
|
tcp_nopush on;
|
||||||
|
tcp_nodelay on;
|
||||||
|
keepalive_timeout 65;
|
||||||
|
|
||||||
|
# Real IP
|
||||||
|
set_real_ip_from 0.0.0.0/0;
|
||||||
|
real_ip_header X-Forwarded-For;
|
||||||
|
real_ip_recursive on;
|
||||||
|
|
||||||
|
# Gzip
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
gzip_types text/plain text/css application/json application/javascript;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### default.conf (주요 부분)
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
upstream php-upstream {
|
||||||
|
server php-fpm:9000;
|
||||||
|
keepalive 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
client_max_body_size 100m;
|
||||||
|
|
||||||
|
location ~ \.php$ {
|
||||||
|
fastcgi_pass php-upstream;
|
||||||
|
fastcgi_keep_conn on;
|
||||||
|
fastcgi_buffer_size 32k;
|
||||||
|
fastcgi_buffers 16 16k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## D. Traefik Real IP 설정
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: helm.cattle.io/v1
|
||||||
|
kind: HelmChartConfig
|
||||||
|
metadata:
|
||||||
|
name: traefik
|
||||||
|
namespace: kube-system
|
||||||
|
spec:
|
||||||
|
valuesContent: |-
|
||||||
|
additionalArguments:
|
||||||
|
- "--entryPoints.web.forwardedHeaders.insecure=true"
|
||||||
|
- "--entryPoints.websecure.forwardedHeaders.insecure=true"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## E. HPA 설정
|
||||||
|
|
||||||
|
### Cold Start 방지
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl patch hpa nginx-hpa -n anvil -p '{"spec":{"minReplicas":2}}'
|
||||||
|
kubectl patch hpa php-fpm-hpa -n anvil -p '{"spec":{"minReplicas":5}}'
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## F. k3s 설정
|
||||||
|
|
||||||
|
### max-pods 증가
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# /etc/rancher/k3s/config.yaml
|
||||||
|
kubelet-arg:
|
||||||
|
- "max-pods=200"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## G. MariaDB 상태 (참고)
|
||||||
|
|
||||||
|
| 지표 | 값 | 평가 |
|
||||||
|
|------|-----|------|
|
||||||
|
| Buffer Pool Size | 512MB | 적정 |
|
||||||
|
| Buffer Pool Hit Rate | 99.998% | 최상 |
|
||||||
|
| max_connections | 500 | 적정 |
|
||||||
|
| Slow Queries | 0 | 최상 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## H. Cloudflare 설정 가이드 (권장)
|
||||||
|
|
||||||
|
### Cache Rules 설정
|
||||||
|
|
||||||
|
**Rule 1: 정적 파일**
|
||||||
|
```
|
||||||
|
If: File extension = css, js, jpg, png, gif, ico, woff2
|
||||||
|
Then: Cache (Edge TTL: 1 month)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Rule 2: 게시판 페이지 (비로그인)**
|
||||||
|
```
|
||||||
|
If: URI contains "/gb5/" AND Cookie NOT contains "ck_mb_id"
|
||||||
|
Then: Cache (Edge TTL: 5 minutes)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Rule 3: 관리자/글쓰기 제외**
|
||||||
|
```
|
||||||
|
If: URI contains "/adm" OR "/bbs/write" OR Cookie contains "ck_mb_id"
|
||||||
|
Then: Bypass cache
|
||||||
|
```
|
||||||
|
|
||||||
|
### 예상 효과
|
||||||
|
|
||||||
|
| 캐시 히트율 | 유효 RPS |
|
||||||
|
|------------|----------|
|
||||||
|
| 50% | ~1,000 |
|
||||||
|
| 70% | ~1,700 |
|
||||||
|
| 80% | ~2,500 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## I. 성능 튜닝 히스토리
|
||||||
|
|
||||||
|
| 설정 | RPS | 성공률 | 비고 |
|
||||||
|
|------|-----|--------|------|
|
||||||
|
| 초기 상태 | ~150 | 93% | Cold Start |
|
||||||
|
| + CPU 2코어 | ~370 | 99% | - |
|
||||||
|
| + minReplicas | 419 | 99.98% | +6% |
|
||||||
|
| **+ Read Replica** | **505.9** | **100%** | **+21%** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## J. 부하 테스트 명령어
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Gnuboard5 테스트
|
||||||
|
hey -n 20000 -c 200 -t 20 -host "gnu.anvil.it.com" "http://10.253.103.124/gb5/"
|
||||||
|
|
||||||
|
# simple-db.php 테스트
|
||||||
|
hey -n 20000 -c 200 -t 20 -host "gnu.anvil.it.com" "http://10.253.103.124/simple-db.php"
|
||||||
|
|
||||||
|
# ProxySQL 캐시 히트율 확인
|
||||||
|
kubectl exec -n anvil deploy/proxysql -- mysql -h127.0.0.1 -P6032 -uadmin -padmin \
|
||||||
|
-e "SELECT * FROM stats.stats_mysql_global WHERE Variable_Name LIKE '%Query_Cache%';"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## K. k9s 단축키
|
||||||
|
|
||||||
|
| 키 | 기능 |
|
||||||
|
|----|------|
|
||||||
|
| `:ns` | 네임스페이스 선택 |
|
||||||
|
| `:pod` | Pod 목록 |
|
||||||
|
| `:hpa` | HPA 목록 |
|
||||||
|
| `l` | 로그 보기 |
|
||||||
|
| `s` | Shell 접속 |
|
||||||
|
| `d` | Describe |
|
||||||
|
| `/` | 필터링 |
|
||||||
61
claude_communication_flow.md
Normal file
61
claude_communication_flow.md
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
# Claude Code 통신 흐름 시각화
|
||||||
|
|
||||||
|
## 1. 기본 통신 구조
|
||||||
|
```
|
||||||
|
┌─────────┐ ┌─────────┐ ┌─────────┐
|
||||||
|
│ User │ ──1──> │ Claude │ ──2──> │ API │
|
||||||
|
│ You │ <──4── │ Code │ <──3── │ Server │
|
||||||
|
└─────────┘ └─────────┘ └─────────┘
|
||||||
|
|
||||||
|
1: 질문 전송 (1-10 KB)
|
||||||
|
2: API 요청
|
||||||
|
3: 응답 생성
|
||||||
|
4: 결과 표시 (1-100 KB)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. 통신 속도와 응답의 관계
|
||||||
|
```
|
||||||
|
빠른 네트워크 (100 Mbps+)
|
||||||
|
User ━━━━━━━━━━━━━━━━━━━━━━> Claude
|
||||||
|
<━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
전송: 0.1초 | 처리: 2초 | 수신: 0.1초
|
||||||
|
총 시간: ~2.2초
|
||||||
|
|
||||||
|
느린 네트워크 (1 Mbps)
|
||||||
|
User ────────────────────────> Claude
|
||||||
|
<────────────────────────
|
||||||
|
전송: 1초 | 처리: 2초 | 수신: 1초
|
||||||
|
총 시간: ~4초
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. 데이터 흐름 크기
|
||||||
|
```
|
||||||
|
┌────────────────────────────────────┐
|
||||||
|
│ 요청 타입별 데이터 크기 │
|
||||||
|
├────────────────────────────────────┤
|
||||||
|
│ 텍스트 질문 │ ▓░░░░░░░░░ │ 1-10 KB │
|
||||||
|
│ 코드 작업 │ ▓▓▓▓░░░░░░ │ 10-100 KB │
|
||||||
|
│ 파일 검색 │ ▓▓▓▓▓▓▓░░░ │ 100 KB-1 MB│
|
||||||
|
│ 이미지 처리 │ ▓▓▓▓▓▓▓▓▓▓ │ 1-10 MB │
|
||||||
|
└────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. 처리 시간 구성
|
||||||
|
```
|
||||||
|
전체 응답 시간 = 네트워크 지연 + 처리 시간 + 전송 시간
|
||||||
|
|
||||||
|
┌─────────────────────────────────────────┐
|
||||||
|
│ 빠른 응답 (단순 질문) │
|
||||||
|
│ [▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░] 1-2초 │
|
||||||
|
│ └─처리시간─┘ │
|
||||||
|
│ │
|
||||||
|
│ 느린 응답 (복잡한 코드 분석) │
|
||||||
|
│ [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 5-10초 │
|
||||||
|
│ └────────처리시간──────────┘ │
|
||||||
|
└─────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## 5. 핵심 포인트
|
||||||
|
- 🚀 **처리 시간은 고정**: 네트워크 속도와 무관
|
||||||
|
- 📡 **네트워크는 전송만 영향**: 느리면 기다리는 시간만 증가
|
||||||
|
- 🤖 **AI는 속도 인지 못함**: 단지 요청 받고 응답할 뿐
|
||||||
346
incus-crowdsec-architecture.md
Normal file
346
incus-crowdsec-architecture.md
Normal file
@@ -0,0 +1,346 @@
|
|||||||
|
# Multi-Layer Security Architecture with CrowdSec and OpenAppSec
|
||||||
|
|
||||||
|
## 🏗️ Infrastructure Overview
|
||||||
|
|
||||||
|
This document describes a multi-layer security architecture implemented using Incus containers, featuring CrowdSec community-driven threat intelligence and OpenAppSec ML-based WAF protection.
|
||||||
|
|
||||||
|
## 📋 Container Inventory
|
||||||
|
|
||||||
|
| Container | IP Address | Role | Technology |
|
||||||
|
|-----------|------------|------|------------|
|
||||||
|
| `ab-test` | 10.90.135.123 | Attack Simulation | curl/testing tools |
|
||||||
|
| `openresty` | 10.90.135.17 | Layer 1 Security | OpenResty + CrowdSec Bouncer |
|
||||||
|
| `crowdsec` | 10.90.135.49 | Threat Intelligence | CrowdSec Engine |
|
||||||
|
| `openappsec` | 10.90.135.186 | Layer 2 Security | ML-based WAF |
|
||||||
|
| `caddy` | 10.90.135.16 | Backend Server | Caddy HTTP Server |
|
||||||
|
| `php-auth` | 10.90.135.83 | Test Endpoint | PHP Authentication Service |
|
||||||
|
|
||||||
|
## 🏗️ Architecture Diagram
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────┐
|
||||||
|
│ Incus Container Infrastructure │
|
||||||
|
│ (10.90.135.0/24) │
|
||||||
|
└─────────────────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
┌─────────────────────────────────────────────────────────────────┐
|
||||||
|
│ 🌐 External Traffic Entry Point │
|
||||||
|
│ │
|
||||||
|
│ ┌─────────────────┐ │
|
||||||
|
│ │ ab-test │ ← Attack simulation container │
|
||||||
|
│ │ 10.90.135.123 │ │
|
||||||
|
│ └─────────────────┘ │
|
||||||
|
└─────────────────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────────┐
|
||||||
|
│ 🛡️ Layer 1: Community-Driven Threat Intelligence │
|
||||||
|
│ │
|
||||||
|
│ ┌─────────────────┐ ┌─────────────────┐ │
|
||||||
|
│ │ openresty │◄──►│ crowdsec │ │
|
||||||
|
│ │ 10.90.135.17 │ │ 10.90.135.49 │ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ │ • OpenResty │ │ • Threat Intel │ │
|
||||||
|
│ │ • CrowdSec │ │ • Scenarios │ │
|
||||||
|
│ │ Bouncer │ │ • Community DB │ │
|
||||||
|
│ │ • Rate Limiting │ │ • API Server │ │
|
||||||
|
│ │ • IP Blocking │ │ • Log Analysis │ │
|
||||||
|
│ └─────────────────┘ └─────────────────┘ │
|
||||||
|
│ │ │ │
|
||||||
|
│ └──── nginx-logs ────────┘ │
|
||||||
|
│ (Shared Volume: /var/log/nginx) │
|
||||||
|
└─────────────────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────────┐
|
||||||
|
│ 🧠 Layer 2: ML-Based Application Security │
|
||||||
|
│ │
|
||||||
|
│ ┌─────────────────┐ │
|
||||||
|
│ │ openappsec │ │
|
||||||
|
│ │ 10.90.135.186 │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ • ML WAF │ │
|
||||||
|
│ │ • Simple Model │ │
|
||||||
|
│ │ V1.0 │ │
|
||||||
|
│ │ • Zero-day │ │
|
||||||
|
│ │ Detection │ │
|
||||||
|
│ │ • No Signatures │ │
|
||||||
|
│ └─────────────────┘ │
|
||||||
|
└─────────────────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────────┐
|
||||||
|
│ 🔗 Layer 3: Backend Application Server │
|
||||||
|
│ │
|
||||||
|
│ ┌─────────────────┐ │
|
||||||
|
│ │ caddy │ │
|
||||||
|
│ │ 10.90.135.16 │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ • HTTP Server │ │
|
||||||
|
│ │ • Reverse Proxy │ │
|
||||||
|
│ │ • Auto HTTPS │ │
|
||||||
|
│ └─────────────────┘ │
|
||||||
|
└─────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
┌─────────────────────────────────────────────────────────────────┐
|
||||||
|
│ 🧪 Supporting Services │
|
||||||
|
│ │
|
||||||
|
│ ┌─────────────────┐ │
|
||||||
|
│ │ php-auth │ ← Authentication test endpoint │
|
||||||
|
│ │ 10.90.135.83 │ (Returns 401 for brute force testing) │
|
||||||
|
│ └─────────────────┘ │
|
||||||
|
└─────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 Traffic Flow & Security Processing
|
||||||
|
|
||||||
|
```
|
||||||
|
🌐 Attack Request
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────┐
|
||||||
|
│ openresty │ ← CrowdSec Bouncer
|
||||||
|
│ 10.90.135.17 │ • Community threat intel
|
||||||
|
│ │ • Behavioral analysis
|
||||||
|
│ │ • IP reputation
|
||||||
|
│ │ • Rate limiting
|
||||||
|
└─────────────────┘
|
||||||
|
│ ✅ Allowed
|
||||||
|
▼
|
||||||
|
┌─────────────────┐
|
||||||
|
│ openappsec │ ← ML-based WAF
|
||||||
|
│ 10.90.135.186 │ • Zero-day detection
|
||||||
|
│ │ • ML pattern analysis
|
||||||
|
│ │ • Application-layer security
|
||||||
|
└─────────────────┘
|
||||||
|
│ ✅ Clean
|
||||||
|
▼
|
||||||
|
┌─────────────────┐
|
||||||
|
│ caddy │ ← Backend Server
|
||||||
|
│ 10.90.135.16 │ • Content delivery
|
||||||
|
│ │ • Application logic
|
||||||
|
└─────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔒 Security Layers Detail
|
||||||
|
|
||||||
|
### Layer 1: CrowdSec Community Intelligence
|
||||||
|
|
||||||
|
**Container**: `openresty` + `crowdsec`
|
||||||
|
|
||||||
|
**Key Features**:
|
||||||
|
- 🌍 Global threat intelligence sharing
|
||||||
|
- 🔍 HTTP brute force detection (`LePresidente/http-generic-401-bf`)
|
||||||
|
- 📊 Scenario-based behavioral analysis
|
||||||
|
- ⏱️ Real-time IP blocking (4-hour default ban)
|
||||||
|
- 🔄 Dynamic bouncer integration with OpenResty
|
||||||
|
|
||||||
|
**Scenarios Enabled**:
|
||||||
|
- `crowdsecurity/http-generic-bf` - Generic HTTP brute force detection
|
||||||
|
- `crowdsecurity/http-admin-interface-probing` - Admin interface scanning
|
||||||
|
- `crowdsecurity/http-probing` - General HTTP probing
|
||||||
|
- `crowdsecurity/http-cve-probing` - CVE exploitation attempts
|
||||||
|
- `crowdsecurity/http-sqli-probing` - SQL injection attempts
|
||||||
|
|
||||||
|
**Configuration**:
|
||||||
|
```yaml
|
||||||
|
# CrowdSec Acquisition
|
||||||
|
filenames:
|
||||||
|
- /var/log/nginx/access.log
|
||||||
|
- /var/log/nginx/error.log
|
||||||
|
labels:
|
||||||
|
type: nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
### Layer 2: OpenAppSec ML WAF
|
||||||
|
|
||||||
|
**Container**: `openappsec`
|
||||||
|
|
||||||
|
**Key Features**:
|
||||||
|
- 🧠 Machine learning-based attack detection
|
||||||
|
- 🆕 Zero-day vulnerability protection
|
||||||
|
- 📝 No signature updates required
|
||||||
|
- ⚡ Simple Model V1.0 for fast processing
|
||||||
|
- 🔄 Automatic threat adaptation
|
||||||
|
|
||||||
|
**ML Model**: Simple Model V1.0
|
||||||
|
- Behavioral analysis
|
||||||
|
- Pattern recognition
|
||||||
|
- Anomaly detection
|
||||||
|
- Real-time learning
|
||||||
|
|
||||||
|
### Layer 3: Backend Application
|
||||||
|
|
||||||
|
**Container**: `caddy`
|
||||||
|
|
||||||
|
**Key Features**:
|
||||||
|
- 🔐 Automatic HTTPS with Let's Encrypt
|
||||||
|
- 🔄 Reverse proxy capabilities
|
||||||
|
- 📈 High-performance HTTP/2 support
|
||||||
|
- 🎯 Clean traffic processing
|
||||||
|
|
||||||
|
## 🧪 Testing Infrastructure
|
||||||
|
|
||||||
|
### Attack Simulation
|
||||||
|
- **Container**: `ab-test`
|
||||||
|
- **Purpose**: Simulate various attack patterns for testing
|
||||||
|
- **Tools**: curl, custom scripts
|
||||||
|
|
||||||
|
### Authentication Endpoint
|
||||||
|
- **Container**: `php-auth`
|
||||||
|
- **Purpose**: Generate 401/403 responses for brute force testing
|
||||||
|
- **Endpoint**: `/login.php` - Always returns 401 Unauthorized
|
||||||
|
|
||||||
|
## 🔧 Implementation Details
|
||||||
|
|
||||||
|
### Volume Mounts
|
||||||
|
```bash
|
||||||
|
# Shared nginx logs between openresty and crowdsec
|
||||||
|
nginx-logs: /var/log/nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
### Network Configuration
|
||||||
|
- **Network**: incus default bridge (10.90.135.0/24)
|
||||||
|
- **Traffic Flow**: ab-test → openresty → openappsec → caddy
|
||||||
|
- **Special Routes**: `/admin/login` → php-auth (testing)
|
||||||
|
|
||||||
|
### Security Configuration
|
||||||
|
|
||||||
|
#### CrowdSec Bouncer
|
||||||
|
```yaml
|
||||||
|
API_URL: http://10.90.135.49:8080
|
||||||
|
API_KEY: s0ENc/6Tw+6m6tr0Qkjt/WAYU1QlC5/MzH7SQOCJX50
|
||||||
|
```
|
||||||
|
|
||||||
|
#### OpenResty Configuration
|
||||||
|
```nginx
|
||||||
|
upstream openappsec_backend {
|
||||||
|
server 10.90.135.186:80;
|
||||||
|
}
|
||||||
|
|
||||||
|
upstream auth_backend {
|
||||||
|
server 10.90.135.83:8080;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
access_log /var/log/nginx/access.log;
|
||||||
|
error_log /var/log/nginx/error.log;
|
||||||
|
|
||||||
|
location /admin/login {
|
||||||
|
proxy_pass http://auth_backend/login.php;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://openappsec_backend;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## ✅ Testing Results
|
||||||
|
|
||||||
|
### Successful Test Cases
|
||||||
|
|
||||||
|
1. **Brute Force Detection**
|
||||||
|
- ✅ 6 failed login attempts → CrowdSec alert triggered
|
||||||
|
- ✅ IP `10.90.135.123` automatically banned
|
||||||
|
- ✅ Scenario: `LePresidente/http-generic-401-bf`
|
||||||
|
|
||||||
|
2. **IP Blocking**
|
||||||
|
- ✅ Banned IP receives `403 Forbidden`
|
||||||
|
- ✅ Traffic completely blocked at Layer 1
|
||||||
|
|
||||||
|
3. **IP Unbanning**
|
||||||
|
- ✅ Manual unban via `cscli decisions delete`
|
||||||
|
- ✅ Immediate traffic restoration
|
||||||
|
|
||||||
|
4. **Multi-Layer Coordination**
|
||||||
|
- ✅ OpenResty logs → CrowdSec analysis
|
||||||
|
- ✅ Real-time threat intelligence updates
|
||||||
|
- ✅ Seamless traffic flow through all layers
|
||||||
|
|
||||||
|
### Attack Patterns Tested
|
||||||
|
- HTTP brute force attacks (401 responses)
|
||||||
|
- Multiple rapid authentication attempts
|
||||||
|
- IP-based blocking and recovery
|
||||||
|
|
||||||
|
## 🚀 Deployment Commands
|
||||||
|
|
||||||
|
### Container Management
|
||||||
|
```bash
|
||||||
|
# List all containers
|
||||||
|
incus list
|
||||||
|
|
||||||
|
# Start security stack
|
||||||
|
incus start crowdsec openresty openappsec caddy
|
||||||
|
|
||||||
|
# Monitor CrowdSec
|
||||||
|
incus exec crowdsec -- cscli alerts list
|
||||||
|
incus exec crowdsec -- cscli decisions list
|
||||||
|
incus exec crowdsec -- cscli metrics
|
||||||
|
```
|
||||||
|
|
||||||
|
### Security Operations
|
||||||
|
```bash
|
||||||
|
# Ban an IP manually
|
||||||
|
incus exec crowdsec -- cscli decisions add --ip 1.2.3.4 --duration 4h --reason "manual-ban"
|
||||||
|
|
||||||
|
# Unban an IP
|
||||||
|
incus exec crowdsec -- cscli decisions delete --ip 1.2.3.4
|
||||||
|
|
||||||
|
# Check bouncer status
|
||||||
|
incus exec crowdsec -- cscli bouncers list
|
||||||
|
|
||||||
|
# View real-time logs
|
||||||
|
incus exec openresty -- tail -f /var/log/nginx/access.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing Commands
|
||||||
|
```bash
|
||||||
|
# Simulate brute force attack
|
||||||
|
incus exec ab-test -- bash -c 'for i in {1..6}; do
|
||||||
|
curl -X POST http://10.90.135.17/admin/login -d "username=admin&password=wrong$i"
|
||||||
|
sleep 1
|
||||||
|
done'
|
||||||
|
|
||||||
|
# Test blocked IP
|
||||||
|
incus exec ab-test -- curl -X POST http://10.90.135.17/admin/login -d "test=blocked"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔍 Monitoring & Alerting
|
||||||
|
|
||||||
|
### CrowdSec Metrics
|
||||||
|
- **Acquisition**: Lines read, parsed, whitelisted
|
||||||
|
- **Scenarios**: Active scenarios, overflows, instantiations
|
||||||
|
- **Decisions**: Active bans, ban duration, ban reasons
|
||||||
|
- **API**: Bouncer heartbeats, decision pulls
|
||||||
|
|
||||||
|
### Log Locations
|
||||||
|
- **OpenResty**: `/var/log/nginx/access.log`, `/var/log/nginx/error.log`
|
||||||
|
- **CrowdSec**: Built-in metrics via `cscli metrics`
|
||||||
|
- **OpenAppSec**: Container logs via `incus exec openappsec -- logs`
|
||||||
|
|
||||||
|
## 📚 Key Learnings
|
||||||
|
|
||||||
|
1. **Whitelist Management**: Internal IP ranges need careful configuration for testing
|
||||||
|
2. **Log Format Compatibility**: OpenResty logs work well with CrowdSec nginx parsers
|
||||||
|
3. **Volume Sharing**: Critical for log analysis between containers
|
||||||
|
4. **Response Codes**: 401/403 responses trigger different CrowdSec scenarios
|
||||||
|
5. **Real-time Detection**: Sub-minute detection and blocking capabilities
|
||||||
|
|
||||||
|
## 🔮 Future Enhancements
|
||||||
|
|
||||||
|
- [ ] Custom CrowdSec scenarios for application-specific attacks
|
||||||
|
- [ ] Integration with external threat intelligence feeds
|
||||||
|
- [ ] Automated incident response workflows
|
||||||
|
- [ ] Performance monitoring and optimization
|
||||||
|
- [ ] Distributed deployment across multiple nodes
|
||||||
|
- [ ] SSL/TLS termination at OpenResty layer
|
||||||
|
- [ ] Rate limiting configuration fine-tuning
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Created**: 2025-08-17
|
||||||
|
**Last Updated**: 2025-08-17
|
||||||
|
**Architecture Version**: 1.0
|
||||||
|
**Status**: Production Ready ✅
|
||||||
312
incus-meilisearch-manual.md
Normal file
312
incus-meilisearch-manual.md
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
# Incus에서 Meilisearch 실행 매뉴얼
|
||||||
|
|
||||||
|
## 목차
|
||||||
|
1. [기본 실행](#1-기본-실행)
|
||||||
|
2. [환경변수 설정](#2-환경변수-설정)
|
||||||
|
3. [포트 포워딩](#3-포트-포워딩)
|
||||||
|
4. [볼륨 마운트](#4-볼륨-마운트)
|
||||||
|
5. [Docker Compose 변환](#5-docker-compose-변환)
|
||||||
|
6. [컨테이너 관리](#6-컨테이너-관리)
|
||||||
|
7. [문제 해결](#7-문제-해결)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 기본 실행
|
||||||
|
|
||||||
|
### 간단한 실행
|
||||||
|
```bash
|
||||||
|
incus launch docker.io/getmeili/meilisearch meilisearch-container
|
||||||
|
```
|
||||||
|
|
||||||
|
### 리소스 제한과 함께 실행
|
||||||
|
```bash
|
||||||
|
incus launch docker.io/getmeili/meilisearch meilisearch-container \
|
||||||
|
--config limits.cpu=2 \
|
||||||
|
--config limits.memory=1GB
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 환경변수 설정
|
||||||
|
|
||||||
|
### 컨테이너 생성 시 환경변수 설정
|
||||||
|
```bash
|
||||||
|
incus launch docker.io/getmeili/meilisearch meilisearch-container \
|
||||||
|
--config environment.MEILI_MASTER_KEY=your-secret-key \
|
||||||
|
--config environment.MEILI_ENV=production \
|
||||||
|
--config environment.MEILI_DB_PATH=/data.ms
|
||||||
|
```
|
||||||
|
|
||||||
|
### 실행 중인 컨테이너에 환경변수 추가
|
||||||
|
```bash
|
||||||
|
# 컨테이너 중지
|
||||||
|
incus stop meilisearch-container
|
||||||
|
|
||||||
|
# 환경변수 설정
|
||||||
|
incus config set meilisearch-container environment.MEILI_MASTER_KEY=your-secret-key
|
||||||
|
incus config set meilisearch-container environment.MEILI_ENV=production
|
||||||
|
incus config set meilisearch-container environment.MEILI_DB_PATH=/data.ms
|
||||||
|
|
||||||
|
# 또는 한 번에 여러 개 설정
|
||||||
|
incus config set meilisearch-container \
|
||||||
|
environment.MEILI_MASTER_KEY=your-secret-key \
|
||||||
|
environment.MEILI_ENV=production \
|
||||||
|
environment.MEILI_DB_PATH=/data.ms
|
||||||
|
|
||||||
|
# 컨테이너 재시작
|
||||||
|
incus restart meilisearch-container
|
||||||
|
```
|
||||||
|
|
||||||
|
### 환경변수 확인 및 삭제
|
||||||
|
```bash
|
||||||
|
# 모든 설정 확인
|
||||||
|
incus config show meilisearch-container
|
||||||
|
|
||||||
|
# 특정 환경변수 확인
|
||||||
|
incus config get meilisearch-container environment.MEILI_MASTER_KEY
|
||||||
|
|
||||||
|
# 환경변수 삭제
|
||||||
|
incus config unset meilisearch-container environment.MEILI_MASTER_KEY
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 포트 포워딩
|
||||||
|
|
||||||
|
### 포트 7700 포워딩
|
||||||
|
```bash
|
||||||
|
incus config device add meilisearch-container http proxy \
|
||||||
|
listen=tcp:0.0.0.0:7700 \
|
||||||
|
connect=tcp:127.0.0.1:7700
|
||||||
|
```
|
||||||
|
|
||||||
|
### 여러 포트 포워딩
|
||||||
|
```bash
|
||||||
|
# HTTP 포트
|
||||||
|
incus config device add meilisearch-container http proxy \
|
||||||
|
listen=tcp:0.0.0.0:7700 \
|
||||||
|
connect=tcp:127.0.0.1:7700
|
||||||
|
|
||||||
|
# 추가 포트 (예: metrics)
|
||||||
|
incus config device add meilisearch-container metrics proxy \
|
||||||
|
listen=tcp:0.0.0.0:8080 \
|
||||||
|
connect=tcp:127.0.0.1:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
### 포트 포워딩 확인
|
||||||
|
```bash
|
||||||
|
incus config device show meilisearch-container
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 볼륨 마운트
|
||||||
|
|
||||||
|
### 데이터 디렉토리 마운트
|
||||||
|
```bash
|
||||||
|
# 호스트 디렉토리를 컨테이너에 마운트
|
||||||
|
incus config device add meilisearch-container data disk \
|
||||||
|
source=/home/user/meilisearch-data \
|
||||||
|
path=/data.ms
|
||||||
|
```
|
||||||
|
|
||||||
|
### 스토리지 풀 사용
|
||||||
|
```bash
|
||||||
|
# 스토리지 풀 생성
|
||||||
|
incus storage create meilisearch-pool dir
|
||||||
|
|
||||||
|
# 볼륨 생성
|
||||||
|
incus storage volume create meilisearch-pool meilisearch-data
|
||||||
|
|
||||||
|
# 볼륨 연결
|
||||||
|
incus config device add meilisearch-container data disk \
|
||||||
|
pool=meilisearch-pool \
|
||||||
|
source=meilisearch-data \
|
||||||
|
path=/data.ms
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Docker Compose 변환
|
||||||
|
|
||||||
|
### Docker Compose 예시
|
||||||
|
```yaml
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
meilisearch:
|
||||||
|
image: getmeili/meilisearch:latest
|
||||||
|
environment:
|
||||||
|
- MEILI_MASTER_KEY=masterKey
|
||||||
|
- MEILI_ENV=production
|
||||||
|
- MEILI_DB_PATH=/data.ms
|
||||||
|
ports:
|
||||||
|
- "7700:7700"
|
||||||
|
volumes:
|
||||||
|
- ./data:/data.ms
|
||||||
|
restart: always
|
||||||
|
```
|
||||||
|
|
||||||
|
### Incus 명령어로 변환
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# meilisearch-setup.sh
|
||||||
|
|
||||||
|
# 1. 컨테이너 생성 및 환경변수 설정
|
||||||
|
incus launch docker.io/getmeili/meilisearch:latest meilisearch \
|
||||||
|
--config environment.MEILI_MASTER_KEY=masterKey \
|
||||||
|
--config environment.MEILI_ENV=production \
|
||||||
|
--config environment.MEILI_DB_PATH=/data.ms
|
||||||
|
|
||||||
|
# 2. 포트 포워딩 설정
|
||||||
|
incus config device add meilisearch http proxy \
|
||||||
|
listen=tcp:0.0.0.0:7700 \
|
||||||
|
connect=tcp:127.0.0.1:7700
|
||||||
|
|
||||||
|
# 3. 볼륨 마운트
|
||||||
|
incus config device add meilisearch data disk \
|
||||||
|
source=$(pwd)/data \
|
||||||
|
path=/data.ms
|
||||||
|
|
||||||
|
# 4. 자동 재시작 설정
|
||||||
|
incus config set meilisearch boot.autostart=true
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 컨테이너 관리
|
||||||
|
|
||||||
|
### 기본 명령어
|
||||||
|
```bash
|
||||||
|
# 시작
|
||||||
|
incus start meilisearch-container
|
||||||
|
|
||||||
|
# 중지
|
||||||
|
incus stop meilisearch-container
|
||||||
|
|
||||||
|
# 재시작
|
||||||
|
incus restart meilisearch-container
|
||||||
|
|
||||||
|
# 삭제
|
||||||
|
incus delete meilisearch-container --force
|
||||||
|
|
||||||
|
# 상태 확인
|
||||||
|
incus list meilisearch-container
|
||||||
|
```
|
||||||
|
|
||||||
|
### 로그 및 모니터링
|
||||||
|
```bash
|
||||||
|
# 로그 확인
|
||||||
|
incus logs meilisearch-container
|
||||||
|
|
||||||
|
# 실시간 로그
|
||||||
|
incus logs meilisearch-container --follow
|
||||||
|
|
||||||
|
# 컨테이너 접속
|
||||||
|
incus exec meilisearch-container -- /bin/bash
|
||||||
|
|
||||||
|
# 프로세스 확인
|
||||||
|
incus exec meilisearch-container -- ps aux
|
||||||
|
```
|
||||||
|
|
||||||
|
### 리소스 모니터링
|
||||||
|
```bash
|
||||||
|
# CPU/메모리 사용량
|
||||||
|
incus info meilisearch-container
|
||||||
|
|
||||||
|
# 상세 정보
|
||||||
|
incus config show meilisearch-container
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 문제 해결
|
||||||
|
|
||||||
|
### 포트 접속 안 될 때
|
||||||
|
```bash
|
||||||
|
# 포트 포워딩 확인
|
||||||
|
incus config device show meilisearch-container
|
||||||
|
|
||||||
|
# 컨테이너 내부에서 서비스 확인
|
||||||
|
incus exec meilisearch-container -- netstat -tlnp
|
||||||
|
|
||||||
|
# 방화벽 확인 (호스트)
|
||||||
|
sudo ufw status
|
||||||
|
```
|
||||||
|
|
||||||
|
### 환경변수 적용 안 될 때
|
||||||
|
```bash
|
||||||
|
# 환경변수 확인
|
||||||
|
incus exec meilisearch-container -- env | grep MEILI
|
||||||
|
|
||||||
|
# 재시작
|
||||||
|
incus restart meilisearch-container
|
||||||
|
```
|
||||||
|
|
||||||
|
### 데이터 영속성 문제
|
||||||
|
```bash
|
||||||
|
# 마운트 확인
|
||||||
|
incus config device show meilisearch-container
|
||||||
|
|
||||||
|
# 권한 확인
|
||||||
|
incus exec meilisearch-container -- ls -la /data.ms
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 실전 예제
|
||||||
|
|
||||||
|
### Production 환경 설정
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# 변수 설정
|
||||||
|
CONTAINER_NAME="meilisearch-prod"
|
||||||
|
MASTER_KEY="$(openssl rand -base64 32)"
|
||||||
|
DATA_PATH="/var/lib/meilisearch"
|
||||||
|
|
||||||
|
# 데이터 디렉토리 생성
|
||||||
|
sudo mkdir -p $DATA_PATH
|
||||||
|
|
||||||
|
# 컨테이너 생성
|
||||||
|
incus launch docker.io/getmeili/meilisearch:latest $CONTAINER_NAME \
|
||||||
|
--config limits.cpu=4 \
|
||||||
|
--config limits.memory=4GB \
|
||||||
|
--config environment.MEILI_MASTER_KEY=$MASTER_KEY \
|
||||||
|
--config environment.MEILI_ENV=production \
|
||||||
|
--config environment.MEILI_DB_PATH=/data.ms \
|
||||||
|
--config environment.MEILI_LOG_LEVEL=INFO
|
||||||
|
|
||||||
|
# 포트 설정
|
||||||
|
incus config device add $CONTAINER_NAME http proxy \
|
||||||
|
listen=tcp:0.0.0.0:7700 \
|
||||||
|
connect=tcp:127.0.0.1:7700
|
||||||
|
|
||||||
|
# 볼륨 마운트
|
||||||
|
incus config device add $CONTAINER_NAME data disk \
|
||||||
|
source=$DATA_PATH \
|
||||||
|
path=/data.ms
|
||||||
|
|
||||||
|
# 자동 시작 설정
|
||||||
|
incus config set $CONTAINER_NAME boot.autostart=true
|
||||||
|
|
||||||
|
echo "Meilisearch Master Key: $MASTER_KEY"
|
||||||
|
echo "Access URL: http://localhost:7700"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 참고 사항
|
||||||
|
|
||||||
|
- Meilisearch 기본 포트: 7700
|
||||||
|
- 프로덕션 환경에서는 반드시 `MEILI_MASTER_KEY` 설정
|
||||||
|
- 데이터 영속성을 위해 볼륨 마운트 권장
|
||||||
|
- 리소스 제한 설정으로 시스템 안정성 확보
|
||||||
|
- 정기적인 백업 필요 (데이터 디렉토리 백업)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 추가 리소스
|
||||||
|
|
||||||
|
- [Meilisearch 공식 문서](https://docs.meilisearch.com/)
|
||||||
|
- [Incus 공식 문서](https://linuxcontainers.org/incus/docs/main/)
|
||||||
|
- [Docker Hub - Meilisearch](https://hub.docker.com/r/getmeili/meilisearch)
|
||||||
321
kitty-setup-guide.md
Normal file
321
kitty-setup-guide.md
Normal file
@@ -0,0 +1,321 @@
|
|||||||
|
# Kitty Terminal 완벽 설정 가이드
|
||||||
|
|
||||||
|
최적화된 kitty 터미널 환경 구성 가이드입니다. Fira Code Nerd Font, Dracula 테마, Fish Shell, tmux 통합이 포함되어 있습니다.
|
||||||
|
|
||||||
|
## 📋 목차
|
||||||
|
|
||||||
|
- [설치된 구성 요소](#설치된-구성-요소)
|
||||||
|
- [폰트 설정](#폰트-설정)
|
||||||
|
- [테마 설정](#테마-설정)
|
||||||
|
- [Shell Integration](#shell-integration)
|
||||||
|
- [tmux 통합](#tmux-통합)
|
||||||
|
- [키보드 단축키](#키보드-단축키)
|
||||||
|
- [유용한 명령어](#유용한-명령어)
|
||||||
|
- [설정 파일 위치](#설정-파일-위치)
|
||||||
|
|
||||||
|
## 🚀 설치된 구성 요소
|
||||||
|
|
||||||
|
### 폰트
|
||||||
|
- **Fira Code Nerd Font**: 리가처와 아이콘 지원
|
||||||
|
- **D2Coding**: 한글 최적화 (주석 처리됨, 필요시 활성화 가능)
|
||||||
|
|
||||||
|
### 테마
|
||||||
|
- **Dracula Theme**: 눈에 편한 어두운 테마
|
||||||
|
|
||||||
|
### Shell 통합
|
||||||
|
- **Fish Shell**: 스마트한 자동완성과 구문 강조
|
||||||
|
- **Fisher**: Fish 플러그인 매니저
|
||||||
|
- **플러그인들**:
|
||||||
|
- `done`: 명령어 완료 알림
|
||||||
|
- `pisces`: 자동 괄호 닫기
|
||||||
|
- `fzf.fish`: 퍼지 파인더 통합
|
||||||
|
|
||||||
|
### 멀티플렉서
|
||||||
|
- **tmux**: 세션 관리와 창 분할
|
||||||
|
- **Dracula 테마**: kitty와 일치하는 색상
|
||||||
|
|
||||||
|
## 🎨 폰트 설정
|
||||||
|
|
||||||
|
### 현재 설정
|
||||||
|
```conf
|
||||||
|
# 폰트 패밀리 (Fira Code Nerd Font)
|
||||||
|
font_family FiraCode Nerd Font
|
||||||
|
bold_font FiraCode Nerd Font Bold
|
||||||
|
italic_font FiraCode Nerd Font Light
|
||||||
|
bold_italic_font FiraCode Nerd Font SemiBold
|
||||||
|
|
||||||
|
# 폰트 크기
|
||||||
|
font_size 17.0
|
||||||
|
```
|
||||||
|
|
||||||
|
### 리가처 예시
|
||||||
|
- `!=` → `≠`
|
||||||
|
- `>=` → `≥`
|
||||||
|
- `=>` → `⇒`
|
||||||
|
- `->` → `→`
|
||||||
|
- `===` → `≡`
|
||||||
|
|
||||||
|
## 🧛♂️ Dracula 테마
|
||||||
|
|
||||||
|
### 색상 팔레트
|
||||||
|
- **배경**: `#282a36` (어두운 보라)
|
||||||
|
- **전경**: `#f8f8f2` (밝은 회색)
|
||||||
|
- **보라**: `#bd93f9`
|
||||||
|
- **핑크**: `#ff79c6`
|
||||||
|
- **청록**: `#8be9fd`
|
||||||
|
- **녹색**: `#50fa7b`
|
||||||
|
- **노랑**: `#f1fa8c`
|
||||||
|
|
||||||
|
### 설정 방법
|
||||||
|
```conf
|
||||||
|
# Dracula 테마 적용
|
||||||
|
include dracula.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🐚 Shell Integration
|
||||||
|
|
||||||
|
### kitty + Fish 통합 기능
|
||||||
|
|
||||||
|
#### 자동 설치된 플러그인
|
||||||
|
```bash
|
||||||
|
# Fisher 플러그인 매니저
|
||||||
|
fisher install jorgebucaran/fisher
|
||||||
|
|
||||||
|
# 유용한 플러그인들
|
||||||
|
fisher install franciscolourenco/done # 명령어 완료 알림
|
||||||
|
fisher install laughedelic/pisces # 자동 괄호 닫기
|
||||||
|
fisher install PatrickF1/fzf.fish # 퍼지 파인더
|
||||||
|
```
|
||||||
|
|
||||||
|
#### kitty 전용 명령어
|
||||||
|
```bash
|
||||||
|
icat image.png # 터미널에서 이미지 보기
|
||||||
|
kdiff file1 file2 # kitty diff 도구
|
||||||
|
kssh user@server # kitty SSH (ssh로 alias됨)
|
||||||
|
preview # fzf 파일 미리보기
|
||||||
|
|
||||||
|
# kitten 유틸리티 (새로 추가됨)
|
||||||
|
img filename.png # 이미지 보기 (icat 간편 alias)
|
||||||
|
imgls # 현재 폴더 이미지들 갤러리로 보기
|
||||||
|
clipboard # 클립보드 히스토리 관리
|
||||||
|
unicode # 유니코드 문자 입력기
|
||||||
|
hgrep pattern files # 클릭 가능한 grep 결과
|
||||||
|
```
|
||||||
|
|
||||||
|
#### SSH 최적화
|
||||||
|
```bash
|
||||||
|
# fish config에서 ssh가 kssh로 alias됨
|
||||||
|
alias ssh=kssh
|
||||||
|
|
||||||
|
# kitty SSH의 장점:
|
||||||
|
# - 테마 동기화 (Dracula 테마가 원격에서도 적용)
|
||||||
|
# - 드래그&드롭 파일 전송
|
||||||
|
# - 이미지 표시 지원
|
||||||
|
# - 고급 키보드 프로토콜
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📺 tmux 통합
|
||||||
|
|
||||||
|
### tmux Dracula 테마
|
||||||
|
```bash
|
||||||
|
# 상태바 색상
|
||||||
|
set -g status-style 'bg=#282a36 fg=#f8f8f2'
|
||||||
|
set -g status-left '#[fg=#282a36,bg=#bd93f9,bold] #S #[fg=#bd93f9,bg=#282a36] '
|
||||||
|
set -g status-right '#[fg=#50fa7b,bg=#282a36] %Y-%m-%d #[fg=#8be9fd,bg=#282a36] %H:%M #[fg=#282a36,bg=#ff79c6,bold] #h '
|
||||||
|
|
||||||
|
# 패널 경계선
|
||||||
|
set -g pane-border-style 'fg=#6272a4 bg=#282a36'
|
||||||
|
set -g pane-active-border-style 'fg=#bd93f9 bg=#282a36'
|
||||||
|
```
|
||||||
|
|
||||||
|
### kitty 최적화
|
||||||
|
```bash
|
||||||
|
# tmux.conf에서 kitty 지원
|
||||||
|
set -g default-terminal "xterm-kitty"
|
||||||
|
set -g terminal-overrides "xterm-kitty:Tc"
|
||||||
|
set -s extended-keys on
|
||||||
|
set -as terminal-features 'xterm-kitty:extkeys'
|
||||||
|
```
|
||||||
|
|
||||||
|
## ⌨️ 키보드 단축키
|
||||||
|
|
||||||
|
### kitty 기본 단축키
|
||||||
|
```bash
|
||||||
|
# 폰트 크기 조절
|
||||||
|
Cmd + =/-/0 # 크기 증가/감소/초기화
|
||||||
|
|
||||||
|
# 탭 관리
|
||||||
|
Cmd + T # 새 탭
|
||||||
|
Cmd + W # 탭 닫기
|
||||||
|
Cmd + 1-5 # 탭 이동
|
||||||
|
|
||||||
|
# 창 분할
|
||||||
|
Cmd + Shift + D # 파일 diff 뷰어 (kitten)
|
||||||
|
Cmd + Shift + V # 하단 분할
|
||||||
|
|
||||||
|
# 설정 다시 로드
|
||||||
|
Cmd + Shift + R # kitty 설정 재로드
|
||||||
|
|
||||||
|
# kitten 통합 기능 (새로 추가됨)
|
||||||
|
Cmd + Shift + H # 클립보드 히스토리 관리
|
||||||
|
Cmd + Shift + I # 현재 폴더 이미지 갤러리 보기
|
||||||
|
Cmd + Shift + U # 유니코드 문자 입력기
|
||||||
|
```
|
||||||
|
|
||||||
|
### tmux 통합 단축키
|
||||||
|
```bash
|
||||||
|
# tmux 세션 관리 (kitty에서)
|
||||||
|
Cmd + Shift + N # 새 tmux 세션
|
||||||
|
Cmd + Shift + A # tmux 세션 연결/생성
|
||||||
|
Cmd + Shift + S # tmux 세션 선택
|
||||||
|
|
||||||
|
# tmux 패널 이동 (kitty에서)
|
||||||
|
Cmd + Shift + 화살표 # tmux 패널 이동
|
||||||
|
|
||||||
|
# Fish shell 기능
|
||||||
|
Cmd + Shift + Z/X # 이전/다음 프롬프트로 이동
|
||||||
|
Cmd + Shift + O # 마지막 명령어 출력 보기
|
||||||
|
Ctrl + G # 히스토리 검색 (fish에서)
|
||||||
|
```
|
||||||
|
|
||||||
|
### tmux 기본 단축키
|
||||||
|
```bash
|
||||||
|
# Prefix: Ctrl + A
|
||||||
|
Ctrl + A, | # 세로 분할
|
||||||
|
Ctrl + A, - # 가로 분할
|
||||||
|
Ctrl + A, h/j/k/l # 패널 이동 (vim 스타일)
|
||||||
|
Ctrl + A, r # 설정 다시 로드
|
||||||
|
|
||||||
|
# Alt 키 조합 (Prefix 불필요)
|
||||||
|
Alt + 화살표 # 패널 이동
|
||||||
|
Shift + 좌우화살표 # 창 이동
|
||||||
|
```
|
||||||
|
|
||||||
|
## 💻 유용한 명령어
|
||||||
|
|
||||||
|
### tmux 세션 관리
|
||||||
|
```bash
|
||||||
|
tm # tmux 시작
|
||||||
|
tma work # 'work' 세션에 연결
|
||||||
|
tmn project # 'project' 새 세션 생성
|
||||||
|
tml # 세션 목록 보기
|
||||||
|
tmk work # 'work' 세션 종료
|
||||||
|
```
|
||||||
|
|
||||||
|
### kitty 도구들
|
||||||
|
```bash
|
||||||
|
icat image.png # 이미지 터미널에서 보기
|
||||||
|
kdiff file1 file2 # 파일 비교
|
||||||
|
ssh user@server # kitty SSH (테마 동기화)
|
||||||
|
preview # fzf 파일 미리보기
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fish 고급 기능
|
||||||
|
```bash
|
||||||
|
# fzf 통합
|
||||||
|
Ctrl + R # 명령어 히스토리 검색
|
||||||
|
Ctrl + Alt + F # 파일 검색
|
||||||
|
Ctrl + Alt + S # git 상태 검색
|
||||||
|
|
||||||
|
# 자동 완성
|
||||||
|
Tab # 스마트 자동완성
|
||||||
|
Tab Tab # 모든 옵션 보기
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🐱 kitten 통합 기능
|
||||||
|
|
||||||
|
### 새로 추가된 kitten 기능들
|
||||||
|
```bash
|
||||||
|
# 키보드 단축키로 접근
|
||||||
|
Cmd + Shift + H # 클립보드 히스토리 관리
|
||||||
|
Cmd + Shift + I # 현재 폴더 이미지 갤러리
|
||||||
|
Cmd + Shift + U # 유니코드 문자 입력기
|
||||||
|
Cmd + Shift + D # 파일 diff 뷰어
|
||||||
|
|
||||||
|
# 터미널 명령어로 접근
|
||||||
|
img image.png # 이미지 보기
|
||||||
|
imgls # 폴더 내 이미지들 갤러리
|
||||||
|
clipboard # 클립보드 히스토리
|
||||||
|
unicode # 유니코드 입력
|
||||||
|
hgrep pattern files # 클릭 가능한 grep
|
||||||
|
```
|
||||||
|
|
||||||
|
### kitten 활용 팁
|
||||||
|
- **이미지 갤러리**: 디자인 작업시 폴더 내 이미지들을 빠르게 미리보기
|
||||||
|
- **클립보드 히스토리**: 복사한 내용들을 기록해서 나중에 재사용
|
||||||
|
- **diff 뷰어**: 파일 비교를 터미널에서 깔끔하게
|
||||||
|
- **유니코드 입력**: 특수문자나 이모지를 쉽게 입력
|
||||||
|
|
||||||
|
## 📁 설정 파일 위치
|
||||||
|
|
||||||
|
### kitty 설정
|
||||||
|
```
|
||||||
|
~/.config/kitty/kitty.conf # 메인 설정 파일
|
||||||
|
~/.config/kitty/dracula.conf # Dracula 테마 파일
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fish 설정
|
||||||
|
```
|
||||||
|
~/.config/fish/config.fish # Fish 메인 설정
|
||||||
|
~/.config/fish/fish_plugins # 설치된 플러그인 목록
|
||||||
|
```
|
||||||
|
|
||||||
|
### tmux 설정
|
||||||
|
```
|
||||||
|
~/.tmux.conf # tmux 설정 파일
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 설정 커스터마이징
|
||||||
|
|
||||||
|
### 테마 변경
|
||||||
|
이전 테마로 돌아가려면:
|
||||||
|
```conf
|
||||||
|
# kitty.conf에서
|
||||||
|
# include dracula.conf # 이 줄을 주석 처리
|
||||||
|
# 그리고 기존 색상 설정들의 주석을 해제
|
||||||
|
```
|
||||||
|
|
||||||
|
### 한글 폰트 활성화
|
||||||
|
D2Coding을 한글에 사용하려면:
|
||||||
|
```conf
|
||||||
|
# kitty.conf에서 23번 줄 주석 해제
|
||||||
|
symbol_map U+AC00-U+D7A3,U+1100-U+11FF,U+3130-U+318F,U+A960-U+A97F,U+D7B0-U+D7FF,U+302E-U+302F D2Coding
|
||||||
|
```
|
||||||
|
|
||||||
|
### 폰트 크기 변경
|
||||||
|
```conf
|
||||||
|
# kitty.conf 9번 줄
|
||||||
|
font_size 17.0 # 원하는 크기로 변경
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 추가 최적화 아이디어
|
||||||
|
|
||||||
|
### 더 많은 Fish 플러그인
|
||||||
|
```bash
|
||||||
|
fisher install jethrokuan/z # 스마트 디렉토리 점프
|
||||||
|
fisher install franciscolourenco/bass # Bash 스크립트 실행
|
||||||
|
fisher install edc/bass # 환경 변수 관리
|
||||||
|
```
|
||||||
|
|
||||||
|
### 추가 tmux 플러그인
|
||||||
|
```bash
|
||||||
|
# ~/.tmux.conf에 추가
|
||||||
|
set -g @plugin 'tmux-plugins/tpm'
|
||||||
|
set -g @plugin 'tmux-plugins/tmux-sensible'
|
||||||
|
set -g @plugin 'tmux-plugins/tmux-resurrect'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 기타 kitty 개선
|
||||||
|
- ✅ kitten 통합 완료 (클립보드, 이미지, diff, 유니코드)
|
||||||
|
- 추가 테마 설치 (Tokyo Night, Catppuccin 등)
|
||||||
|
- 더 많은 kitten 탐색 (session, transfer 등)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 노트
|
||||||
|
|
||||||
|
이 설정은 macOS와 kitty 0.42.2 버전을 기준으로 작성되었습니다. 다른 OS나 버전에서는 일부 설정이 다를 수 있습니다.
|
||||||
|
|
||||||
|
설정에 문제가 있거나 개선이 필요한 부분이 있다면 각 설정 파일을 개별적으로 수정할 수 있습니다.
|
||||||
|
|
||||||
|
**Happy coding! 🎉**
|
||||||
276
openappsec-setup-20250817.md
Normal file
276
openappsec-setup-20250817.md
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
# OpenAppSec Separate Container 구성 완료 보고서
|
||||||
|
|
||||||
|
## 📋 프로젝트 개요
|
||||||
|
|
||||||
|
**목표**: OpenAppSec을 incus 환경에서 Separate Container 방식으로 구성하여 1000명 동시접속 처리
|
||||||
|
|
||||||
|
**완료일**: 2025-08-17
|
||||||
|
**환경**: incus 컨테이너 플랫폼, 8코어 CPU, 15.6GB RAM
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🏗️ 최종 아키텍처
|
||||||
|
|
||||||
|
### Separate Container 구조
|
||||||
|
```
|
||||||
|
Client Request
|
||||||
|
↓
|
||||||
|
nginx-attachment (10.90.135.233)
|
||||||
|
↓ (Unix Socket via /dev/shm)
|
||||||
|
OpenAppSec Agent (10.90.135.243)
|
||||||
|
↓ (ML Security Analysis)
|
||||||
|
Backend Decision (Allow/Block)
|
||||||
|
↓
|
||||||
|
Caddy Server (10.90.135.16)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 컨테이너 구성
|
||||||
|
|
||||||
|
| 컨테이너명 | 이미지 | IP 주소 | 역할 | 리소스 |
|
||||||
|
|-----------|--------|---------|------|---------|
|
||||||
|
| **openappsec-oci** | `ghcr.io/openappsec/nginx-attachment:latest` | 10.90.135.233 | nginx + attachment | 4 CPU, 4GB RAM |
|
||||||
|
| **openappsec-agent** | `ghcr.io/openappsec/agent:latest` | 10.90.135.243 | ML 보안 엔진 | 4 CPU, 4GB RAM |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 핵심 설정
|
||||||
|
|
||||||
|
### 1. IPC 통신 구성
|
||||||
|
```bash
|
||||||
|
# 두 컨테이너 모두 호스트 IPC 네임스페이스 공유
|
||||||
|
incus config set openappsec-oci raw.lxc="lxc.namespace.share.ipc=1"
|
||||||
|
incus config set openappsec-agent raw.lxc="lxc.namespace.share.ipc=1"
|
||||||
|
|
||||||
|
# 호스트 공유 메모리 마운트
|
||||||
|
incus config set openappsec-oci raw.lxc="lxc.namespace.share.ipc=1"$'\n'"lxc.mount.entry=/dev/shm dev/shm none bind,create=dir 0 0"
|
||||||
|
incus config set openappsec-agent raw.lxc="lxc.namespace.share.ipc=1"$'\n'"lxc.mount.entry=/dev/shm dev/shm none bind,create=dir 0 0"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 스토리지 볼륨 구성
|
||||||
|
```bash
|
||||||
|
# 정책 파일용 영구 스토리지
|
||||||
|
incus storage volume create default appsec
|
||||||
|
incus config device add openappsec-oci appsec-volume disk pool=default source=appsec path=/ext/appsec
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 보안 정책 설정
|
||||||
|
```yaml
|
||||||
|
# /ext/appsec/local_policy.yaml
|
||||||
|
policies:
|
||||||
|
default:
|
||||||
|
mode: detect # 학습 모드
|
||||||
|
practices: [appsec-best-practice]
|
||||||
|
triggers: [appsec-log-trigger]
|
||||||
|
custom-response: 403-forbidden
|
||||||
|
|
||||||
|
practices:
|
||||||
|
- name: appsec-best-practice
|
||||||
|
web-attacks:
|
||||||
|
minimum-confidence: medium
|
||||||
|
override-mode: detect
|
||||||
|
max-body-size-kb: 1000
|
||||||
|
|
||||||
|
log-triggers:
|
||||||
|
- name: appsec-log-trigger
|
||||||
|
appsec-logging:
|
||||||
|
detect-events: true
|
||||||
|
prevent-events: true
|
||||||
|
log-destination:
|
||||||
|
stdout:
|
||||||
|
format: json
|
||||||
|
file:
|
||||||
|
path: /ext/appsec/security.log
|
||||||
|
format: json
|
||||||
|
max-file-size-mb: 100
|
||||||
|
max-files: 5
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ 검증 결과
|
||||||
|
|
||||||
|
### 1. 컨테이너 상태
|
||||||
|
```bash
|
||||||
|
$ incus list | grep openappsec
|
||||||
|
| openappsec-agent | RUNNING | 10.90.135.243 (eth0) | CONTAINER (APP) |
|
||||||
|
| openappsec-oci | RUNNING | 10.90.135.233 (eth0) | CONTAINER (APP) |
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. IPC 통신 확인
|
||||||
|
```bash
|
||||||
|
$ incus exec openappsec-oci -- ls -la /dev/shm/check-point/
|
||||||
|
srw-rw-rw- 1 root root 0 Aug 17 06:07 cp-nano-attachment-registration
|
||||||
|
srw-rw-rw- 1 root root 0 Aug 17 06:07 cp-nano-http-transaction-handler-1
|
||||||
|
srw-rw-rw- 1 root root 0 Aug 17 06:07 cp-nano-http-transaction-handler-2
|
||||||
|
srw-rw-rw- 1 root root 0 Aug 17 06:07 cp-nano-http-transaction-handler-3
|
||||||
|
srw-rw-rw- 1 root root 0 Aug 17 06:07 cp-nano-http-transaction-handler-4
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Agent 프로세스 확인
|
||||||
|
```bash
|
||||||
|
$ incus exec openappsec-agent -- ps aux | grep cp-nano
|
||||||
|
root 952 /etc/cp/orchestration/cp-nano-orchestration --orchestration-mode=hybrid_mode
|
||||||
|
root 985 /etc/cp/attachmentRegistrator/cp-nano-attachment-registrator
|
||||||
|
root 1036 /etc/cp/agentCache/cp-nano-agent-cache 127.0.0.1:6379
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 네트워크 테스트
|
||||||
|
```bash
|
||||||
|
$ curl -s http://10.90.135.233/health
|
||||||
|
OCI OpenAppSec OK
|
||||||
|
|
||||||
|
$ curl -s -I http://10.90.135.233/ | grep X-Security
|
||||||
|
X-Security: OpenAppSec-OCI
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 성능 최적화
|
||||||
|
|
||||||
|
### 1000명 동시접속 대응 설정
|
||||||
|
|
||||||
|
#### nginx-attachment 최적화
|
||||||
|
```nginx
|
||||||
|
# /etc/nginx/nginx.conf
|
||||||
|
worker_processes 4; # 1000명/4 = 250명/워커
|
||||||
|
worker_connections 512; # 안전 여유분 포함
|
||||||
|
client_body_buffer_size 64k; # 메모리 효율성
|
||||||
|
keepalive_timeout 10s; # 빠른 연결 회전
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 리소스 제한
|
||||||
|
```bash
|
||||||
|
# 각 컨테이너 4 CPU, 4GB RAM으로 제한
|
||||||
|
incus config set openappsec-oci limits.cpu=4 limits.memory=4GB
|
||||||
|
incus config set openappsec-agent limits.cpu=4 limits.memory=4GB
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔍 문제 해결 과정
|
||||||
|
|
||||||
|
### 1. 초기 문제: nginx-attachment만으로는 보안 기능 미작동
|
||||||
|
**원인**: attachment 모듈만 있고 실제 보안 분석을 담당하는 agent가 없음
|
||||||
|
**해결**: Separate Container 방식으로 agent 컨테이너 추가
|
||||||
|
|
||||||
|
### 2. IPC 통신 문제
|
||||||
|
**원인**: incus에서 `lxc.namespace.share.ipc=host` 문법 오류
|
||||||
|
**해결**: `lxc.namespace.share.ipc=1` (PID 1) 사용
|
||||||
|
|
||||||
|
### 3. Unix Socket 공유 문제
|
||||||
|
**원인**: 각 컨테이너가 독립적인 tmpfs 사용
|
||||||
|
**해결**: 호스트 `/dev/shm` 디렉토리를 두 컨테이너에 바인드 마운트
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Separate Container vs Unified Container 비교
|
||||||
|
|
||||||
|
| 구분 | Separate Container | Unified Container |
|
||||||
|
|------|-------------------|-------------------|
|
||||||
|
| **구성 복잡도** | 높음 (2개 컨테이너) | 낮음 (1개 컨테이너) |
|
||||||
|
| **리소스 효율성** | 독립적 스케일링 가능 | 고정적 리소스 할당 |
|
||||||
|
| **장애 격리** | 우수 (agent 장애 시 nginx 계속 동작) | 보통 (전체 장애) |
|
||||||
|
| **업데이트 유연성** | 독립적 업데이트 가능 | 통합 업데이트 필요 |
|
||||||
|
| **성능** | Unix Socket 오버헤드 | 프로세스 간 직접 통신 |
|
||||||
|
| **운영 복잡도** | 높음 | 낮음 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 장점 및 활용 방안
|
||||||
|
|
||||||
|
### Separate Container 방식의 장점
|
||||||
|
|
||||||
|
1. **확장성**
|
||||||
|
- nginx 트래픽 증가 시: attachment 컨테이너만 스케일 아웃
|
||||||
|
- 보안 처리 부하 증가 시: agent 컨테이너만 리소스 증설
|
||||||
|
|
||||||
|
2. **멀티 서비스 지원**
|
||||||
|
- 하나의 agent로 여러 nginx 인스턴스 처리 가능
|
||||||
|
- 중앙 집중식 보안 정책 관리
|
||||||
|
|
||||||
|
3. **운영 유연성**
|
||||||
|
- 독립적인 업데이트 및 배포
|
||||||
|
- 컴포넌트별 모니터링 및 로깅
|
||||||
|
|
||||||
|
### 향후 확장 계획
|
||||||
|
|
||||||
|
1. **고가용성 구성**
|
||||||
|
```bash
|
||||||
|
# Agent 이중화
|
||||||
|
incus copy openappsec-agent openappsec-agent-backup
|
||||||
|
|
||||||
|
# nginx-attachment 로드밸런싱
|
||||||
|
incus copy openappsec-oci openappsec-oci-2
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **모니터링 구성**
|
||||||
|
- nginx-attachment: 응답 속도, 처리량 모니터링
|
||||||
|
- agent: 위협 탐지율, ML 정확도 모니터링
|
||||||
|
|
||||||
|
3. **보안 정책 고도화**
|
||||||
|
- 학습 모드 → 차단 모드 전환
|
||||||
|
- 도메인별 차별화된 보안 정책
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 체크리스트
|
||||||
|
|
||||||
|
### 필수 구성 요소
|
||||||
|
- [x] nginx-attachment 컨테이너 (ghcr.io/openappsec/nginx-attachment:latest)
|
||||||
|
- [x] agent 컨테이너 (ghcr.io/openappsec/agent:latest)
|
||||||
|
- [x] IPC 네임스페이스 공유 설정
|
||||||
|
- [x] 공유 메모리 마운트 (/dev/shm)
|
||||||
|
- [x] 보안 정책 파일 (local_policy.yaml)
|
||||||
|
- [x] 영구 스토리지 볼륨 (appsec)
|
||||||
|
|
||||||
|
### 검증 항목
|
||||||
|
- [x] 컨테이너 정상 실행
|
||||||
|
- [x] Unix Socket 생성 확인
|
||||||
|
- [x] Agent 프로세스 실행 확인
|
||||||
|
- [x] 웹 서비스 응답 확인
|
||||||
|
- [x] 보안 헤더 확인
|
||||||
|
|
||||||
|
### 성능 테스트
|
||||||
|
- [x] 기본 응답 속도 테스트
|
||||||
|
- [x] 1000명 동접 리소스 계산
|
||||||
|
- [x] 컨테이너 리소스 제한 설정
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛡️ 보안 고려사항
|
||||||
|
|
||||||
|
1. **IPC 네임스페이스 공유 위험성**
|
||||||
|
- 호스트 IPC 자원에 접근 가능
|
||||||
|
- 프로덕션 환경에서는 추가 격리 방안 검토 필요
|
||||||
|
|
||||||
|
2. **정책 파일 보안**
|
||||||
|
- `/ext/appsec/local_policy.yaml` 파일 권한 관리
|
||||||
|
- 민감한 설정 정보 암호화 검토
|
||||||
|
|
||||||
|
3. **로깅 및 모니터링**
|
||||||
|
- 보안 이벤트 로그 중앙 집중화
|
||||||
|
- 실시간 위협 탐지 알림 구성
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📞 지원 및 문의
|
||||||
|
|
||||||
|
**OpenAppSec 공식 문서**: https://docs.openappsec.io/
|
||||||
|
**GitHub Repository**: https://github.com/openappsec/openappsec
|
||||||
|
**Community Forum**: https://community.openappsec.io/
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📅 버전 정보
|
||||||
|
|
||||||
|
- **OpenAppSec nginx-attachment**: latest (2025-08-17)
|
||||||
|
- **OpenAppSec agent**: latest (2025-08-17)
|
||||||
|
- **incus**: 최신 버전
|
||||||
|
- **nginx**: 1.25.4
|
||||||
|
- **정책 파일 버전**: v1.0 (detect 모드)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**문서 작성**: Claude Code SuperClaude Framework
|
||||||
|
**최종 수정**: 2025-08-17
|
||||||
|
**상태**: 구성 완료 ✅
|
||||||
808
xray-proxy-guide.md
Normal file
808
xray-proxy-guide.md
Normal file
@@ -0,0 +1,808 @@
|
|||||||
|
# Xray 프록시 완벽 가이드: XHTTP & Reality
|
||||||
|
|
||||||
|
> 검열 우회를 위한 스텔스 프록시 구축 가이드
|
||||||
|
>
|
||||||
|
> 참고 영상: [How to Hide a Proxy Inside a Real Website (Xray + XHTTP)](https://www.youtube.com/watch?v=NziF6Srh-08) - LinuxCloudHacks
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 목차
|
||||||
|
|
||||||
|
1. [핵심 개념](#핵심-개념)
|
||||||
|
2. [프로토콜 스택 이해](#프로토콜-스택-이해)
|
||||||
|
3. [XHTTP 설정](#xhttp-설정)
|
||||||
|
4. [Reality 설정](#reality-설정)
|
||||||
|
5. [XHTTP vs Reality 비교](#xhttp-vs-reality-비교)
|
||||||
|
6. [TLS와 검열 우회 원리](#tls와-검열-우회-원리)
|
||||||
|
7. [트러블슈팅](#트러블슈팅)
|
||||||
|
8. [참고 자료](#참고-자료)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 핵심 개념
|
||||||
|
|
||||||
|
### 현대 검열의 문제점
|
||||||
|
|
||||||
|
기존 VPN/프록시가 차단되는 이유:
|
||||||
|
|
||||||
|
| 방식 | 탐지 방법 |
|
||||||
|
|------|----------|
|
||||||
|
| 일반 VPN | VPN 프로토콜 시그니처 탐지 |
|
||||||
|
| Shadowsocks | 랜덤 노이즈 패턴 → DPI가 "비정상" 판단 |
|
||||||
|
| 단순 프록시 | 특이한 포트, 서버 프로빙 시 프록시 응답 |
|
||||||
|
|
||||||
|
### 해결책: 섞여들기 (Blending In)
|
||||||
|
|
||||||
|
> "현대 검열은 숨김으로 이기는 게 아니라, **섞여들어감**으로 이긴다"
|
||||||
|
|
||||||
|
- 일반 HTTPS 트래픽처럼 보이게 위장
|
||||||
|
- 실제 웹사이트 또는 대형 사이트의 TLS를 활용
|
||||||
|
- 클라이언트와 서버 양쪽 모두 위장 필요
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 프로토콜 스택 이해
|
||||||
|
|
||||||
|
### 3계층 구조
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────┐
|
||||||
|
│ TLS (누구처럼) │
|
||||||
|
│ - 암호화 │
|
||||||
|
│ - 핑거프린트 위장 (UTLS → Chrome 흉내) │
|
||||||
|
├─────────────────────────────────────────┤
|
||||||
|
│ XHTTP (어떻게) │
|
||||||
|
│ - HTTP POST/GET으로 데이터 전송 │
|
||||||
|
│ - 일반 API 트래픽처럼 보임 │
|
||||||
|
├─────────────────────────────────────────┤
|
||||||
|
│ VLESS (무엇을) │
|
||||||
|
│ - 프록시 프로토콜 │
|
||||||
|
│ - 경량, 상태 비저장 │
|
||||||
|
│ - UUID 기반 인증 │
|
||||||
|
└─────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### VLESS 프레임 구조
|
||||||
|
|
||||||
|
```
|
||||||
|
[버전][클라이언트ID][명령][포트][주소타입][주소][페이로드...]
|
||||||
|
1B 16B 1B 2B 1B 가변 가변
|
||||||
|
```
|
||||||
|
|
||||||
|
- **명령**: 1=TCP, 2=UDP
|
||||||
|
- **주소타입**: 1=IPv4, 2=도메인, 3=IPv6
|
||||||
|
- **암호화 없음** → 전송 계층(TLS)에서 처리
|
||||||
|
|
||||||
|
### XHTTP 동작 방식
|
||||||
|
|
||||||
|
```
|
||||||
|
클라이언트 → 서버: HTTP POST (세션ID + VLESS 프레임)
|
||||||
|
서버 → 클라이언트: HTTP GET (스트리밍 응답)
|
||||||
|
```
|
||||||
|
|
||||||
|
- 세션 ID로 다중 연결 관리
|
||||||
|
- 병렬 POST 요청 가능 (Head-of-line blocking 회피)
|
||||||
|
- 일반 REST API 호출처럼 보임
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## XHTTP 설정
|
||||||
|
|
||||||
|
### 아키텍처
|
||||||
|
|
||||||
|
```
|
||||||
|
[클라이언트]
|
||||||
|
↓ HTTPS (일반 브라우저처럼 보임)
|
||||||
|
[Nginx - Port 443]
|
||||||
|
├── / (루트) → 실제 게임 웹사이트
|
||||||
|
└── /api/stream (비밀 경로) → Xray (Port 8080)
|
||||||
|
↓
|
||||||
|
[인터넷]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 준비물
|
||||||
|
|
||||||
|
- Linux 서버 (VPS/클라우드)
|
||||||
|
- **도메인** (필수)
|
||||||
|
- DNS 제공자 (Cloudflare 등)
|
||||||
|
- 포트 80, 443 오픈
|
||||||
|
|
||||||
|
### 서버 설정
|
||||||
|
|
||||||
|
#### 1. Nginx + Certbot 설치
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt update && apt install -y nginx certbot python3-certbot-nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. 위장용 웹사이트 배포
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 기본 페이지 삭제 후 게임 템플릿 다운로드
|
||||||
|
rm /var/www/html/index.html
|
||||||
|
wget -O /var/www/html/index.html https://example.com/game-template.html
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. SSL 인증서 발급
|
||||||
|
|
||||||
|
```bash
|
||||||
|
certbot certonly --webroot -w /var/www/html -d yourdomain.com
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4. Xray 설치
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 5. UUID 생성
|
||||||
|
|
||||||
|
```bash
|
||||||
|
xray uuid
|
||||||
|
# 출력 예: a3482e88-686a-4a58-8126-99c9df64b060
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 6. Xray 서버 설정
|
||||||
|
|
||||||
|
`/usr/local/etc/xray/config.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"log": {
|
||||||
|
"loglevel": "warning"
|
||||||
|
},
|
||||||
|
"inbounds": [
|
||||||
|
{
|
||||||
|
"port": 8080,
|
||||||
|
"listen": "127.0.0.1",
|
||||||
|
"protocol": "vless",
|
||||||
|
"settings": {
|
||||||
|
"clients": [
|
||||||
|
{
|
||||||
|
"id": "여기에-UUID-입력"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"decryption": "none"
|
||||||
|
},
|
||||||
|
"streamSettings": {
|
||||||
|
"network": "xhttp",
|
||||||
|
"xhttpSettings": {
|
||||||
|
"path": "/api/stream"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outbounds": [
|
||||||
|
{
|
||||||
|
"protocol": "freedom"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 7. Nginx 설정
|
||||||
|
|
||||||
|
`/etc/nginx/sites-available/xray`:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name yourdomain.com;
|
||||||
|
return 301 https://$server_name$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name yourdomain.com;
|
||||||
|
|
||||||
|
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
|
||||||
|
|
||||||
|
# 루트: 실제 웹사이트 (위장용)
|
||||||
|
location / {
|
||||||
|
root /var/www/html;
|
||||||
|
index index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 비밀 경로: Xray로 프록시
|
||||||
|
location /api/stream {
|
||||||
|
proxy_pass http://127.0.0.1:8080;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header Connection "";
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_read_timeout 300s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ln -sf /etc/nginx/sites-available/xray /etc/nginx/sites-enabled/
|
||||||
|
rm -f /etc/nginx/sites-enabled/default
|
||||||
|
nginx -t && systemctl reload nginx
|
||||||
|
systemctl restart xray
|
||||||
|
```
|
||||||
|
|
||||||
|
### 클라이언트 설정
|
||||||
|
|
||||||
|
#### CLI (config.json)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"log": {
|
||||||
|
"loglevel": "warning"
|
||||||
|
},
|
||||||
|
"inbounds": [
|
||||||
|
{
|
||||||
|
"port": 1080,
|
||||||
|
"listen": "127.0.0.1",
|
||||||
|
"protocol": "socks"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outbounds": [
|
||||||
|
{
|
||||||
|
"protocol": "vless",
|
||||||
|
"settings": {
|
||||||
|
"vnext": [
|
||||||
|
{
|
||||||
|
"address": "yourdomain.com",
|
||||||
|
"port": 443,
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"id": "서버와-동일한-UUID",
|
||||||
|
"encryption": "none"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"streamSettings": {
|
||||||
|
"network": "xhttp",
|
||||||
|
"security": "tls",
|
||||||
|
"tlsSettings": {
|
||||||
|
"serverName": "yourdomain.com",
|
||||||
|
"fingerprint": "chrome"
|
||||||
|
},
|
||||||
|
"xhttpSettings": {
|
||||||
|
"path": "/api/stream"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### V2rayN GUI 설정
|
||||||
|
|
||||||
|
| 항목 | 값 |
|
||||||
|
|------|-----|
|
||||||
|
| Address | yourdomain.com |
|
||||||
|
| Port | 443 |
|
||||||
|
| UUID | 서버와 동일 |
|
||||||
|
| Network | xhttp |
|
||||||
|
| Path | /api/stream |
|
||||||
|
| TLS | 활성화 |
|
||||||
|
| SNI | yourdomain.com |
|
||||||
|
| Fingerprint | chrome |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Reality 설정
|
||||||
|
|
||||||
|
### Reality란?
|
||||||
|
|
||||||
|
> **도메인/인증서 없이, 대형 사이트의 TLS를 빌려 쓰는 기술**
|
||||||
|
|
||||||
|
```
|
||||||
|
[클라이언트] --TLS(SNI: www.microsoft.com)--> [내 서버:443]
|
||||||
|
↓
|
||||||
|
Reality가 TLS 처리
|
||||||
|
(microsoft.com 인증서 흉내)
|
||||||
|
↓
|
||||||
|
[인터넷]
|
||||||
|
```
|
||||||
|
|
||||||
|
외부에서 보이는 것: `www.microsoft.com`에 접속
|
||||||
|
실제: 내 VPS를 통해 터널링
|
||||||
|
|
||||||
|
### 준비물
|
||||||
|
|
||||||
|
- Linux 서버 (VPS/클라우드)
|
||||||
|
- 포트 443 오픈
|
||||||
|
- **도메인 불필요!**
|
||||||
|
|
||||||
|
### 서버 설정
|
||||||
|
|
||||||
|
#### 1. Xray 설치
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. 키 생성
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# UUID 생성
|
||||||
|
xray uuid
|
||||||
|
# 출력 예: a3482e88-686a-4a58-8126-99c9df64b060
|
||||||
|
|
||||||
|
# X25519 키쌍 생성
|
||||||
|
xray x25519
|
||||||
|
# 출력 예:
|
||||||
|
# Private key: 2KZ4uouMKgI8nR-LDJNP1_MHisCJOmKGj9jUjZLncVU
|
||||||
|
# Public key: Z84J2IelR9ch3k8VtlVhhs5ycBUlXA7wHBWcBrjqnAw
|
||||||
|
|
||||||
|
# Short ID 생성
|
||||||
|
openssl rand -hex 8
|
||||||
|
# 출력 예: 6ba85179e30d4fc2
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. 위장 사이트 선택
|
||||||
|
|
||||||
|
**선택 기준**:
|
||||||
|
|
||||||
|
| 조건 | 설명 |
|
||||||
|
|------|------|
|
||||||
|
| 외국 사이트 | 검열 대상이 아닌 사이트 |
|
||||||
|
| TLSv1.3 지원 | 필수 |
|
||||||
|
| H2 지원 | HTTP/2 지원 필요 |
|
||||||
|
| 리다이렉트 없음 | URL이 다른 곳으로 이동하지 않음 |
|
||||||
|
| 서버와 가까운 지역 | 보너스 (속도 향상) |
|
||||||
|
|
||||||
|
**추천 사이트**:
|
||||||
|
- `www.microsoft.com`
|
||||||
|
- `www.apple.com`
|
||||||
|
- `www.amazon.com`
|
||||||
|
- `www.cloudflare.com`
|
||||||
|
- `www.yahoo.com`
|
||||||
|
|
||||||
|
#### 4. 서버 설정 파일
|
||||||
|
|
||||||
|
`/usr/local/etc/xray/config.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"log": {
|
||||||
|
"loglevel": "warning"
|
||||||
|
},
|
||||||
|
"inbounds": [
|
||||||
|
{
|
||||||
|
"listen": "0.0.0.0",
|
||||||
|
"port": 443,
|
||||||
|
"protocol": "vless",
|
||||||
|
"settings": {
|
||||||
|
"clients": [
|
||||||
|
{
|
||||||
|
"id": "여기에-UUID-입력",
|
||||||
|
"flow": "xtls-rprx-vision"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"decryption": "none"
|
||||||
|
},
|
||||||
|
"streamSettings": {
|
||||||
|
"network": "tcp",
|
||||||
|
"security": "reality",
|
||||||
|
"realitySettings": {
|
||||||
|
"dest": "www.microsoft.com:443",
|
||||||
|
"serverNames": [
|
||||||
|
"www.microsoft.com",
|
||||||
|
"microsoft.com"
|
||||||
|
],
|
||||||
|
"privateKey": "여기에-Private-Key-입력",
|
||||||
|
"shortIds": [
|
||||||
|
"여기에-Short-ID-입력"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sniffing": {
|
||||||
|
"enabled": true,
|
||||||
|
"destOverride": ["http", "tls"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outbounds": [
|
||||||
|
{
|
||||||
|
"protocol": "freedom",
|
||||||
|
"tag": "direct"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl restart xray
|
||||||
|
systemctl status xray
|
||||||
|
```
|
||||||
|
|
||||||
|
### 클라이언트 설정
|
||||||
|
|
||||||
|
#### CLI (config.json)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"log": {
|
||||||
|
"loglevel": "warning"
|
||||||
|
},
|
||||||
|
"inbounds": [
|
||||||
|
{
|
||||||
|
"listen": "127.0.0.1",
|
||||||
|
"port": 1080,
|
||||||
|
"protocol": "socks"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outbounds": [
|
||||||
|
{
|
||||||
|
"protocol": "vless",
|
||||||
|
"settings": {
|
||||||
|
"vnext": [
|
||||||
|
{
|
||||||
|
"address": "서버-IP-주소",
|
||||||
|
"port": 443,
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"id": "서버와-동일한-UUID",
|
||||||
|
"encryption": "none",
|
||||||
|
"flow": "xtls-rprx-vision"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"streamSettings": {
|
||||||
|
"network": "tcp",
|
||||||
|
"security": "reality",
|
||||||
|
"realitySettings": {
|
||||||
|
"fingerprint": "chrome",
|
||||||
|
"serverName": "www.microsoft.com",
|
||||||
|
"publicKey": "서버의-Public-Key",
|
||||||
|
"shortId": "서버와-동일한-Short-ID"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tag": "proxy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"protocol": "freedom",
|
||||||
|
"tag": "direct"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### V2rayN GUI 설정
|
||||||
|
|
||||||
|
| 항목 | 값 |
|
||||||
|
|------|-----|
|
||||||
|
| Address | 서버 IP |
|
||||||
|
| Port | 443 |
|
||||||
|
| UUID | 생성한 UUID |
|
||||||
|
| Flow | xtls-rprx-vision |
|
||||||
|
| Network | tcp |
|
||||||
|
| TLS | reality |
|
||||||
|
| SNI | www.microsoft.com |
|
||||||
|
| Fingerprint | chrome |
|
||||||
|
| Public Key | 서버에서 생성한 공개키 |
|
||||||
|
| Short ID | 서버와 동일 |
|
||||||
|
|
||||||
|
### Docker로 설정 (간편)
|
||||||
|
|
||||||
|
#### docker-compose.yml
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
xray:
|
||||||
|
image: ghcr.io/xtls/xray-core:latest
|
||||||
|
container_name: xray-reality
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./config.json:/usr/local/etc/xray/config.json:ro
|
||||||
|
ports:
|
||||||
|
- "443:443/tcp"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 키 생성 (Docker)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run --rm ghcr.io/xtls/xray-core x25519
|
||||||
|
docker run --rm ghcr.io/xtls/xray-core uuid
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 실행
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## XHTTP vs Reality 비교
|
||||||
|
|
||||||
|
### 기능 비교
|
||||||
|
|
||||||
|
| 구분 | XHTTP | Reality |
|
||||||
|
|------|-------|---------|
|
||||||
|
| 도메인 | 필요 | **불필요** |
|
||||||
|
| SSL 인증서 | 필요 (Let's Encrypt) | **불필요** |
|
||||||
|
| Nginx | 필요 | **불필요** |
|
||||||
|
| 설정 시간 | 30분+ | **5분** |
|
||||||
|
| CDN 통과 | **가능** | 불가 |
|
||||||
|
| 위장 방식 | 실제 웹사이트 운영 | 대형 사이트 TLS 흉내 |
|
||||||
|
| SNI 노출 | 내 도메인 | 대형 사이트 (microsoft.com 등) |
|
||||||
|
|
||||||
|
### 사용 시나리오
|
||||||
|
|
||||||
|
#### Reality 사용
|
||||||
|
|
||||||
|
| 상황 | 이유 |
|
||||||
|
|------|------|
|
||||||
|
| 도메인 없음 | 도메인 구매/관리 불필요 |
|
||||||
|
| 빠른 설정 | 키 생성만으로 완료 |
|
||||||
|
| VPS만 있음 | IP 하나로 바로 시작 |
|
||||||
|
| 단순 우회 목적 | 복잡한 구성 불필요 |
|
||||||
|
| SNI 노출 걱정 | 대형 사이트로 위장 |
|
||||||
|
|
||||||
|
#### XHTTP 사용
|
||||||
|
|
||||||
|
| 상황 | 이유 |
|
||||||
|
|------|------|
|
||||||
|
| CDN 필요 | Cloudflare 등 CDN 뒤에 숨기기 |
|
||||||
|
| IP 차단 환경 | VPS IP가 이미 차단된 경우 |
|
||||||
|
| 실제 서비스 운영 | 웹사이트 + 프록시 동시 운영 |
|
||||||
|
| 다수 사용자 | 여러 명에게 서비스 제공 |
|
||||||
|
| 서버 프로빙 대응 | 443 접속 시 실제 웹사이트 표시 |
|
||||||
|
|
||||||
|
### 결정 가이드
|
||||||
|
|
||||||
|
```
|
||||||
|
도메인이 없다 ──────────────────→ Reality
|
||||||
|
│
|
||||||
|
↓ 있다
|
||||||
|
VPS IP가 차단됐다 ─────────────→ XHTTP + CDN
|
||||||
|
│
|
||||||
|
↓ 아니다
|
||||||
|
SNI 노출이 걱정된다 ───────────→ Reality
|
||||||
|
│
|
||||||
|
↓ 괜찮다
|
||||||
|
실제 웹사이트도 운영할 것이다 ──→ XHTTP
|
||||||
|
│
|
||||||
|
↓ 아니다
|
||||||
|
빠른 설정을 원한다 ────────────→ Reality
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## TLS와 검열 우회 원리
|
||||||
|
|
||||||
|
### TLS 핸드셰이크 구조
|
||||||
|
|
||||||
|
```
|
||||||
|
[클라이언트] [서버]
|
||||||
|
│ │
|
||||||
|
│─── Client Hello ──────────→│ 평문! (SNI 노출)
|
||||||
|
│ │
|
||||||
|
│←── Server Hello ───────────│
|
||||||
|
│←── Certificate ────────────│
|
||||||
|
│←── Server Key Exchange ────│
|
||||||
|
│ │
|
||||||
|
│─── Client Key Exchange ───→│
|
||||||
|
│─── Finished ──────────────→│
|
||||||
|
│ │
|
||||||
|
│←── Finished ───────────────│
|
||||||
|
│ │
|
||||||
|
[암호화 통신 시작]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Client Hello 구조
|
||||||
|
|
||||||
|
```
|
||||||
|
TLS Record Layer
|
||||||
|
├── Content Type: 0x16 (Handshake)
|
||||||
|
├── Version: 0x0301
|
||||||
|
└── Handshake Protocol
|
||||||
|
├── Type: 0x01 (Client Hello)
|
||||||
|
└── Client Hello Data
|
||||||
|
├── Version: 0x0303 (TLS 1.2)
|
||||||
|
├── Random: 32바이트
|
||||||
|
├── Session ID
|
||||||
|
├── Cipher Suites (암호화 목록)
|
||||||
|
├── Compression Methods
|
||||||
|
└── Extensions
|
||||||
|
├── SNI (server_name) ← 평문 노출!
|
||||||
|
├── Supported Versions
|
||||||
|
├── Signature Algorithms
|
||||||
|
└── ...
|
||||||
|
```
|
||||||
|
|
||||||
|
### SNI 노출 문제
|
||||||
|
|
||||||
|
**SNI(Server Name Indication)**는 TLS 암호화 **전**에 평문으로 전송됨:
|
||||||
|
|
||||||
|
```
|
||||||
|
Extension: server_name
|
||||||
|
├── Type: 0x0000 (SNI)
|
||||||
|
└── Server Name
|
||||||
|
└── Name: "www.microsoft.com" ← ISP가 볼 수 있음
|
||||||
|
```
|
||||||
|
|
||||||
|
| 방식 | SNI에 보이는 것 | 위험도 |
|
||||||
|
|------|----------------|--------|
|
||||||
|
| XHTTP | `myproxy.com` (내 도메인) | 도메인 차단 가능 |
|
||||||
|
| Reality | `www.microsoft.com` | 차단 어려움 |
|
||||||
|
|
||||||
|
### DPI 핑거프린팅
|
||||||
|
|
||||||
|
검열 시스템이 Client Hello를 분석하는 방식:
|
||||||
|
|
||||||
|
```
|
||||||
|
Client Hello 수신
|
||||||
|
↓
|
||||||
|
특징 추출:
|
||||||
|
- Cipher Suite 개수 및 순서
|
||||||
|
- Extension 목록 및 순서
|
||||||
|
- Supported Groups
|
||||||
|
- 전체 패킷 길이
|
||||||
|
↓
|
||||||
|
데이터베이스 비교:
|
||||||
|
- Chrome: 일치 ✓
|
||||||
|
- Firefox: 불일치
|
||||||
|
- Python requests: 불일치
|
||||||
|
↓
|
||||||
|
결과: "Chrome 브라우저로 판단"
|
||||||
|
```
|
||||||
|
|
||||||
|
### UTLS를 통한 위장
|
||||||
|
|
||||||
|
Xray는 **UTLS** 라이브러리를 사용하여 실제 브라우저의 Client Hello를 **바이트 단위로** 복제:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"tlsSettings": {
|
||||||
|
"fingerprint": "chrome" // Chrome의 정확한 핑거프린트 사용
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
복제하는 요소:
|
||||||
|
- Cipher Suites (암호화 알고리즘 목록 + 순서)
|
||||||
|
- Extensions (확장 목록 + 순서)
|
||||||
|
- Supported Groups (지원 곡선)
|
||||||
|
- Signature Algorithms (서명 알고리즘)
|
||||||
|
- ALPN (프로토콜 협상)
|
||||||
|
- Key Share (키 교환 데이터)
|
||||||
|
|
||||||
|
### 서버 측 위장의 필요성
|
||||||
|
|
||||||
|
**양방향 모두 위장 필요**:
|
||||||
|
|
||||||
|
| 방향 | 검사 대상 | 위장 주체 |
|
||||||
|
|------|----------|----------|
|
||||||
|
| Client → Server | Client Hello, SNI | 클라이언트 (UTLS) |
|
||||||
|
| Server → Client | 인증서, Server Hello | 서버 설정 |
|
||||||
|
|
||||||
|
#### Reality 서버의 프로빙 대응
|
||||||
|
|
||||||
|
```
|
||||||
|
정상 클라이언트 (올바른 shortId/publicKey):
|
||||||
|
↓
|
||||||
|
서버: "인증된 클라이언트"
|
||||||
|
↓
|
||||||
|
Reality 터널 연결 ✓
|
||||||
|
|
||||||
|
프로빙/스캐너 (shortId 없음):
|
||||||
|
↓
|
||||||
|
서버: "모르는 요청"
|
||||||
|
↓
|
||||||
|
실제 microsoft.com으로 포워딩
|
||||||
|
↓
|
||||||
|
스캐너: "그냥 microsoft.com이네" → 의심 없음
|
||||||
|
```
|
||||||
|
|
||||||
|
#### XHTTP 서버의 프로빙 대응
|
||||||
|
|
||||||
|
```
|
||||||
|
일반 접속 (루트 경로):
|
||||||
|
↓
|
||||||
|
Nginx: 게임 웹사이트 표시 ✓
|
||||||
|
|
||||||
|
프록시 클라이언트 (비밀 경로):
|
||||||
|
↓
|
||||||
|
Nginx: Xray로 프록시 ✓
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 트러블슈팅
|
||||||
|
|
||||||
|
### 공통 문제
|
||||||
|
|
||||||
|
| 문제 | 원인 | 해결 |
|
||||||
|
|------|------|------|
|
||||||
|
| 연결 안됨 | 방화벽 | 443 포트 오픈 확인 |
|
||||||
|
| 인증 실패 | UUID 불일치 | 서버/클라이언트 UUID 동일한지 확인 |
|
||||||
|
| 느린 속도 | 서버 위치 | 더 가까운 VPS 선택 |
|
||||||
|
|
||||||
|
### XHTTP 문제
|
||||||
|
|
||||||
|
| 문제 | 원인 | 해결 |
|
||||||
|
|------|------|------|
|
||||||
|
| 502 Bad Gateway | Xray 미실행 | `systemctl status xray` 확인 |
|
||||||
|
| SSL 에러 | 인증서 만료 | `certbot renew` 실행 |
|
||||||
|
| 경로 불일치 | path 설정 | Nginx와 Xray의 path 동일한지 확인 |
|
||||||
|
|
||||||
|
### Reality 문제
|
||||||
|
|
||||||
|
| 문제 | 원인 | 해결 |
|
||||||
|
|------|------|------|
|
||||||
|
| TLS 에러 | 위장 사이트 문제 | TLSv1.3 지원 사이트로 변경 |
|
||||||
|
| shortId 에러 | ID 불일치 | 서버/클라이언트 shortId 확인 |
|
||||||
|
| 키 에러 | 공개키/개인키 혼동 | 서버=개인키, 클라이언트=공개키 |
|
||||||
|
|
||||||
|
### 연결 테스트
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 서버에서 Xray 상태 확인
|
||||||
|
systemctl status xray
|
||||||
|
journalctl -u xray -f
|
||||||
|
|
||||||
|
# 클라이언트에서 연결 테스트
|
||||||
|
curl -x socks5h://127.0.0.1:1080 https://ipinfo.io
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 참고 자료
|
||||||
|
|
||||||
|
### 공식 문서
|
||||||
|
|
||||||
|
- [Project X 공식 문서](https://xtls.github.io/en/config/)
|
||||||
|
- [XTLS/Xray-core GitHub](https://github.com/XTLS/Xray-core)
|
||||||
|
|
||||||
|
### 튜토리얼
|
||||||
|
|
||||||
|
- [Xray REALITY Tutorial - cscot](https://cscot.pages.dev/2023/03/02/Xray-REALITY-tutorial/)
|
||||||
|
- [XRAY XTLS Reality in Docker](https://linuxguidance.net/xray-xtls-reality-in-docker/)
|
||||||
|
- [XRAY XHTTP Behind Cloudflare CDN](https://linuxguidance.net/xray-xhttp-server-behind-cloudflares-cdn-in-docker/)
|
||||||
|
- [Coexisting Xray VLESS with XHTTP-Reality](https://henrywithu.com/coexisting-xray-vless-tcp-xtls-vision-and-vless-xhttp-reality-on-a-single-port/)
|
||||||
|
|
||||||
|
### GitHub Discussions
|
||||||
|
|
||||||
|
- [VLESS + TCP + REALITY + VISION 설정](https://github.com/XTLS/Xray-core/discussions/3518)
|
||||||
|
- [Xray + VLESS + Reality + Caddy](https://github.com/XTLS/Xray-core/discussions/4542)
|
||||||
|
|
||||||
|
### 클라이언트 앱
|
||||||
|
|
||||||
|
- **Windows**: [v2rayN](https://github.com/2dust/v2rayN)
|
||||||
|
- **macOS**: [V2rayU](https://github.com/yanue/V2rayU)
|
||||||
|
- **Android**: [v2rayNG](https://github.com/2dust/v2rayNG)
|
||||||
|
- **iOS**: Shadowrocket (유료), Quantumult X
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 부록: 빠른 설정 체크리스트
|
||||||
|
|
||||||
|
### Reality 설정 (5분)
|
||||||
|
|
||||||
|
- [ ] VPS 준비 (포트 443 오픈)
|
||||||
|
- [ ] Xray 설치
|
||||||
|
- [ ] UUID 생성
|
||||||
|
- [ ] X25519 키쌍 생성
|
||||||
|
- [ ] Short ID 생성
|
||||||
|
- [ ] 서버 config.json 작성
|
||||||
|
- [ ] 클라이언트 설정
|
||||||
|
|
||||||
|
### XHTTP 설정 (30분)
|
||||||
|
|
||||||
|
- [ ] VPS 준비 (포트 80, 443 오픈)
|
||||||
|
- [ ] 도메인 준비 + DNS 설정
|
||||||
|
- [ ] Nginx 설치
|
||||||
|
- [ ] 위장용 웹사이트 배포
|
||||||
|
- [ ] Certbot으로 SSL 인증서 발급
|
||||||
|
- [ ] Xray 설치
|
||||||
|
- [ ] UUID 생성
|
||||||
|
- [ ] Xray config.json 작성
|
||||||
|
- [ ] Nginx 설정 (루트 + 비밀 경로)
|
||||||
|
- [ ] 클라이언트 설정
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*마지막 업데이트: 2025-01*
|
||||||
Reference in New Issue
Block a user