Strip IP Intel entirely

This commit is contained in:
Alfie Cleveland 2017-09-24 14:39:13 +01:00
parent 408124f5cd
commit 6394b7e4ef
6 changed files with 13 additions and 276 deletions

View File

@ -48,7 +48,6 @@ import net.frozenorb.apiv3.web.route.ipBans.DELETEIpBansId;
import net.frozenorb.apiv3.web.route.ipBans.GETIpBans; import net.frozenorb.apiv3.web.route.ipBans.GETIpBans;
import net.frozenorb.apiv3.web.route.ipBans.GETIpBansId; import net.frozenorb.apiv3.web.route.ipBans.GETIpBansId;
import net.frozenorb.apiv3.web.route.ipBans.POSTIpBans; import net.frozenorb.apiv3.web.route.ipBans.POSTIpBans;
import net.frozenorb.apiv3.web.route.ipIntel.GETIpInteld;
import net.frozenorb.apiv3.web.route.ipLog.GETIpLogId; import net.frozenorb.apiv3.web.route.ipLog.GETIpLogId;
import net.frozenorb.apiv3.web.route.lookup.POSTLookupByName; import net.frozenorb.apiv3.web.route.lookup.POSTLookupByName;
import net.frozenorb.apiv3.web.route.lookup.POSTLookupByUuid; import net.frozenorb.apiv3.web.route.lookup.POSTLookupByUuid;
@ -190,7 +189,6 @@ public final class APIv3 {
//httpPut(router, "/ipBans/:ipBanId", PUTIpBansId.class); //httpPut(router, "/ipBans/:ipBanId", PUTIpBansId.class);
httpDelete(router, "/ipBans/:ipBanId", DELETEIpBansId.class); httpDelete(router, "/ipBans/:ipBanId", DELETEIpBansId.class);
httpGet(router, "/ipIntel/:userIp", GETIpInteld.class);
httpGet(router, "/ipLog/:id", GETIpLogId.class); httpGet(router, "/ipLog/:id", GETIpLogId.class);

View File

@ -1,160 +0,0 @@
package net.frozenorb.apiv3.domain;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.bson.Document;
import com.google.common.base.Charsets;
import com.google.common.hash.Hashing;
import com.mongodb.async.SingleResultCallback;
import com.mongodb.async.client.MongoCollection;
import com.mongodb.async.client.MongoDatabase;
import fr.javatic.mongo.jacksonCodec.Entity;
import fr.javatic.mongo.jacksonCodec.objectId.Id;
import io.vertx.core.CompositeFuture;
import io.vertx.core.Future;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import net.frozenorb.apiv3.service.geoip.GeoIpInfo;
import net.frozenorb.apiv3.util.GeoJsonPoint;
import net.frozenorb.apiv3.util.SpringUtils;
import net.frozenorb.apiv3.util.SyncUtils;
@Entity
@AllArgsConstructor
public final class IpIntel {
private static final MongoCollection<IpIntel> ipIntelCollection = SpringUtils.getBean(MongoDatabase.class).getCollection("ipIntel", IpIntel.class);
@Getter @Setter @Id private String id;
@Getter private String hashedIp;
@Getter private Instant lastUpdatedAt;
@Getter private GeoIpInfo result;
@Getter private GeoJsonPoint location;
public static void findAllNoSort(SingleResultCallback<List<IpIntel>> callback) {
ipIntelCollection.find().into(new LinkedList<>(), SyncUtils.vertxWrap(callback));
}
public static void findAll(SingleResultCallback<List<IpIntel>> callback) {
ipIntelCollection.find().sort(new Document("lastSeenAt", -1)).into(new LinkedList<>(), SyncUtils.vertxWrap(callback));
}
public static void findById(String id, SingleResultCallback<IpIntel> callback) {
ipIntelCollection.find(new Document("_id", id)).first(SyncUtils.vertxWrap(callback));
}
public static void findByHashedIp(String hashedIp, SingleResultCallback<IpIntel> callback) {
ipIntelCollection.find(new Document("hashedIp", hashedIp)).first(SyncUtils.vertxWrap(callback));
}
public static void findOrCreateById(String id, SingleResultCallback<IpIntel> callback) {
findById(id, (existingIpIntel, error) -> {
if (error != null) {
callback.onResult(null, error);
} else if (existingIpIntel != null) {
callback.onResult(existingIpIntel, null);
} else {
/*
SpringUtils.getBean(GeoIpService.class).lookupInfo(id, (geoIpResult, error2) -> {
if (error2 != null) {
callback.onResult(null, error2);
} else if (geoIpResult != null) {
IpIntel newIpIntel = new IpIntel(id, geoIpResult);
ipIntelCollection.insertOne(newIpIntel, SyncUtils.vertxWrap((ignored, error3) -> {
if (error3 != null) {
callback.onResult(null, error3);
} else {
callback.onResult(newIpIntel, null);
}
}));
} else {
// MaxMind failed to return result
callback.onResult(null, null);
}
});*/
callback.onResult(null, null);
}
});
}
public static void findOrCreateByIdGrouped(Collection<String> search, SingleResultCallback<Map<String, IpIntel>> callback) {
ipIntelCollection.find(new Document("_id", new Document("$in", search))).into(new LinkedList<>(), SyncUtils.vertxWrap((existingIntel, error) -> {
if (error != null) {
callback.onResult(null, error);
return;
}
Map<String, IpIntel> result = new ConcurrentHashMap<>();
for (IpIntel ipIntel : existingIntel) {
result.put(ipIntel.getId(), ipIntel);
}
List<Future> createNewIntelFutures = new ArrayList<>();
search.forEach((ip) -> {
if (result.containsKey(ip)) {
return;
}
Future createNewIntelFuture = Future.future();
createNewIntelFutures.add(createNewIntelFuture);
/*
SpringUtils.getBean(GeoIpService.class).lookupInfo(ip, (geoIpResult, error2) -> {
if (error2 != null) {
createNewIntelFuture.fail(error2);
return;
}
// MaxMind failed to return result
if (geoIpResult == null) {
createNewIntelFuture.complete();
return;
}
IpIntel newIpIntel = new IpIntel(ip, geoIpResult);
ipIntelCollection.insertOne(newIpIntel, SyncUtils.vertxWrap((ignored, error3) -> {
if (error3 != null) {
createNewIntelFuture.fail(error3);
} else {
result.put(ip, newIpIntel);
createNewIntelFuture.complete();
}
}));
});*/
createNewIntelFuture.complete();
});
CompositeFuture.all(createNewIntelFutures).setHandler((creationStatus) -> {
if (creationStatus.failed()) {
callback.onResult(null, creationStatus.cause());
} else {
callback.onResult(result, null);
}
});
}));
}
private IpIntel() {} // For Jackson
private IpIntel(String ip, GeoIpInfo result) {
this.id = ip;
this.hashedIp = Hashing.sha256().hashString(id + SpringUtils.getProperty("ipHashing.salt"), Charsets.UTF_8).toString();
this.lastUpdatedAt = Instant.now();
this.result = result;
this.location = new GeoJsonPoint(result.getLocation());
}
}

View File

@ -309,7 +309,6 @@ public final class User {
public void getLoginInfo(Server server, String userIp, SingleResultCallback<Map<String, Object>> callback) { public void getLoginInfo(Server server, String userIp, SingleResultCallback<Map<String, Object>> callback) {
Future<List<Punishment>> punishmentsFuture = Future.future(); Future<List<Punishment>> punishmentsFuture = Future.future();
Future<IpIntel> ipIntelFuture = Future.future();
Future<List<IpBan>> ipBansFuture = Future.future(); Future<List<IpBan>> ipBansFuture = Future.future();
Future<List<Grant>> grantsFuture = Future.future(); Future<List<Grant>> grantsFuture = Future.future();
@ -320,27 +319,24 @@ public final class User {
), new MongoToVertxCallback<>(punishmentsFuture)); ), new MongoToVertxCallback<>(punishmentsFuture));
if (userIp != null) { if (userIp != null) {
IpIntel.findOrCreateById(userIp, new MongoToVertxCallback<>(ipIntelFuture));
IpBan.findByIp(userIp, new MongoToVertxCallback<>(ipBansFuture)); IpBan.findByIp(userIp, new MongoToVertxCallback<>(ipBansFuture));
} else { } else {
ipIntelFuture.complete(null);
ipBansFuture.complete(ImmutableList.of()); ipBansFuture.complete(ImmutableList.of());
} }
Grant.findByUser(this, new MongoToVertxCallback<>(grantsFuture)); Grant.findByUser(this, new MongoToVertxCallback<>(grantsFuture));
CompositeFuture.all(punishmentsFuture, ipIntelFuture, ipBansFuture, grantsFuture).setHandler((result) -> { CompositeFuture.all(punishmentsFuture, ipBansFuture, grantsFuture).setHandler((result) -> {
if (result.failed()) { if (result.failed()) {
callback.onResult(null, result.cause()); callback.onResult(null, result.cause());
return; return;
} }
Iterable<Punishment> punishments = result.result().result(0); Iterable<Punishment> punishments = result.result().result(0);
IpIntel ipIntel = result.result().result(1); Iterable<IpBan> ipBans = result.result().result(1);
Iterable<IpBan> ipBans = result.result().result(2); Iterable<Grant> grants = result.result().result(2);
Iterable<Grant> grants = result.result().result(3);
getLoginInfo(server, ipIntel, punishments, ipBans, grants, (loginInfo, error) -> { getLoginInfo(server, punishments, ipBans, grants, (loginInfo, error) -> {
if (error != null) { if (error != null) {
callback.onResult(null, error); callback.onResult(null, error);
} else { } else {
@ -351,8 +347,8 @@ public final class User {
} }
// This is only used to help batch requests to mongo // This is only used to help batch requests to mongo
public void getLoginInfo(Server server, IpIntel ipIntel, Iterable<Punishment> punishments, Iterable<IpBan> ipBans, Iterable<Grant> grants, SingleResultCallback<Map<String, Object>> callback) { public void getLoginInfo(Server server, Iterable<Punishment> punishments, Iterable<IpBan> ipBans, Iterable<Grant> grants, SingleResultCallback<Map<String, Object>> callback) {
getAccessInfo(ipIntel, punishments, ipBans, (accessInfo, error) -> { getAccessInfo(punishments, ipBans, (accessInfo, error) -> {
if (error != null) { if (error != null) {
callback.onResult(null, error); callback.onResult(null, error);
return; return;
@ -398,7 +394,7 @@ public final class User {
}); });
} }
private void getAccessInfo(IpIntel ipIntel, Iterable<Punishment> punishments, Iterable<IpBan> ipBans, SingleResultCallback<Map<String, Object>> callback) { private void getAccessInfo(Iterable<Punishment> punishments, Iterable<IpBan> ipBans, SingleResultCallback<Map<String, Object>> callback) {
Punishment activeBan = null; Punishment activeBan = null;
IpBan activeIpBan = null; IpBan activeIpBan = null;
@ -432,38 +428,6 @@ public final class User {
), null); ), null);
} }
}); });
} else if (ipIntel != null) {
GeoIpInfo geoIpInfo = ipIntel.getResult();
GeoIpUserType userType = geoIpInfo.getTraits().getUserType();
Map<String, Object> proposedAccess = null;
if (!userType.isAllowed()) {
proposedAccess = ImmutableMap.of(
"allowed", false,
"message", "You cannot join the " + SpringUtils.getProperty("network.name") + " from a VPN."
);
} else if (BannedAsn.findById(geoIpInfo.getTraits().getAsn()) != null) {
proposedAccess = ImmutableMap.of(
"allowed", false,
"message", "You cannot join the " + SpringUtils.getProperty("network.name") + " from this ISP."
);
}
Map<String, Object> finalProposedAccess = proposedAccess;
if (proposedAccess != null) {
hasPermissionAnywhere(Permissions.BYPASS_VPN_CHECK, (bypass, error) -> {
if (error != null) {
callback.onResult(null, error);
} else if (bypass) {
callback.onResult(null, null);
} else {
callback.onResult(finalProposedAccess, null);
}
});
} else {
callback.onResult(null, null);
}
} else { } else {
callback.onResult(null, null); callback.onResult(null, null);
} }

View File

@ -9,7 +9,6 @@ import net.frozenorb.apiv3.unsorted.actor.Actor;
import net.frozenorb.apiv3.unsorted.actor.ActorType; import net.frozenorb.apiv3.unsorted.actor.ActorType;
import net.frozenorb.apiv3.domain.Grant; import net.frozenorb.apiv3.domain.Grant;
import net.frozenorb.apiv3.domain.IpBan; import net.frozenorb.apiv3.domain.IpBan;
import net.frozenorb.apiv3.domain.IpIntel;
import net.frozenorb.apiv3.domain.Punishment; import net.frozenorb.apiv3.domain.Punishment;
import net.frozenorb.apiv3.domain.Rank; import net.frozenorb.apiv3.domain.Rank;
import net.frozenorb.apiv3.domain.Server; import net.frozenorb.apiv3.domain.Server;
@ -147,26 +146,6 @@ public final class GETDumpsType implements Handler<RoutingContext> {
this.ipBanCache = ipBanCache; this.ipBanCache = ipBanCache;
}); });
IpIntel.findAllNoSort((ipIntel, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
Map<String, GeoJsonPoint> ipIntelCache = new HashMap<>();
for (IpIntel intel : ipIntel) {
GeoJsonPoint point = intel.getLocation();
if (point != null) {
String key = coordinateFormat.format(point.getLongitude()) + ":" + coordinateFormat.format(point.getLatitude());
ipIntelCache.put(key, point);
}
}
this.ipIntelCache = ipIntelCache;
});
} }
public void handle(RoutingContext ctx) { public void handle(RoutingContext ctx) {

View File

@ -1,39 +0,0 @@
package net.frozenorb.apiv3.web.route.ipIntel;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.domain.IpIntel;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import org.springframework.stereotype.Component;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
@Component
public final class GETIpInteld implements Handler<RoutingContext> {
public void handle(RoutingContext ctx) {
String userIp = ctx.request().getParam("userIp");
if (IpUtils.isValidIp(userIp)) {
IpIntel.findOrCreateById(userIp, (ipIntel, error) -> {
if (error != null) {
ErrorUtils.respondInternalError(ctx, error);
} else {
APIv3.respondJson(ctx, 200, ipIntel);
}
});
} else {
IpIntel.findByHashedIp(userIp, (ipIntel, error) -> {
if (error != null) {
ErrorUtils.respondInternalError(ctx, error);
} else {
ipIntel.setId(null); // hide actual ip field if we found the entry via hash
APIv3.respondJson(ctx, 200, ipIntel);
}
});
}
}
}

View File

@ -7,7 +7,6 @@ import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.unsorted.actor.Actor; import net.frozenorb.apiv3.unsorted.actor.Actor;
import net.frozenorb.apiv3.unsorted.actor.ActorType; import net.frozenorb.apiv3.unsorted.actor.ActorType;
import net.frozenorb.apiv3.domain.Grant; import net.frozenorb.apiv3.domain.Grant;
import net.frozenorb.apiv3.domain.IpIntel;
import net.frozenorb.apiv3.domain.Punishment; import net.frozenorb.apiv3.domain.Punishment;
import net.frozenorb.apiv3.domain.Rank; import net.frozenorb.apiv3.domain.Rank;
import net.frozenorb.apiv3.domain.Server; import net.frozenorb.apiv3.domain.Server;
@ -92,18 +91,15 @@ public final class POSTServersHeartbeat implements Handler<RoutingContext> {
Future<Map<String, Object>> callback = Future.future(); Future<Map<String, Object>> callback = Future.future();
Future<Map<UUID, User>> userLookupCallback = Future.future(); Future<Map<UUID, User>> userLookupCallback = Future.future();
Future<Map<String, IpIntel>> ipIntelCallback = Future.future();
Future<Map<UUID, List<Grant>>> grantLookupCallback = Future.future(); Future<Map<UUID, List<Grant>>> grantLookupCallback = Future.future();
Future<Map<UUID, List<Punishment>>> punishmentLookupCallback = Future.future(); Future<Map<UUID, List<Punishment>>> punishmentLookupCallback = Future.future();
User.findOrCreateByIdGrouped(playerNames, new MongoToVertxCallback<>(userLookupCallback)); User.findOrCreateByIdGrouped(playerNames, new MongoToVertxCallback<>(userLookupCallback));
IpIntel.findOrCreateByIdGrouped(playerIps.values(), new MongoToVertxCallback<>(ipIntelCallback));
Grant.findByUserGrouped(playerNames.keySet(), new MongoToVertxCallback<>(grantLookupCallback)); Grant.findByUserGrouped(playerNames.keySet(), new MongoToVertxCallback<>(grantLookupCallback));
Punishment.findByUserGrouped(playerNames.keySet(), new MongoToVertxCallback<>(punishmentLookupCallback)); Punishment.findByUserGrouped(playerNames.keySet(), new MongoToVertxCallback<>(punishmentLookupCallback));
CompositeFuture.all( CompositeFuture.all(
userLookupCallback, userLookupCallback,
ipIntelCallback,
grantLookupCallback, grantLookupCallback,
punishmentLookupCallback punishmentLookupCallback
).setHandler((batchLookupInfo) -> { ).setHandler((batchLookupInfo) -> {
@ -113,14 +109,13 @@ public final class POSTServersHeartbeat implements Handler<RoutingContext> {
} }
Map<UUID, User> users = batchLookupInfo.result().result(0); Map<UUID, User> users = batchLookupInfo.result().result(0);
Map<String, IpIntel> ipIntel = batchLookupInfo.result().result(1); Map<UUID, List<Grant>> grants = batchLookupInfo.result().result(1);
Map<UUID, List<Grant>> grants = batchLookupInfo.result().result(2); Map<UUID, List<Punishment>> punishments = batchLookupInfo.result().result(2);
Map<UUID, List<Punishment>> punishments = batchLookupInfo.result().result(3);
Map<UUID, Future> loginInfoFutures = new HashMap<>(); Map<UUID, Future> loginInfoFutures = new HashMap<>();
users.forEach((uuid, user) -> { users.forEach((uuid, user) -> {
Future<Map<String, Object>> loginInfoFuture = Future.future(); Future<Map<String, Object>> loginInfoFuture = Future.future();
createLoginInfo(user, server, ipIntel.get(playerIps.get(uuid)), grants.get(uuid), punishments.get(uuid), loginInfoFuture); createLoginInfo(user, server, grants.get(uuid), punishments.get(uuid), loginInfoFuture);
loginInfoFutures.put(uuid, loginInfoFuture); loginInfoFutures.put(uuid, loginInfoFuture);
}); });
@ -242,7 +237,7 @@ public final class POSTServersHeartbeat implements Handler<RoutingContext> {
return result; return result;
} }
private void createLoginInfo(User user, Server server, IpIntel ipIntel, List<Grant> grants, List<Punishment> punishments, Future<Map<String, Object>> callback) { private void createLoginInfo(User user, Server server, List<Grant> grants, List<Punishment> punishments, Future<Map<String, Object>> callback) {
if (user.seenOnServer(server)) { if (user.seenOnServer(server)) {
user.save((ignored, error) -> { user.save((ignored, error) -> {
if (error != null) { if (error != null) {
@ -250,10 +245,10 @@ public final class POSTServersHeartbeat implements Handler<RoutingContext> {
return; return;
} }
user.getLoginInfo(server, ipIntel, punishments, ImmutableList.of(), grants, new MongoToVertxCallback<>(callback)); user.getLoginInfo(server, punishments, ImmutableList.of(), grants, new MongoToVertxCallback<>(callback));
}); });
} else { } else {
user.getLoginInfo(server, ipIntel, punishments, ImmutableList.of(), grants, new MongoToVertxCallback<>(callback)); user.getLoginInfo(server, punishments, ImmutableList.of(), grants, new MongoToVertxCallback<>(callback));
} }
} }