프로젝트 최종 완성
지난 프로젝트2(문서 중앙화 실패)의 경험을 바탕으로 처음부터 설계를 다시 잡아 완성한 기업용 DLP(Data Loss Prevention) + ECM(Enterprise Content Management) 시스템입니다.
GitHub: https://github.com/LEntropy/Document_Management
전체 구성 요소
| 구성 요소 |
기술 |
역할 |
| Spring Boot 서버 |
Java, AWS EC2 |
KMS 키 관리, ECM 파일 저장, JWT 인증, 정책 관리, 승인, 로그 |
| C# KmsClient |
.NET Framework 4.8 |
파일 암/복호화, .enc 열기, 저장 감지 재암호화 |
| DlpMiniFilter.sys |
C, WDK (커널 드라이버) |
파일 I/O 필터링, USB 차단, CDR 후보 마킹 |
| DlpAgent.Service |
C#, Windows 서비스 |
드라이버 Named Pipe 통신, 정책 적용, 감사 로그 전송 |
| MariaDB |
AWS RDS or EC2 내부 |
사용자, 정책, 파일 메타, 승인, 로그 테이블 |
| MinIO |
S3 호환 오브젝트 스토리지 |
암호화된 .enc 파일 저장 |
전체 통신 흐름도
┌─────────────────────────────────────────────────┐
│ Windows 클라이언트 PC │
│ │
│ ┌─────────────────┐ ┌───────────────────┐ │
│ │ C# KmsClient │ │ DlpAgent.Service │ │
│ │ (WinForms) │ │ (Windows 서비스) │ │
│ └────────┬────────┘ └────────┬──────────┘ │
│ │ │ Named Pipe │
│ │ ┌────┴──────────┐ │
│ │ │ DlpMiniFilter │ │
│ │ │ (.sys 드라이버)│ │
│ │ └───────────────┘ │
└───────────┼─────────────────────────────────────┘
│ TLS (port 8443) → KMS 복호화 요청
│ REST API (port 8080) → 파일 업/다운로드
▼
┌─────────────────────────────────────────────────┐
│ AWS EC2 서버 (3.37.149.78) │
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ Spring Boot KMS/ECM 서버 │ │
│ │ AuthController → JWT 인증 │ │
│ │ FileController → MinIO 업/다운로드 │ │
│ │ PolicyController → 정책 CRUD │ │
│ │ ApprovalController → USB/메일 승인 │ │
│ │ LogController → 감사 로그 │ │
│ └──────────┬──────────────────┬────────────┘ │
│ │ │ │
│ ┌──────┴──────┐ ┌──────┴──────┐ │
│ │ MariaDB │ │ MinIO │ │
│ │ (ecm_db) │ │ (ecm-files) │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────┘
파일 암호화 흐름 (업로드)
1. 사용자가 KmsClient에서 파일 선택
2. 랜덤 AES-256 키 + IV 생성
3. AES-256-CBC로 파일 암호화 → ciphertext
4. 서버 로그인 시 받은 조직 RSA 공개키(인증서)로 AES 키 암호화
5. .enc 파일 헤더 조립:
[Magic 4B][keyId][namespace][IV 16B][encKey 512B][ciphertext]
6. REST API로 MinIO에 .enc 파일 업로드 + FileMeta DB 저장
파일 복호화 흐름 (열기)
1. 사용자가 .enc 파일 더블클릭
2. 헤더 파싱: keyId, namespace, IV, encKey(512B) 추출
3. TLS 소켓(port 8443)으로 KMS 서버 연결
4. KMS 서버에 requesterOrg, fileOrg, keyId, encKey 전송
5. KMS 서버: 정책 확인(requesterOrg가 fileOrg 파일에 접근 가능?)
- 허용: RSA 개인키로 encKey 복호화 → rawAesKey 반환
- 거부: -403 반환 (팝업 알림)
6. rawAesKey + IV로 AES 복호화 → 원본 bytes
7. 보안 임시 폴더(%LOCALAPPDATA%/KmsClient/TempOpen/)에 저장
8. explorer.exe로 원본 앱 실행
9. 저장 감지(FileSystemWatcher) → 재암호화 → .enc 덮어쓰기
10. 30초 후 임시 파일 자동 삭제
DLP 정책 적용 흐름
1. DlpAgent.Service 시작 → Spring 서버에서 조직 정책 JSON 수신
예: { BlockRemovableWrite: true, BlockNetworkRename: true, ... }
2. Named Pipe로 DlpMiniFilter 드라이버에 정책 전달
3. 사용자가 USB에 파일 쓰기 시도:
DlpMiniFilter.PreWrite() 실행
→ DlpLocRemovable + BlockRemovableWrite=true
→ STATUS_ACCESS_DENIED 반환 (쓰기 차단)
→ Named Pipe로 DlpAgent.Service에 이벤트 전송
4. DlpAgent.Service → Spring 서버 감사 로그 전송
POST /api/log { action:"USB_BLOCKED", userId:"john", ... }
5. 관리자 화면에서 실시간 로그 조회 가능
USB 사용 승인 흐름
1. 직원: KmsClient에서 "USB 사용 신청" 버튼
2. POST /api/approval/request { type:"USB", reason:"출장 자료 복사", expireAt:"2025-01-10" }
3. 관리자: 승인 화면에서 확인
4. PUT /api/approval/{id}/status?status=APPROVED
5. DlpAgent.Service가 주기적으로 GET /api/approval/status/{user}/USB 폴링
6. APPROVED + expireAt 이내 → BlockRemovableWrite=false 적용
만료 후 → 자동으로 차단 복구
보안 설계 원칙
| 원칙 |
구현 |
| 클라이언트는 개인키 없음 |
RSA 개인키는 KMS 서버에만 존재. 복호화는 항상 서버 인증 후 |
| 임시 파일 격리 |
복호화 파일은 현재 사용자 ACL로 보호된 TempOpen 폴더에만 존재 |
| 자동 재암호화 |
저장 후 즉시 .enc로 재암호화, 원본 bytes는 메모리에만 존재 |
| 조직 간 접근 제어 |
KMS 서버가 requesterOrg/fileOrg 검증 (-403 Forbidden) |
| 커널 레벨 차단 |
USB/네트워크 쓰기 차단은 드라이버 레벨 → 우회 불가 |
| 감사 로그 |
모든 파일 접근, USB 차단, 로그인 이벤트 서버 기록 |
실패했던 프로젝트2와의 차이
| 항목 |
프로젝트2 (실패) |
프로젝트4 (성공) |
| 아키텍처 설계 |
기능 목록만 있고 데이터 흐름 설계 없음 |
통신 흐름 먼저 설계 후 구현 |
| 암호화 키 관리 |
Key/IV를 DB에 저장했지만 복호화 레이어 미완 |
KMS 서버가 키 관리, 클라이언트는 개인키 불보유 |
| 파일 서버 |
Samba 권한 설계 미완 |
MinIO S3 호환 스토리지로 단순화 |
| 통합 테스트 |
Linux C + Windows C# 혼합 환경 테스트 어려움 |
Spring REST API + C# 클라이언트로 명확한 경계 |
| 드라이버 |
미구현 |
Windows Minifilter 드라이버 완성 |