docs: add MC Domain Filter Proxy spec
This commit is contained in:
223
mc-domain-filter.md
Normal file
223
mc-domain-filter.md
Normal file
@@ -0,0 +1,223 @@
|
||||
# MC Domain Filter Proxy
|
||||
|
||||
마인크래프트 서버 접속 시 특정 도메인(`mc.tkrmagid.kr`)으로만 접속 가능하게 필터링하는 프록시 + 웹 관리 대시보드
|
||||
|
||||
---
|
||||
|
||||
## 프로젝트 개요
|
||||
|
||||
### 목적
|
||||
- 외부 IP 직접입력, 다른 도메인으로 접속 시 차단
|
||||
- `mc.tkrmagid.kr` 도메인으로만 마인크래프트 서버 접속 허용
|
||||
- Fabric, Paper, Spigot, NeoForge 등 **어떤 서버 종류든 무관하게** 동작
|
||||
|
||||
### 동작 원리
|
||||
마인크래프트 클라이언트는 접속 시 첫 핸드셰이크 패킷에 사용자가 입력한 주소(서버 주소창의 문자열)를 담아 전송한다.
|
||||
이 프록시는 해당 패킷을 읽어 허용된 도메인이 아니면 연결을 즉시 차단한다.
|
||||
|
||||
### 네트워크 구조
|
||||
```
|
||||
외부 인터넷
|
||||
↓
|
||||
공유기 (포트포워딩 25565 → Proxmox IP)
|
||||
↓
|
||||
Proxmox Docker 컨테이너 (MC Domain Filter)
|
||||
↓
|
||||
게임PC 내부IP:25565 (실제 마인크래프트 서버)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 기술 스택
|
||||
|
||||
| 구성 요소 | 기술 |
|
||||
|-----------|------|
|
||||
| 프록시 코어 | Python (asyncio) |
|
||||
| 웹 대시보드 | React + Vite (또는 Next.js) |
|
||||
| 백엔드 API | FastAPI |
|
||||
| 설정 저장 | JSON 파일 (sqlite도 가능) |
|
||||
| 컨테이너 | Docker + docker-compose |
|
||||
| 리버스 프록시 | nginx (대시보드용) |
|
||||
|
||||
---
|
||||
|
||||
## 기능 요구사항
|
||||
|
||||
### 핵심 기능 (프록시)
|
||||
- [ ] Minecraft 핸드셰이크 패킷 파싱 (varint 포함)
|
||||
- [ ] 허용 도메인 리스트와 비교 후 차단/통과 결정
|
||||
- [ ] 통과된 패킷을 백엔드 서버로 투명하게 중계
|
||||
- [ ] 첫 패킷 이후 양방향 TCP 터널링
|
||||
|
||||
### 웹 대시보드 (NPM 스타일 UI)
|
||||
- [ ] **허용 도메인 관리** - 추가 / 삭제 / 활성화 토글
|
||||
- [ ] **백엔드 서버 설정** - 게임PC IP, 포트 변경
|
||||
- [ ] **실시간 접속 로그** - 허용/차단 내역, 접속 IP, 사용 도메인, 시각
|
||||
- [ ] **대시보드 홈** - 현재 상태, 총 접속 수, 차단 수 통계 카드
|
||||
- [ ] **프록시 on/off** 토글
|
||||
- [ ] 설정 변경 후 프록시 재시작 없이 즉시 반영 (hot reload)
|
||||
|
||||
### UI 디자인 레퍼런스
|
||||
- **Nginx Proxy Manager Plus** 스타일
|
||||
- 다크/라이트 모드
|
||||
- 사이드바 네비게이션
|
||||
- 카드 기반 레이아웃
|
||||
- 토글 스위치, 모달 폼
|
||||
|
||||
---
|
||||
|
||||
## 프로젝트 구조
|
||||
|
||||
```
|
||||
mc-domain-filter/
|
||||
├── docker-compose.yml
|
||||
├── proxy/
|
||||
│ ├── Dockerfile
|
||||
│ ├── main.py # asyncio TCP 프록시
|
||||
│ ├── config.py # 설정 로드/저장
|
||||
│ ├── handshake.py # MC 핸드셰이크 파서
|
||||
│ └── requirements.txt
|
||||
├── api/
|
||||
│ ├── Dockerfile
|
||||
│ ├── main.py # FastAPI 백엔드
|
||||
│ ├── routes/
|
||||
│ │ ├── config.py # 설정 CRUD
|
||||
│ │ └── logs.py # 로그 조회
|
||||
│ └── requirements.txt
|
||||
├── frontend/
|
||||
│ ├── Dockerfile
|
||||
│ ├── src/
|
||||
│ │ ├── pages/
|
||||
│ │ │ ├── Dashboard.jsx
|
||||
│ │ │ ├── Domains.jsx
|
||||
│ │ │ └── Logs.jsx
|
||||
│ │ └── components/
|
||||
│ └── package.json
|
||||
├── nginx/
|
||||
│ └── nginx.conf
|
||||
└── data/
|
||||
├── config.json # 설정 파일 (볼륨 마운트)
|
||||
└── logs.db # 접속 로그
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 설정 파일 구조 (config.json)
|
||||
|
||||
```json
|
||||
{
|
||||
"proxy": {
|
||||
"listen_port": 25565,
|
||||
"enabled": true
|
||||
},
|
||||
"backend": {
|
||||
"host": "192.168.0.xx",
|
||||
"port": 25565
|
||||
},
|
||||
"allowed_domains": [
|
||||
{
|
||||
"domain": "mc.tkrmagid.kr",
|
||||
"enabled": true,
|
||||
"note": "메인 도메인"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Minecraft 핸드셰이크 파싱
|
||||
|
||||
```
|
||||
패킷 구조:
|
||||
[varint] Packet Length
|
||||
[varint] Packet ID (0x00)
|
||||
[varint] Protocol Version
|
||||
[varint] Server Address Length
|
||||
[string] Server Address ← 이게 클라이언트가 입력한 주소
|
||||
[ushort] Server Port
|
||||
[varint] Next State (1=status, 2=login)
|
||||
```
|
||||
|
||||
서버 주소 끝에 `\x00` 널 문자가 붙는 경우 있음 → strip 처리 필요
|
||||
|
||||
---
|
||||
|
||||
## docker-compose.yml 예시
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
services:
|
||||
proxy:
|
||||
build: ./proxy
|
||||
ports:
|
||||
- "25565:25565"
|
||||
volumes:
|
||||
- ./data:/data
|
||||
restart: unless-stopped
|
||||
network_mode: bridge
|
||||
|
||||
api:
|
||||
build: ./api
|
||||
expose:
|
||||
- "8000"
|
||||
volumes:
|
||||
- ./data:/data
|
||||
restart: unless-stopped
|
||||
|
||||
frontend:
|
||||
build: ./frontend
|
||||
expose:
|
||||
- "3000"
|
||||
restart: unless-stopped
|
||||
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
ports:
|
||||
- "8080:80" # 대시보드 접근 포트
|
||||
volumes:
|
||||
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
|
||||
depends_on:
|
||||
- api
|
||||
- frontend
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API 엔드포인트
|
||||
|
||||
| 메서드 | 경로 | 설명 |
|
||||
|--------|------|------|
|
||||
| GET | `/api/config` | 전체 설정 조회 |
|
||||
| PUT | `/api/config` | 설정 저장 |
|
||||
| GET | `/api/domains` | 도메인 목록 |
|
||||
| POST | `/api/domains` | 도메인 추가 |
|
||||
| DELETE | `/api/domains/{domain}` | 도메인 삭제 |
|
||||
| PATCH | `/api/domains/{domain}` | 도메인 활성화/비활성화 |
|
||||
| GET | `/api/logs` | 접속 로그 (페이지네이션) |
|
||||
| GET | `/api/status` | 프록시 상태, 통계 |
|
||||
| POST | `/api/proxy/restart` | 프록시 재시작 |
|
||||
|
||||
---
|
||||
|
||||
## 환경 정보
|
||||
|
||||
### Proxmox 서버 스펙 (프록시 실행 환경)
|
||||
- CPU: Intel Core i3-10100 (4코어 8스레드, 3.6GHz, 최대 4.3GHz)
|
||||
- RAM: DDR4 32GB (Samsung 16GB × 2, 3200 MT/s, 듀얼채널)
|
||||
- 가상화: VT-x 지원
|
||||
|
||||
### 게임PC (실제 MC 서버)
|
||||
- 같은 공유기 내 LAN 환경
|
||||
- 내부 IP로 통신
|
||||
|
||||
---
|
||||
|
||||
## 주의사항
|
||||
|
||||
- 프록시와 FastAPI는 `data/config.json`을 공유 볼륨으로 사용
|
||||
- 설정 변경 시 프록시 프로세스에 SIGHUP 또는 내부 이벤트로 hot reload
|
||||
- 게임PC의 MC 서버는 포트 변경 불필요 (프록시가 25565→25565 그대로 중계)
|
||||
- 대시보드는 Proxmox 내부 IP:8080 으로 접근
|
||||
- 대시보드 포트(8080)는 외부에 포트포워딩 하지 않을 것 권장
|
||||
Reference in New Issue
Block a user