13
0
geforkt von Mirrors/Velocity

Velocity Dump WIP Part 2

Dieser Commit ist enthalten in:
Five (Xer) 2020-10-25 20:04:52 +01:00
Ursprung 6331e1af3e
Commit 140eaaf5ab
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: A3F306B10E6330E7
2 geänderte Dateien mit 208 neuen und 6 gelöschten Zeilen

Datei anzeigen

@ -5,7 +5,11 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.io.CharStreams;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSyntaxException;
import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.command.SimpleCommand; import com.velocitypowered.api.command.SimpleCommand;
import com.velocitypowered.api.permission.Tristate; import com.velocitypowered.api.permission.Tristate;
@ -17,6 +21,12 @@ import com.velocitypowered.api.util.ProxyVersion;
import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.VelocityServer;
import com.velocitypowered.proxy.util.InformationUtils; import com.velocitypowered.proxy.util.InformationUtils;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@ -320,9 +330,18 @@ public class VelocityCommand implements SimpleCommand {
servers.add(iter.getServerInfo().getName(), servers.add(iter.getServerInfo().getName(),
InformationUtils.collectServerInfo(iter)); InformationUtils.collectServerInfo(iter));
} }
JsonArray connectOrder = new JsonArray();
List<String> attemptedConnectionOrder = ImmutableList.copyOf(
server.getConfiguration().getAttemptConnectionOrder());
for (int i = 0; i < attemptedConnectionOrder.size(); i++) {
connectOrder.add(attemptedConnectionOrder.get(i));
}
JsonObject proxyConfig = InformationUtils.collectProxyConfig(server.getConfiguration()); JsonObject proxyConfig = InformationUtils.collectProxyConfig(server.getConfiguration());
proxyConfig.add("servers", servers); proxyConfig.add("servers", servers);
proxyConfig.add("connectOrder", connectOrder);
proxyConfig.add("forcedHosts",
InformationUtils.collectForcedHosts(server.getConfiguration()));
JsonObject dump = new JsonObject(); JsonObject dump = new JsonObject();
dump.add("versionInfo", InformationUtils.collectProxyInfo(server.getVersion())); dump.add("versionInfo", InformationUtils.collectProxyInfo(server.getVersion()));
@ -330,7 +349,90 @@ public class VelocityCommand implements SimpleCommand {
dump.add("config", proxyConfig); dump.add("config", proxyConfig);
dump.add("plugins", InformationUtils.collectPluginInfo(server)); dump.add("plugins", InformationUtils.collectPluginInfo(server));
// TODO: Finish source.sendMessage(Component.text().content("Uploading gathered information...").build());
HttpURLConnection upload = null;
try {
upload = (HttpURLConnection) new URL("https://dump.velocitypowered.com/documents")
.openConnection();
} catch (IOException e1) {
// Couldn't open connection;
source.sendMessage(
Component.text()
.content("Failed to open a connection!")
.color(NamedTextColor.RED).build());
return;
}
upload.setRequestProperty("Content-Type", "text/plain");
upload.addRequestProperty(
"User-Agent", server.getVersion().getName() + "/"
+ server.getVersion().getVersion());
try {
upload.setRequestMethod("POST");
upload.setDoOutput(true);
OutputStream uploadStream = upload.getOutputStream();
uploadStream.write(
InformationUtils.toHumanReadableString(dump).getBytes(StandardCharsets.UTF_8));
uploadStream.close();
} catch (IOException e2) {
// Couldn't POST the Data
source.sendMessage(
Component.text()
.content("Couldn't upload the data!")
.color(NamedTextColor.RED).build());
return;
}
String rawResponse = null;
try {
rawResponse = CharStreams.toString(
new InputStreamReader(upload.getInputStream(), StandardCharsets.UTF_8));
upload.getInputStream().close();
} catch (IOException e3) {
// Couldn't read response
source.sendMessage(
Component.text()
.content("Invalid server response received!")
.color(NamedTextColor.RED).build());
}
JsonObject returned = null;
try {
returned = InformationUtils.parseString(rawResponse);
if (returned == null || !returned.has("key")) {
throw new JsonParseException("Invalid json response");
}
} catch (JsonSyntaxException e4) {
// Mangled json
source.sendMessage(
Component.text()
.content("Server responded with invalid data!")
.color(NamedTextColor.RED).build());
return;
} catch (JsonParseException e5) {
// Backend error?
source.sendMessage(
Component.text()
.content("Data was uploaded successfully but couldn't be posted")
.color(NamedTextColor.RED).build());
return;
}
TextComponent response = Component.text()
.content("Created an anonymised report containing useful information about")
.append(Component.newline()
.append(
Component.text("this proxy. If a developer requested it"
+ ", you may share the"))
.append(Component.newline())
.append(Component.text("following link with them:"))
.append(Component.newline())
.append(Component.text("https://dump.velocitypowered.com/"
+ returned.get("key").getAsString() + ".json")
.color(NamedTextColor.GREEN)))
.append(Component.newline())
.append(Component.text("Note: This link is only valid for a few days"))
.build();
source.sendMessage(response);
} }
@Override @Override

Datei anzeigen

