use of net.i2p.data.router.RouterInfo in project i2p.i2p by i2p.
the class SybilRenderer method renderIPGroups16.
private void renderIPGroups16(Writer out, StringBuilder buf, List<RouterInfo> ris, Map<Hash, Points> points) throws IOException {
buf.append("<h3 id=\"same16\" class=\"sybils\">Floodfills in the Same /16 (4 minimum)</h3>");
ObjectCounter<Integer> oc = new ObjectCounter<Integer>();
for (RouterInfo info : ris) {
byte[] ip = getIP(info);
if (ip == null)
continue;
Integer x = Integer.valueOf((int) DataHelper.fromLong(ip, 0, 2));
oc.increment(x);
}
List<Integer> foo = new ArrayList<Integer>();
for (Integer ii : oc.objects()) {
int count = oc.count(ii);
if (count >= 4)
foo.add(ii);
}
Collections.sort(foo, new FooComparator(oc));
boolean found = false;
for (Integer ii : foo) {
int count = oc.count(ii);
int i = ii.intValue();
int i0 = i >> 8;
int i1 = i & 0xff;
String sip = i0 + "." + i1 + ".0/16";
buf.append("<p class=\"sybil_info\"><b>").append(count).append(" floodfills with IP <a href=\"/netdb?ip=").append(sip).append("&sybil\">").append(sip).append("</a></b></p>");
for (RouterInfo info : ris) {
byte[] ip = getIP(info);
if (ip == null)
continue;
if ((ip[0] & 0xff) != i0)
continue;
if ((ip[1] & 0xff) != i1)
continue;
found = true;
// limit display
// renderRouterInfo(buf, info, null, false, false);
double point = POINTS16 * (count - 1);
addPoints(points, info.getHash(), point, "Same /16 IP with " + (count - 1) + " other" + ((count > 2) ? "s" : ""));
}
}
if (!found)
buf.append("<p class=\"notfound\">None</p>");
out.write(buf.toString());
out.flush();
buf.setLength(0);
}
use of net.i2p.data.router.RouterInfo in project i2p.i2p by i2p.
the class SybilRenderer method renderPairDistance.
private void renderPairDistance(Writer out, StringBuilder buf, List<RouterInfo> ris, Map<Hash, Points> points) throws IOException {
int sz = ris.size();
List<Pair> pairs = new ArrayList<Pair>(PAIRMAX);
double total = 0;
for (int i = 0; i < sz; i++) {
RouterInfo info1 = ris.get(i);
for (int j = i + 1; j < sz; j++) {
RouterInfo info2 = ris.get(j);
BigInteger dist = HashDistance.getDistance(info1.getHash(), info2.getHash());
if (pairs.isEmpty()) {
pairs.add(new Pair(info1, info2, dist));
} else if (pairs.size() < PAIRMAX) {
pairs.add(new Pair(info1, info2, dist));
Collections.sort(pairs);
} else if (dist.compareTo(pairs.get(PAIRMAX - 1).dist) < 0) {
pairs.set(PAIRMAX - 1, new Pair(info1, info2, dist));
Collections.sort(pairs);
}
total += biLog2(dist);
}
}
double avg = total / (sz * sz / 2d);
buf.append("<h3 class=\"sybils\">Average Floodfill Distance is ").append(fmt.format(avg)).append("</h3>");
buf.append("<h3 id=\"pairs\" class=\"sybils\">Closest Floodfill Pairs by Hash</h3>");
for (Pair p : pairs) {
double distance = biLog2(p.dist);
double point = MIN_CLOSE - distance;
if (point < 0)
// sorted;
break;
if (point >= 2) {
// limit display
buf.append("<p class=\"hashdist\"><b>Hash Distance: ").append(fmt.format(distance)).append(": </b>");
buf.append("</p>");
renderRouterInfo(buf, p.r1, null, false, false);
renderRouterInfo(buf, p.r2, null, false, false);
}
point *= PAIR_DISTANCE_FACTOR;
String b2 = p.r2.getHash().toBase64();
addPoints(points, p.r1.getHash(), point, "Very close (" + fmt.format(distance) + ") to other floodfill <a href=\"netdb?r=" + b2 + "\">" + b2 + "</a>");
String b1 = p.r1.getHash().toBase64();
addPoints(points, p.r2.getHash(), point, "Very close (" + fmt.format(distance) + ") to other floodfill <a href=\"netdb?r=" + b1 + "\">" + b1 + "</a>");
}
out.write(buf.toString());
out.flush();
buf.setLength(0);
}
use of net.i2p.data.router.RouterInfo in project i2p.i2p by i2p.
the class SybilRenderer method renderIPGroups32.
private void renderIPGroups32(Writer out, StringBuilder buf, List<RouterInfo> ris, Map<Hash, Points> points) throws IOException {
buf.append("<h3 id=\"sameIP\" class=\"sybils\">Floodfills with the Same IP</h3>");
ObjectCounter<Integer> oc = new ObjectCounter<Integer>();
for (RouterInfo info : ris) {
byte[] ip = getIP(info);
if (ip == null)
continue;
Integer x = Integer.valueOf((int) DataHelper.fromLong(ip, 0, 4));
oc.increment(x);
}
List<Integer> foo = new ArrayList<Integer>();
for (Integer ii : oc.objects()) {
int count = oc.count(ii);
if (count >= 2)
foo.add(ii);
}
Collections.sort(foo, new FooComparator(oc));
boolean found = false;
for (Integer ii : foo) {
int count = oc.count(ii);
int i = ii.intValue();
int i0 = (i >> 24) & 0xff;
int i1 = (i >> 16) & 0xff;
int i2 = (i >> 8) & 0xff;
int i3 = i & 0xff;
String sip = i0 + "." + i1 + '.' + i2 + '.' + i3;
buf.append("<p class=\"sybil_info\"><b>").append(count).append(" floodfills with IP <a href=\"/netdb?ip=").append(sip).append("&sybil\">").append(sip).append("</a>:</b></p>");
for (RouterInfo info : ris) {
byte[] ip = getIP(info);
if (ip == null)
continue;
if ((ip[0] & 0xff) != i0)
continue;
if ((ip[1] & 0xff) != i1)
continue;
if ((ip[2] & 0xff) != i2)
continue;
if ((ip[3] & 0xff) != i3)
continue;
found = true;
renderRouterInfo(buf, info, null, false, false);
double point = POINTS32 * (count - 1);
addPoints(points, info.getHash(), point, "Same IP with " + (count - 1) + " other" + ((count > 2) ? "s" : ""));
}
}
if (!found)
buf.append("<p class=\"notfound\">None</p>");
out.write(buf.toString());
out.flush();
buf.setLength(0);
}
use of net.i2p.data.router.RouterInfo in project i2p.i2p by i2p.
the class SybilRenderer method renderRouterInfoHTML.
/**
* The whole thing
*
* @param routerPrefix ignored
*/
private void renderRouterInfoHTML(Writer out, String routerPrefix) throws IOException {
Set<Hash> ffs = _context.peerManager().getPeersByCapability('f');
List<RouterInfo> ris = new ArrayList<RouterInfo>(ffs.size());
Hash us = _context.routerHash();
Hash ourRKey = _context.router().getRouterInfo().getRoutingKey();
for (Hash ff : ffs) {
if (ff.equals(us))
continue;
RouterInfo ri = _context.netDb().lookupRouterInfoLocally(ff);
if (ri != null)
ris.add(ri);
}
if (ris.isEmpty()) {
out.write("<h3 class=\"sybils\">No known floodfills</h3>");
return;
}
StringBuilder buf = new StringBuilder(4 * 1024);
buf.append("<p id=\"sybilinfo\"><b>This is an experimental network database tool for debugging and analysis. Do not panic even if you see warnings below. " + "Possible \"threats\" are summarized at the bottom, however these are unlikely to be real threats. " + "If you see anything you would like to discuss with the devs, contact us on IRC #i2p-dev.</b></p>" + "<div id=\"sybilnav\"><ul><li><a href=\"#known\">FF Summary</a>" + "</li><li><a href=\"#family\">Same Family</a>" + "</li><li><a href=\"#ourIP\">IP close to us</a>" + "</li><li><a href=\"#sameIP\">Same IP</a>" + "</li><li><a href=\"#same24\">Same /24</a>" + "</li><li><a href=\"#same16\">Same /16</a>" + "</li><li><a href=\"#pairs\">Pair distance</a>" + "</li><li><a href=\"#ritoday\">Close to us</a>" + "</li><li><a href=\"#ritmrw\">Close to us tomorrow</a>" + "</li><li><a href=\"#dht\">DHT neighbors</a>" + "</li><li><a href=\"#dest\">Close to our destinations</a>" + "</li><li><a href=\"#threats\">Highest threats</a>" + "</li></ul></div>");
renderRouterInfo(buf, _context.router().getRouterInfo(), null, true, false);
buf.append("<h3 id=\"known\" class=\"sybils\">Known Floodfills: ").append(ris.size()).append("</h3>");
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;
buf.append("<div id=\"sybils_summary\">\n");
buf.append("<b>Average closest floodfill distance:</b> ").append(fmt.format(avgMinDist)).append("<br>\n");
buf.append("<b>Routing Data:</b> \"").append(DataHelper.getUTF8(_context.routerKeyGenerator().getModData())).append("\" <b>Last Changed:</b> ").append(new Date(_context.routerKeyGenerator().getLastChanged())).append("<br>\n");
buf.append("<b>Next Routing Data:</b> \"").append(DataHelper.getUTF8(_context.routerKeyGenerator().getNextModData())).append("\" <b>Rotates in:</b> ").append(DataHelper.formatDuration(_context.routerKeyGenerator().getTimeTillMidnight())).append("\n");
buf.append("</div>\n");
Map<Hash, Points> points = new HashMap<Hash, Points>(64);
// IP analysis
renderIPGroupsFamily(out, buf, ris, points);
renderIPGroupsUs(out, buf, ris, points);
renderIPGroups32(out, buf, ris, points);
renderIPGroups24(out, buf, ris, points);
renderIPGroups16(out, buf, ris, points);
// Pairwise distance analysis
renderPairDistance(out, buf, ris, points);
// 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("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&sybil\">See all</a></p>");
renderRouterInfoHTML(out, buf, ourRKey, avgMinDist, ris, points);
RouterKeyGenerator rkgen = _context.routerKeyGenerator();
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("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&sybil\">See all</a></p>");
renderRouterInfoHTML(out, buf, nkey, avgMinDist, ris, points);
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);
// Distance to our published destinations analysis
buf.append("<h3 id=\"dest\" class=\"sybils\">Floodfills Close to Our Destinations</h3>");
Map<Hash, TunnelPool> clientInboundPools = _context.tunnelManager().getInboundClientPools();
List<Hash> destinations = new ArrayList<Hash>(clientInboundPools.keySet());
// boolean debug = _context.getBooleanProperty(HelperBase.PROP_ADVANCED);
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) ? 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("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&sybil=" + ls.getHash().toBase64() + "\">See all</a></p>");
renderRouterInfoHTML(out, buf, rkey, avgMinDist, ris, points);
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("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&sybil=" + ls.getHash().toBase64() + "\">See all</a></p>");
renderRouterInfoHTML(out, buf, nkey, avgMinDist, ris, points);
}
// Profile analysis
addProfilePoints(ris, points);
addVersionPoints(ris, points);
if (!points.isEmpty()) {
List<Hash> warns = new ArrayList<Hash>(points.keySet());
Collections.sort(warns, new PointsComparator(points));
buf.append("<h3 id=\"threats\" class=\"sybils\">Routers with Most Threat Points</h3>");
for (Hash h : warns) {
RouterInfo ri = _context.netDb().lookupRouterInfoLocally(h);
if (ri == null)
continue;
Points pp = points.get(h);
double p = pp.points;
if (p < MIN_DISPLAY_POINTS)
// sorted
break;
buf.append("<p class=\"threatpoints\"><b>Threat Points: " + fmt.format(p) + "</b></p><ul>");
for (String s : pp.reasons) {
buf.append("<li>").append(s).append("</li>");
}
buf.append("</ul>");
renderRouterInfo(buf, ri, null, false, false);
}
}
out.write(buf.toString());
out.flush();
buf.setLength(0);
}
use of net.i2p.data.router.RouterInfo in project i2p.i2p by i2p.
the class DatabaseStoreMessage method readMessage.
public void readMessage(byte[] data, int offset, int dataSize, int type) throws I2NPMessageException {
if (type != MESSAGE_TYPE)
throw new I2NPMessageException("Message type is incorrect for this message");
int curIndex = offset;
_key = Hash.create(data, curIndex);
// Fast-fail here to save resources.
if (_key.equals(Hash.FAKE_HASH)) {
// createRateStat in KNDF
_context.statManager().addRateData("netDb.DSMAllZeros", 1);
throw new I2NPMessageException("DSM all zeros");
}
curIndex += Hash.HASH_LENGTH;
// as of 0.9.18, ignore other 7 bits of the type byte, in preparation for future options
int dbType = data[curIndex] & 0x01;
curIndex++;
_replyToken = DataHelper.fromLong(data, curIndex, 4);
curIndex += 4;
if (_replyToken > 0) {
long tunnel = DataHelper.fromLong(data, curIndex, 4);
if (tunnel > 0)
_replyTunnel = new TunnelId(tunnel);
curIndex += 4;
_replyGateway = Hash.create(data, curIndex);
curIndex += Hash.HASH_LENGTH;
} else {
_replyTunnel = null;
_replyGateway = null;
}
if (dbType == DatabaseEntry.KEY_TYPE_LEASESET) {
_dbEntry = new LeaseSet();
try {
_dbEntry.readBytes(new ByteArrayInputStream(data, curIndex, data.length - curIndex));
} catch (DataFormatException dfe) {
throw new I2NPMessageException("Error reading the leaseSet", dfe);
} catch (IOException ioe) {
throw new I2NPMessageException("Error reading the leaseSet", ioe);
}
} else {
// dbType == DatabaseEntry.KEY_TYPE_ROUTERINFO
_dbEntry = new RouterInfo();
int compressedSize = (int) DataHelper.fromLong(data, curIndex, 2);
curIndex += 2;
if (compressedSize <= 0 || curIndex + compressedSize > data.length || curIndex + compressedSize > dataSize + offset)
throw new I2NPMessageException("Compressed RI length: " + compressedSize + " but remaining bytes: " + Math.min(data.length - curIndex, dataSize + offset - curIndex));
try {
// TODO we could delay decompression, just copy to a new byte array and store in _byteCache
// May not be necessary since the IBGW now uses UnknownI2NPMessage.
// DSMs at the OBEP are generally garlic wrapped, so the OBEP won't see it.
// If we do delay it, getEntry() will have to check if _dbEntry is null and _byteCache
// is non-null, and then decompress.
byte[] decompressed = DataHelper.decompress(data, curIndex, compressedSize);
_dbEntry.readBytes(new ByteArrayInputStream(decompressed));
} catch (DataFormatException dfe) {
throw new I2NPMessageException("Error reading the routerInfo", dfe);
} catch (IOException ioe) {
throw new I2NPMessageException("Corrupt compressed routerInfo size = " + compressedSize, ioe);
}
}
// if (!key.equals(_dbEntry.getHash()))
// throw new I2NPMessageException("Hash mismatch in DSM");
}
Aggregations