-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create automated tests for establishing connection via hole-punch signalling message #161
Comments
This can likely be resolved once we deploy the testnet in #194, and look into multinode testing. |
Should spec out this into a We can make this deterministic by mocking/simulating the seed nodes. And as we are finishing up #194, this should enable us to automate the seed node deployment during these tests. These tests are likely to be expensive to run alot of, and therefore impacts #264. |
Fleshed out the specification for this issue. |
Seems like planning here should be incorporated into #159. @joshuakarp will rely on you to flesh out the specification for both issues. |
Note that we had a previous
where we relayed a hole-punch message to a target, but the target couldn't relay it any further. Keeping it here for posterity (with the test('sends hole punch message to connected target (expected to be broker, to relay further)', async () => {
const conn = await NodeConnection.createNodeConnection({
targetNodeId: targetNodeId,
targetHost: targetHost,
targetPort: targetPort,
forwardProxy: clientFwdProxy,
keyManager: clientKeyManager,
logger: logger,
});
await serverRevProxy.openConnection(sourceHost, sourcePort);
const egressAddress = networkUtils.buildAddress(
clientFwdProxy.egressHost as Host,
clientFwdProxy.egressPort as Port,
);
const signature = await clientKeyManager.signWithRootKeyPair(
Buffer.from(egressAddress),
);
const dummyNode = makeNodeId(
'vi3et1hrpv2m2lrplcm7cu913kr45v51cak54vm68anlbvuf83ra0',
);
// The dummyNode differs from the node ID of the connected target,
// indicating that this relay message is intended for another node.
// Expected to throw an error, as the connection to 1.1.1.1:11111 would not
// exist on the server's side. A broker is expected to have this pre-existing
// connection.
await expect(
async () =>
await conn.sendHolePunchMessage(
sourceNodeId,
dummyNode,
egressAddress,
signature,
),
).rejects.toThrow(grpcErrors.ErrorGRPCClientCall);
await conn.stop();
await serverRevProxy.closeConnection(
clientFwdProxy.egressHost,
clientFwdProxy.egressPort,
);
await conn.destroy();
}); |
We can potentially use the global Alternatively, we just run another keynode, making it a 3-keynode test. It's worthwhile as a reminder too that this test wouldn't actually be testing the "hole-punching" functionality, as all the nodes would be running on localhost, and inherently this requires no hole-punching to establish a connection. |
In the past we have simulated firewalls/NATs on the OS to test this. This used NixOS modules to do so before. If we want the test to be as portable as possible, in terms of being able to run in CI/CD, it might work by using docker in docker, and so we can use setup network namespaces inside the dind system that we are using in #292 to build the docker image and testing it. However I'm not sure what the full capabilities are. I think for now we can test the entire behaviour spec by mocking and other things and then do a manual real world tests. |
As a result of #310, we should have general connection behaviour tested appropriately. As far as I'm aware though, there's no simulation of firewalls/NATs to test the hole-punching mechanism that were added in #310. Perhaps @tegefaulkes can confirm this too. As a result, this can come after the testnet deployment (most likely arising from manual testing with the deployed seed nodes). |
Remember any automated tests (for |
No tests were added for NAT and hole punching testing. They seemed out of scope for #310 and as testing goes they are very involved and tricky tests to create. |
These tests must be written outside or separately from
It's best to continue using our jest tooling for these tests, but if we need to use OS simulation, then the jest tests may need to be executing shell commands which then encapsulate scripts that run inside a network namespaces. |
For testing the hole punching relay message, this can be done inside the normal However to test the hole punching relay message for the |
Let's clarify our terminology. This is signalling message, not a relay message. Otherwise it confuses with NAT relaying. |
With #381 merged, this is already done. |
Specification
In order to establish a unidirectional connection between two nodes (a 'client' and a 'server'), both nodes need to send each other hole-punching packets (that is, we require a relay message to be passed to the 'server' node to send relay packets back to the 'client' node). It's not sufficient enough for a node to simply be in its node table to establish a connection - the node needs to be aware that a connection is desired.
For a brand new keynode in the Polykey network, it will rely on the seed node/s to establish connections to other nodes in this manner. (However, note that once it becomes aware of other nodes in the network through Kademlia, it can send relay messages to these other nodes, with the aim that the relay message will eventually converge on the target node by "hopping" between nodes.)
This scenario of 3 keynodes needs to be incorporated into the
NodeConnection
testing suite (currently we only have automated tests for a direct connection between two nodes).For example, for a node
A
to connect to nodeB
, we require another nodeSeed
to facilitate the connection. This process is depicted in the following diagram:We make the assumption that direct, unidirectional connections are already established from
A
toSeed
, and fromSeed
toB
. We also assume thatA
already knowsB
's host and port (butB
may not know ofA
's host and port, or evenA
's node ID). Then, it follows the process:A
sends the relay message toSeed
(via its direct connection), and simultaneously begins sending hole-punching packets toB
's IPSeed
receives the relay message, noting the target node ID. It relays this hole-punching message toB
(via its direct connection)B
receives the hole-punching message, and begins sending hole-punching packets back toA
.Assuming that
A
is still sending hole-punching packets whenB
begins sending their own back toA
, then a unidirectional connection is established fromA
toB
.The above process was previously manually verified by a collection of 3 scratchpad test files:
test-triple-client.ts:
test-triple-broker.ts:
test-triple-server.ts:
Additional context
Tasks
The text was updated successfully, but these errors were encountered: