I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Unverified Commit 13ee324d authored by zzz's avatar zzz
Browse files

NTCP2: Clock skew handling improvements

as discussed in #ls2 meeting
- Bob replies with Session Created even if skewed,
  so that Alice finds out what the skew is
- Alice handles Session Created timestamp and drops if skewed,
  bans Bob, and updates clock if NTP failed
- If Alice does reply with SessionConfirmed, Bob will send a
  destroy with a skew error code
- Don't change skew error code if netdb store failed
- Fix skew adjustment for RTT by Bob
- Call setLastBadSkew() in the right places
- Fix ntcp.invalidInboundSkew and ntcp.invalidOutboundSkew stats
parent afa72780
No related branches found
No related tags found
No related merge requests found
...@@ -199,6 +199,10 @@ class InboundEstablishState extends EstablishBase implements NTCP2Payload.Payloa ...@@ -199,6 +199,10 @@ class InboundEstablishState extends EstablishBase implements NTCP2Payload.Payloa
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug(prefix() + "verification successful for " + _con); _log.debug(prefix() + "verification successful for " + _con);
// Adjust skew calculation now that we know RTT
// rtt from receiving #1 to receiving #3
long rtt = _context.clock().now() - _con.getCreated();
_peerSkew -= ((rtt / 2) + 500) / 1000;
long diff = 1000*Math.abs(_peerSkew); long diff = 1000*Math.abs(_peerSkew);
if (!_context.clock().getUpdatedSuccessfully()) { if (!_context.clock().getUpdatedSuccessfully()) {
// Adjust the clock one time in desperation // Adjust the clock one time in desperation
...@@ -209,16 +213,12 @@ class InboundEstablishState extends EstablishBase implements NTCP2Payload.Payloa ...@@ -209,16 +213,12 @@ class InboundEstablishState extends EstablishBase implements NTCP2Payload.Payloa
if (diff != 0) if (diff != 0)
_log.logAlways(Log.WARN, "NTP failure, NTCP adjusting clock by " + DataHelper.formatDuration(diff)); _log.logAlways(Log.WARN, "NTP failure, NTCP adjusting clock by " + DataHelper.formatDuration(diff));
} else if (diff >= Router.CLOCK_FUDGE_FACTOR) { } else if (diff >= Router.CLOCK_FUDGE_FACTOR) {
_context.statManager().addRateData("ntcp.invalidInboundSkew", diff);
_transport.markReachable(aliceHash, true);
// Only banlist if we know what time it is // Only banlist if we know what time it is
_context.banlist().banlistRouter(DataHelper.formatDuration(diff), _context.banlist().banlistRouter(DataHelper.formatDuration(diff),
aliceHash, aliceHash,
_x("Excessive clock skew: {0}")); _x("Excessive clock skew: {0}"));
_transport.setLastBadSkew(_peerSkew); _transport.setLastBadSkew(_peerSkew);
if (getVersion() < 2) if (_log.shouldWarn())
fail("Clocks too skewed (" + diff + " ms)", null, true);
else if (_log.shouldWarn())
_log.warn("Clocks too skewed (" + diff + " ms)"); _log.warn("Clocks too skewed (" + diff + " ms)");
_msg3p2FailReason = NTCPConnection.REASON_SKEW; _msg3p2FailReason = NTCPConnection.REASON_SKEW;
return false; return false;
...@@ -361,18 +361,21 @@ class InboundEstablishState extends EstablishBase implements NTCP2Payload.Payloa ...@@ -361,18 +361,21 @@ class InboundEstablishState extends EstablishBase implements NTCP2Payload.Payloa
_msg3p2len = (int) DataHelper.fromLong(options, 4, 2); _msg3p2len = (int) DataHelper.fromLong(options, 4, 2);
long tsA = DataHelper.fromLong(options, 8, 4); long tsA = DataHelper.fromLong(options, 8, 4);
long now = _context.clock().now(); long now = _context.clock().now();
// In NTCP1, timestamp comes in msg 3 so we know the RTT. // Will be adjusted for RTT in verifyInbound()
// In NTCP2, it comes in msg 1, so just guess. _peerSkew = (now - (tsA * 1000) + 500) / 1000;
// We could defer this to msg 3 to calculate the RTT? if (_peerSkew > MAX_SKEW || _peerSkew < 0 - MAX_SKEW) {
long rtt = 250; long diff = 1000*Math.abs(_peerSkew);
_peerSkew = (now - (tsA * 1000) - (rtt / 2) + 500) / 1000; _context.statManager().addRateData("ntcp.invalidInboundSkew", diff);
if ((_peerSkew > MAX_SKEW || _peerSkew < 0 - MAX_SKEW) && _transport.setLastBadSkew(_peerSkew);
!_context.clock().getUpdatedSuccessfully()) { if (_log.shouldWarn())
// If not updated successfully, allow it. _log.warn("Clock Skew: " + _peerSkew + " on " + this);
// This isn't very likely, outbound will do it first // Do them a favor, keep going with msg 2 so they get our timestamp.
// See verifyInbound() above. // They should disconnect after that.
fail("Clock Skew: " + _peerSkew, null, true); // If they do send a msg 3, verifyInbound() will catch it and
return; // will send a destroy with code 7 and
// ban the peer for a while.
//fail("Clock Skew: " + _peerSkew, null, true);
//return;
} }
if (_msg3p2len < MSG3P2_MIN || _msg3p2len > MSG3P2_MAX) { if (_msg3p2len < MSG3P2_MIN || _msg3p2len > MSG3P2_MAX) {
fail("bad msg3p2 len: " + _msg3p2len); fail("bad msg3p2 len: " + _msg3p2len);
...@@ -671,9 +674,10 @@ class InboundEstablishState extends EstablishBase implements NTCP2Payload.Payloa ...@@ -671,9 +674,10 @@ class InboundEstablishState extends EstablishBase implements NTCP2Payload.Payloa
ok = verifyInboundNetworkID(ri); ok = verifyInboundNetworkID(ri);
if (!ok) if (!ok)
throw new DataFormatException("NTCP2 network ID mismatch"); throw new DataFormatException("NTCP2 network ID mismatch");
// hash collision? // generally expired/future RI
// expired RI? // don't change reason if already set as clock skew
_msg3p2FailReason = NTCPConnection.REASON_MSG3; if (_msg3p2FailReason <= 0)
_msg3p2FailReason = NTCPConnection.REASON_MSG3;
throw new DataFormatException("RI store fail: " + ri, iae); throw new DataFormatException("RI store fail: " + ri, iae);
} }
_con.setRemotePeer(_aliceIdent); _con.setRemotePeer(_aliceIdent);
......
...@@ -300,8 +300,23 @@ class OutboundNTCP2State implements EstablishState { ...@@ -300,8 +300,23 @@ class OutboundNTCP2State implements EstablishState {
long rtt = now - _con.getCreated(); long rtt = now - _con.getCreated();
_peerSkew = (now - (tsB * 1000) - (rtt / 2) + 500) / 1000; _peerSkew = (now - (tsB * 1000) - (rtt / 2) + 500) / 1000;
if (_peerSkew > MAX_SKEW || _peerSkew < 0 - MAX_SKEW) { if (_peerSkew > MAX_SKEW || _peerSkew < 0 - MAX_SKEW) {
fail("Clock Skew: " + _peerSkew, null, true); long diff = 1000 * Math.abs(_peerSkew);
return; if (_context.clock().getUpdatedSuccessfully()) {
// usual case
_context.statManager().addRateData("ntcp.invalidOutboundSkew", diff);
fail("Clock Skew: " + _peerSkew, null, true);
// Only banlist if we know what time it is
_context.banlist().banlistRouter(DataHelper.formatDuration(diff),
_con.getRemotePeer().calculateHash(),
"Excessive clock skew: {0}"); // _x in IES
_transport.setLastBadSkew(_peerSkew);
return;
}
// Adjust the clock one time in desperation
// We are Alice, he is Bob, adjust to match Bob
_context.clock().setOffset(1000 * (0 - _peerSkew), true);
_peerSkew = 0;
_log.logAlways(Log.WARN, "NTP failure, NTCP adjusting clock by " + DataHelper.formatDuration(diff));
} }
changeState(State.OB_GOT_HXY); changeState(State.OB_GOT_HXY);
_received = 0; _received = 0;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment