SSU1: Symmetric NAT detection fixes

Never let SSU1 test result be symmetric NAT, it's probably charlie
Don't use SSU1 test if we think we are symmetric NAT
Cleanup two places to call new fail() method
This commit is contained in:
zzz
2022-12-26 14:13:43 -05:00
parent d655ad206c
commit 2b8d3477ce
2 changed files with 35 additions and 17 deletions

View File

@ -512,12 +512,7 @@ class PeerTestManager {
if (bobRI == null || VersionComparator.comp(bobRI.getVersion(), "0.9.52") >= 0) {
if (_log.shouldInfo())
_log.info("Bob replied to us (Alice) with intro key " + fromPeer);
// reset all state
// so testComplete() will return UNKNOWN
test.setAlicePortFromCharlie(0);
test.setReceiveCharlieTime(0);
test.setReceiveBobTime(0);
testComplete();
fail();
return;
}
}
@ -535,12 +530,7 @@ class PeerTestManager {
// check every time.
if (_log.shouldLog(Log.WARN))
_log.warn("Bad IP length " + ipSize + " from bob's reply: " + from);
// reset all state
// so testComplete() will return UNKNOWN
test.setAlicePortFromCharlie(0);
test.setReceiveCharlieTime(0);
test.setReceiveBobTime(0);
testComplete();
fail();
return;
}
byte ip[] = new byte[ipSize];
@ -588,8 +578,8 @@ class PeerTestManager {
// this is our second charlie, yay!
try {
int testPort = testInfo.readPort();
if (testPort == 0)
throw new UnknownHostException("port 0");
if (testPort < 1024)
throw new UnknownHostException("port " + testPort);
test.setAlicePortFromCharlie(testPort);
byte ip[] = new byte[testInfo.readIPSize()];
int ipSize = ip.length;
@ -599,9 +589,32 @@ class PeerTestManager {
throw new UnknownHostException("bad sz - expect v6? " + expectV6 + " act sz: " + ipSize);
testInfo.readIP(ip, 0);
InetAddress addr = InetAddress.getByAddress(ip);
test.setAliceIPFromCharlie(addr);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Receive test reply from Charlie: " + test);
boolean portok = testPort == test.getAlicePort();
boolean IPok = DataHelper.eq(ip, test.getAliceIP().getAddress());
if (!portok || !IPok) {
if (_log.shouldWarn())
_log.warn("Charlie said we had a different IP/port: " +
Addresses.toString(ip, testPort) + " on " + test);
// Since we did get msg 5, it's almost impossible for us to be symmetric natted.
// It's much more likely that Charlie is symmetric natted.
// However, our IP could have changed.
// Force result to OK
// testComplete() will deal with it
if (!portok) {
// Port different. Charlie probably symmetric natted.
// Reset port so testComplete() will return success.
test.setAlicePortFromCharlie(test.getAlicePort());
}
if (!IPok) {
// Our IP changed?
// Reset IP so testComplete() will return success.
addr = test.getAliceIP();
}
}
test.setAliceIPFromCharlie(addr);
if (test.getReceiveBobTime() > 0)
testComplete();
} catch (UnknownHostException uhe) {

View File

@ -4131,13 +4131,18 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
PeerState pickTestPeer(PeerTestState.Role peerRole, int version, boolean isIPv6, RemoteHostId dontInclude) {
if (peerRole == ALICE)
throw new IllegalArgumentException();
// if we are or may be symmetric natted, require SSU2 so we don't let an SSU1 test change the state
boolean requireV2 = peerRole == BOB && !isIPv6 && _enableSSU2 &&
(isSymNatted() || STATUS_IPV4_SYMNAT.contains(_reachabilityStatusPending));
List<PeerState> peers = new ArrayList<PeerState>(_peersByIdent.values());
for (Iterator<PeerState> iter = new RandomIterator<PeerState>(peers); iter.hasNext(); ) {
PeerState peer = iter.next();
if (peerRole == BOB) {
// Skip SSU2 until we have support for peer test
version = peer.getVersion();
if (version != 1) {
if (version == 1) {
if (requireV2)
continue;
} else {
// we must know our IP/port
PeerState2 bob = (PeerState2) peer;
if (bob.getOurIP() == null || bob.getOurPort() <= 0)