Skip to content

Commit d37ca24

Browse files
feat: 新增一键防护服务模块,支持多级别安全策略
1 parent d07e128 commit d37ca24

3 files changed

Lines changed: 383 additions & 0 deletions

File tree

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""
2+
Protection Service Module
3+
一键保护服务模块
4+
"""
5+
6+
from networksecurity.protection.service import (
7+
ProtectionService,
8+
ProtectionStatus,
9+
ProtectionLevel,
10+
ProtectionStats,
11+
get_protection_service
12+
)
13+
14+
from networksecurity.protection.api import protection_router
15+
16+
__all__ = [
17+
'ProtectionService',
18+
'ProtectionStatus',
19+
'ProtectionLevel',
20+
'ProtectionStats',
21+
'get_protection_service',
22+
'protection_router'
23+
]

networksecurity/protection/api.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
"""
2+
保护服务API路由
3+
提供一键开启/关闭防护的REST API
4+
"""
5+
6+
from fastapi import APIRouter, HTTPException
7+
from pydantic import BaseModel
8+
from typing import Optional, Dict, Any
9+
10+
from networksecurity.protection.service import (
11+
get_protection_service,
12+
ProtectionLevel,
13+
ProtectionStatus
14+
)
15+
16+
protection_router = APIRouter(prefix="/api/v1/protection", tags=["Protection"])
17+
18+
19+
class ToggleRequest(BaseModel):
20+
level: Optional[str] = None
21+
22+
23+
class LevelRequest(BaseModel):
24+
level: str
25+
26+
27+
class ConfigRequest(BaseModel):
28+
config: Dict[str, Any]
29+
30+
31+
@protection_router.get("/state")
32+
async def get_state():
33+
"""获取保护状态"""
34+
service = get_protection_service()
35+
return service.get_state()
36+
37+
38+
@protection_router.post("/start")
39+
async def start_protection(request: Optional[ToggleRequest] = None):
40+
"""启动保护服务"""
41+
service = get_protection_service()
42+
level = None
43+
if request and request.level:
44+
try:
45+
level = ProtectionLevel(request.level)
46+
except ValueError:
47+
raise HTTPException(400, f"无效的保护级别: {request.level}")
48+
return await service.start(level)
49+
50+
51+
@protection_router.post("/stop")
52+
async def stop_protection():
53+
"""停止保护服务"""
54+
service = get_protection_service()
55+
return await service.stop()
56+
57+
58+
@protection_router.post("/toggle")
59+
async def toggle_protection():
60+
"""切换保护状态"""
61+
service = get_protection_service()
62+
return await service.toggle()
63+
64+
65+
@protection_router.post("/level")
66+
async def set_level(request: LevelRequest):
67+
"""设置保护级别"""
68+
service = get_protection_service()
69+
try:
70+
level = ProtectionLevel(request.level)
71+
except ValueError:
72+
raise HTTPException(400, f"无效的保护级别: {request.level}")
73+
return service.set_level(level)
74+
75+
76+
@protection_router.post("/config")
77+
async def update_config(request: ConfigRequest):
78+
"""更新配置"""
79+
service = get_protection_service()
80+
return service.update_config(request.config)
81+
82+
83+
@protection_router.get("/health")
84+
async def health():
85+
"""健康检查"""
86+
service = get_protection_service()
87+
return {
88+
"status": "healthy",
89+
"protection_active": service.is_active,
90+
"level": service.level.value
91+
}
Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
"""
2+
一键保护服务
3+
提供类似VPN的一键开启/关闭防护功能
4+
"""
5+
6+
import asyncio
7+
import threading
8+
import time
9+
import logging
10+
from datetime import datetime
11+
from typing import Optional, Dict, Any, List
12+
from dataclasses import dataclass, field
13+
from enum import Enum
14+
15+
logger = logging.getLogger(__name__)
16+
17+
18+
class ProtectionStatus(str, Enum):
19+
"""保护状态"""
20+
OFF = "off"
21+
STARTING = "starting"
22+
ON = "on"
23+
STOPPING = "stopping"
24+
ERROR = "error"
25+
26+
27+
class ProtectionLevel(str, Enum):
28+
"""保护级别"""
29+
LOW = "low" # 仅监控,不拦截
30+
MEDIUM = "medium" # 拦截高风险
31+
HIGH = "high" # 拦截中高风险
32+
STRICT = "strict" # 严格模式,拦截所有可疑
33+
34+
35+
@dataclass
36+
class ProtectionStats:
37+
"""保护统计"""
38+
start_time: Optional[datetime] = None
39+
total_requests: int = 0
40+
blocked_requests: int = 0 # 本系统二层拦截数
41+
allowed_requests: int = 0
42+
threats_detected: int = 0
43+
server_blocked: int = 0 # 服务器一层拦截数
44+
second_layer_blocked: int = 0 # 二层额外拦截数
45+
last_threat_time: Optional[datetime] = None
46+
47+
def to_dict(self) -> Dict[str, Any]:
48+
return {
49+
"start_time": self.start_time.isoformat() if self.start_time else None,
50+
"uptime_seconds": (datetime.now() - self.start_time).total_seconds() if self.start_time else 0,
51+
"total_requests": self.total_requests,
52+
"blocked_requests": self.blocked_requests,
53+
"allowed_requests": self.allowed_requests,
54+
"threats_detected": self.threats_detected,
55+
"server_blocked": self.server_blocked,
56+
"second_layer_blocked": self.second_layer_blocked,
57+
"block_rate": round(self.blocked_requests / max(self.total_requests, 1) * 100, 2),
58+
"last_threat_time": self.last_threat_time.isoformat() if self.last_threat_time else None
59+
}
60+
61+
62+
class ProtectionService:
63+
"""一键保护服务 - 单例模式"""
64+
65+
_instance: Optional['ProtectionService'] = None
66+
_lock = threading.Lock()
67+
68+
def __new__(cls):
69+
if cls._instance is None:
70+
with cls._lock:
71+
if cls._instance is None:
72+
cls._instance = super().__new__(cls)
73+
cls._instance._initialized = False
74+
return cls._instance
75+
76+
def __init__(self):
77+
if self._initialized:
78+
return
79+
80+
self._initialized = True
81+
self._status = ProtectionStatus.OFF
82+
self._level = ProtectionLevel.MEDIUM
83+
self._stats = ProtectionStats()
84+
self._config = {
85+
"auto_block": True,
86+
"log_all_traffic": True,
87+
"alert_on_threat": True,
88+
"captcha_on_suspicious": True,
89+
"rate_limit_enabled": True,
90+
"rate_limit_per_minute": 100,
91+
"whitelist_ips": [],
92+
"blacklist_ips": [],
93+
}
94+
self._models_loaded = False
95+
self._monitor_task: Optional[asyncio.Task] = None
96+
logger.info("ProtectionService initialized")
97+
98+
@property
99+
def status(self) -> ProtectionStatus:
100+
return self._status
101+
102+
@property
103+
def level(self) -> ProtectionLevel:
104+
return self._level
105+
106+
@property
107+
def is_active(self) -> bool:
108+
return self._status == ProtectionStatus.ON
109+
110+
async def start(self, level: Optional[ProtectionLevel] = None) -> Dict[str, Any]:
111+
"""启动保护服务"""
112+
if self._status == ProtectionStatus.ON:
113+
return {"success": True, "message": "保护已开启", "status": self._status.value}
114+
115+
if self._status == ProtectionStatus.STARTING:
116+
return {"success": False, "message": "正在启动中...", "status": self._status.value}
117+
118+
try:
119+
self._status = ProtectionStatus.STARTING
120+
logger.info("Starting protection service...")
121+
122+
if level:
123+
self._level = level
124+
125+
# 1. 加载检测模型
126+
await self._load_models()
127+
128+
# 2. 初始化统计
129+
self._stats = ProtectionStats(start_time=datetime.now())
130+
131+
# 3. 启动监控任务
132+
self._monitor_task = asyncio.create_task(self._monitor_loop())
133+
134+
self._status = ProtectionStatus.ON
135+
logger.info(f"Protection service started with level: {self._level.value}")
136+
137+
return {
138+
"success": True,
139+
"message": f"保护已开启 - {self._get_level_description()}",
140+
"status": self._status.value,
141+
"level": self._level.value
142+
}
143+
except Exception as e:
144+
self._status = ProtectionStatus.ERROR
145+
logger.error(f"Failed to start protection: {e}")
146+
return {"success": False, "message": f"启动失败: {str(e)}", "status": self._status.value}
147+
148+
async def stop(self) -> Dict[str, Any]:
149+
"""停止保护服务"""
150+
if self._status == ProtectionStatus.OFF:
151+
return {"success": True, "message": "保护已关闭", "status": self._status.value}
152+
153+
try:
154+
self._status = ProtectionStatus.STOPPING
155+
logger.info("Stopping protection service...")
156+
157+
# 停止监控任务
158+
if self._monitor_task:
159+
self._monitor_task.cancel()
160+
try:
161+
await self._monitor_task
162+
except asyncio.CancelledError:
163+
pass
164+
self._monitor_task = None
165+
166+
self._status = ProtectionStatus.OFF
167+
logger.info("Protection service stopped")
168+
169+
return {
170+
"success": True,
171+
"message": "保护已关闭",
172+
"status": self._status.value,
173+
"stats": self._stats.to_dict()
174+
}
175+
except Exception as e:
176+
self._status = ProtectionStatus.ERROR
177+
logger.error(f"Failed to stop protection: {e}")
178+
return {"success": False, "message": f"停止失败: {str(e)}", "status": self._status.value}
179+
180+
async def toggle(self) -> Dict[str, Any]:
181+
"""切换保护状态"""
182+
if self._status == ProtectionStatus.ON:
183+
return await self.stop()
184+
else:
185+
return await self.start()
186+
187+
def set_level(self, level: ProtectionLevel) -> Dict[str, Any]:
188+
"""设置保护级别"""
189+
old_level = self._level
190+
self._level = level
191+
logger.info(f"Protection level changed: {old_level.value} -> {level.value}")
192+
return {
193+
"success": True,
194+
"message": f"保护级别已设置为: {self._get_level_description()}",
195+
"level": level.value
196+
}
197+
198+
def get_state(self) -> Dict[str, Any]:
199+
"""获取当前状态"""
200+
return {
201+
"status": self._status.value,
202+
"is_active": self.is_active,
203+
"level": self._level.value,
204+
"level_description": self._get_level_description(),
205+
"config": self._config,
206+
"stats": self._stats.to_dict() if self._stats.start_time else None,
207+
"models_loaded": self._models_loaded
208+
}
209+
210+
def update_config(self, config: Dict[str, Any]) -> Dict[str, Any]:
211+
"""更新配置"""
212+
for key, value in config.items():
213+
if key in self._config:
214+
self._config[key] = value
215+
return {"success": True, "config": self._config}
216+
217+
def record_request(self, is_threat: bool, blocked: bool):
218+
"""记录请求统计"""
219+
if not self.is_active:
220+
return
221+
222+
self._stats.total_requests += 1
223+
if blocked:
224+
self._stats.blocked_requests += 1
225+
else:
226+
self._stats.allowed_requests += 1
227+
228+
if is_threat:
229+
self._stats.threats_detected += 1
230+
self._stats.last_threat_time = datetime.now()
231+
232+
async def _load_models(self):
233+
"""加载检测模型"""
234+
await asyncio.sleep(0.5) # 模拟加载
235+
self._models_loaded = True
236+
logger.info("Detection models loaded")
237+
238+
async def _monitor_loop(self):
239+
"""监控循环"""
240+
while True:
241+
try:
242+
await asyncio.sleep(5)
243+
# 可以在这里添加定期检查逻辑
244+
except asyncio.CancelledError:
245+
break
246+
except Exception as e:
247+
logger.error(f"Monitor error: {e}")
248+
249+
def _get_level_description(self) -> str:
250+
"""获取级别描述"""
251+
descriptions = {
252+
ProtectionLevel.LOW: "低级 - 仅监控记录",
253+
ProtectionLevel.MEDIUM: "中级 - 拦截高风险威胁",
254+
ProtectionLevel.HIGH: "高级 - 拦截中高风险威胁",
255+
ProtectionLevel.STRICT: "严格 - 拦截所有可疑流量"
256+
}
257+
return descriptions.get(self._level, "未知")
258+
259+
260+
# 全局实例
261+
_protection_service: Optional[ProtectionService] = None
262+
263+
264+
def get_protection_service() -> ProtectionService:
265+
"""获取保护服务实例"""
266+
global _protection_service
267+
if _protection_service is None:
268+
_protection_service = ProtectionService()
269+
return _protection_service

0 commit comments

Comments
 (0)