forked from I2P_Developers/i2p.i2p
Sybil: More prep and refactor for background analysis
Put dest name in too-close reasons
This commit is contained in:
@ -105,7 +105,7 @@ class SybilRenderer {
|
|||||||
/**
|
/**
|
||||||
* A total score and a List of reason Strings
|
* A total score and a List of reason Strings
|
||||||
*/
|
*/
|
||||||
private static class Points implements Comparable<Points> {
|
public static class Points implements Comparable<Points> {
|
||||||
private double points;
|
private double points;
|
||||||
private final List<String> reasons;
|
private final List<String> reasons;
|
||||||
|
|
||||||
@ -156,6 +156,24 @@ class SybilRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge points1 into points2.
|
||||||
|
* points1 is unmodified.
|
||||||
|
*/
|
||||||
|
private void mergePoints(Map<Hash, Points> points1, Map<Hash, Points> points2) {
|
||||||
|
for (Map.Entry<Hash, Points> e : points1.entrySet()) {
|
||||||
|
Hash h = e.getKey();
|
||||||
|
Points p1 = e.getValue();
|
||||||
|
Points p2 = points2.get(h);
|
||||||
|
if (p2 != null) {
|
||||||
|
p2.points += p1.points;
|
||||||
|
p2.reasons.addAll(p1.reasons);
|
||||||
|
} else {
|
||||||
|
points2.put(h, p1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void addPoints(Map<Hash, Points> points, Hash h, double d, String reason) {
|
private void addPoints(Map<Hash, Points> points, Hash h, double d, String reason) {
|
||||||
String rsn = "<b>" + fmt.format(d) + ":</b> " + reason;
|
String rsn = "<b>" + fmt.format(d) + ":</b> " + reason;
|
||||||
Points dd = points.get(h);
|
Points dd = points.get(h);
|
||||||
@ -168,15 +186,12 @@ class SybilRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The whole thing
|
* All the floodfills, not including us
|
||||||
*
|
* @since 0.9.38 split out from renderRouterInfoHTML
|
||||||
* @param routerPrefix ignored
|
|
||||||
*/
|
*/
|
||||||
private void renderRouterInfoHTML(Writer out, String routerPrefix) throws IOException {
|
private List<RouterInfo> getFloodfills(Hash us) {
|
||||||
Set<Hash> ffs = _context.peerManager().getPeersByCapability('f');
|
Set<Hash> ffs = _context.peerManager().getPeersByCapability('f');
|
||||||
List<RouterInfo> ris = new ArrayList<RouterInfo>(ffs.size());
|
List<RouterInfo> ris = new ArrayList<RouterInfo>(ffs.size());
|
||||||
Hash us = _context.routerHash();
|
|
||||||
Hash ourRKey = _context.router().getRouterInfo().getRoutingKey();
|
|
||||||
for (Hash ff : ffs) {
|
for (Hash ff : ffs) {
|
||||||
if (ff.equals(us))
|
if (ff.equals(us))
|
||||||
continue;
|
continue;
|
||||||
@ -184,6 +199,32 @@ class SybilRenderer {
|
|||||||
if (ri != null)
|
if (ri != null)
|
||||||
ris.add(ri);
|
ris.add(ri);
|
||||||
}
|
}
|
||||||
|
return ris;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double getAvgMinDist(List<RouterInfo> ris) {
|
||||||
|
double tot = 0;
|
||||||
|
int count = 200;
|
||||||
|
byte[] b = new byte[32];
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
_context.random().nextBytes(b);
|
||||||
|
Hash h = new Hash(b);
|
||||||
|
double d = closestDistance(h, ris);
|
||||||
|
tot += d;
|
||||||
|
}
|
||||||
|
double avgMinDist = tot / count;
|
||||||
|
return avgMinDist;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The whole thing
|
||||||
|
*
|
||||||
|
* @param routerPrefix ignored
|
||||||
|
*/
|
||||||
|
private void renderRouterInfoHTML(Writer out, String routerPrefix) throws IOException {
|
||||||
|
Hash us = _context.routerHash();
|
||||||
|
Hash ourRKey = _context.router().getRouterInfo().getRoutingKey();
|
||||||
|
List<RouterInfo> ris = getFloodfills(us);
|
||||||
if (ris.isEmpty()) {
|
if (ris.isEmpty()) {
|
||||||
out.write("<h3 class=\"sybils\">No known floodfills</h3>");
|
out.write("<h3 class=\"sybils\">No known floodfills</h3>");
|
||||||
return;
|
return;
|
||||||
@ -210,16 +251,7 @@ class SybilRenderer {
|
|||||||
renderRouterInfo(buf, _context.router().getRouterInfo(), null, true, false);
|
renderRouterInfo(buf, _context.router().getRouterInfo(), null, true, false);
|
||||||
buf.append("<h3 id=\"known\" class=\"sybils\">Known Floodfills: ").append(ris.size()).append("</h3>");
|
buf.append("<h3 id=\"known\" class=\"sybils\">Known Floodfills: ").append(ris.size()).append("</h3>");
|
||||||
|
|
||||||
double tot = 0;
|
double avgMinDist = getAvgMinDist(ris);
|
||||||
int count = 200;
|
|
||||||
byte[] b = new byte[32];
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
_context.random().nextBytes(b);
|
|
||||||
Hash h = new Hash(b);
|
|
||||||
double d = closestDistance(h, ris);
|
|
||||||
tot += d;
|
|
||||||
}
|
|
||||||
double avgMinDist = tot / count;
|
|
||||||
buf.append("<div id=\"sybils_summary\">\n" +
|
buf.append("<div id=\"sybils_summary\">\n" +
|
||||||
"<b>Average closest floodfill distance:</b> ").append(fmt.format(avgMinDist)).append("<br>\n" +
|
"<b>Average closest floodfill distance:</b> ").append(fmt.format(avgMinDist)).append("<br>\n" +
|
||||||
"<b>Routing Data:</b> \"").append(DataHelper.getUTF8(_context.routerKeyGenerator().getModData()))
|
"<b>Routing Data:</b> \"").append(DataHelper.getUTF8(_context.routerKeyGenerator().getModData()))
|
||||||
@ -243,15 +275,15 @@ class SybilRenderer {
|
|||||||
// Distance to our router analysis
|
// Distance to our router analysis
|
||||||
buf.append("<h3 id=\"ritoday\" class=\"sybils\">Closest Floodfills to Our Routing Key (Where we Store our RI)</h3>");
|
buf.append("<h3 id=\"ritoday\" class=\"sybils\">Closest Floodfills to Our Routing Key (Where we Store our RI)</h3>");
|
||||||
buf.append("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&sybil\">See all</a></p>");
|
buf.append("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&sybil\">See all</a></p>");
|
||||||
renderRouterInfoHTML(out, buf, ourRKey, avgMinDist, ris, points);
|
renderRouterInfoHTML(out, buf, ourRKey, "our rkey", avgMinDist, ris, points);
|
||||||
RouterKeyGenerator rkgen = _context.routerKeyGenerator();
|
RouterKeyGenerator rkgen = _context.routerKeyGenerator();
|
||||||
Hash nkey = rkgen.getNextRoutingKey(us);
|
Hash nkey = rkgen.getNextRoutingKey(us);
|
||||||
buf.append("<h3 id=\"ritmrw\" class=\"sybils\">Closest Floodfills to Tomorrow's Routing Key (Where we will Store our RI)</h3>");
|
buf.append("<h3 id=\"ritmrw\" class=\"sybils\">Closest Floodfills to Tomorrow's Routing Key (Where we will Store our RI)</h3>");
|
||||||
buf.append("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&sybil\">See all</a></p>");
|
buf.append("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&sybil\">See all</a></p>");
|
||||||
renderRouterInfoHTML(out, buf, nkey, avgMinDist, ris, points);
|
renderRouterInfoHTML(out, buf, nkey, "our rkey (tomorrow)", avgMinDist, ris, points);
|
||||||
|
|
||||||
buf.append("<h3 id=\"dht\" class=\"sybils\">Closest Floodfills to Our Router Hash (DHT Neighbors if we are Floodfill)</h3>");
|
buf.append("<h3 id=\"dht\" class=\"sybils\">Closest Floodfills to Our Router Hash (DHT Neighbors if we are Floodfill)</h3>");
|
||||||
renderRouterInfoHTML(out, buf, us, avgMinDist, ris, points);
|
renderRouterInfoHTML(out, buf, us, "our router", avgMinDist, ris, points);
|
||||||
|
|
||||||
// Distance to our published destinations analysis
|
// Distance to our published destinations analysis
|
||||||
buf.append("<h3 id=\"dest\" class=\"sybils\">Floodfills Close to Our Destinations</h3>");
|
buf.append("<h3 id=\"dest\" class=\"sybils\">Floodfills Close to Our Destinations</h3>");
|
||||||
@ -269,14 +301,14 @@ class SybilRenderer {
|
|||||||
continue;
|
continue;
|
||||||
Hash rkey = ls.getRoutingKey();
|
Hash rkey = ls.getRoutingKey();
|
||||||
TunnelPool in = clientInboundPools.get(client);
|
TunnelPool in = clientInboundPools.get(client);
|
||||||
String name = (in != null) ? in.getSettings().getDestinationNickname() : client.toBase64().substring(0,4);
|
String name = (in != null) ? DataHelper.escapeHTML(in.getSettings().getDestinationNickname()) : client.toBase64().substring(0,4);
|
||||||
buf.append("<h3 class=\"sybils\">Closest floodfills to the Routing Key for " + DataHelper.escapeHTML(name) + " (where we store our LS)</h3>");
|
buf.append("<h3 class=\"sybils\">Closest floodfills to the Routing Key for " + name + " (where we store our LS)</h3>");
|
||||||
buf.append("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&sybil=" + ls.getHash().toBase64() + "\">See all</a></p>");
|
buf.append("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&sybil=" + ls.getHash().toBase64() + "\">See all</a></p>");
|
||||||
renderRouterInfoHTML(out, buf, rkey, avgMinDist, ris, points);
|
renderRouterInfoHTML(out, buf, rkey, name, avgMinDist, ris, points);
|
||||||
nkey = rkgen.getNextRoutingKey(ls.getHash());
|
nkey = rkgen.getNextRoutingKey(ls.getHash());
|
||||||
buf.append("<h3 class=\"sybils\">Closest floodfills to Tomorrow's Routing Key for " + DataHelper.escapeHTML(name) + " (where we will store our LS)</h3>");
|
buf.append("<h3 class=\"sybils\">Closest floodfills to Tomorrow's Routing Key for " + name + " (where we will store our LS)</h3>");
|
||||||
buf.append("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&sybil=" + ls.getHash().toBase64() + "\">See all</a></p>");
|
buf.append("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&sybil=" + ls.getHash().toBase64() + "\">See all</a></p>");
|
||||||
renderRouterInfoHTML(out, buf, nkey, avgMinDist, ris, points);
|
renderRouterInfoHTML(out, buf, nkey, name + " (tomorrow)", avgMinDist, ris, points);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Profile analysis
|
// Profile analysis
|
||||||
@ -311,6 +343,67 @@ class SybilRenderer {
|
|||||||
buf.setLength(0);
|
buf.setLength(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Analyze threats. No output.
|
||||||
|
* Return separate maps for each cause instead?
|
||||||
|
* @since 0.9.38
|
||||||
|
*/
|
||||||
|
public Map<Hash, Points> backgroundAnalysis() throws IOException {
|
||||||
|
Hash us = _context.routerHash();
|
||||||
|
List<RouterInfo> ris = getFloodfills(us);
|
||||||
|
|
||||||
|
double avgMinDist = getAvgMinDist(ris);
|
||||||
|
Map<Hash, Points> points = new HashMap<Hash, Points>(64);
|
||||||
|
|
||||||
|
// IP analysis
|
||||||
|
renderIPGroupsFamily(null, null, ris, points);
|
||||||
|
renderIPGroupsUs(null, null, ris, points);
|
||||||
|
renderIPGroups32(null, null, ris, points);
|
||||||
|
renderIPGroups24(null, null, ris, points);
|
||||||
|
renderIPGroups16(null, null, ris, points);
|
||||||
|
|
||||||
|
// Pairwise distance analysis
|
||||||
|
renderPairDistance(null, null, ris, points);
|
||||||
|
|
||||||
|
// Distance to our router analysis
|
||||||
|
// closest to our routing key today
|
||||||
|
Hash ourRKey = _context.router().getRouterInfo().getRoutingKey();
|
||||||
|
renderRouterInfoHTML(null, null, ourRKey, "our rkey", avgMinDist, ris, points);
|
||||||
|
// closest to our routing key tomorrow
|
||||||
|
RouterKeyGenerator rkgen = _context.routerKeyGenerator();
|
||||||
|
Hash nkey = rkgen.getNextRoutingKey(us);
|
||||||
|
renderRouterInfoHTML(null, null, nkey, "our rkey (tomorrow)", avgMinDist, ris, points);
|
||||||
|
// closest to us
|
||||||
|
renderRouterInfoHTML(null, null, us, "our router", avgMinDist, ris, points);
|
||||||
|
|
||||||
|
// Distance to our published destinations analysis
|
||||||
|
Map<Hash, TunnelPool> clientInboundPools = _context.tunnelManager().getInboundClientPools();
|
||||||
|
List<Hash> destinations = new ArrayList<Hash>(clientInboundPools.keySet());
|
||||||
|
for (Hash client : destinations) {
|
||||||
|
boolean isLocal = _context.clientManager().isLocal(client);
|
||||||
|
if (!isLocal)
|
||||||
|
continue;
|
||||||
|
if (! _context.clientManager().shouldPublishLeaseSet(client))
|
||||||
|
continue;
|
||||||
|
LeaseSet ls = _context.netDb().lookupLeaseSetLocally(client);
|
||||||
|
if (ls == null)
|
||||||
|
continue;
|
||||||
|
Hash rkey = ls.getRoutingKey();
|
||||||
|
TunnelPool in = clientInboundPools.get(client);
|
||||||
|
String name = (in != null) ? DataHelper.escapeHTML(in.getSettings().getDestinationNickname()) : client.toBase64().substring(0,4);
|
||||||
|
// closest to routing key today
|
||||||
|
renderRouterInfoHTML(null, null, rkey, name, avgMinDist, ris, points);
|
||||||
|
// closest to routing key tomorrow
|
||||||
|
nkey = rkgen.getNextRoutingKey(ls.getHash());
|
||||||
|
renderRouterInfoHTML(null, null, nkey, name + " (tomorrow)", avgMinDist, ris, points);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Profile analysis
|
||||||
|
addProfilePoints(ris, points);
|
||||||
|
addVersionPoints(ris, points);
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
private static class Pair implements Comparable<Pair> {
|
private static class Pair implements Comparable<Pair> {
|
||||||
public final RouterInfo r1, r2;
|
public final RouterInfo r1, r2;
|
||||||
public final BigInteger dist;
|
public final BigInteger dist;
|
||||||
@ -380,7 +473,7 @@ class SybilRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private double closestDistance(Hash h, List<RouterInfo> ris) throws IOException {
|
private double closestDistance(Hash h, List<RouterInfo> ris) {
|
||||||
BigInteger min = (new BigInteger("2")).pow(256);
|
BigInteger min = (new BigInteger("2")).pow(256);
|
||||||
for (RouterInfo info : ris) {
|
for (RouterInfo info : ris) {
|
||||||
BigInteger dist = HashDistance.getDistance(h, info.getHash());
|
BigInteger dist = HashDistance.getDistance(h, info.getHash());
|
||||||
@ -799,8 +892,9 @@ class SybilRenderer {
|
|||||||
/**
|
/**
|
||||||
* @param out null for background analysis
|
* @param out null for background analysis
|
||||||
* @param buf null for background analysis
|
* @param buf null for background analysis
|
||||||
|
* @param usName HTML escaped
|
||||||
*/
|
*/
|
||||||
private void renderRouterInfoHTML(Writer out, StringBuilder buf, Hash us, double avgMinDist,
|
private void renderRouterInfoHTML(Writer out, StringBuilder buf, Hash us, String usName, double avgMinDist,
|
||||||
List<RouterInfo> ris, Map<Hash, Points> points) throws IOException {
|
List<RouterInfo> ris, Map<Hash, Points> points) throws IOException {
|
||||||
Collections.sort(ris, new RouterInfoRoutingKeyComparator(us));
|
Collections.sort(ris, new RouterInfoRoutingKeyComparator(us));
|
||||||
double min = 256;
|
double min = 256;
|
||||||
@ -843,7 +937,7 @@ class SybilRenderer {
|
|||||||
double point = MIN_CLOSE - dist;
|
double point = MIN_CLOSE - dist;
|
||||||
if (point > 0) {
|
if (point > 0) {
|
||||||
point *= OUR_KEY_FACTOR;
|
point *= OUR_KEY_FACTOR;
|
||||||
addPoints(points, ri.getHash(), point, "Very close (" + fmt.format(dist) + ") to our key " + us.toBase64());
|
addPoints(points, ri.getHash(), point, "Very close (" + fmt.format(dist) + ") to our key " + usName + ": " + us.toBase64());
|
||||||
}
|
}
|
||||||
if (i >= MAX - 1)
|
if (i >= MAX - 1)
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user