#include <tnlNetInterface.h>
Inheritance diagram for TNL::NetInterface:
Manages all valid and pending notify protocol connections for a port/IP. If you are providing multiple services or servicing multiple networks, you may have more than one NetInterface.
Connection handshaking basic overview:
TNL does a two phase connect handshake to prevent a several types of Denial-of-Service (DoS) attacks.
The initiator of the connection (client) starts the connection by sending a unique random nonce (number, used once) value to the server as part of the ConnectChallengeRequest packet. C->S: ConnectChallengeRequest, Nc
The server responds to the ConnectChallengeRequest with a "Client Puzzle" that has the property that verifying a solution to the puzzle is computationally simple, but can be of a specified computational, brute-force difficulty to compute the solution itself. The client puzzle is of the form: secureHash(Ic, Nc, Ns, X) = Y >> k, where Ic is the identity of the client, and X is a value computed by the client such that the high k bits of the value y are all zero. The client identity is computed by the server as a partial hash of the client's IP address and port and some random data on the server. its current nonce (Ns), Nc, k, and the server's authentication certificate. S->C: ConnectChallengeResponse, Nc, Ns, Ic, Cs
The client, upon receipt of the ConnectChallengeResponse, validates the packet sent by the server and computes a solution to the puzzle the server sent. If the connection is to be authenticated, the client can also validate the server's certificate (if it's been signed by a Certificate Authority), and then generates a shared secret from the client's key pair and the server's public key. The client response to the server consists of: C->S: ConnectRequest, Nc, Ns, X, Cc, sharedSecret(key1, sequence1, NetConnectionClass, class-specific sendData)
The server then can validation the solution to the puzzle the client submitted, along with the client identity (Ic). Until this point the server has allocated no memory for the client and has verified that the client is sending from a valid IP address, and that the client has done some amount of work to prove its willingness to start a connection. As the server load increases, the server may choose to increase the difficulty (k) of the client puzzle, thereby making a resource depletion DoS attack successively more difficult to launch.
If the server accepts the connection, it sends a connect accept packet that is encrypted and hashed using the shared secret. The contents of the packet are another sequence number (sequence2) and another key (key2). The sequence numbers are the initial send and receive sequence numbers for the connection, and the key2 value becomes the IV of the symmetric cipher. The connection subclass is also allowed to write any connection specific data into this packet.
This system can operate in one of 3 ways: unencrypted, encrypted key exchange (ECDH), or encrypted key exchange with server and/or client signed certificates (ECDSA).
The unencrypted communication mode is NOT secure. Packets en route between hosts can be modified without detection by the hosts at either end. Connections using the secure key exchange are still vulnerable to Man-in-the-middle attacks, but still much more secure than the unencrypted channels. Using certificate(s) signed by a trusted certificate authority (CA), makes the communications channel as securely trusted as the trust in the CA.
Arranged Connection handshaking:
NetInterface can also facilitate "arranged" connections. Arranged connections are necessary when both parties to the connection are behind firewalls or NAT routers. Suppose there are two clients, A and B that want to esablish a direct connection with one another. If A and B are both logged into some common server S, then S can send A and B the public (NAT'd) address, as well as the IP addresses each client detects for itself.
A and B then both send "Punch" packets to the known possible addresses of each other. The punch packet client A sends enables the punch packets client B sends to be delivered through the router or firewall since it will appear as though it is a service response to A's initial packet.
Upon receipt of the Punch packet by the "initiator" of the connection, an ArrangedConnectRequest packet is sent. if the non-initiator of the connection gets an ArrangedPunch packet, it simply sends another Punch packet to the remote host, but narrows down its Address range to the address it received the packet from. The ArrangedPunch packet from the intiator contains the nonce for the non-initiator, and the nonce for the initiator encrypted with the shared secret. The ArrangedPunch packet for the receiver of the connection contains all that, plus the public key/keysize or the certificate of the receiver.
Public Types | |
enum | PacketType { ConnectChallengeRequest = 0, ConnectChallengeResponse = 1, ConnectRequest = 2, ConnectReject = 3, ConnectAccept = 4, Disconnect = 5, Punch = 6, ArrangedConnectRequest = 7, FirstValidInfoPacketId = 8 } |
PacketType is encoded as the first byte of each packet. More... | |
Public Member Functions | |
NetInterface (const Address &bindAddress) | |
bindAddress Local network address to bind this interface to. | |
~NetInterface () | |
Address | getFirstBoundInterfaceAddress () |
Returns the address of the first network interface in the list that the socket on this NetInterface is bound to. | |
void | setPrivateKey (AsymmetricKey *theKey) |
Sets the private key this NetInterface will use for authentication and key exchange. | |
void | setRequiresKeyExchange (bool requires) |
Requires that all connections use encryption and key exchange. | |
void | setCertificate (Certificate *theCertificate) |
Sets the public certificate that validates the private key and stores information about this host. | |
bool | doesAllowConnections () |
Returns whether or not this NetInterface allows connections from remote hosts. | |
void | setAllowsConnections (bool conn) |
Sets whether or not this NetInterface allows connections from remote hosts. | |
Socket & | getSocket () |
Returns the Socket associated with this NetInterface. | |
NetError | sendto (const Address &address, BitStream *stream) |
Sends a packet to the remote address over this interface's socket. | |
void | sendtoDelayed (const Address &address, BitStream *stream, U32 millisecondDelay) |
Sends a packet to the remote address after millisecondDelay time has elapsed. | |
void | checkIncomingPackets () |
Dispatch function for processing all network packets through this NetInterface. | |
virtual void | processPacket (const Address &address, BitStream *packetStream) |
Processes a single packet, and dispatches either to handleInfoPacket or to the NetConnection associated with the remote address. | |
virtual void | handleInfoPacket (const Address &address, U8 packetType, BitStream *stream) |
Handles all packets that don't fall into the category of connection handshake or game data. | |
void | processConnections () |
Checks all connections on this interface for packet sends, and for timeouts and all valid and pending connections. | |
Vector< NetConnection * > & | getConnectionList () |
Returns the list of connections on this NetInterface. | |
NetConnection * | findConnection (const Address &remoteAddress) |
looks up a connected connection on this NetInterface | |
U32 | getCurrentTime () |
returns the current process time for this NetInterface | |
Protected Types | |
enum | NetInterfaceConstants { ChallengeRetryCount = 4, ChallengeRetryTime = 2500, ConnectRetryCount = 4, ConnectRetryTime = 2500, PunchRetryCount = 6, PunchRetryTime = 2500, TimeoutCheckInterval = 1500, PuzzleSolutionTimeout = 30000 } |
Protected Member Functions | |
U32 | computeClientIdentityToken (const Address &theAddress, const Nonce &theNonce) |
Computes an identity token for the connecting client based on the address of the client and the client's unique nonce value. | |
NetConnection * | findPendingConnection (const Address &address) |
Finds a connection instance that this NetInterface has initiated. | |
void | addPendingConnection (NetConnection *conn) |
Adds a connection the list of pending connections. | |
void | removePendingConnection (NetConnection *conn) |
Removes a connection from the list of pending connections. | |
void | findAndRemovePendingConnection (const Address &address) |
Finds a connection by address from the pending list and removes it. | |
void | addConnection (NetConnection *connection) |
Adds a connection to the internal connection list. | |
void | removeConnection (NetConnection *connection) |
Remove a connection from the list. | |
void | startConnection (NetConnection *conn) |
Begins the connection handshaking process for a connection. Called from NetConnection::connect(). | |
void | sendConnectChallengeRequest (NetConnection *conn) |
Sends a connect challenge request on behalf of the connection to the remote host. | |
void | handleConnectChallengeRequest (const Address &addr, BitStream *stream) |
Handles a connect challenge request by replying to the requestor of a connection with a unique token for that connection, as well as (possibly) a client puzzle (for DoS prevention), or this NetInterface's public key. | |
void | sendConnectChallengeResponse (const Address &addr, Nonce &clientNonce, bool wantsKeyExchange, bool wantsCertificate) |
Sends a connect challenge request to the specified address. | |
void | handleConnectChallengeResponse (const Address &address, BitStream *stream) |
Processes a ConnectChallengeResponse, by issueing a connect request if it was for a connection this NetInterface has pending. | |
void | continuePuzzleSolution (NetConnection *conn) |
Continues computation of the solution of a client puzzle, and issues a connect request when the solution is found. | |
void | sendConnectRequest (NetConnection *conn) |
Sends a connect request on behalf of a pending connection. | |
void | handleConnectRequest (const Address &address, BitStream *stream) |
Handles a connection request from a remote host. | |
void | sendConnectAccept (NetConnection *conn) |
Sends a connect accept packet to acknowledge the successful acceptance of a connect request. | |
void | handleConnectAccept (const Address &address, BitStream *stream) |
Handles a connect accept packet, putting the connection associated with the remote host (if there is one) into an active state. | |
void | sendConnectReject (ConnectionParameters *theParams, const Address &theAddress, const char *reason) |
Sends a connect rejection to a valid connect request in response to possible error conditions (server full, wrong password, etc). | |
void | handleConnectReject (const Address &address, BitStream *stream) |
Handles a connect rejection packet by notifying the connection object that the connection was rejected. | |
void | startArrangedConnection (NetConnection *conn) |
Begins the connection handshaking process for an arranged connection. | |
void | sendPunchPackets (NetConnection *conn) |
Sends Punch packets to each address in the possible connection address list. | |
void | handlePunch (const Address &theAddress, BitStream *stream) |
Handles an incoming Punch packet from a remote host. | |
void | sendArrangedConnectRequest (NetConnection *conn) |
Sends an arranged connect request. | |
void | handleArrangedConnectRequest (const Address &theAddress, BitStream *stream) |
Handles an incoming connect request from an arranged connection. | |
void | handleDisconnect (const Address &address, BitStream *stream) |
Dispatches a disconnect packet for a specified connection. | |
void | handleConnectionError (NetConnection *theConnection, const char *errorString) |
Handles an error reported while reading a packet from this remote connection. | |
void | disconnect (NetConnection *conn, NetConnection::TerminationReason reason, const char *reasonString) |
Disconnects the given connection and removes it from the NetInterface. | |
Protected Attributes | |
Vector< NetConnection * > | mConnectionList |
List of all the connections that are in a connected state on this NetInterface. | |
Vector< NetConnection * > | mConnectionHashTable |
A resizable hash table for all connected connections. This is a flat hash table (no buckets). | |
Vector< NetConnection * > | mPendingConnections |
List of connections that are in the startup state, where the remote host has not fully validated the connection. | |
RefPtr< AsymmetricKey > | mPrivateKey |
The private key used by this NetInterface for secure key exchange. | |
RefPtr< Certificate > | mCertificate |
A certificate, signed by some Certificate Authority, to authenticate this host. | |
ClientPuzzleManager | mPuzzleManager |
The object that tracks the current client puzzle difficulty, current puzzle and solutions for this NetInterface. | |
U32 | mCurrentTime |
Current time tracked by this NetInterface. | |
bool | mRequiresKeyExchange |
True if all connections outgoing and incoming require key exchange. | |
U32 | mLastTimeoutCheckTime |
Last time all the active connections were checked for timeouts. | |
U8 | mRandomHashData [12] |
Data that gets hashed with connect challenge requests to prevent connection spoofing. | |
bool | mAllowConnections |
Set if this NetInterface allows connections from remote instances. | |
DelaySendPacket * | mSendPacketList |
List of delayed packets pending to send. | |
NetInterfaceSocket Socket | |
State regarding the socket this NetInterface controls. | |
Socket | mSocket |
Network socket this NetInterface communicates over. | |
Friends | |
class | NetConnection |
|
PacketType is encoded as the first byte of each packet. Subclasses of NetInterface can add custom, non-connected data packet types starting at FirstValidInfoPacketId, and overriding handleInfoPacket to process them. Packets that arrive with the high bit of the first byte set (i.e. the first unsigned byte is greater than 127), are assumed to be connected protocol packets, and are dispatched to the appropriate connection for further processing.
|
|
|
bindAddress Local network address to bind this interface to.
|
|
|
|
Computes an identity token for the connecting client based on the address of the client and the client's unique nonce value.
|
|
Finds a connection instance that this NetInterface has initiated.
|
|
Adds a connection the list of pending connections.
|
|
Removes a connection from the list of pending connections.
|
|
Finds a connection by address from the pending list and removes it.
|
|
Adds a connection to the internal connection list.
|
|
Remove a connection from the list.
|
|
Begins the connection handshaking process for a connection. Called from NetConnection::connect().
|
|
Sends a connect challenge request on behalf of the connection to the remote host.
|
|
Handles a connect challenge request by replying to the requestor of a connection with a unique token for that connection, as well as (possibly) a client puzzle (for DoS prevention), or this NetInterface's public key.
|
|
Sends a connect challenge request to the specified address. This can happen as a result of receiving a connect challenge request, or during an "arranged" connection for the non-initiator of the connection. |
|
Processes a ConnectChallengeResponse, by issueing a connect request if it was for a connection this NetInterface has pending.
|
|
Continues computation of the solution of a client puzzle, and issues a connect request when the solution is found.
|
|
Sends a connect request on behalf of a pending connection.
|
|
Handles a connection request from a remote host. This will verify the validity of the connection token, as well as any solution to a client puzzle this NetInterface sent to the remote host. If those tests pass, it will construct a local connection instance to handle the rest of the connection negotiation. |
|
Sends a connect accept packet to acknowledge the successful acceptance of a connect request.
|
|
Handles a connect accept packet, putting the connection associated with the remote host (if there is one) into an active state.
|
|
Sends a connect rejection to a valid connect request in response to possible error conditions (server full, wrong password, etc).
|
|
Handles a connect rejection packet by notifying the connection object that the connection was rejected.
|
|
Begins the connection handshaking process for an arranged connection.
|
|
Sends Punch packets to each address in the possible connection address list.
|
|
Handles an incoming Punch packet from a remote host.
|
|
Sends an arranged connect request.
|
|
Handles an incoming connect request from an arranged connection.
|
|
Dispatches a disconnect packet for a specified connection.
|
|
Handles an error reported while reading a packet from this remote connection.
|
|
Disconnects the given connection and removes it from the NetInterface.
|
|
Returns the address of the first network interface in the list that the socket on this NetInterface is bound to.
|
|
Sets the private key this NetInterface will use for authentication and key exchange.
|
|
Requires that all connections use encryption and key exchange.
|
|
Sets the public certificate that validates the private key and stores information about this host. If no certificate is set, this interface can still initiate and accept encrypted connections, but they will be vulnerable to man in the middle attacks, unless the remote host can validate the public key in another way. |
|
Returns whether or not this NetInterface allows connections from remote hosts.
|
|
Sets whether or not this NetInterface allows connections from remote hosts.
|
|
Returns the Socket associated with this NetInterface.
|
|
Sends a packet to the remote address over this interface's socket.
|
|
Sends a packet to the remote address after millisecondDelay time has elapsed. This is used to simulate network latency on a LAN or single computer. |
|
Dispatch function for processing all network packets through this NetInterface.
|
|
Processes a single packet, and dispatches either to handleInfoPacket or to the NetConnection associated with the remote address.
|
|
Handles all packets that don't fall into the category of connection handshake or game data.
|
|
Checks all connections on this interface for packet sends, and for timeouts and all valid and pending connections.
|
|
Returns the list of connections on this NetInterface.
|
|
looks up a connected connection on this NetInterface
|
|
returns the current process time for this NetInterface
|
|
|
|
List of all the connections that are in a connected state on this NetInterface.
|
|
A resizable hash table for all connected connections. This is a flat hash table (no buckets).
|
|
List of connections that are in the startup state, where the remote host has not fully validated the connection.
|
|
The private key used by this NetInterface for secure key exchange.
|
|
A certificate, signed by some Certificate Authority, to authenticate this host.
|
|
The object that tracks the current client puzzle difficulty, current puzzle and solutions for this NetInterface.
|
|
Network socket this NetInterface communicates over.
|
|
Current time tracked by this NetInterface.
|
|
True if all connections outgoing and incoming require key exchange.
|
|
Last time all the active connections were checked for timeouts.
|
|
Data that gets hashed with connect challenge requests to prevent connection spoofing.
|
|
Set if this NetInterface allows connections from remote instances.
|
|
List of delayed packets pending to send.
|