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

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

View File

@@ -359,11 +359,24 @@ class PacketHandler {
// For now, try SSU2 Session/Token Request processing here.
// After we've migrated the majority of the network over to SSU2,
// we can try SSU2 first.
if (_enableSSU2 && peerType == PeerType.NEW_PEER &&
packet.getPacket().getLength() >= SSU2Util.MIN_TOKEN_REQUEST_LEN) {
boolean handled = receiveSSU2Packet(remoteHost, packet, (InboundEstablishState2) null);
if (handled)
return;
if (_enableSSU2 && peerType == PeerType.NEW_PEER) {
int len = packet.getPacket().getLength();
if (len >= SSU2Util.MIN_TOKEN_REQUEST_LEN) {
boolean handled = receiveSSU2Packet(remoteHost, packet, (InboundEstablishState2) null);
if (handled)
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())
_log.debug("Continuing with SSU1 fallback processing, wasn't an SSU2 packet from " + remoteHost);
}
@@ -827,6 +840,14 @@ class PacketHandler {
ps2.receivePacket(from, packet);
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;
}

View File

@@ -57,6 +57,7 @@ import net.i2p.router.util.EventLog;
import net.i2p.router.util.RandomIterator;
import net.i2p.util.Addresses;
import net.i2p.util.ConcurrentHashSet;
import net.i2p.util.LHMCache;
import net.i2p.util.Log;
import net.i2p.util.OrderedProperties;
import net.i2p.util.SimpleTimer;
@@ -76,6 +77,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
/** RemoteHostId to PeerState */
private final Map<RemoteHostId, PeerState> _peersByRemoteHost;
private final Map<Long, PeerState2> _peersByConnID;
private final Map<Long, Object> _recentlyClosedConnIDs;
private PacketHandler _handler;
private EstablishmentManager _establisher;
private final MessageQueue _outboundMessages;
@@ -166,6 +168,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
private static final int DROPLIST_PERIOD = 10*60*1000;
public static final String STYLE = "SSU";
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
* @deprecated unused
@@ -338,6 +341,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_peersByIdent = new ConcurrentHashMap<Hash, PeerState>(128);
_peersByRemoteHost = new ConcurrentHashMap<RemoteHostId, PeerState>(128);
_peersByConnID = (xdh != null) ? new ConcurrentHashMap<Long, PeerState2>(32) : null;
_recentlyClosedConnIDs = (xdh != null) ? new LHMCache<Long, Object>(24) : null;
_dropList = new ConcurrentHashSet<RemoteHostId>(2);
_endpoints = new CopyOnWriteArrayList<UDPEndpoint>();
@@ -856,6 +860,11 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_peersByIdent.clear();
if (_peersByConnID != null)
_peersByConnID.clear();
if (_recentlyClosedConnIDs != null) {
synchronized(_addDropLock) {
_recentlyClosedConnIDs.clear();
}
}
_dropList.clear();
_introManager.reset();
UDPPacket.clearCache();
@@ -1651,6 +1660,17 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
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.
*
@@ -1824,7 +1844,9 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
}
if (oldPeer != peer && oldPeer.getVersion() == 2) {
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) {
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();