@ -1,6 +1,7 @@
package com.velocitypowered.proxy.util; package com.velocitypowered.proxy.util;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
@ -16,9 +17,15 @@ import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.api.util.ProxyVersion; import com.velocitypowered.api.util.ProxyVersion;
import io.netty.channel.unix.DomainSocketAddress; import io.netty.channel.unix.DomainSocketAddress;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.util.List; import java.util.List;
import java.util.Map;
import joptsimple.internal.Strings; import joptsimple.internal.Strings;
public enum InformationUtils { public enum InformationUtils {
@ -84,6 +91,75 @@ public enum InformationUtils {
return envInfo; return envInfo;
} }
/**
* Creates a {@link JsonObject} containing information about the
* forced hosts of the {@link ProxyConfig} instance.
*
* @return {@link JsonArray} containing forced hosts
*/
public static JsonObject collectForcedHosts(ProxyConfig config) {
JsonObject forcedHosts = new JsonObject();
Map<String, List<String>> allForcedHosts = ImmutableMap.copyOf(
config.getForcedHosts());
for (Map.Entry<String, List<String>> entry : allForcedHosts.entrySet()) {
JsonArray host = new JsonArray();
for (int i = 0; i < entry.getValue().size(); i++) {
host.add(entry.getValue().get(i));
}
forcedHosts.add(entry.getKey(), host);
}
return forcedHosts;
}
/**
* Anonymises or redacts a given {@link InetAddress}
* public address bits.
*
* @param address The address to redact
* @return {@link String} address with public parts redacted
*/
public static String anonymizeInetAddress(InetAddress address) {
if (address instanceof Inet4Address) {
Inet4Address v4 = (Inet4Address) address;
if (v4.isAnyLocalAddress() || v4.isLoopbackAddress()
|| v4.isLinkLocalAddress()
|| v4.isSiteLocalAddress()) {
return address.getHostAddress();
} else {
byte[] addr = v4.getAddress();
return (addr[0] & 0xff) + "." + (addr[1] & 0xff) + ".XXX.XXX";
}
} else if (address instanceof Inet6Address) {
Inet6Address v6 = (Inet6Address) address;
if (v6.isAnyLocalAddress() || v6.isLoopbackAddress()
|| v6.isSiteLocalAddress()
|| v6.isSiteLocalAddress()) {
return address.getHostAddress();
} else {
String[] bits = v6.getHostAddress().split(":");
String ret = "";
boolean flag = false;
for (int iter = 0; iter < bits.length; iter++) {
if (flag) {
ret += ":X";
continue;
}
if (!bits[iter].equals("0")) {
if (iter == 0) {
ret = bits[iter];
} else {
ret = "::" + bits[iter];
}
flag = true;
}
}
return ret;
}
} else {
return address.getHostAddress();
}
}
/** /**
* Creates a {@link JsonObject} containing most relevant * Creates a {@link JsonObject} containing most relevant
* information of the {@link RegisteredServer} for diagnosis. * information of the {@link RegisteredServer} for diagnosis.
@ -97,18 +173,22 @@ public enum InformationUtils {
SocketAddress address = server.getServerInfo().getAddress(); SocketAddress address = server.getServerInfo().getAddress();
if (address instanceof InetSocketAddress) { if (address instanceof InetSocketAddress) {
InetSocketAddress iaddr = (InetSocketAddress) address; InetSocketAddress iaddr = (InetSocketAddress) address;
info.addProperty("socketType", "EventLoop"); info.addProperty("socketType", "EventLoop/NIO");
info.addProperty("unresolved", iaddr.isUnresolved()); info.addProperty("unresolved", iaddr.isUnresolved());
if (iaddr.isUnresolved()) {
// Greetings form Netty 4aa10db9 // Greetings form Netty 4aa10db9
info.addProperty("host", iaddr.getHostString()); info.addProperty("host", iaddr.getHostString());
} else {
info.addProperty("host", anonymizeInetAddress(iaddr.getAddress()));
}
info.addProperty("port", iaddr.getPort()); info.addProperty("port", iaddr.getPort());
} else if (address instanceof DomainSocketAddress) { } else if (address instanceof DomainSocketAddress) {
DomainSocketAddress daddr = (DomainSocketAddress) address; DomainSocketAddress daddr = (DomainSocketAddress) address;
info.addProperty("socketType", "Unix/Epoll"); info.addProperty("socketType", "Unix/Epoll");
info.addProperty("host", daddr.path()); info.addProperty("path", daddr.path());
} else { } else {
info.addProperty("socketType", "Unknown/Generic"); info.addProperty("socketType", "Unknown/Generic");
info.addProperty("host", address.toString()); info.addProperty("info", address.toString());
} }
return info; return info;
} }
@ -135,6 +215,26 @@ public enum InformationUtils {
return (JsonObject) serializeObject(config, true); return (JsonObject) serializeObject(config, true);
} }
/**
* Creates a human-readable String from a {@link JsonElement}.
*
* @param json the {@link JsonElement} object
* @return the human-readable String
*/
public static String toHumanReadableString(JsonElement json) {
return GSON_WITHOUT_EXCLUDES.toJson(json);
}
/**
* Creates a {@link JsonObject} from a String.
*
* @param toParse the String to parse
* @return {@link JsonObject} object
*/
public static JsonObject parseString(String toParse) {
return GSON_WITHOUT_EXCLUDES.fromJson(toParse, JsonObject.class);
}
private static JsonElement serializeObject(Object toSerialize, boolean withExcludes) { private static JsonElement serializeObject(Object toSerialize, boolean withExcludes) {
return JsonParser.parseString( return JsonParser.parseString(
withExcludes ? GSON_WITH_EXCLUDES.toJson(toSerialize) : withExcludes ? GSON_WITH_EXCLUDES.toJson(toSerialize) :