forked from vmangos/core
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
152 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
#include "ProxyV2Reader.h" | ||
#include "Log.h" | ||
|
||
// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform | ||
#if defined( __GNUC__ ) | ||
#pragma pack(1) | ||
#else | ||
#pragma pack(push,1) | ||
#endif | ||
|
||
struct proxy_hdr_v2 { | ||
uint8_t sig[12]; /* hex 0D 0A 0D 0A 00 0D 0A 51 55 49 54 0A */ | ||
uint8_t ver_cmd; /* protocol version and command */ | ||
uint8_t fam; /* protocol family and address */ | ||
uint16_t len; /* number of following bytes part of the header */ | ||
}; | ||
|
||
union proxy_addr { | ||
struct { /* for TCP/UDP over IPv4, len = 12 */ | ||
uint32_t src_addr; | ||
uint32_t dst_addr; | ||
uint16_t src_port; | ||
uint16_t dst_port; | ||
} ipv4_addr; | ||
struct { /* for TCP/UDP over IPv6, len = 36 */ | ||
uint8_t src_addr[16]; | ||
uint8_t dst_addr[16]; | ||
uint16_t src_port; | ||
uint16_t dst_port; | ||
} ipv6_addr; | ||
struct { /* for AF_UNIX sockets, len = 216 */ | ||
uint8_t src_addr[108]; | ||
uint8_t dst_addr[108]; | ||
} unix_addr; | ||
}; | ||
|
||
// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform | ||
#if defined( __GNUC__ ) | ||
#pragma pack() | ||
#else | ||
#pragma pack(pop) | ||
#endif | ||
|
||
// https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt | ||
|
||
void ProxyProtocol::ReadProxyV2Handshake(IO::Networking::AsyncSocket* socket, std::function<void(nonstd::expected<IO::Networking::IpAddress, IO::NetworkError> const&)> const& callback) | ||
{ | ||
std::shared_ptr<proxy_hdr_v2> proxyHeader(new proxy_hdr_v2()); | ||
socket->Read((char*)(proxyHeader.get()), sizeof(proxyHeader), [socket, callback, proxyHeader](IO::NetworkError const& error, size_t) | ||
{ | ||
if (error) | ||
{ | ||
callback(nonstd::make_unexpected(error)); | ||
return; | ||
} | ||
|
||
constexpr uint8_t expectedSignature[12] = { 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A }; | ||
// We have a valid signature | ||
if (std::memcmp(proxyHeader->sig, expectedSignature, sizeof(expectedSignature)) != 0) | ||
{ | ||
sLog.Out(LOG_NETWORK, LOG_LVL_ERROR, "ProxyV2 invalid signature"); | ||
callback(nonstd::make_unexpected(IO::NetworkError(IO::NetworkError::ErrorType::InvalidProtocolBehavior))); | ||
return; | ||
} | ||
|
||
// Check if we have IPv4_TCP which is currently the only one supported by the vanilla client | ||
constexpr uint8_t PROXY_V2_TCP_OVER_IPV4 = 0x11; | ||
if (proxyHeader->fam != PROXY_V2_TCP_OVER_IPV4) | ||
{ | ||
sLog.Out(LOG_NETWORK, LOG_LVL_ERROR, "ProxyV2 unexpected familyAndProtocol"); | ||
callback(nonstd::make_unexpected(IO::NetworkError(IO::NetworkError::ErrorType::InvalidProtocolBehavior))); | ||
return; | ||
} | ||
|
||
// Check cmd version | ||
if (proxyHeader->ver_cmd != 0x21) | ||
{ | ||
sLog.Out(LOG_NETWORK, LOG_LVL_ERROR, "ProxyV2 unexpected ver_cmd"); | ||
callback(nonstd::make_unexpected(IO::NetworkError(IO::NetworkError::ErrorType::InvalidProtocolBehavior))); | ||
return; | ||
} | ||
|
||
// Unexpected body size | ||
uint16_t headerLength = ::ntohs(proxyHeader->len); | ||
if (headerLength != 12) | ||
{ | ||
sLog.Out(LOG_NETWORK, LOG_LVL_ERROR, "ProxyV2 unexpected body size"); | ||
callback(nonstd::make_unexpected(IO::NetworkError(IO::NetworkError::ErrorType::InvalidProtocolBehavior))); | ||
return; | ||
} | ||
|
||
// Now we can read the actual payload | ||
std::shared_ptr<proxy_addr> addressBody(new proxy_addr()); | ||
socket->Read((char*)(addressBody.get()), headerLength, [callback, addressBody](IO::NetworkError const& error, size_t) | ||
{ | ||
if (error) | ||
{ | ||
callback(nonstd::make_unexpected(error)); | ||
return; | ||
} | ||
IO::Networking::IpAddress ipAddress = IO::Networking::IpAddress::FromIpv4Uint32(::ntohl(addressBody->ipv4_addr.src_addr)); | ||
callback(ipAddress); | ||
}); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#ifndef MANGOS_PROXYPROTOCOL_PROXYV2READER_H | ||
#define MANGOS_PROXYPROTOCOL_PROXYV2READER_H | ||
|
||
#include "IO/Networking/AsyncSocket.h" | ||
|
||
#include "nonstd/expected.hpp" | ||
|
||
namespace ProxyProtocol | ||
{ | ||
/// Allows you to read the proxy protocol V2 | ||
/// Keep in mind that this must be from a trusted source | ||
void ReadProxyV2Handshake(IO::Networking::AsyncSocket* socket, std::function<void(nonstd::expected<IO::Networking::IpAddress, IO::NetworkError> const&)> const& callback); | ||
} | ||
|
||
#endif //MANGOS_PROXYPROTOCOL_PROXYV2READER_H |