From 2700a58e5a76ecb77368b0dca90178c1baca7939 Mon Sep 17 00:00:00 2001 From: orbiter Date: Fri, 29 Apr 2011 01:52:20 +0000 Subject: [PATCH] added a magic to the peer ping that will be used in case that the contacting peer requests that it's reported IP shall be used for a back-ping. The back-ping now also returns the same magic which will make it possible that the requested peer can verify that the back-pinged peer is actually the same peer. This is also a protection against the foced-fake of a external IP: if such an IP was faked, then the next ping from the affected peer to another peer looks like a staticIP report. Such a bad staticIP-by-faked-response can now be discovered and fixed by the peer that gets the second ping after the first ping contained a faked response. git-svn-id: https://svn.berlios.de/svnroot/repos/yacy/trunk@7683 6c8d7289-2bf4-0310-a012-ef5d649a1542 --- htroot/yacy/hello.java | 20 ++++++++++++-------- htroot/yacy/query.html | 3 ++- htroot/yacy/query.java | 4 ++++ source/de/anomic/yacy/yacyClient.java | 23 ++++++++++++++--------- source/de/anomic/yacy/yacyCore.java | 6 +++--- 5 files changed, 35 insertions(+), 21 deletions(-) diff --git a/htroot/yacy/hello.java b/htroot/yacy/hello.java index a16a604ec..2a8df04e5 100644 --- a/htroot/yacy/hello.java +++ b/htroot/yacy/hello.java @@ -73,6 +73,7 @@ public final class hello { final String key = post.get("key", ""); // transmission key for response final String seed = post.get("seed", ""); int count = post.getInt("count", 0); + long magic = post.getLong("magic", 0); // final Date remoteTime = yacyCore.parseUniversalDate(post.get(MYTIME)); // read remote time final String clientip = header.get(HeaderFramework.CONNECTION_PROP_CLIENTIP, ""); // read an artificial header addendum long time = System.currentTimeMillis(); @@ -119,7 +120,7 @@ public final class hello { return prop; } - int urls = -1; + long[] callback = new long[]{-1, -1}; if (sb.clusterhashes != null) remoteSeed.setAlternativeAddress(sb.clusterhashes.get(remoteSeed.hash.getBytes())); // if the remote client has reported its own IP address and the client supports @@ -128,13 +129,16 @@ public final class hello { time = System.currentTimeMillis(); long time_backping = 0; String backping_method = "none"; - if (reportedip.length() > 0 && !clientip.equals(reportedip) && clientversion >= yacyVersion.YACY_SUPPORTS_PORT_FORWARDING) { + if (reportedip.length() > 0 && + !clientip.equals(reportedip) && + clientversion >= yacyVersion.YACY_SUPPORTS_PORT_FORWARDING && + magic != 0) { serverCore.checkInterruption(); // try first the reportedip, since this may be a connect from a port-forwarding host prop.put("yourip", reportedip); remoteSeed.setIP(reportedip); - urls = yacyClient.queryUrlCount(remoteSeed); + callback = yacyClient.queryUrlCount(remoteSeed); time_backping = System.currentTimeMillis() - time; backping_method = "reportedip=" + reportedip; } else { @@ -144,7 +148,7 @@ public final class hello { // if the previous attempt (using the reported ip address) was not successful, // then try the ip where the request came from - if (urls < 0) { + if (callback[0] < 0 || (magic != 0 && magic != callback[1])) { boolean isNotLocal = true; // we are only allowed to connect to the client IP address if it's not our own address @@ -157,7 +161,7 @@ public final class hello { prop.put("yourip", clientip); remoteSeed.setIP(clientip); - urls = yacyClient.queryUrlCount(remoteSeed); + callback = yacyClient.queryUrlCount(remoteSeed); time_backping = System.currentTimeMillis() - time; backping_method = "clientip=" + clientip; } @@ -168,7 +172,7 @@ public final class hello { remoteSeed.setLastSeenUTC(); // assign status - if (urls >= 0) { + if (callback[0] >= 0) { if (remoteSeed.get(yacySeed.PEERTYPE, yacySeed.PEERTYPE_SENIOR) == null) { prop.put(yacySeed.YOURTYPE, yacySeed.PEERTYPE_SENIOR); remoteSeed.put(yacySeed.PEERTYPE, yacySeed.PEERTYPE_SENIOR); @@ -179,12 +183,12 @@ public final class hello { remoteSeed.put(yacySeed.PEERTYPE, yacySeed.PEERTYPE_SENIOR); } // connect the seed - yacyCore.log.logInfo("hello/server: responded remote senior peer '" + remoteSeed.getName() + "' from " + reportedip + ", time_dnsResolve=" + time_dnsResolve + ", time_backping=" + time_backping + ", method=" + backping_method + ", urls=" + urls); + yacyCore.log.logInfo("hello/server: responded remote senior peer '" + remoteSeed.getName() + "' from " + reportedip + ", time_dnsResolve=" + time_dnsResolve + ", time_backping=" + time_backping + ", method=" + backping_method + ", urls=" + callback[0]); sb.peers.peerActions.peerArrival(remoteSeed, true); } else { prop.put(yacySeed.YOURTYPE, yacySeed.PEERTYPE_JUNIOR); remoteSeed.put(yacySeed.PEERTYPE, yacySeed.PEERTYPE_JUNIOR); - yacyCore.log.logInfo("hello/server: responded remote junior peer '" + remoteSeed.getName() + "' from " + reportedip + ", time_dnsResolve=" + time_dnsResolve + ", time_backping=" + time_backping + ", method=" + backping_method + ", urls=" + urls); + yacyCore.log.logInfo("hello/server: responded remote junior peer '" + remoteSeed.getName() + "' from " + reportedip + ", time_dnsResolve=" + time_dnsResolve + ", time_backping=" + time_backping + ", method=" + backping_method + ", urls=" + callback[0]); // no connection here, instead store junior in connection cache if ((remoteSeed.hash != null) && (remoteSeed.isProper(false) == null)) { sb.peers.peerActions.peerPing(remoteSeed); diff --git a/htroot/yacy/query.html b/htroot/yacy/query.html index 462743956..9a66a63cb 100644 --- a/htroot/yacy/query.html +++ b/htroot/yacy/query.html @@ -1,4 +1,5 @@ version=#[version]# uptime=#[uptime]# response=#[response]# -mytime=#[mytime]# \ No newline at end of file +mytime=#[mytime]# +magic=#[magic]# \ No newline at end of file diff --git a/htroot/yacy/query.java b/htroot/yacy/query.java index de0721d02..2e0b091a8 100644 --- a/htroot/yacy/query.java +++ b/htroot/yacy/query.java @@ -36,6 +36,7 @@ import de.anomic.search.Segments; import de.anomic.search.Switchboard; import de.anomic.server.serverObjects; import de.anomic.server.serverSwitch; +import de.anomic.yacy.yacyCore; import de.anomic.yacy.yacyNetwork; public final class query { @@ -49,6 +50,9 @@ public final class query { // return variable that accumulates replacements final Switchboard sb = (Switchboard) ss; final serverObjects prop = new serverObjects(); + + prop.put("magic", yacyCore.speedKey); + if ((post == null) || (ss == null) || !yacyNetwork.authentifyRequest(post, ss)) { prop.put("response", "-1"); // request rejected return prop; diff --git a/source/de/anomic/yacy/yacyClient.java b/source/de/anomic/yacy/yacyClient.java index 1937e9963..03a57c20f 100644 --- a/source/de/anomic/yacy/yacyClient.java +++ b/source/de/anomic/yacy/yacyClient.java @@ -139,6 +139,7 @@ public final class yacyClient { // generate request final Map parts = yacyNetwork.basicRequestParts(Switchboard.getSwitchboard(), null, salt); parts.put("count", UTF8.StringBody("20")); + parts.put("magic", UTF8.StringBody(Long.toString(yacyCore.speedKey))); parts.put("seed", UTF8.StringBody(mySeed.genSeedStr(salt))); // send request final long start = System.currentTimeMillis(); @@ -299,8 +300,13 @@ public final class yacyClient { } } - public static int queryUrlCount(final yacySeed target) { - if (target == null) { return -1; } + /** + * check the status of a remote peer + * @param target + * @return an array of two long: [0] is the count of urls, [1] is a magic + */ + public static long[] queryUrlCount(final yacySeed target) { + if (target == null) return new long[]{-1, -1}; // prepare request final String salt = crypt.randomSalt(); @@ -314,19 +320,18 @@ public final class yacyClient { final byte[] content = postToFile(target, "query.html", parts, 5000); final Map result = FileUtils.table(content); - if (result == null || result.isEmpty()) return -1; + if (result == null || result.isEmpty()) return new long[]{-1, -1}; final String resp = result.get("response"); - if (resp == null) { - return -1; - } + if (resp == null) return new long[]{-1, -1}; + String magic = result.get("magic"); if (magic == null) magic = "0"; try { - return Integer.parseInt(resp); + return new long[]{Long.parseLong(resp), Long.parseLong(magic)}; } catch (final NumberFormatException e) { - return -1; + return new long[]{-1, -1}; } } catch (final IOException e) { if (yacyCore.log.isFine()) yacyCore.log.logFine("yacyClient.queryUrlCount error asking peer '" + target.getName() + "':" + e.toString()); - return -1; + return new long[]{-1, -1}; } } diff --git a/source/de/anomic/yacy/yacyCore.java b/source/de/anomic/yacy/yacyCore.java index 100a21311..dc0b7b067 100644 --- a/source/de/anomic/yacy/yacyCore.java +++ b/source/de/anomic/yacy/yacyCore.java @@ -70,7 +70,7 @@ public class yacyCore { public static final Log log = new Log("YACY"); public static long lastOnlineTime = 0; /** pseudo-random key derived from a time-interval while YaCy startup*/ - public static long speedKey = 0; + public static long speedKey = System.currentTimeMillis(); public static final Map amIAccessibleDB = new ConcurrentHashMap(); // Holds PeerHash / yacyAccessible Relations // constants for PeerPing behavior private static final int PING_INITIAL = 10; @@ -201,8 +201,8 @@ public class yacyCore { private boolean canReachMyself() { // TODO: check if this method is necessary - depending on the used router it will not work // returns true if we can reach ourself under our known peer address // if we cannot reach ourself, we call a forced publishMySeed and return false - final int urlc = yacyClient.queryUrlCount(sb.peers.mySeed()); - if (urlc >= 0) { + final long[] callback = yacyClient.queryUrlCount(sb.peers.mySeed()); + if (callback[0] >= 0 && callback[1] == speedKey) { sb.peers.mySeed().setLastSeenUTC(); return true; }