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, // 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. // 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; quint32 addr;
int err = LiFindExternalAddressIP4("stun.moonlight-stream.org", 3478, &addr); int err = LiFindExternalAddressIP4("stun.moonlight-stream.org", 3478, &addr);
if (err == 0) { if (err == 0) {

View File

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

View File

@ -1227,17 +1227,27 @@ bool Session::startConnectionAsync()
m_Preferences->packetSize); m_Preferences->packetSize);
} }
else { else {
// isReachableOverVpn() does network I/O, so we only attempt to check // Use 1392 byte video packets by default
// VPN reachability if we've already contacted the PC successfully m_StreamConfig.packetSize = 1392;
if (m_Computer->isReachableOverVpn()) {
// It looks like our route to this PC is over a VPN. // 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. // Treat it as remote even if the target address is in RFC 1918 address space.
m_StreamConfig.streamingRemotely = STREAM_CFG_REMOTE; m_StreamConfig.streamingRemotely = STREAM_CFG_REMOTE;
m_StreamConfig.packetSize = 1024; m_StreamConfig.packetSize = 1024;
} break;
else { default:
// If we don't have reachability info, let moonlight-common-c decide.
m_StreamConfig.streamingRemotely = STREAM_CFG_AUTO; m_StreamConfig.streamingRemotely = STREAM_CFG_AUTO;
m_StreamConfig.packetSize = 1392; break;
} }
} }