服务器插件 ipvalidate-for-mcpaper1.21.jar。
在搞一些东西时发现了GeoLite2这个数据库,本质上它应该算是一个离线的ip地理数据库,就是可以查询到IP对应的国家或地区,MAXMIND还提供了更具体的城市数据库,似乎也可以查到ip对应的城市位置。
那么言归正传,突然想起来之前我的世界服务器被入侵的鸟事🤬,就是有陌生的玩家闯入未设防的私人服务器,然后在里面搞破坏,或者乱插牌子。查询ip地址发现这些入侵者ip均来自国外虚拟服务提供商。
类似于[个人Minecraft服务器被境外黑客/熊孩子攻击的事例分享]。(https://www.bilibili.com/opus/829121476347035681?spm_id_from=333.1007.0.0&jump_opus=1)
这种类似的入侵其实不难理解,毕竟ipv4的范围也没多大,像咱们一般租用的这种阿里云或者腾讯云的小服务器本身就没啥防御,还在Discord上发现了一个叫ServerSeeker的机器人,声称能扫描到整个互联网的私人服务器。
所以之前的思路是写一个判断玩家的ip地址的paper插件Minecraft服务器被境外黑客/熊孩子入侵——开启IP验证,如果是国外ip就直接踢出去,但是当时采用的方法是插件查询类似http://www.cip.cc/这种网站,然后根据网站返回的结果判断ip属于哪个国家。但问题是这个网站也不太靠谱,经常拒绝访问什么的。
既然有GeoLite2这个东西,那就好办了,直接把数据库放到本地查询呗。
获取GeoLite2-Country.mmdb
从官网下载最新的离线数据库。
MAXMIND_GEOLITE2
解压后里面的GeoLite2-Country.mmdb就是我们需要的数据库。
代码
一点参考
intellij创建一个新项目,插件市场下载那个Minecraft developer插件
新建一个minecraft plugin项目,记得Build System选maven
在pom.xml里添加依赖
<dependencies><dependency>...其他的一些依赖...</dependency><dependency><groupId>com.maxmind.geoip2</groupId><artifactId>geoip2</artifactId><version>3.0.1</version></dependency></dependencies>
把GeoLite2-Country.mmdb丢到resources文件夹下边
然后主函数里的代码:
package org.iplocation.ipvalidate;import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.exception.GeoIp2Exception;
import com.maxmind.geoip2.model.CountryResponse;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.plugin.java.JavaPlugin;import java.io.File;
import java.io.IOException;
import java.net.InetAddress;public class Ipvalidate extends JavaPlugin implements Listener {private DatabaseReader databaseReader;@Overridepublic void onEnable() {// 加载 GeoLite2 数据库try {File dbFile = new File(getDataFolder(), "GeoLite2-Country.mmdb");if (!dbFile.exists()) {saveResource("GeoLite2-Country.mmdb", false);}databaseReader = new DatabaseReader.Builder(dbFile).build();getLogger().info("GeoLite2-Country database loaded successfully.");} catch (IOException e) {getLogger().severe("Failed to load GeoLite2-Country.mmdb: " + e.getMessage());getServer().getPluginManager().disablePlugin(this);}// 注册事件监听器getServer().getPluginManager().registerEvents(this, this);}@Overridepublic void onDisable() {// 关闭数据库连接if (databaseReader != null) {try {databaseReader.close();} catch (IOException e) {getLogger().severe("Failed to close GeoLite2-Country database: " + e.getMessage());}}}@EventHandlerpublic void onPlayerLogin(PlayerLoginEvent event) {String playerName = event.getPlayer().getName();InetAddress ipAddress = event.getAddress();try {String country = getCountryByIp(ipAddress);if (!"China".equalsIgnoreCase(country)) {event.disallow(PlayerLoginEvent.Result.KICK_OTHER, "You are not welcomed.");getLogger().info("Player " + playerName + " was kicked. Country: " + country);}String message ="Player " + playerName + " enters the game. Player IP: " + ipAddress + " Location: " + country;Player player = event.getPlayer();player.sendMessage(message);Bukkit.broadcastMessage(message);getLogger().info(message);} catch (Exception e) {getLogger().severe("Failed to determine country for IP: " + ipAddress + " - " + e.getMessage());}}// 根据 IP 获取国家名称private String getCountryByIp(InetAddress ipAddress) throws IOException, GeoIp2Exception {CountryResponse response = databaseReader.country(ipAddress);return response.getCountry().getName();}// 测试函数public void testIp(String ipAddress) {try {InetAddress inetAddress = InetAddress.getByName(ipAddress);String country = getCountryByIp(inetAddress);getLogger().info("IP: " + ipAddress + " belongs to country: " + country);} catch (Exception e) {getLogger().severe("Error testing IP: " + ipAddress + " - " + e.getMessage());}}
}
接下来就可以构建jar包了
左侧,先双击clean,再双击package
导出的jar包丢到mc服务器的plugin目录下
启动服务器就行了。
ipvalidate-for-mcpaper1.21.jar