mirror of
https://github.com/lubosz/overte.git
synced 2025-04-11 13:42:07 +02:00
add additional IP check to DS packet filter operator
This commit is contained in:
parent
80eac56c4d
commit
c122b22dfc
7 changed files with 80 additions and 17 deletions
|
@ -54,6 +54,7 @@ void DomainGatekeeper::processConnectRequestPacket(QSharedPointer<ReceivedMessag
|
|||
if (message->getSize() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
QDataStream packetStream(message->getMessage());
|
||||
|
||||
// read a NodeConnectionData object from the packet so we can pass around this data while we're inspecting it
|
||||
|
|
|
@ -458,7 +458,7 @@ const QString DISABLED_AUTOMATIC_NETWORKING_VALUE = "disabled";
|
|||
|
||||
|
||||
|
||||
bool DomainServer::packetVersionMatch(const udt::Packet& packet) {
|
||||
bool DomainServer::isPacketVerified(const udt::Packet& packet) {
|
||||
PacketType headerType = NLPacket::typeInHeader(packet);
|
||||
PacketVersion headerVersion = NLPacket::versionInHeader(packet);
|
||||
|
||||
|
@ -471,7 +471,50 @@ bool DomainServer::packetVersionMatch(const udt::Packet& packet) {
|
|||
DomainGatekeeper::sendProtocolMismatchConnectionDenial(packet.getSenderSockAddr());
|
||||
}
|
||||
|
||||
// let the normal nodeList implementation handle all other packets.
|
||||
if (!PacketTypeEnum::getNonSourcedPackets().contains(headerType)) {
|
||||
// this is a sourced packet - first check if we have a node that matches
|
||||
QUuid sourceID = NLPacket::sourceIDInHeader(packet);
|
||||
SharedNodePointer sourceNode = nodeList->nodeWithUUID(sourceID);
|
||||
|
||||
if (sourceNode) {
|
||||
// unverified DS packets (due to a lack of connection secret between DS + node)
|
||||
// must come either from the same public IP address or a local IP address (set by RFC 1918)
|
||||
|
||||
DomainServerNodeData* nodeData = static_cast<DomainServerNodeData*>(sourceNode->getLinkedData());
|
||||
|
||||
bool exactAddressMatch = nodeData->getSendingSockAddr() == packet.getSenderSockAddr();
|
||||
bool bothPrivateAddresses = nodeData->getSendingSockAddr().hasPrivateAddress()
|
||||
&& packet.getSenderSockAddr().hasPrivateAddress();
|
||||
|
||||
qDebug() << exactAddressMatch << bothPrivateAddresses;
|
||||
|
||||
if (nodeData && (exactAddressMatch || bothPrivateAddresses)) {
|
||||
// to the best of our ability we've verified that this packet comes from the right place
|
||||
// let the NodeList do its checks now (but pass it the sourceNode so it doesn't need to look it up again)
|
||||
return nodeList->isPacketVerifiedWithSource(packet, sourceNode.data());
|
||||
} else {
|
||||
static const QString UNKNOWN_REGEX = "Packet of type \\d+ \\([\\sa-zA-Z:]+\\) received from unmatched IP for UUID";
|
||||
static QString repeatedMessage
|
||||
= LogHandler::getInstance().addRepeatedMessageRegex(UNKNOWN_REGEX);
|
||||
|
||||
qDebug() << "Packet of type" << headerType
|
||||
<< "received from unmatched IP for UUID" << uuidStringWithoutCurlyBraces(sourceID);
|
||||
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
static const QString UNKNOWN_REGEX = "Packet of type \\d+ \\([\\sa-zA-Z:]+\\) received from unknown node with UUID";
|
||||
static QString repeatedMessage
|
||||
= LogHandler::getInstance().addRepeatedMessageRegex(UNKNOWN_REGEX);
|
||||
|
||||
qDebug() << "Packet of type" << headerType
|
||||
<< "received from unknown node with UUID" << uuidStringWithoutCurlyBraces(sourceID);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// fallback to allow the normal NodeList implementation to verify packets
|
||||
return nodeList->isPacketVerified(packet);
|
||||
}
|
||||
|
||||
|
@ -570,7 +613,7 @@ void DomainServer::setupNodeListAndAssignments() {
|
|||
addStaticAssignmentsToQueue();
|
||||
|
||||
// set a custom packetVersionMatch as the verify packet operator for the udt::Socket
|
||||
nodeList->setPacketFilterOperator(&DomainServer::packetVersionMatch);
|
||||
nodeList->setPacketFilterOperator(&DomainServer::isPacketVerified);
|
||||
}
|
||||
|
||||
const QString ACCESS_TOKEN_KEY_PATH = "metaverse.access_token";
|
||||
|
@ -853,7 +896,6 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSet<Ass
|
|||
}
|
||||
|
||||
void DomainServer::processListRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
|
||||
|
||||
QDataStream packetStream(message->getMessage());
|
||||
NodeConnectionData nodeRequestData = NodeConnectionData::fromDataStream(packetStream, message->getSenderSockAddr(), false);
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ public slots:
|
|||
|
||||
void restart();
|
||||
|
||||
private slots:
|
||||
void processRequestAssignmentPacket(QSharedPointer<ReceivedMessage> packet);
|
||||
void processListRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
|
||||
void processNodeJSONStatsPacket(QSharedPointer<ReceivedMessage> packetList, SharedNodePointer sendingNode);
|
||||
|
@ -79,7 +80,6 @@ public slots:
|
|||
void processICEServerHeartbeatDenialPacket(QSharedPointer<ReceivedMessage> message);
|
||||
void processICEServerHeartbeatACK(QSharedPointer<ReceivedMessage> message);
|
||||
|
||||
private slots:
|
||||
void setupPendingAssignmentCredits();
|
||||
void sendPendingTransactionsToServer();
|
||||
|
||||
|
@ -129,7 +129,7 @@ private:
|
|||
|
||||
void getTemporaryName(bool force = false);
|
||||
|
||||
static bool packetVersionMatch(const udt::Packet& packet);
|
||||
static bool isPacketVerified(const udt::Packet& packet);
|
||||
|
||||
bool resetAccountManagerAccessToken();
|
||||
|
||||
|
|
|
@ -113,6 +113,18 @@ QString HifiSockAddr::toString() const {
|
|||
return _address.toString() + ":" + QString::number(_port);
|
||||
}
|
||||
|
||||
bool HifiSockAddr::hasPrivateAddress() const {
|
||||
// an address is private if it falls in any of the RFC1918 address spaces
|
||||
const QPair<QHostAddress, int> TWENTY_FOUR_BIT_BLOCK = { QHostAddress("10.0.0.0"), 8 };
|
||||
const QPair<QHostAddress, int> TWENTY_BIT_BLOCK = { QHostAddress("172.16.0.0") , 12 };
|
||||
const QPair<QHostAddress, int> SIXTEEN_BIT_BLOCK = { QHostAddress("192.168.0.0"), 16 };
|
||||
|
||||
return _address.isLoopback()
|
||||
|| _address.isInSubnet(TWENTY_FOUR_BIT_BLOCK)
|
||||
|| _address.isInSubnet(TWENTY_BIT_BLOCK)
|
||||
|| _address.isInSubnet(SIXTEEN_BIT_BLOCK);
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, const HifiSockAddr& sockAddr) {
|
||||
debug.nospace() << sockAddr._address.toString().toLocal8Bit().constData() << ":" << sockAddr._port;
|
||||
return debug.space();
|
||||
|
|
|
@ -55,6 +55,8 @@ public:
|
|||
|
||||
QString toString() const;
|
||||
|
||||
bool hasPrivateAddress() const; // checks if the address behind this sock addr is private per RFC 1918
|
||||
|
||||
friend QDebug operator<<(QDebug debug, const HifiSockAddr& sockAddr);
|
||||
friend QDataStream& operator<<(QDataStream& dataStream, const HifiSockAddr& sockAddr);
|
||||
friend QDataStream& operator>>(QDataStream& dataStream, HifiSockAddr& sockAddr);
|
||||
|
|
|
@ -202,12 +202,12 @@ QUdpSocket& LimitedNodeList::getDTLSSocket() {
|
|||
return *_dtlsSocket;
|
||||
}
|
||||
|
||||
bool LimitedNodeList::isPacketVerified(const udt::Packet& packet) {
|
||||
bool LimitedNodeList::isPacketVerifiedWithSource(const udt::Packet& packet, Node* sourceNode) {
|
||||
// We track bandwidth when doing packet verification to avoid needing to do a node lookup
|
||||
// later when we already do it in packetSourceAndHashMatchAndTrackBandwidth. A node lookup
|
||||
// incurs a lock, so it is ideal to avoid needing to do it 2+ times for each packet
|
||||
// received.
|
||||
return packetVersionMatch(packet) && packetSourceAndHashMatchAndTrackBandwidth(packet);
|
||||
return packetVersionMatch(packet) && packetSourceAndHashMatchAndTrackBandwidth(packet, sourceNode);
|
||||
}
|
||||
|
||||
bool LimitedNodeList::packetVersionMatch(const udt::Packet& packet) {
|
||||
|
@ -256,7 +256,7 @@ bool LimitedNodeList::packetVersionMatch(const udt::Packet& packet) {
|
|||
}
|
||||
}
|
||||
|
||||
bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packet& packet) {
|
||||
bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packet& packet, Node* sourceNode) {
|
||||
|
||||
PacketType headerType = NLPacket::typeInHeader(packet);
|
||||
|
||||
|
@ -298,14 +298,18 @@ bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packe
|
|||
} else {
|
||||
QUuid sourceID = NLPacket::sourceIDInHeader(packet);
|
||||
|
||||
// figure out which node this is from
|
||||
SharedNodePointer matchingNode = nodeWithUUID(sourceID);
|
||||
// check if we were passed a sourceNode hint or if we need to look it up
|
||||
if (!sourceNode) {
|
||||
// figure out which node this is from
|
||||
SharedNodePointer matchingNode = nodeWithUUID(sourceID);
|
||||
sourceNode = matchingNode.data();
|
||||
}
|
||||
|
||||
if (matchingNode) {
|
||||
if (sourceNode) {
|
||||
if (!PacketTypeEnum::getNonVerifiedPackets().contains(headerType)) {
|
||||
|
||||
QByteArray packetHeaderHash = NLPacket::verificationHashInHeader(packet);
|
||||
QByteArray expectedHash = NLPacket::hashForPacketAndSecret(packet, matchingNode->getConnectionSecret());
|
||||
QByteArray expectedHash = NLPacket::hashForPacketAndSecret(packet, sourceNode->getConnectionSecret());
|
||||
|
||||
// check if the md5 hash in the header matches the hash we would expect
|
||||
if (packetHeaderHash != expectedHash) {
|
||||
|
@ -323,9 +327,9 @@ bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packe
|
|||
|
||||
// No matter if this packet is handled or not, we update the timestamp for the last time we heard
|
||||
// from this sending node
|
||||
matchingNode->setLastHeardMicrostamp(usecTimestampNow());
|
||||
sourceNode->setLastHeardMicrostamp(usecTimestampNow());
|
||||
|
||||
emit dataReceived(matchingNode->getType(), packet.getPayloadSize());
|
||||
emit dataReceived(sourceNode->getType(), packet.getPayloadSize());
|
||||
|
||||
return true;
|
||||
|
||||
|
|
|
@ -286,7 +286,9 @@ public:
|
|||
|
||||
void setPacketFilterOperator(udt::PacketFilterOperator filterOperator) { _nodeSocket.setPacketFilterOperator(filterOperator); }
|
||||
bool packetVersionMatch(const udt::Packet& packet);
|
||||
bool isPacketVerified(const udt::Packet& packet);
|
||||
|
||||
bool isPacketVerifiedWithSource(const udt::Packet& packet, Node* sourceNode = nullptr);
|
||||
bool isPacketVerified(const udt::Packet& packet) { return isPacketVerifiedWithSource(packet); }
|
||||
|
||||
static void makeSTUNRequestPacket(char* stunRequestPacket);
|
||||
|
||||
|
@ -352,7 +354,7 @@ protected:
|
|||
|
||||
void setLocalSocket(const HifiSockAddr& sockAddr);
|
||||
|
||||
bool packetSourceAndHashMatchAndTrackBandwidth(const udt::Packet& packet);
|
||||
bool packetSourceAndHashMatchAndTrackBandwidth(const udt::Packet& packet, Node* sourceNode = nullptr);
|
||||
void processSTUNResponse(std::unique_ptr<udt::BasePacket> packet);
|
||||
|
||||
void handleNodeKill(const SharedNodePointer& node);
|
||||
|
|
Loading…
Reference in a new issue