pterodactyl / panel

Pterodactyl® is a free, open-source game server management panel built with PHP, React, and Go. Designed with security in mind, Pterodactyl runs all game servers in isolated Docker containers while exposing a beautiful and intuitive UI to end users.
https://pterodactyl.io
Other
6.69k stars 1.7k forks source link

HWID constantly changes after reloading instances with Pterodactyl #3991

Closed AlbeMiglio closed 2 years ago

AlbeMiglio commented 2 years ago

Current Behavior

Hello, I'm using this #getLinuxMacAddress() method in Java to get a unique mac address for linux machines:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Scanner;

public class HWUtils {

    private static final String UNKNOWN = "unknown";

    private static String OS = System.getProperty("os.name").toLowerCase();

    public static String getHWID() {
        try {
            if (isWindows()) {
                return getWindowsIdentifier();
            } else if (isMac()) {
                return getMacOsIdentifier();
            } else if (isLinux()) {
                return getLinuxMacAddress();
            } else {
                return UNKNOWN;
            }
        } catch (Exception e) {
            return UNKNOWN;
        }
    }

    private static boolean isWindows() {
        return (OS.contains("win"));
    }

    private static boolean isMac() {
        return (OS.contains("mac"));
    }

    private static boolean isLinux() {
        return (OS.contains("inux"));
    }

    private static String getLinuxMacAddress() throws FileNotFoundException, NoSuchAlgorithmException {
        File machineId = new File("/var/lib/dbus/machine-id");
        if (!machineId.exists()) {
            machineId = new File("/etc/machine-id");
        }
        if (!machineId.exists()) {
            return UNKNOWN;
        }

        Scanner scanner = null;
        try {
            scanner = new Scanner(machineId);
            String id = scanner.useDelimiter("\\A").next();
            return hexStringify(sha256Hash(id.getBytes()));
        } finally {
            if (scanner != null) {
                scanner.close();
            }
        }
    }

    private static String getMacOsIdentifier() throws SocketException, NoSuchAlgorithmException {
        NetworkInterface networkInterface = NetworkInterface.getByName("en0");
        byte[] hardwareAddress = networkInterface.getHardwareAddress();
        return hexStringify(sha256Hash(hardwareAddress));
    }

    private static String getWindowsIdentifier() throws IOException, NoSuchAlgorithmException {
        Runtime runtime = Runtime.getRuntime();
        Process process = runtime.exec(new String[]{"wmic", "csproduct", "get", "UUID"});

        String result = null;
        InputStream is = process.getInputStream();
        Scanner sc = new Scanner(process.getInputStream());
        try {
            while (sc.hasNext()) {
                String next = sc.next();
                if (next.contains("UUID")) {
                    result = sc.next().trim();
                    break;
                }
            }
        } finally {
            is.close();
        }

        return result == null ? UNKNOWN : hexStringify(sha256Hash(result.getBytes()));
    }

    /**
     * Compute the SHA-256 hash of the given byte array
     *
     * @param data the byte array to hash
     * @return the hashed byte array
     * @throws NoSuchAlgorithmException
     */
    public static byte[] sha256Hash(byte[] data) throws NoSuchAlgorithmException {
        MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
        return messageDigest.digest(data);
    }

    /**
     * Convert a byte array to its hex-string
     *
     * @param data the byte array to convert
     * @return the hex-string of the byte array
     */
    public static String hexStringify(byte[] data) {
        StringBuilder stringBuilder = new StringBuilder();
        for (byte singleByte : data) {
            stringBuilder.append(Integer.toString((singleByte & 0xff) + 0x100, 16).substring(1));
        }

        return stringBuilder.toString();
    }
}

It actually changes after restarting a few times my java process (held on pterodactyl). Starting it outside pterodactyl does not cause the issue of seeing my HWID changing.

Expected Behavior

HWID should always be the same, even if process is started inside pterodactyl panel.

Steps to Reproduce

Use the java line of code written above to generate a mac address from a java process started from pterodactyl.

Panel Version

1.7

Wings Version

1.5

Games and/or Eggs Affected

No response

Docker Image

No response

Error Logs

MAXIMUM_HWIDS error (given when stored HWID is different from the current one)

Is there an existing issue for this?

parkervcp commented 2 years ago

Outside of pterodactyl the process uses your host adapter, thus getting its mac address..

It is my understanding that, unless we specify mac addresses, they are assigned automatically by docker. You could run the network in host mode but that then gets rid of the ability to use the network for things like having a minecraft network on a single host.

See here - https://stackoverflow.com/questions/42946453/how-does-the-docker-assign-mac-addresses-to-containers

AlbeMiglio commented 2 years ago

Never used pterodactyl before, so I'm sorry in advance for my ignorance, but; can't pterodactyl simply specify the address managed by host adapter as its mac address, instead of letting docker manage it?

DaneEveritt commented 2 years ago

I'm not interested in adding such functionality to Pterodactyl's core.

arima0k commented 2 years ago

Never used pterodactyl before, so I'm sorry in advance for my ignorance, but; can't pterodactyl simply specify the address managed by host adapter as its mac address, instead of letting docker manage it?

static --mac-address= sounds more reasonable