forked from I2P_Developers/i2p.i2p
SSU: SessionRequest replay prevention (ticket #1212)
NTCP: Just use first 8 bytes of Hx^Hi for replay check
This commit is contained in:
@ -178,7 +178,7 @@ public class NTCPTransport extends TransportImpl {
|
|||||||
_establishing = new ConcurrentHashSet<NTCPConnection>(16);
|
_establishing = new ConcurrentHashSet<NTCPConnection>(16);
|
||||||
_conLock = new Object();
|
_conLock = new Object();
|
||||||
_conByIdent = new ConcurrentHashMap<Hash, NTCPConnection>(64);
|
_conByIdent = new ConcurrentHashMap<Hash, NTCPConnection>(64);
|
||||||
_replayFilter = new DecayingHashSet(ctx, 10*60*1000, 32, "NTCP-Hx^HI");
|
_replayFilter = new DecayingHashSet(ctx, 10*60*1000, 8, "NTCP-Hx^HI");
|
||||||
|
|
||||||
_finisher = new NTCPSendFinisher(ctx, this);
|
_finisher = new NTCPSendFinisher(ctx, this);
|
||||||
|
|
||||||
@ -522,7 +522,7 @@ public class NTCPTransport extends TransportImpl {
|
|||||||
* @since 0.9.12
|
* @since 0.9.12
|
||||||
*/
|
*/
|
||||||
boolean isHXHIValid(byte[] hxhi) {
|
boolean isHXHIValid(byte[] hxhi) {
|
||||||
return !_replayFilter.add(hxhi);
|
return !_replayFilter.add(hxhi, 0, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int MIN_CONCURRENT_READERS = 2; // unless < 32MB
|
private static final int MIN_CONCURRENT_READERS = 2; // unless < 32MB
|
||||||
|
@ -23,6 +23,8 @@ import net.i2p.router.RouterContext;
|
|||||||
import net.i2p.router.transport.crypto.DHSessionKeyBuilder;
|
import net.i2p.router.transport.crypto.DHSessionKeyBuilder;
|
||||||
import static net.i2p.router.transport.udp.InboundEstablishState.InboundState.*;
|
import static net.i2p.router.transport.udp.InboundEstablishState.InboundState.*;
|
||||||
import static net.i2p.router.transport.udp.OutboundEstablishState.OutboundState.*;
|
import static net.i2p.router.transport.udp.OutboundEstablishState.OutboundState.*;
|
||||||
|
import net.i2p.router.util.DecayingHashSet;
|
||||||
|
import net.i2p.router.util.DecayingBloomFilter;
|
||||||
import net.i2p.util.Addresses;
|
import net.i2p.util.Addresses;
|
||||||
import net.i2p.util.I2PThread;
|
import net.i2p.util.I2PThread;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
@ -82,6 +84,9 @@ class EstablishmentManager {
|
|||||||
private volatile boolean _alive;
|
private volatile boolean _alive;
|
||||||
private final Object _activityLock;
|
private final Object _activityLock;
|
||||||
private int _activity;
|
private int _activity;
|
||||||
|
|
||||||
|
/** "bloom filter" */
|
||||||
|
private final DecayingBloomFilter _replayFilter;
|
||||||
|
|
||||||
/** max outbound in progress - max inbound is half of this */
|
/** max outbound in progress - max inbound is half of this */
|
||||||
private final int DEFAULT_MAX_CONCURRENT_ESTABLISH;
|
private final int DEFAULT_MAX_CONCURRENT_ESTABLISH;
|
||||||
@ -132,6 +137,7 @@ class EstablishmentManager {
|
|||||||
_outboundByClaimedAddress = new ConcurrentHashMap<RemoteHostId, OutboundEstablishState>();
|
_outboundByClaimedAddress = new ConcurrentHashMap<RemoteHostId, OutboundEstablishState>();
|
||||||
_outboundByHash = new ConcurrentHashMap<Hash, OutboundEstablishState>();
|
_outboundByHash = new ConcurrentHashMap<Hash, OutboundEstablishState>();
|
||||||
_activityLock = new Object();
|
_activityLock = new Object();
|
||||||
|
_replayFilter = new DecayingHashSet(ctx, 10*60*1000, 8, "SSU-DH-X");
|
||||||
DEFAULT_MAX_CONCURRENT_ESTABLISH = Math.max(DEFAULT_LOW_MAX_CONCURRENT_ESTABLISH,
|
DEFAULT_MAX_CONCURRENT_ESTABLISH = Math.max(DEFAULT_LOW_MAX_CONCURRENT_ESTABLISH,
|
||||||
Math.min(DEFAULT_HIGH_MAX_CONCURRENT_ESTABLISH,
|
Math.min(DEFAULT_HIGH_MAX_CONCURRENT_ESTABLISH,
|
||||||
ctx.bandwidthLimiter().getOutboundKBytesPerSecond() / 2));
|
ctx.bandwidthLimiter().getOutboundKBytesPerSecond() / 2));
|
||||||
@ -159,6 +165,7 @@ class EstablishmentManager {
|
|||||||
_context.statManager().createRateStat("udp.rejectConcurrentSequence", "How many consecutive concurrency rejections have we had when we stop rejecting (period is how many concurrent packets we are on)", "udp", UDPTransport.RATES);
|
_context.statManager().createRateStat("udp.rejectConcurrentSequence", "How many consecutive concurrency rejections have we had when we stop rejecting (period is how many concurrent packets we are on)", "udp", UDPTransport.RATES);
|
||||||
//_context.statManager().createRateStat("udp.queueDropSize", "How many messages were queued up when it was considered full, causing a tail drop?", "udp", UDPTransport.RATES);
|
//_context.statManager().createRateStat("udp.queueDropSize", "How many messages were queued up when it was considered full, causing a tail drop?", "udp", UDPTransport.RATES);
|
||||||
//_context.statManager().createRateStat("udp.queueAllowTotalLifetime", "When a peer is retransmitting and we probabalistically allow a new message, what is the sum of the pending message lifetimes? (period is the new message's lifetime)?", "udp", UDPTransport.RATES);
|
//_context.statManager().createRateStat("udp.queueAllowTotalLifetime", "When a peer is retransmitting and we probabalistically allow a new message, what is the sum of the pending message lifetimes? (period is the new message's lifetime)?", "udp", UDPTransport.RATES);
|
||||||
|
_context.statManager().createRateStat("udp.dupDHX", "Session request replay", "udp", new long[] { 24*60*60*1000L } );
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void startup() {
|
public synchronized void startup() {
|
||||||
@ -450,6 +457,14 @@ class EstablishmentManager {
|
|||||||
_transport.getExternalPort(fromIP.length == 16),
|
_transport.getExternalPort(fromIP.length == 16),
|
||||||
_transport.getDHBuilder());
|
_transport.getDHBuilder());
|
||||||
state.receiveSessionRequest(reader.getSessionRequestReader());
|
state.receiveSessionRequest(reader.getSessionRequestReader());
|
||||||
|
|
||||||
|
if (_replayFilter.add(state.getReceivedX(), 0, 8)) {
|
||||||
|
if (_log.shouldLog(Log.WARN))
|
||||||
|
_log.warn("Duplicate X in session request from: " + from);
|
||||||
|
_context.statManager().addRateData("udp.dupDHX", 1);
|
||||||
|
return; // drop the packet
|
||||||
|
}
|
||||||
|
|
||||||
InboundEstablishState oldState = _inboundStates.putIfAbsent(from, state);
|
InboundEstablishState oldState = _inboundStates.putIfAbsent(from, state);
|
||||||
isNew = oldState == null;
|
isNew = oldState == null;
|
||||||
if (!isNew)
|
if (!isNew)
|
||||||
|
Reference in New Issue
Block a user