Add firewall penetration for IPv6 client
This commit is contained in:
parent
6abd3bbf69
commit
9132fba714
@ -23,6 +23,7 @@
|
||||
#include "network/event.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
#include "network/socket_address.hpp"
|
||||
#include "network/transport_address.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/log.hpp"
|
||||
@ -179,6 +180,90 @@ int Network::receiveRawPacket(char *buffer, int buf_len,
|
||||
return len;
|
||||
} // receiveRawPacket
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** \brief Sends a packet whithout ENet adding its headers.
|
||||
* This function is used in particular to achieve the STUN protocol.
|
||||
* \param data : Data to send.
|
||||
* \param dst : Destination of the packet.
|
||||
*/
|
||||
void Network::sendRawPacket(const BareNetworkString &buffer,
|
||||
const SocketAddress& dst)
|
||||
{
|
||||
sendto(m_host->socket, buffer.getData(), buffer.size(), 0,
|
||||
dst.getSockaddr(), dst.getSocklen());
|
||||
if (m_connection_debug)
|
||||
{
|
||||
Log::verbose("Network", "Raw packet sent to %s",
|
||||
dst.toString().c_str());
|
||||
}
|
||||
Network::logPacket(buffer, false);
|
||||
} // sendRawPacket
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** \brief Receives a packet directly from the network interface and
|
||||
* filter its address.
|
||||
* Receive a packet whithout ENet processing it. Checks that the
|
||||
* sender of the packet is the one that corresponds to the sender
|
||||
* parameter. Does not check the port right now.
|
||||
* \param buffer A buffer to receive the data in.
|
||||
* \param buf_len Length of the buffer.
|
||||
* \param[out] sender : Transport address of the original sender of the
|
||||
* wanted packet. If the ip address is 0, do not check
|
||||
* the sender's ip address, otherwise wait till a message
|
||||
* from the specified sender arrives. All other messages
|
||||
* are discarded.
|
||||
* \param max_tries : Number of times we try to read data from the
|
||||
* socket. This is aproximately the time we wait in
|
||||
* milliseconds. -1 means eternal tries.
|
||||
* \return Length of the received data, or -1 if no data was received.
|
||||
*/
|
||||
int Network::receiveRawPacket(char *buffer, int buf_len,
|
||||
SocketAddress *sender, int max_tries)
|
||||
{
|
||||
memset(buffer, 0, buf_len);
|
||||
|
||||
struct sockaddr_storage addr = {};
|
||||
socklen_t from_len = sizeof(addr);
|
||||
|
||||
int len = recvfrom(m_host->socket, buffer, buf_len, 0,
|
||||
(struct sockaddr*)(&addr), &from_len);
|
||||
|
||||
int count = 0;
|
||||
// wait to receive the message because enet sockets are non-blocking
|
||||
while(len < 0 && (count<max_tries || max_tries==-1) )
|
||||
{
|
||||
count++;
|
||||
StkTime::sleep(1); // wait 1 millisecond between two checks
|
||||
len = recvfrom(m_host->socket, buffer, buf_len, 0,
|
||||
(struct sockaddr*)(&addr), &from_len);
|
||||
}
|
||||
|
||||
// No message received
|
||||
if(len<0)
|
||||
return -1;
|
||||
|
||||
Network::logPacket(BareNetworkString(buffer, len), true);
|
||||
switch (addr.ss_family)
|
||||
{
|
||||
case AF_INET:
|
||||
sender->setSockAddrIn(AF_INET, (sockaddr*)(&addr),
|
||||
sizeof(sockaddr_in));
|
||||
break;
|
||||
case AF_INET6:
|
||||
sender->setSockAddrIn(AF_INET6, (sockaddr*)(&addr),
|
||||
sizeof(sockaddr_in6));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (m_connection_debug)
|
||||
{
|
||||
Log::verbose("Network", "Address of the sender was %s",
|
||||
sender->toString().c_str());
|
||||
}
|
||||
return len;
|
||||
} // receiveRawPacket
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** \brief Broadcasts a packet to all peers.
|
||||
* \param data : Data to send.
|
||||
|
@ -37,6 +37,7 @@
|
||||
class BareNetworkString;
|
||||
class NetworkString;
|
||||
class TransportAddress;
|
||||
class SocketAddress;
|
||||
|
||||
/** \class EnetHost
|
||||
* A small wrapper around enet to allow sending and receiving
|
||||
@ -68,6 +69,10 @@ public:
|
||||
const TransportAddress& dst);
|
||||
int receiveRawPacket(char *buffer, int buf_len,
|
||||
TransportAddress* sender, int max_tries = -1);
|
||||
void sendRawPacket(const BareNetworkString &buffer,
|
||||
const SocketAddress& dst);
|
||||
int receiveRawPacket(char *buffer, int buf_len,
|
||||
SocketAddress* sender, int max_tries = -1);
|
||||
void broadcastPacket(NetworkString *data,
|
||||
bool reliable = true);
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/protocols/connect_to_peer.hpp"
|
||||
|
||||
#include "network/network.hpp"
|
||||
#include "network/stk_host.hpp"
|
||||
#include "utils/time.hpp"
|
||||
#include "utils/log.hpp"
|
||||
@ -26,7 +26,7 @@
|
||||
/** Constructor for peer address.
|
||||
* \param address The address to connect to.
|
||||
*/
|
||||
ConnectToPeer::ConnectToPeer(const TransportAddress &address)
|
||||
ConnectToPeer::ConnectToPeer(const SocketAddress &address)
|
||||
: Protocol(PROTOCOL_CONNECTION)
|
||||
{
|
||||
m_peer_address = address;
|
||||
@ -62,13 +62,14 @@ void ConnectToPeer::asynchronousUpdate()
|
||||
// the client will use enet intercept to discover if server
|
||||
// address or port is different from stk addons database.
|
||||
// (Happens if there is firewall in between)
|
||||
TransportAddress broadcast_address;
|
||||
broadcast_address = m_peer_address;
|
||||
BareNetworkString aloha("aloha-stk");
|
||||
|
||||
// Enet packet will not have 0xFFFF for first 2 bytes
|
||||
BareNetworkString aloha("aloha-stk");
|
||||
// We use the feature to distinguish between the enet packets
|
||||
// and this aloha
|
||||
aloha.getBuffer().insert(aloha.getBuffer().begin(), 2, 0xFF);
|
||||
STKHost::get()->sendRawPacket(aloha, broadcast_address);
|
||||
|
||||
STKHost::get()->sendRawPacket(aloha, m_peer_address);
|
||||
Log::debug("ConnectToPeer", "Broadcast aloha sent.");
|
||||
// 20 seconds timeout
|
||||
if (m_tried_connection++ > 10)
|
||||
|
@ -20,7 +20,7 @@
|
||||
#define CONNECT_TO_PEER_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include "network/transport_address.hpp"
|
||||
#include "network/socket_address.hpp"
|
||||
#include "utils/cpp2011.hpp"
|
||||
|
||||
/** One instance of this is started for every peer who tries to
|
||||
@ -29,8 +29,7 @@
|
||||
class ConnectToPeer : public Protocol
|
||||
{
|
||||
protected:
|
||||
|
||||
TransportAddress m_peer_address;
|
||||
SocketAddress m_peer_address;
|
||||
|
||||
/** Timer use for tracking broadcast. */
|
||||
uint64_t m_timer = 0;
|
||||
@ -46,7 +45,7 @@ protected:
|
||||
} m_state;
|
||||
|
||||
public:
|
||||
ConnectToPeer(const TransportAddress &address);
|
||||
ConnectToPeer(const SocketAddress &address);
|
||||
virtual ~ConnectToPeer() {}
|
||||
virtual void setup() OVERRIDE {}
|
||||
virtual void update(int ticks) OVERRIDE {}
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "network/crypto.hpp"
|
||||
#include "network/event.hpp"
|
||||
#include "network/game_setup.hpp"
|
||||
#include "network/network.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/network_player_profile.hpp"
|
||||
#include "network/peer_vote.hpp"
|
||||
@ -2604,7 +2605,9 @@ void ServerLobby::checkIncomingConnectionRequests()
|
||||
{
|
||||
uint32_t addr, id;
|
||||
uint16_t port;
|
||||
std::string ipv6;
|
||||
users_xml->getNode(i)->get("ip", &addr);
|
||||
users_xml->getNode(i)->get("ipv6", &ipv6);
|
||||
users_xml->getNode(i)->get("port", &port);
|
||||
users_xml->getNode(i)->get("id", &id);
|
||||
users_xml->getNode(i)->get("aes-key", &keys[id].m_aes_key);
|
||||
@ -2615,7 +2618,10 @@ void ServerLobby::checkIncomingConnectionRequests()
|
||||
keys[id].m_tried = false;
|
||||
if (ServerConfig::m_firewalled_server)
|
||||
{
|
||||
TransportAddress peer_addr(addr, port);
|
||||
SocketAddress peer_addr(addr, port);
|
||||
if (!ipv6.empty())
|
||||
peer_addr.init(ipv6, port);
|
||||
peer_addr.convertForIPv6Socket();
|
||||
std::string peer_addr_str = peer_addr.toString();
|
||||
if (sl->m_pending_peer_connection.find(peer_addr_str) !=
|
||||
sl->m_pending_peer_connection.end())
|
||||
|
@ -344,9 +344,7 @@ void loadServerLobbyFromConfig()
|
||||
|
||||
if (m_ipv6_server)
|
||||
{
|
||||
#ifdef ENABLE_IPV6
|
||||
m_firewalled_server = false;
|
||||
#else
|
||||
#ifndef ENABLE_IPV6
|
||||
Log::warn("ServerConfig", "IPv6 support not compiled.");
|
||||
#endif
|
||||
}
|
||||
|
@ -1302,7 +1302,7 @@ void STKHost::handleDirectSocketRequest(Network* direct_socket,
|
||||
const int LEN=2048;
|
||||
char buffer[LEN];
|
||||
|
||||
TransportAddress sender;
|
||||
SocketAddress sender;
|
||||
int len = direct_socket->receiveRawPacket(buffer, LEN, &sender, 1);
|
||||
if(len<=0) return;
|
||||
BareNetworkString message(buffer, len);
|
||||
@ -1383,6 +1383,25 @@ bool STKHost::peerExists(const TransportAddress& peer)
|
||||
return false;
|
||||
} // peerExists
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** \brief Tells if a peer is known.
|
||||
* \return True if the peer is known, false elseway.
|
||||
*/
|
||||
bool STKHost::peerExists(const SocketAddress& peer)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_peers_mutex);
|
||||
for (auto p : m_peers)
|
||||
{
|
||||
auto stk_peer = p.second;
|
||||
if (stk_peer->getSocketAddress() == peer ||
|
||||
((stk_peer->getSocketAddress().isPublicAddressLocalhost() &&
|
||||
peer.isPublicAddressLocalhost()) &&
|
||||
stk_peer->getSocketAddress().getPort() == peer.getPort()))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} // peerExists
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** \brief Return the only server peer for client.
|
||||
* \return STKPeer the STKPeer of server.
|
||||
@ -1691,3 +1710,17 @@ std::string STKHost::getVaildPublicAddress() const
|
||||
return m_public_address.toString();
|
||||
return "";
|
||||
} // getVaildPublicAddress
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
int STKHost::receiveRawPacket(char *buffer, int buffer_len,
|
||||
SocketAddress* sender, int max_tries)
|
||||
{
|
||||
return m_network->receiveRawPacket(buffer, buffer_len, sender,
|
||||
max_tries);
|
||||
} // receiveRawPacket
|
||||
// ----------------------------------------------------------------------------
|
||||
void STKHost::sendRawPacket(const BareNetworkString &buffer,
|
||||
const SocketAddress& dst)
|
||||
{
|
||||
m_network->sendRawPacket(buffer, dst);
|
||||
} // sendRawPacket
|
||||
|
@ -54,6 +54,7 @@ class NetworkTimerSynchronizer;
|
||||
class Server;
|
||||
class ServerLobby;
|
||||
class SeparateProcess;
|
||||
class SocketAddress;
|
||||
|
||||
enum ENetCommandType : unsigned int
|
||||
{
|
||||
@ -273,6 +274,8 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
bool peerExists(const TransportAddress& peer_address);
|
||||
// ------------------------------------------------------------------------
|
||||
bool peerExists(const SocketAddress& peer_address);
|
||||
// ------------------------------------------------------------------------
|
||||
bool isConnectedTo(const TransportAddress& peer_address);
|
||||
// ------------------------------------------------------------------------
|
||||
std::shared_ptr<STKPeer> getServerPeerForClient() const;
|
||||
@ -307,6 +310,12 @@ public:
|
||||
m_network->sendRawPacket(buffer, dst);
|
||||
} // sendRawPacket
|
||||
// ------------------------------------------------------------------------
|
||||
int receiveRawPacket(char *buffer, int buffer_len,
|
||||
SocketAddress* sender, int max_tries = -1);
|
||||
// ------------------------------------------------------------------------
|
||||
void sendRawPacket(const BareNetworkString &buffer,
|
||||
const SocketAddress& dst);
|
||||
// ------------------------------------------------------------------------
|
||||
Network* getNetwork() const { return m_network; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a copied list of peers. */
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "network/event.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
#include "network/socket_address.hpp"
|
||||
#include "network/stk_ipv6.hpp"
|
||||
#include "network/stk_host.hpp"
|
||||
#include "network/transport_address.hpp"
|
||||
@ -38,9 +39,25 @@ STKPeer::STKPeer(ENetPeer *enet_peer, STKHost* host, uint32_t host_id)
|
||||
: m_peer_address(enet_peer->address), m_host(host)
|
||||
{
|
||||
m_addons_scores.fill(-1);
|
||||
// We use 0.x.x.x ip to map to IPv6 address internally
|
||||
if (m_peer_address.getIP() < 16777216)
|
||||
m_ipv6_address = getIPV6ReadableFromMappedAddress(&enet_peer->address);
|
||||
uint32_t addr = htonl(enet_peer->address.host);
|
||||
#ifdef ENABLE_IPV6
|
||||
if (isIPv6Socket())
|
||||
{
|
||||
// This will return the mapped IPv4 address too for IPv6 socket
|
||||
// So we can sendto directly with it
|
||||
struct sockaddr_in6 in6 = {};
|
||||
getIPV6FromMappedAddress(&enet_peer->address, &in6);
|
||||
m_socket_address.reset(new SocketAddress());
|
||||
m_socket_address->setSockAddrIn(AF_INET6, (sockaddr*)&in6, sizeof(in6));
|
||||
if (m_socket_address->isIPv6())
|
||||
m_ipv6_address = m_socket_address->toString(false/*show_port*/);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
m_socket_address.reset(
|
||||
new SocketAddress(addr, enet_peer->address.port));
|
||||
}
|
||||
m_enet_peer = enet_peer;
|
||||
m_host_id = host_id;
|
||||
m_connected_time = StkTime::getMonoTimeMs();
|
||||
|
@ -43,7 +43,7 @@ class Crypto;
|
||||
class NetworkPlayerProfile;
|
||||
class NetworkString;
|
||||
class STKHost;
|
||||
class TransportAddress;
|
||||
class SocketAddress;
|
||||
|
||||
enum PeerDisconnectInfo : unsigned int
|
||||
{
|
||||
@ -89,6 +89,8 @@ protected:
|
||||
|
||||
TransportAddress m_peer_address;
|
||||
|
||||
std::unique_ptr<SocketAddress> m_socket_address;
|
||||
|
||||
STKHost* m_host;
|
||||
|
||||
std::vector<std::shared_ptr<NetworkPlayerProfile> > m_players;
|
||||
@ -293,6 +295,9 @@ public:
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
int getConsecutiveMessages() const { return m_consecutive_messages; }
|
||||
// ------------------------------------------------------------------------
|
||||
const SocketAddress& getSocketAddress() const
|
||||
{ return *m_socket_address.get(); }
|
||||
}; // STKPeer
|
||||
|
||||
#endif // STK_PEER_HPP
|
||||
|
Loading…
Reference in New Issue
Block a user