• 欢迎加入MineBBS QQ讨论群:点击查看所有的官方讨论群
  • 我们将于近期对服务器进行迁移,服务可能中断至多2日。请各位安排好自己的访问计划,造成不便敬请谅解!
  • MineBBS入站考试已经上线!想要成为【正式会员】解锁更多功能吗?快来参与吧!【点我去看】

核心代理(虚假核心),用于不允许修改启动命令的面板服务器启用外置登录

zhaishis

【Lv:2】

注册
2025/06/24
消息
4
金粒
16.00金粒
我去蓝夜服务器搞了一台我的世界服务器面板,结果发现很多朋友没有正版,于是给自己的社区写了一个外置登录功能
然后发现面板服没办法修改启动命令
经过我n秒思考,决定写一个虚假核心拼接带-javaagent的启动命令启动真核心。

如果你也有相同需求,请把附件的.jar上传到与authlib和server核心的同级目录,然后创建一个文件,名字:fake-core.properties

然后写入:
代码:
# 真实服务端核心文件名(默认 server.jar)
realCore = paper-1.20.4.jar

# authlib-injector 文件名(默认 authlib-injector.jar)
authInjector = authlib-injector-1.2.5.jar

# 外置登录验证服务器地址
authUrl = https://littleskin.cn/api/yggdrasil

# Java 命令(一般不用改)
javaCmd = java

# 默认 JVM 内存参数(可被环境变量 FAKE_JVM_OPTS 覆盖)
jvmOpts = -Xmx2G -Xms1G

即可,其次由于这个假核心代码过于简单,我就不上传GitHub了,你们自己看着吧

对了,请把面板的启动核心名字换成这个或者修改两个核心的名字,保证以虚假核心启动即可。

代码:
import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.lang.reflect.Method;

public class FakeCoreBootstrap {

    private static String REAL_CORE = "server.jar";
    private static String AUTH_INJECTOR = "authlib-injector.jar";
    private static String AUTH_URL = "https://littleskin.cn/api/yggdrasil";
    private static String JAVA_CMD = "java";
    private static String JVM_OPTS = "-Xmx1024M -Xms1024M";

    public static void main(String[] args) throws Exception {
        loadConfig();

        Path workDir = Paths.get("").toAbsolutePath();
        Path realCorePath = workDir.resolve(REAL_CORE);
        Path authJarPath = workDir.resolve(AUTH_INJECTOR);

        if (!Files.exists(realCorePath)) {
            System.err.println("[ERROR] 找不到真实核心文件: " + realCorePath);
            System.err.println("请将真实核心命名为 " + REAL_CORE + " 并放在同一目录下。");
            System.exit(1);
        }
        if (!Files.exists(authJarPath)) {
            System.err.println("[ERROR] 找不到 authlib-injector: " + authJarPath);
            System.err.println("请从 https://github.com/yushijinhun/authlib-injector/releases 下载并放入目录。");
            System.exit(1);
        }

        List<String> command = new ArrayList<>();
        command.add(JAVA_CMD);

        String extraJvm = System.getenv("FAKE_JVM_OPTS");
        if (extraJvm != null && !extraJvm.isEmpty()) {
            command.addAll(Arrays.asList(extraJvm.split("\\s+")));
        } else if (JVM_OPTS != null && !JVM_OPTS.isEmpty()) {
            command.addAll(Arrays.asList(JVM_OPTS.split("\\s+")));
        }

        String agentArg = "-javaagent:" + authJarPath.toString() + "=" + AUTH_URL;
        command.add(agentArg);

        command.add("-jar");
        command.add(realCorePath.toString());

        command.addAll(Arrays.asList(args));

        System.out.println("[INFO] 启动命令: " + command.stream().collect(Collectors.joining(" ")));

        ProcessBuilder pb = new ProcessBuilder(command);
        pb.inheritIO();

        Process process = pb.start();

        // 注册关闭钩子,确保面板停止时能终止子进程(兼容 Android)
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            if (process.isAlive()) {
                System.out.println("[INFO] 接收到停止信号,正在终止服务端子进程...");
                process.destroy(); // 先尝试优雅终止
                try {
                    if (!process.waitFor(5, TimeUnit.SECONDS)) {
                        System.out.println("[WARN] 子进程未能正常退出,尝试强制终止...");
                        // 尝试调用 destroyForced(如果可用)
                        boolean forced = false;
                        try {
                            Method destroyForced = process.getClass().getMethod("destroyForced");
                            destroyForced.invoke(process);
                            forced = true;
                        } catch (Exception e) {
                            // 方法不存在或调用失败,忽略
                        }
                        if (!forced) {
                            System.out.println("[WARN] 无法强制终止,进程可能仍然残留。");
                        }
                    } else {
                        System.out.println("[INFO] 子进程正常退出。");
                    }
                } catch (InterruptedException ignored) {
                    Thread.currentThread().interrupt();
                }
            }
        }));

        int exitCode = process.waitFor();
        System.exit(exitCode);
    }

    private static void loadConfig() {
        Path configPath = Paths.get("fake-core.properties");
        if (!Files.exists(configPath)) {
            return;
        }
        Properties props = new Properties();
        try (InputStream in = Files.newInputStream(configPath)) {
            props.load(in);
            REAL_CORE = props.getProperty("realCore", REAL_CORE);
            AUTH_INJECTOR = props.getProperty("authInjector", AUTH_INJECTOR);
            AUTH_URL = props.getProperty("authUrl", AUTH_URL);
            JAVA_CMD = props.getProperty("javaCmd", JAVA_CMD);
            JVM_OPTS = props.getProperty("jvmOpts", JVM_OPTS);
        } catch (IOException e) {
            System.err.println("[WARN] 读取配置文件失败,使用默认值。");
        }
    }
}
 

附件

那段java代码是虚假核心的完整代码,自己研究一下怎么编译即可。
 
实现起来真的很简单,把需求提给AI,他都能帮你实现,你手机上下载termux安装openjdk-21就可以编译
 

在线管理成员

在线会员

  • oYuyio
  • 小小的子沐呀
后退
顶部 底部