Implement detection of local IPv6 addresses

This commit is contained in:
Cameron Gutman 2022-11-02 20:35:41 -05:00
parent 371906445e
commit 411998d4e3
4 changed files with 47 additions and 23 deletions

View File

@ -878,7 +878,7 @@ private:
// If this wasn't added via mDNS but it is a RFC 1918 IPv4 address and not a VPN,
// go ahead and do the STUN request now to populate an external address.
if (!m_Mdns && addressIsSiteLocalV4 && !newComputer->isReachableOverVpn()) {
if (!m_Mdns && addressIsSiteLocalV4 && newComputer->getActiveAddressReachability() != NvComputer::RI_VPN) {
quint32 addr;
int err = LiFindExternalAddressIP4("stun.moonlight-stream.org", 3478, &addr);
if (err == 0) {

View File

@ -293,7 +293,7 @@ bool NvComputer::wake() const
return success;
}
bool NvComputer::isReachableOverVpn() const
NvComputer::ReachabilityType NvComputer::getActiveAddressReachability() const
{
NvAddress copyOfActiveAddress;
@ -301,7 +301,7 @@ bool NvComputer::isReachableOverVpn() const
QReadLocker readLocker(&lock);
if (activeAddress.isNull()) {
return false;
return ReachabilityType::RI_UNKNOWN;
}
// Grab a copy of the active address to avoid having to hold
@ -332,48 +332,55 @@ bool NvComputer::isReachableOverVpn() const
if (nic.type() == QNetworkInterface::Virtual ||
nic.type() == QNetworkInterface::Ppp) {
// Treat PPP and virtual interfaces as likely VPNs
return true;
return ReachabilityType::RI_VPN;
}
if (nic.maximumTransmissionUnit() != 0 && nic.maximumTransmissionUnit() < 1500) {
// Treat MTUs under 1500 as likely VPNs
return true;
return ReachabilityType::RI_VPN;
}
#endif
if (nic.flags() & QNetworkInterface::IsPointToPoint) {
// Treat point-to-point links as likely VPNs.
// This check detects OpenVPN on Unix-like OSes.
return true;
return ReachabilityType::RI_VPN;
}
if (nic.hardwareAddress().startsWith("00:FF", Qt::CaseInsensitive)) {
// OpenVPN TAP interfaces have a MAC address starting with 00:FF on Windows
return true;
return ReachabilityType::RI_VPN;
}
if (nic.humanReadableName().startsWith("ZeroTier")) {
// ZeroTier interfaces always start with "ZeroTier"
return true;
return ReachabilityType::RI_VPN;
}
if (nic.humanReadableName().contains("VPN")) {
// This one is just a final heuristic if all else fails
return true;
// This one is just a final VPN heuristic if all else fails
return ReachabilityType::RI_VPN;
}
// Didn't meet any of our VPN heuristics
return false;
// Didn't meet any of our VPN heuristics. Let's see if it's on-link.
Q_ASSERT(addr.prefixLength() >= 0);
if (addr.prefixLength() >= 0 && s.localAddress().isInSubnet(addr.ip(), addr.prefixLength())) {
return ReachabilityType::RI_LAN;
}
// Default to unknown if nothing else matched
return ReachabilityType::RI_UNKNOWN;
}
}
}
qWarning() << "No match found for address:" << s.localAddress();
return false;
return ReachabilityType::RI_UNKNOWN;
}
else {
// If we fail to connect, just pretend that it's not a VPN
return false;
qWarning() << "Unable to check for reachability within 3 seconds";
return ReachabilityType::RI_UNKNOWN;
}
}

View File

@ -35,8 +35,15 @@ public:
bool
wake() const;
bool
isReachableOverVpn() const;
enum ReachabilityType
{
RI_UNKNOWN,
RI_LAN,
RI_VPN,
};
ReachabilityType
getActiveAddressReachability() const;
QVector<NvAddress>
uniqueAddresses() const;

View File

@ -1227,17 +1227,27 @@ bool Session::startConnectionAsync()
m_Preferences->packetSize);
}
else {
// isReachableOverVpn() does network I/O, so we only attempt to check
// VPN reachability if we've already contacted the PC successfully
if (m_Computer->isReachableOverVpn()) {
// It looks like our route to this PC is over a VPN.
// Use 1392 byte video packets by default
m_StreamConfig.packetSize = 1392;
// getActiveAddressReachability() does network I/O, so we only attempt to check
// reachability if we've already contacted the PC successfully.
switch (m_Computer->getActiveAddressReachability()) {
case NvComputer::RI_LAN:
// This address is on-link, so treat it as a local address
// even if it's not in RFC 1918 space or it's an IPv6 address.
m_StreamConfig.streamingRemotely = STREAM_CFG_LOCAL;
break;
case NvComputer::RI_VPN:
// It looks like our route to this PC is over a VPN, so cap at 1024 bytes.
// Treat it as remote even if the target address is in RFC 1918 address space.
m_StreamConfig.streamingRemotely = STREAM_CFG_REMOTE;
m_StreamConfig.packetSize = 1024;
}
else {
break;
default:
// If we don't have reachability info, let moonlight-common-c decide.
m_StreamConfig.streamingRemotely = STREAM_CFG_AUTO;
m_StreamConfig.packetSize = 1392;
break;
}
}