创建新工程

This commit is contained in:
moyin
2025-12-05 19:00:14 +08:00
commit ff4fa5fffd
227 changed files with 32804 additions and 0 deletions

230
scripts/RateLimiter.gd Normal file
View File

@@ -0,0 +1,230 @@
extends Node
class_name RateLimiter
## 速率限制器
## 防止消息洪水攻击和垃圾消息
# 速率限制配置
var max_messages_per_window: int = 10
var time_window: float = 1.0 # 1秒窗口
var cleanup_interval: float = 60.0 # 1分钟清理间隔
# 客户端消息记录
var client_message_history: Dictionary = {}
# 清理定时器
var cleanup_timer: Timer
## 初始化速率限制器
func _ready():
"""初始化速率限制器"""
# 从配置获取参数
max_messages_per_window = SecurityConfig.get_config("network_security", "max_message_rate", 10)
time_window = SecurityConfig.get_config("network_security", "rate_limit_window", 1.0)
# 设置清理定时器
cleanup_timer = Timer.new()
cleanup_timer.wait_time = cleanup_interval
cleanup_timer.timeout.connect(_cleanup_old_records)
cleanup_timer.autostart = true
add_child(cleanup_timer)
print("RateLimiter initialized - Max: %d msgs/%s sec" % [max_messages_per_window, time_window])
## 检查是否允许消息
func is_message_allowed(client_id: String) -> bool:
"""
检查客户端是否允许发送消息
@param client_id: 客户端ID
@return: 是否允许
"""
var current_time = Time.get_unix_time_from_system()
# 获取或创建客户端记录
if not client_message_history.has(client_id):
client_message_history[client_id] = {
"messages": [],
"last_cleanup": current_time
}
var client_record = client_message_history[client_id]
var messages = client_record.messages
# 清理过期消息
_cleanup_client_messages(client_id, current_time)
# 检查是否超过限制
if messages.size() >= max_messages_per_window:
print("WARNING: Rate limit exceeded for client: " + client_id + " (" + str(messages.size()) + " messages)")
return false
# 记录新消息
messages.append(current_time)
return true
## 清理客户端的过期消息记录
func _cleanup_client_messages(client_id: String, current_time: float):
"""
清理客户端的过期消息记录
@param client_id: 客户端ID
@param current_time: 当前时间
"""
if not client_message_history.has(client_id):
return
var client_record = client_message_history[client_id]
var messages = client_record.messages
var cutoff_time = current_time - time_window
# 移除过期消息
var valid_messages = []
for timestamp in messages:
if timestamp > cutoff_time:
valid_messages.append(timestamp)
client_record.messages = valid_messages
client_record.last_cleanup = current_time
## 清理所有过期记录
func _cleanup_old_records():
"""清理所有客户端的过期记录"""
var current_time = Time.get_unix_time_from_system()
var cleaned_clients = 0
var removed_clients = []
for client_id in client_message_history:
var client_record = client_message_history[client_id]
# 如果客户端超过5分钟没有活动移除记录
if current_time - client_record.last_cleanup > 300.0:
removed_clients.append(client_id)
else:
# 清理过期消息
_cleanup_client_messages(client_id, current_time)
cleaned_clients += 1
# 移除不活跃的客户端记录
for client_id in removed_clients:
client_message_history.erase(client_id)
if removed_clients.size() > 0:
print("Rate limiter cleaned up %d inactive clients, %d active clients remain" % [removed_clients.size(), cleaned_clients])
## 重置客户端限制
func reset_client_limit(client_id: String):
"""
重置客户端的速率限制(用于特殊情况)
@param client_id: 客户端ID
"""
if client_message_history.has(client_id):
client_message_history[client_id].messages.clear()
print("Rate limit reset for client: " + client_id)
## 获取客户端消息统计
func get_client_stats(client_id: String) -> Dictionary:
"""
获取客户端的消息统计
@param client_id: 客户端ID
@return: 统计信息
"""
if not client_message_history.has(client_id):
return {
"message_count": 0,
"remaining_quota": max_messages_per_window,
"window_reset_time": 0
}
var current_time = Time.get_unix_time_from_system()
_cleanup_client_messages(client_id, current_time)
var client_record = client_message_history[client_id]
var message_count = client_record.messages.size()
var remaining_quota = max(0, max_messages_per_window - message_count)
# 计算窗口重置时间
var oldest_message_time = 0.0
if client_record.messages.size() > 0:
oldest_message_time = client_record.messages[0]
var window_reset_time = oldest_message_time + time_window
return {
"message_count": message_count,
"remaining_quota": remaining_quota,
"window_reset_time": window_reset_time,
"current_time": current_time
}
## 获取全局统计
func get_global_stats() -> Dictionary:
"""
获取全局速率限制统计
@return: 全局统计信息
"""
var total_clients = client_message_history.size()
var active_clients = 0
var total_messages = 0
var current_time = Time.get_unix_time_from_system()
for client_id in client_message_history:
var client_record = client_message_history[client_id]
if current_time - client_record.last_cleanup < 60.0: # 1分钟内活跃
active_clients += 1
total_messages += client_record.messages.size()
return {
"total_clients": total_clients,
"active_clients": active_clients,
"total_messages_in_window": total_messages,
"max_rate": max_messages_per_window,
"time_window": time_window
}
## 设置速率限制参数
func set_rate_limit(max_messages: int, window_seconds: float):
"""
动态设置速率限制参数
@param max_messages: 最大消息数
@param window_seconds: 时间窗口(秒)
"""
max_messages_per_window = max_messages
time_window = window_seconds
print("Rate limit updated - Max: %d msgs/%s sec" % [max_messages, window_seconds])
## 检查是否为可疑活动
func is_suspicious_activity(client_id: String) -> bool:
"""
检查客户端是否有可疑活动
@param client_id: 客户端ID
@return: 是否可疑
"""
var stats = get_client_stats(client_id)
# 如果消息数量接近限制,认为可疑
if stats.message_count >= max_messages_per_window * 0.8:
return true
# 检查消息发送模式是否异常(过于规律可能是机器人)
if client_message_history.has(client_id):
var messages = client_message_history[client_id].messages
if messages.size() >= 3:
var intervals = []
for i in range(1, messages.size()):
intervals.append(messages[i] - messages[i-1])
# 如果所有间隔都非常相似差异小于0.1秒),可能是机器人
if intervals.size() >= 2:
var avg_interval = 0.0
for interval in intervals:
avg_interval += interval
avg_interval /= intervals.size()
var variance = 0.0
for interval in intervals:
variance += (interval - avg_interval) * (interval - avg_interval)
variance /= intervals.size()
if variance < 0.01: # 方差很小,模式过于规律
return true
return false