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
pull/1/head
orbiter 14 years ago
parent 8879cc1db2
commit 2700a58e5a

@ -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, "<unknown>"); // 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);

@ -1,4 +1,5 @@
version=#[version]#
uptime=#[uptime]#
response=#[response]#
mytime=#[mytime]#
mytime=#[mytime]#
magic=#[magic]#

@ -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;

@ -139,6 +139,7 @@ public final class yacyClient {
// generate request
final Map<String,ContentBody> 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<String, String> 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};
}
}

@ -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<String, yacyAccessible> amIAccessibleDB = new ConcurrentHashMap<String, yacyAccessible>(); // 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;
}

Loading…
Cancel
Save