-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: refactored hole punch signalling procedure
* general refactor of the signalling protocol. * Added signatures and verification to the signalling requests and relay messages. #148
- Loading branch information
1 parent
5b01c9e
commit 6123329
Showing
22 changed files
with
1,244 additions
and
706 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
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,12 @@ | ||
import type { HandlerTypes } from '@matrixai/rpc'; | ||
import type NodesConnectionSignalFinal from '../handlers/NodesConnectionSignalFinal'; | ||
import { UnaryCaller } from '@matrixai/rpc'; | ||
|
||
type CallerTypes = HandlerTypes<NodesConnectionSignalFinal>; | ||
|
||
const nodesConnectionSignalFinal = new UnaryCaller< | ||
CallerTypes['input'], | ||
CallerTypes['output'] | ||
>(); | ||
|
||
export default nodesConnectionSignalFinal; |
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,12 @@ | ||
import type { HandlerTypes } from '@matrixai/rpc'; | ||
import type NodesConnectionSignalInitial from '../handlers/NodesConnectionSignalInitial'; | ||
import { UnaryCaller } from '@matrixai/rpc'; | ||
|
||
type CallerTypes = HandlerTypes<NodesConnectionSignalInitial>; | ||
|
||
const nodesConnectionSignalInitial = new UnaryCaller< | ||
CallerTypes['input'], | ||
CallerTypes['output'] | ||
>(); | ||
|
||
export default nodesConnectionSignalInitial; |
This file was deleted.
Oops, something went wrong.
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,73 @@ | ||
import type Logger from '@matrixai/logger'; | ||
import type { | ||
AgentRPCRequestParams, | ||
AgentRPCResponseResult, | ||
HolePunchRequestMessage, | ||
} from '../types'; | ||
import type NodeConnectionManager from '../../NodeConnectionManager'; | ||
import type { Host, Port } from '../../../network/types'; | ||
import { UnaryHandler } from '@matrixai/rpc'; | ||
import * as keysUtils from '../../../keys/utils'; | ||
import * as ids from '../../../ids'; | ||
import * as agentErrors from '../errors'; | ||
import * as agentUtils from '../utils'; | ||
|
||
class NodesConnectionSignalFinal extends UnaryHandler< | ||
{ | ||
nodeConnectionManager: NodeConnectionManager; | ||
logger: Logger; | ||
}, | ||
AgentRPCRequestParams<HolePunchRequestMessage>, | ||
AgentRPCResponseResult | ||
> { | ||
public handle = async ( | ||
input: AgentRPCRequestParams<HolePunchRequestMessage>, | ||
_cancel, | ||
meta, | ||
): Promise<AgentRPCResponseResult> => { | ||
const { nodeConnectionManager, logger } = this.container; | ||
// Connections should always be validated | ||
const sourceNodeId = ids.parseNodeId(input.sourceNodeIdEncoded); | ||
const targetNodeId = ids.parseNodeId(input.targetNodeIdEncoded); | ||
const relayingNodeId = agentUtils.nodeIdFromMeta(meta); | ||
if (relayingNodeId == null) { | ||
throw new agentErrors.ErrorAgentNodeIdMissing(); | ||
} | ||
const requestSignature = Buffer.from(input.requestSignature, 'base64url'); | ||
// Checking request requestSignature, requestData is just `<sourceNodeId><targetNodeId>` concatenated | ||
const requestData = Buffer.concat([sourceNodeId, targetNodeId]); | ||
const sourcePublicKey = keysUtils.publicKeyFromNodeId(sourceNodeId); | ||
if ( | ||
!keysUtils.verifyWithPublicKey( | ||
sourcePublicKey, | ||
requestData, | ||
requestSignature, | ||
) | ||
) { | ||
throw new agentErrors.ErrorNodesConnectionSignalRequestVerificationFailed(); | ||
} | ||
// Checking relay message relaySignature. | ||
// relayData is just `<sourceNodeId><targetNodeId><Address><requestSignature>` concatenated. | ||
const relayData = Buffer.concat([ | ||
sourceNodeId, | ||
targetNodeId, | ||
Buffer.from(JSON.stringify(input.address), 'utf-8'), | ||
requestSignature, | ||
]); | ||
const relayPublicKey = keysUtils.publicKeyFromNodeId(relayingNodeId); | ||
const relaySignature = Buffer.from(input.relaySignature, 'base64url'); | ||
if ( | ||
!keysUtils.verifyWithPublicKey(relayPublicKey, relayData, relaySignature) | ||
) { | ||
throw new agentErrors.ErrorNodesConnectionSignalRelayVerificationFailed(); | ||
} | ||
|
||
const host = input.address.host as Host; | ||
const port = input.address.port as Port; | ||
logger.debug(`Received signaling message to target ${host}:${port}`); | ||
nodeConnectionManager.handleNodesConnectionSignalFinal(host, port); | ||
return {}; | ||
}; | ||
} | ||
|
||
export default NodesConnectionSignalFinal; |
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,66 @@ | ||
import type { | ||
AgentRPCRequestParams, | ||
AgentRPCResponseResult, | ||
HolePunchSignalMessage, | ||
} from '../types'; | ||
import type NodeConnectionManager from '../../../nodes/NodeConnectionManager'; | ||
import type { Host, Port } from '../../../network/types'; | ||
import type { NodeAddress } from '../../../nodes/types'; | ||
import type { JSONValue } from '../../../types'; | ||
import { UnaryHandler } from '@matrixai/rpc'; | ||
import * as agentErrors from '../errors'; | ||
import * as agentUtils from '../utils'; | ||
import { never } from '../../../utils'; | ||
import * as keysUtils from '../../../keys/utils'; | ||
import * as ids from '../../../ids'; | ||
|
||
class NodesConnectionSignalInitial extends UnaryHandler< | ||
{ | ||
nodeConnectionManager: NodeConnectionManager; | ||
}, | ||
AgentRPCRequestParams<HolePunchSignalMessage>, | ||
AgentRPCResponseResult | ||
> { | ||
public handle = async ( | ||
input: AgentRPCRequestParams<HolePunchSignalMessage>, | ||
_cancel, | ||
meta: Record<string, JSONValue> | undefined, | ||
): Promise<AgentRPCResponseResult> => { | ||
const { nodeConnectionManager } = this.container; | ||
// Connections should always be validated | ||
const requestingNodeId = agentUtils.nodeIdFromMeta(meta); | ||
if (requestingNodeId == null) { | ||
throw new agentErrors.ErrorAgentNodeIdMissing(); | ||
} | ||
const targetNodeId = ids.parseNodeId(input.targetNodeIdEncoded); | ||
const signature = Buffer.from(input.signature, 'base64url'); | ||
// Checking signature, data is just `<sourceNodeId><targetNodeId>` concatenated | ||
const data = Buffer.concat([requestingNodeId, targetNodeId]); | ||
const sourcePublicKey = keysUtils.publicKeyFromNodeId(requestingNodeId); | ||
if (!keysUtils.verifyWithPublicKey(sourcePublicKey, data, signature)) { | ||
throw new agentErrors.ErrorNodesConnectionSignalRelayVerificationFailed(); | ||
} | ||
if (meta == null) never('Missing metadata from stream'); | ||
const remoteHost = meta.remoteHost; | ||
const remotePort = meta.remotePort; | ||
if (remoteHost == null || typeof remoteHost !== 'string') { | ||
never('Missing or invalid remoteHost'); | ||
} | ||
if (remotePort == null || typeof remotePort !== 'number') { | ||
never('Missing or invalid remotePort'); | ||
} | ||
const address: NodeAddress = { | ||
host: remoteHost as Host, | ||
port: remotePort as Port, | ||
}; | ||
nodeConnectionManager.handleNodesConnectionSignalInitial( | ||
requestingNodeId, | ||
targetNodeId, | ||
address, | ||
input.signature, | ||
); | ||
return {}; | ||
}; | ||
} | ||
|
||
export default NodesConnectionSignalInitial; |
This file was deleted.
Oops, something went wrong.
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
Oops, something went wrong.