SSU2: Track recently-closed sessions (gitlab #370)

and drop packets received on them, to prevent SSU1 fallback processing
This commit is contained in:
zzz
2022-10-10 11:33:05 -04:00
parent 64873218ba
commit 166d1ba86b
4 changed files with 58 additions and 8 deletions

View File

@@ -1,3 +1,6 @@
2022-10-10 zzz
* SSU2: Track recently-closed sessions (gitlab #370)
2022-09-28 zzz 2022-09-28 zzz
* Installer: Fix error on Windows when username contains a space (gitlab #367) * Installer: Fix error on Windows when username contains a space (gitlab #367)
* SSU2: Enable by default * SSU2: Enable by default

View File

@@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */ /** deprecated */
public final static String ID = "Git"; public final static String ID = "Git";
public final static String VERSION = CoreVersion.VERSION; public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 11; public final static long BUILD = 12;
/** for example "-test" */ /** for example "-test" */
public final static String EXTRA = ""; public final static String EXTRA = "";

View File

@@ -359,11 +359,24 @@ class PacketHandler {
// For now, try SSU2 Session/Token Request processing here. // For now, try SSU2 Session/Token Request processing here.
// After we've migrated the majority of the network over to SSU2, // After we've migrated the majority of the network over to SSU2,
// we can try SSU2 first. // we can try SSU2 first.
if (_enableSSU2 && peerType == PeerType.NEW_PEER && if (_enableSSU2 && peerType == PeerType.NEW_PEER) {
packet.getPacket().getLength() >= SSU2Util.MIN_TOKEN_REQUEST_LEN) { int len = packet.getPacket().getLength();
if (len >= SSU2Util.MIN_TOKEN_REQUEST_LEN) {
boolean handled = receiveSSU2Packet(remoteHost, packet, (InboundEstablishState2) null); boolean handled = receiveSSU2Packet(remoteHost, packet, (InboundEstablishState2) null);
if (handled) if (handled)
return; return;
} else if (len >= SSU2Util.MIN_DATA_LEN) {
byte[] k1 = _transport.getSSU2StaticIntroKey();
long id = SSU2Header.decryptDestConnID(packet.getPacket(), k1);
if (_transport.wasRecentlyClosed(id)) {
// Probably termination ack.
// Prevent attempted SSU1 fallback processing and adding to fail cache
if (_log.shouldDebug())
_log.debug("Dropping " + len + " byte packet from " + remoteHost +
" for recently closed ID " + id);
return;
}
}
if (_log.shouldDebug()) if (_log.shouldDebug())
_log.debug("Continuing with SSU1 fallback processing, wasn't an SSU2 packet from " + remoteHost); _log.debug("Continuing with SSU1 fallback processing, wasn't an SSU2 packet from " + remoteHost);
} }
@@ -827,6 +840,14 @@ class PacketHandler {
ps2.receivePacket(from, packet); ps2.receivePacket(from, packet);
return true; return true;
} }
if (_transport.wasRecentlyClosed(id)) {
// Probably termination ack.
// Prevent attempted SSU1 fallback processing and adding to fail cache
if (_log.shouldDebug())
_log.debug("Dropping " + packet.getPacket().getLength() + " byte packet from " + from +
" for recently closed ID " + id);
return true;
}
} }
return false; return false;
} }

View File

