Sybil: Option to run on non-floodfills too

This commit is contained in:
zzz
2019-05-18 21:45:55 +00:00
parent 03bd3e2db3
commit 10354df425
3 changed files with 51 additions and 7 deletions

View File

@@ -65,6 +65,7 @@ public class Analysis extends JobImpl implements RouterApp {
public static final String PROP_FREQUENCY = "router.sybilFrequency";
public static final String PROP_THRESHOLD = "router.sybilThreshold";
public static final String PROP_BLOCK = "router.sybilBlock.enable";
public static final String PROP_NONFF = "router.sybilIncludeAll";
public static final String PROP_BLOCKTIME = "router.sybilBlock.period";
private static final long MIN_FREQUENCY = 60*60*1000L;
private static final long MIN_UPTIME = 75*60*1000L;
@@ -81,6 +82,7 @@ public class Analysis extends JobImpl implements RouterApp {
private static final double POINTS_US24 = 20.0;
private static final double POINTS_US16 = 10.0;
private static final double POINTS_FAMILY = -10.0;
private static final double POINTS_NONFF = -5.0;
private static final double POINTS_BAD_OUR_FAMILY = 100.0;
private static final double POINTS_OUR_FAMILY = -100.0;
public static final double MIN_CLOSE = 242.0;
@@ -126,7 +128,7 @@ public class Analysis extends JobImpl implements RouterApp {
public void runJob() {
long now = _context.clock().now();
_log.info("Running analysis");
Map<Hash, Points> points = backgroundAnalysis();
Map<Hash, Points> points = backgroundAnalysis(_context.getBooleanProperty(PROP_NONFF));
if (!points.isEmpty()) {
try {
_log.info("Storing analysis");
@@ -282,17 +284,30 @@ public class Analysis extends JobImpl implements RouterApp {
/**
* Analyze threats. No output.
* Return separate maps for each cause instead?
* @param includeAll false for floodfills only
* @since 0.9.38
*/
public synchronized Map<Hash, Points> backgroundAnalysis() {
public synchronized Map<Hash, Points> backgroundAnalysis(boolean includeAll) {
_wasRun = true;
Map<Hash, Points> points = new HashMap<Hash, Points>(64);
Hash us = _context.routerHash();
if (us == null)
return points;
List<RouterInfo> ris = getFloodfills(us);
List<RouterInfo> ris;
if (includeAll) {
Set<RouterInfo> set = _context.netDb().getRouters();
ris = new ArrayList<RouterInfo>(set.size());
for (RouterInfo ri : set) {
if (!ri.getIdentity().getHash().equals(us))
ris.add(ri);
}
} else {
ris = getFloodfills(us);
}
if (ris.isEmpty())
return points;
if (_log.shouldWarn())
_log.warn("Analyzing " + ris.size() + " routers, including non-floodfills? " + includeAll);
double avgMinDist = getAvgMinDist(ris);
@@ -396,8 +411,14 @@ public class Analysis extends JobImpl implements RouterApp {
double total = 0;
for (int i = 0; i < sz; i++) {
RouterInfo info1 = ris.get(i);
// don't do distance calculation for non-floodfills
if (!info1.getCapabilities().contains("f"))
continue;
for (int j = i + 1; j < sz; j++) {
RouterInfo info2 = ris.get(j);
// don't do distance calculation for non-floodfills
if (!info2.getCapabilities().contains("f"))
continue;
BigInteger dist = HashDistance.getDistance(info1.getHash(), info2.getHash());
if (pairs.isEmpty()) {
pairs.add(new Pair(info1, info2, dist));
@@ -699,6 +720,9 @@ public class Analysis extends JobImpl implements RouterApp {
}
addPoints(points, h, POINTS_BANLIST, buf.toString());
}
// don't do profile calcluations for non-floodfills
if (!info.getCapabilities().contains("f"))
continue;
PeerProfile prof = _context.profileOrganizer().getProfileNonblocking(h);
if (prof != null) {
long heard = prof.getFirstHeardAbout();
@@ -748,6 +772,8 @@ public class Analysis extends JobImpl implements RouterApp {
String caps = info.getCapabilities();
if (!caps.contains("R"))
addPoints(points, h, POINTS_UNREACHABLE, "Unreachable: " + DataHelper.escapeHTML(caps));
if (!caps.contains("f"))
addPoints(points, h, POINTS_NONFF, "Non-floodfill");
String hisFullVer = info.getVersion();
if (!hisFullVer.startsWith("0.9.")) {
addPoints(points, h, POINTS_BAD_VERSION, "Strange version " + DataHelper.escapeHTML(hisFullVer));
@@ -779,6 +805,9 @@ public class Analysis extends JobImpl implements RouterApp {
int count = Math.min(MAX, ris.size());
for (int i = 0; i < count; i++) {
RouterInfo ri = ris.get(i);
// don't do distance calculation for non-floodfills
if (!ri.getCapabilities().contains("f"))
continue;
BigInteger bidist = HashDistance.getDistance(us, ri.getHash());
double dist = biLog2(bidist);
double point = MIN_CLOSE - dist;

View File

@@ -242,6 +242,8 @@ public class NetDbHelper extends FormHandler {
}
String enable = getJettyString("block");
toSave.put(Analysis.PROP_BLOCK, Boolean.toString(enable != null));
String nonff = getJettyString("nonff");
toSave.put(Analysis.PROP_NONFF, Boolean.toString(nonff != null));
if (_context.router().saveConfig(toSave, null))
addFormNotice(_t("Configuration saved successfully."));
else
@@ -273,7 +275,7 @@ public class NetDbHelper extends FormHandler {
} else if (_full == 3) {
if (_mode == 12 && !_postOK)
_mode = 0;
else if (_mode == 13 && !_postOK)
else if ((_mode == 13 || _mode == 16) && !_postOK)
_mode = 14;
(new SybilRenderer(_context)).getNetDbSummary(_out, _newNonce, _mode, _date);
} else if (_full == 4) {

View File

@@ -134,7 +134,7 @@ public class SybilRenderer {
Hash us = _context.routerHash();
Analysis analysis = Analysis.getInstance(_context);
List<RouterInfo> ris = null;
if (mode != 0 && mode != 12 && mode != 13 && mode != 14) {
if (mode != 0 && mode != 12 && mode != 13 && mode != 14 && mode != 16) {
ris = analysis.getFloodfills(us);
if (ris.isEmpty()) {
out.write("<h3 class=\"sybils\">No known floodfills</h3>");
@@ -208,10 +208,10 @@ public class SybilRenderer {
} else {
renderThreatsHTML(out, buf, date, points);
}
} else if (mode == 13) {
} else if (mode == 13 || mode == 16) {
// run analysis and store it
long now = _context.clock().now();
points = analysis.backgroundAnalysis();
points = analysis.backgroundAnalysis(mode == 16);
if (!points.isEmpty()) {
PersistSybil ps = analysis.getPersister();
try {
@@ -273,6 +273,14 @@ public class SybilRenderer {
"<input type=\"hidden\" name=\"m\" value=\"13\">\n" +
"<input type=\"hidden\" name=\"nonce\" value=\"").append(nonce).append("\" >\n" +
"<input type=\"submit\" name=\"action\" class=\"go\" value=\"Run new analysis\" />" +
"(floodfills only)" +
"</form><br>\n");
buf.append("<form action=\"netdb\" method=\"POST\">\n" +
"<input type=\"hidden\" name=\"f\" value=\"3\">\n" +
"<input type=\"hidden\" name=\"m\" value=\"16\">\n" +
"<input type=\"hidden\" name=\"nonce\" value=\"").append(nonce).append("\" >\n" +
"<input type=\"submit\" name=\"action\" class=\"go\" value=\"Run new analysis\" />" +
"(all routers)" +
"</form>\n");
writeBuf(out, buf);
}
@@ -302,12 +310,17 @@ public class SybilRenderer {
buf.append("</option>\n");
}
boolean auto = _context.getBooleanProperty(Analysis.PROP_BLOCK);
boolean nonff = _context.getBooleanProperty(Analysis.PROP_NONFF);
String thresh = _context.getProperty(Analysis.PROP_THRESHOLD, "50");
long days = _context.getProperty(Analysis.PROP_BLOCKTIME, 7*24*60*60*1000L) / (24*60*60*1000L);
buf.append("</select></td></tr>\n<tr><td>" +
"Auto-block routers?</td><td><input type=\"checkbox\" class=\"optbox\" value=\"1\" name=\"block\" ");
if (auto)
buf.append(HelperBase.CHECKED);
buf.append("></td></tr>\n<tr><td>" +
"Include non-floodfills?</td><td><input type=\"checkbox\" class=\"optbox\" value=\"1\" name=\"nonff\" ");
if (nonff)
buf.append(HelperBase.CHECKED);
buf.append("></td></tr>\n<tr><td>" +
"Minimum threat points to block:</td><td><input type=\"text\" name=\"threshold\" value=\"").append(thresh).append("\"></td></tr>\n<tr><td>" +
"Days to block:</td><td><input type=\"text\" name=\"days\" value=\"").append(days).append("\"></td></tr>\n<tr><td></td><td>" +