Say you have infrastructure deployed in the above architecture for some reason. Typically you might expect that connectivity between A and B isn’t possible – ping and netcat both fail to yield responses after all.

It turns out that if an instance has a public IP address in a VPC with an internet gateway attached it can receive traffic – it just can’t respond to it. This is because response packets are routed via the subnet’s route table and would transit via the NAT GW with a different IP.

But what if we were to do something really silly. Could we make it work then? Enter matconnect.

matconnect works by combining two physical unidirectional streams (A->B and B->A) into a single logical stream via shenanigans. This works via UDP’s ability to send/receive over “unconnected sockets”. At the start of each UDP “session” we send a six byte packet with the client’s public IP address and port that it expects to receive a response on. Then we proceed with the application protocol itself. In this case, we use HTTP/3 to get TLS 1.3 encryption (can’t have our nonsense be insecure). On top of HTTP/3 we use WebTransport for multiplexing arbitrary bidirectional streams. And on one of those bidirectional streams we have our client and server sing a duet. It looks like this:

    participant A as Instance A
    participant NA as NAT GW A
    participant NB as NAT GW B
    participant B as Instance B
    A->>NA: From<br>To<br> "I am listening on ... ${payload}"
    NA->>B: From<br>To<br> "I am listening on ... ${payload}"
    Note left of B: Normally a response now <br>would go to <br> But we read our silly header <br> and "open a new connection" 😉
    B->>NB: From<br>To<br> ${response payload}
    NB->>A: From<br>To<br> ${response payload}

And the result is beautiful:

demo gif


On one instance (that we’ll call the server), run ./matconnect. On the other instance (which we’ll call the client), run ./matconnect <server public ip>:8080. Now watch the important data flow in both directions.


View Github