423 字
2 分钟
防止假人压测的一种简单的手段
起因
我之前写了一款多平台(指mc服务端)的Motd插件, 并且里面内置了一个防止假人压测的功能 这里会来简单讨论一下这个功能以及, 实现方式和部分代码, 教程基于Kotlin
原理
判断一个客户端是否在服务器列表中ping过一次服务器
MC客户端连接到服务器时会附带客户端的IP地址, 可以用这个IP地址来判断玩家是否ping了服务器 Velocity服务端代码示例, 监听Ping服务器的event
class ProxyPingEventListener {
@Subscribe
fun onProxyPingEvent(event: ProxyPingEvent) {
val ip = event.connection.remoteAddress.hostName
// pinRecordManager是一个使用json来管理记录的管理类
// 本质上就是一个list存储了一些ip地址
if (pingRecordManager.exists(ip)) {
pingRecordManager.removeRecord(ip)
}
pingRecordManager.addRecord(ip)
}
}然后监听玩家进入服务器的event
class LoginEventListener(private val proxy: ProxyServer) {
// 定义一个超时时间, ping了一次服务器之后超过120秒没进入服务器就把这次结果
// 作废,需要再次ping一次服务器才行
private val pingExpirationTime = 120
@Subscribe
fun onLogin(event: LoginEvent) {
val ip = event.player.remoteAddress.hostName
if (pingRecordManager.exists(ip)) {
val record = pingRecordManager.getRecord(ip)
val currentTimestamp = Instant.now().epochSecond
if (currentTimestamp - record.timestamp > pingExpirationTime) {
// PING_AGAIN_TEXT 是一个constant值用于显示玩家在ping过一次服务器之后
// 时间超过了pingExpirationTime是超时时间, 断开连接后
// 屏幕上显示的文字
event.player.disconnect(Component.text(PING_AGAIN_TEXT))
pingRecordManager.removeRecord(ip)
}
} else {
// PING_FIRST_TEXT 是一个constant值用于显示玩家没有ping就进入服务器后
// 断开连接时屏幕上显示的文字
event.player.disconnect(Component.text(PING_FIRST_TEXT))
}
}
}结尾
这个功能是YeeeesMOTD的其中一小部分功能, 完整的代码可以在这里查看