SSU2: More MTU checks

Add code for bob rejecting alice peer test address
Don't allow MTU to exceed his MTU
Don't use a token about to expire
Send token with termination message
Add internal type to termination message
log tweaks
This commit is contained in:
zzz
2022-06-22 11:00:56 -04:00
parent 5d27ce3f8d
commit 08e95655c1
8 changed files with 56 additions and 15 deletions

View File

@@ -415,6 +415,17 @@ class EstablishmentManager {
version = 1;
}
}
if (version == 2) {
int mtu = addr.getMTU();
if (mtu > 0 && mtu < PeerState2.MIN_MTU) {
if (ra.getTransportStyle().equals("SSU2")) {
_transport.markUnreachable(toHash);
_transport.failed(msg, "MTU too small");
return;
}
version = 1;
}
}
if (version == 1) {
keyBytes = addr.getIntroKey();
} else {
@@ -2435,6 +2446,8 @@ class EstablishmentManager {
* @since 0.9.54
*/
public void addOutboundToken(RemoteHostId peer, long token, long expires) {
// so we don't use a token about to expire
expires -= 2*60*1000;
if (expires < _context.clock().now())
return;
Token tok = new Token(token, expires);

View File

@@ -202,8 +202,8 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa
}
public void gotRI(RouterInfo ri, boolean isHandshake, boolean flood) throws DataFormatException {
if (_log.shouldDebug())
_log.debug("Got RI block: " + ri);
//if (_log.shouldDebug())
// _log.debug("Got RI block: " + ri);
if (isHandshake)
throw new DataFormatException("RI in Sess Req");
if (_receivedUnconfirmedIdentity != null)
@@ -275,7 +275,9 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa
mtu = PeerState2.DEFAULT_SSU_IPV4_MTU;
}
} else {
// TODO if too small, give up now
// if too small, give up now
if (mtu < PeerState2.MIN_MTU)
throw new DataFormatException("MTU too small " + mtu);
if (ra.getTransportStyle().equals(UDPTransport.STYLE2)) {
mtu = Math.min(Math.max(mtu, PeerState2.MIN_MTU), PeerState2.MAX_MTU);
} else {
@@ -369,6 +371,8 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa
}
public void gotToken(long token, long expires) {
if (_log.shouldDebug())
_log.debug("Got token: " + token + " expires " + DataHelper.formatTime(expires) + " on " + this);
if (_receivedConfirmedIdentity == null)
throw new IllegalStateException("RI must be first");
_transport.getEstablisher().addOutboundToken(_remoteHostId, token, expires);

View File

@@ -1059,7 +1059,8 @@ class IntroductionManager {
}
UDPPacket packet = _builder2.buildRelayResponse(data, bob);
if (_log.shouldInfo())
_log.info("Send relay response " + rcode + " as charlie " + " nonce " + nonce + " to bob " + bob);
_log.info("Send relay response " + rcode + " as charlie " + " nonce " + nonce + " to bob " + bob +
" for alice " + Addresses.toString(testIP, testPort) + ' ' + aliceRI);
_transport.send(packet);
if (rcode == SSU2Util.RELAY_ACCEPT) {
// send hole punch with the same data we sent to Bob

View File

@@ -155,9 +155,11 @@ class OutboundEstablishState2 extends OutboundEstablishState implements SSU2Payl
mtu = PeerState2.DEFAULT_SSU_IPV4_MTU;
}
} else {
// TODO if too small, give up now
// If too small, give up now
if (mtu < PeerState2.MIN_MTU)
throw new IllegalArgumentException("MTU " + mtu + " too small for " + remotePeer.getHash());
if (ra.getTransportStyle().equals(UDPTransport.STYLE2)) {
mtu = Math.min(Math.max(mtu, PeerState2.MIN_MTU), PeerState2.MAX_MTU);
mtu = Math.min(mtu, PeerState2.MAX_MTU);
} else {
if (_bobIP != null && _bobIP.length == 16)
mtu = Math.min(Math.max(mtu, PeerState2.MIN_SSU_IPV6_MTU), PeerState2.MAX_SSU_IPV6_MTU);
@@ -321,6 +323,8 @@ class OutboundEstablishState2 extends OutboundEstablishState implements SSU2Payl
}
public void gotToken(long token, long expires) {
if (_log.shouldDebug())
_log.debug("Got token: " + token + " expires " + DataHelper.formatTime(expires) + " on " + this);
_transport.getEstablisher().addOutboundToken(_remoteHostId, token, expires);
}

View File

@@ -60,6 +60,7 @@ class PacketBuilder2 {
static final int TYPE_CONF = 71;
static final int TYPE_SREQ = 72;
static final int TYPE_CREAT = 73;
static final int TYPE_DESTROY = 74;
/** IPv4 only */
public static final int IP_HEADER_SIZE = PacketBuilder.IP_HEADER_SIZE;
@@ -100,6 +101,7 @@ class PacketBuilder2 {
/**
* Will a packet to 'peer' that already has 'numFragments' fragments
* totalling 'curDataSize' bytes fit another fragment?
* This includes the 3 byte block overhead, but NOT the 5 byte followon fragment overhead.
*
* This doesn't leave anything for acks or anything else.
*
@@ -279,7 +281,7 @@ class PacketBuilder2 {
if (_log.shouldWarn()) {
int maxMTU = PeerState2.MAX_MTU;
off += MAC_LEN;
if (off + ipHeaderSize > maxMTU) {
if (off + ipHeaderSize > currentMTU) {
_log.warn("Size is " + off + " for " + packet +
" data size " + dataSize +
" pkt size " + (off + ipHeaderSize) +
@@ -340,11 +342,24 @@ class PacketBuilder2 {
/**
* Build a data packet with a termination block.
* This will also include acks and padding.
* This will also include acks, a new token block, and padding.
*/
public UDPPacket buildSessionDestroyPacket(int reason, PeerState2 peer) {
if (_log.shouldWarn())
_log.warn("Sending termination " + reason + " to : " + peer);
List<Block> blocks = new ArrayList<Block>(2);
if (peer.getKeyEstablishedTime() - _context.clock().now() > EstablishmentManager.IB_TOKEN_EXPIRATION / 2 &&
!_context.router().gracefulShutdownInProgress()) {
// update token
EstablishmentManager.Token token = _transport.getEstablisher().getInboundToken(peer.getRemoteHostId());
Block block = new SSU2Payload.NewTokenBlock(token.token, token.expires);
blocks.add(block);
}
Block block = new SSU2Payload.TerminationBlock(reason, peer.getReceivedMessages().getHighestSet());
return buildPacket(Collections.emptyList(), Collections.singletonList(block), peer);
blocks.add(block);
UDPPacket packet = buildPacket(Collections.emptyList(), blocks, peer);
packet.setMessageType(TYPE_DESTROY);
return packet;
}
/**

View File

@@ -1267,7 +1267,8 @@ public class PeerState {
synchronized void setHisMTU(int mtu) {
if (mtu <= _minMTU || mtu >= _largeMTU)
return;
_largeMTU = mtu;
if (mtu < _largeMTU)
_largeMTU = mtu;
if (mtu < _mtu)
_mtu = mtu;
}

View File

@@ -563,14 +563,16 @@ public class PeerState2 extends PeerState implements SSU2Payload.PayloadCallback
public void gotACK(long ackThru, int acks, byte[] ranges) {
int hc = (((int) ackThru) << 8) ^ (acks << 24) ^ DataHelper.hashCode(ranges);
if (_lastAckHashCode.getAndSet(hc) == hc) {
if (_log.shouldDebug())
_log.debug("Got dup ACK block: " + SSU2Bitfield.toString(ackThru, acks, ranges, (ranges != null ? ranges.length / 2 : 0)));
//if (_log.shouldDebug())
// _log.debug("Got dup ACK block: " + SSU2Bitfield.toString(ackThru, acks, ranges, (ranges != null ? ranges.length / 2 : 0)));
return;
}
try {
SSU2Bitfield ackbf = SSU2Bitfield.fromACKBlock(ackThru, acks, ranges, (ranges != null ? ranges.length / 2 : 0));
if (_log.shouldDebug())
_log.debug("Got new ACK block: " + SSU2Bitfield.toString(ackThru, acks, ranges, (ranges != null ? ranges.length / 2 : 0)));
_log.debug("Got new ACK block from " +
_remotePeer.toBase64().substring(0,6) + ' ' +
SSU2Bitfield.toString(ackThru, acks, ranges, (ranges != null ? ranges.length / 2 : 0)));
// calls bitSet() below
ackbf.forEachAndNot(_ackedMessages, this);
} catch (Exception e) {
@@ -583,8 +585,8 @@ public class PeerState2 extends PeerState implements SSU2Payload.PayloadCallback
}
public void gotTermination(int reason, long count) {
if (_log.shouldDebug())
_log.debug("Got TERMINATION block, reason: " + reason + " count: " + count + " on " + this);
if (_log.shouldInfo())
_log.info("Got TERMINATION block, reason: " + reason + " count: " + count + " on " + this);
_transport.getEstablisher().receiveSessionDestroy(_remoteHostId, this);
}

View File

@@ -125,6 +125,7 @@ final class SSU2Util {
public static final int TEST_REJECT_BOB_NO_CHARLIE = 2;
public static final int TEST_REJECT_BOB_LIMIT = 3;
public static final int TEST_REJECT_BOB_SIGFAIL = 4;
public static final int TEST_REJECT_BOB_ADDRESS = 5;
public static final int TEST_REJECT_CHARLIE_UNSPEC = 64;
public static final int TEST_REJECT_CHARLIE_ADDRESS = 65;
public static final int TEST_REJECT_CHARLIE_LIMIT = 66;