@@ -57,6 +57,7 @@ import net.i2p.router.util.EventLog;
import net.i2p.router.util.RandomIterator; import net.i2p.router.util.RandomIterator;
import net.i2p.util.Addresses; import net.i2p.util.Addresses;
import net.i2p.util.ConcurrentHashSet; import net.i2p.util.ConcurrentHashSet;
import net.i2p.util.LHMCache;
import net.i2p.util.Log; import net.i2p.util.Log;
import net.i2p.util.OrderedProperties; import net.i2p.util.OrderedProperties;
import net.i2p.util.SimpleTimer; import net.i2p.util.SimpleTimer;
@@ -76,6 +77,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
/** RemoteHostId to PeerState */ /** RemoteHostId to PeerState */
private final Map<RemoteHostId, PeerState> _peersByRemoteHost; private final Map<RemoteHostId, PeerState> _peersByRemoteHost;
private final Map<Long, PeerState2> _peersByConnID; private final Map<Long, PeerState2> _peersByConnID;
private final Map<Long, Object> _recentlyClosedConnIDs;
private PacketHandler _handler; private PacketHandler _handler;
private EstablishmentManager _establisher; private EstablishmentManager _establisher;
private final MessageQueue _outboundMessages; private final MessageQueue _outboundMessages;
@@ -166,6 +168,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
private static final int DROPLIST_PERIOD = 10*60*1000; private static final int DROPLIST_PERIOD = 10*60*1000;
public static final String STYLE = "SSU"; public static final String STYLE = "SSU";
public static final String PROP_INTERNAL_PORT = "i2np.udp.internalPort"; public static final String PROP_INTERNAL_PORT = "i2np.udp.internalPort";
private static final Object DUMMY = Integer.valueOf(0);
/** now unused, we pick a random port /** now unused, we pick a random port
* @deprecated unused * @deprecated unused
@@ -338,6 +341,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_peersByIdent = new ConcurrentHashMap<Hash, PeerState>(128); _peersByIdent = new ConcurrentHashMap<Hash, PeerState>(128);
_peersByRemoteHost = new ConcurrentHashMap<RemoteHostId, PeerState>(128); _peersByRemoteHost = new ConcurrentHashMap<RemoteHostId, PeerState>(128);
_peersByConnID = (xdh != null) ? new ConcurrentHashMap<Long, PeerState2>(32) : null; _peersByConnID = (xdh != null) ? new ConcurrentHashMap<Long, PeerState2>(32) : null;
_recentlyClosedConnIDs = (xdh != null) ? new LHMCache<Long, Object>(24) : null;
_dropList = new ConcurrentHashSet<RemoteHostId>(2); _dropList = new ConcurrentHashSet<RemoteHostId>(2);
_endpoints = new CopyOnWriteArrayList<UDPEndpoint>(); _endpoints = new CopyOnWriteArrayList<UDPEndpoint>();
@@ -856,6 +860,11 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_peersByIdent.clear(); _peersByIdent.clear();
if (_peersByConnID != null) if (_peersByConnID != null)
_peersByConnID.clear(); _peersByConnID.clear();
if (_recentlyClosedConnIDs != null) {
synchronized(_addDropLock) {
_recentlyClosedConnIDs.clear();
}
}
_dropList.clear(); _dropList.clear();
_introManager.reset(); _introManager.reset();
UDPPacket.clearCache(); UDPPacket.clearCache();
@@ -1651,6 +1660,17 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
return _peersByConnID.get(Long.valueOf(rcvConnID)); return _peersByConnID.get(Long.valueOf(rcvConnID));
} }
/**
* Was the state for this SSU2 receive connection ID recently closed?
* @since 0.9.56
*/
boolean wasRecentlyClosed(long rcvConnID) {
Long id = Long.valueOf(rcvConnID);
synchronized(_addDropLock) {
return _recentlyClosedConnIDs.get(id) != null;
}
}
/** /**
* For /peers UI only. Not a public API, not for external use. * For /peers UI only. Not a public API, not for external use.
* *
@@ -1824,7 +1844,9 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
} }
if (oldPeer != peer && oldPeer.getVersion() == 2) { if (oldPeer != peer && oldPeer.getVersion() == 2) {
PeerState2 state2 = (PeerState2) oldPeer; PeerState2 state2 = (PeerState2) oldPeer;
_peersByConnID.remove(Long.valueOf(state2.getRcvConnID())); Long id = Long.valueOf(state2.getRcvConnID());
_recentlyClosedConnIDs.put(id, DUMMY);
_peersByConnID.remove(id);
} }
} }
@@ -2028,7 +2050,11 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
if (peer.getVersion() == 2) { if (peer.getVersion() == 2) {
PeerState2 state2 = (PeerState2) peer; PeerState2 state2 = (PeerState2) peer;
_peersByConnID.remove(Long.valueOf(state2.getRcvConnID())); Long id = Long.valueOf(state2.getRcvConnID());
// for now, we don't save the PeerState2 for doing termination retransmissions,
// but we may in the future
_recentlyClosedConnIDs.put(id, DUMMY);
_peersByConnID.remove(id);
} }
RemoteHostId remoteId = peer.getRemoteHostId(); RemoteHostId remoteId = peer.getRemoteHostId();