Initial RDP connection on a remote machine over Relay Hybrid Connection and Web Sockets - Azure Relay
In one of my latest post I presented how we can establish a PuTTy connection between two different machines through Azure Relay Hybrid Connection using web sockets.
Today, we will take a look over a Node.JS sample that initiate the tunnel that can be used for an RDP connection between two machines over Azure Relay.
Context
Before jumping to the solution let's take a look on RDP Connection Sequence (https://msdn.microsoft.com/en-us/library/cc240452.aspx?f=255&MSPPError=-2147217396).
As we can see in the connection sequence flow, there are multiple connections that are open during a RDP session. The initial session that is open between client and server is used for the initial handshake and credentials validation. Once the credential are validated, the current connection is closed and other socket connection are open automatically.
In the current sample, we will update the original one that was written for Telnet. The first 5 steps from the flow will be supported, until in the moment when the initial socket connection is close and a new one is open.
More information on what we should do after this steps are presented at the end of the post.
Implementation
The implementation is straightforward and similar with the one that was used for PuTTy connection. There are only some small things that we need to take into account.
GitHub Source code: https://github.com/vunvulear/Stuff/tree/master/Azure/relay-hybrid-connections-rdp-initial
Server.js needs to run on the machine that we want to access. In our code, we will need to open the socket and redirect all the content that is send through Azure Relay Hybrid Connection to the local socket.
The second step needs to be done on our local socket, where is necessary to redirect the content from our local socket to our web socket.
On the other machine, where we run client.js we will do a similar thing. Listen to web socket that is communication with Azure Relay Hybrid Connection and redirect content to local port and redirect all content from the local port to our web socket.
Next steps
What if we would like to extend the current solution to be able to do a full RDP connection over Azure Relay Hybrid Connection? There are two clear steps that need to be done.
1. Support multiple connection
We shall extend client.js and server.js to be able to send through the web sockets multiple socket connections. This would required that on one side to mark each package that we send over Azure Relay with a flag that would allow us to know on the other side on what socket we need to redirect the content.
2. Buffering
Even if the solution will work, it is pretty clear that we need a buffering mechanism that is able to stream uniformly all content that is send over Azure Relay. If we would have only one connection open, this would not be necessary. Having multiple open connection that goes over the same web socket, then it is required to have a buffering mechanism.
Without it, the solution will work, but the connection will not be stable enough.
Conclusion
Yes, it is possible to tunnel a RDP connection over Azure Relay. We have all the functionality and tools available already. The support for multiple connection and buffering are two features that are necessary for any kind of remote connection that we will want to establish.
Once we will do this, we will be able to tunnel a VNC or a FTP connection without any problems.
Today, we will take a look over a Node.JS sample that initiate the tunnel that can be used for an RDP connection between two machines over Azure Relay.
Context
Before jumping to the solution let's take a look on RDP Connection Sequence (https://msdn.microsoft.com/en-us/library/cc240452.aspx?f=255&MSPPError=-2147217396).
As we can see in the connection sequence flow, there are multiple connections that are open during a RDP session. The initial session that is open between client and server is used for the initial handshake and credentials validation. Once the credential are validated, the current connection is closed and other socket connection are open automatically.
In the current sample, we will update the original one that was written for Telnet. The first 5 steps from the flow will be supported, until in the moment when the initial socket connection is close and a new one is open.
More information on what we should do after this steps are presented at the end of the post.
Implementation
The implementation is straightforward and similar with the one that was used for PuTTy connection. There are only some small things that we need to take into account.
GitHub Source code: https://github.com/vunvulear/Stuff/tree/master/Azure/relay-hybrid-connections-rdp-initial
Server.js needs to run on the machine that we want to access. In our code, we will need to open the socket and redirect all the content that is send through Azure Relay Hybrid Connection to the local socket.
function (socket) {
relaysocket = socket;
console.log('New connection from client');
relaysocket.onmessage = function (event) {
// Send data to local socket (local port)
myLocalHost.write(event.data);
};
relaysocket.on('close', function () {
console.log('Relay connectin was closed');
});
});
The second step needs to be done on our local socket, where is necessary to redirect the content from our local socket to our web socket.
net.createServer(function(localsocket)
{
myLocalHost = localsocket;
myLocalHost.on('data', function(d) {
relaysocket.send(d);
myLocalHost.on('error', function(err) {console.log("Socket close: " + err.stack)});
});
}).listen(localport);
On the other machine, where we run client.js we will do a similar thing. Listen to web socket that is communication with Azure Relay Hybrid Connection and redirect content to local port and redirect all content from the local port to our web socket.
var relayclient = webrelay.relayedConnect(
webrelay.createRelaySendUri(ns, path),
webrelay.createRelayToken('http://'+ns, keyrule, key),
function (socket) {
// Create local socket to the given port
console.log("Connected to relay")
relayclient.onmessage = function (event) {
if(typeof localsocket === "undefined")
{
localsocket = net.connect(sourceport,function(socket) {
console.log("New socket");
});
localsocket.on('data', function(data) {
relayclient.send(data);
});
localsocket.on('error', function(err) {console.log("Socket close: " + err.stack)});
}
localsocket.write(event.data);
};
}
);
Next steps
What if we would like to extend the current solution to be able to do a full RDP connection over Azure Relay Hybrid Connection? There are two clear steps that need to be done.
1. Support multiple connection
We shall extend client.js and server.js to be able to send through the web sockets multiple socket connections. This would required that on one side to mark each package that we send over Azure Relay with a flag that would allow us to know on the other side on what socket we need to redirect the content.
2. Buffering
Even if the solution will work, it is pretty clear that we need a buffering mechanism that is able to stream uniformly all content that is send over Azure Relay. If we would have only one connection open, this would not be necessary. Having multiple open connection that goes over the same web socket, then it is required to have a buffering mechanism.
Without it, the solution will work, but the connection will not be stable enough.
Conclusion
Yes, it is possible to tunnel a RDP connection over Azure Relay. We have all the functionality and tools available already. The support for multiple connection and buffering are two features that are necessary for any kind of remote connection that we will want to establish.
Once we will do this, we will be able to tunnel a VNC or a FTP connection without any problems.
Works great! Thank you for the good work.
ReplyDeleteam working on RDP(Remote Desktop Sharing) project in which the remote desktop and client are firewall protected , so one can not directly use VNC viewer and VNC connect directly as the devices doesn't have their public IP exposed , I came to know such kind of situation is handled using Service Relay (Azure) which act as a tunnel between the devices to allow remote sharing .It will be very thankful if somebody can help me in solving me this situation of Sevice relay,by providing some useful links of the projects ,or such concepts ,aur any site that had implemented this logic .Thanks in advance .I am using c/c++ for implementation
ReplyDelete