Rosbridge with Ngrok
Introduction
rosbridge_suite offers provides JSON interface to ROS via WebSockets, allowing flexibility to interact with ROS through APIs.
ngrok, on the other hand, allows you to expose a local development server to the internet.
Combining them allows you to have access to ROS on a remote client that does not have ROS installed over the internet.
In this post, two methods would be described. The results of this post was obtained on Ubuntu 20.04 with ROS Noetic.
Setup
First, you need to have ngrok set up. The getting started guide can be found here. Note that you would need to sign up an account to have access to an auth token that is required to start the ngrok service.
Second, make sure to have rosbridge_suite
installed. You can install it with:
For the example client here, the roslibpy is needed. The example publisher running on the machine with ROS (roscore
) is:
TCP Tunnel
The TCP tunnel method was first described by ibrahimessam. Chiefly, as the name would suggest, ngrok
acts as a tunnel, funnelling websocket packets through it. Indeed, you may follow the steps in ibrahimessam’s post to achieve the same result. Here, a simplified approach is described to demonstrate the principle.
On the machine running ROS, start ngrok with the intention to forward tcp traffic to port 9090
:
The window should show some statistics about the connection and more importantly, the Forwarding
address. In my case it was tcp://0.tcp.ap.ngrok.io:12032 -> localhost:9090
and then start rosbridge_server
on port 9090
and expecting traffic from port 12032
with:
An example remote client would be:
Indeed, the down side to this approach is that it may not be trivial to use the same rosbridge_server
to handle both local and remote connections, because all connections need to connect to _port
while declaring that they are on websocket_external_port
. For the remote client, this is trivial, because they are connecting via the port ngrok
specified, which is then used as the websocket_external_port
number. For local connections, the port 9090
. If only one rosbridge_server
is to handle both local and remote clients, another approach is required.
Reverse Proxy
In this approach, ngrok
acts as a reverse proxy.
On the machine running ROS, start ngrok with the intention to forward https traffic to port 9090
:
rosbridge_server
accepts both local and remote connections on one port (9090
in this case). The host portion of the host header does not seem to be used by rosbrige_server
, but one may still consider putting in something descriptive. If you wish to use this method BUT keep local and remote rosbridge_server
seperate, launch the remote rosbridge_server
to have websocket_external_port
at 443
instead.The window should show some statistics about the connection and more importantly, the Forwarding
address. In my case it was https://6eae-118-200-93-224.ap.ngrok.io -> localhost:9090
and then start rosbridge_server
on port 9090
with:
An example remote client would be:
Note the inclusion of is_secure=True
as compared to the TCP tunnel case.
Conclusion
In this post, use of ngork
as tcp tunnel and reverse proxy is described to expose ROS to remote clients over the internet, with the latter approach potentially allowing the use of one rosbridge_server
to handle both local and remote connections. Securing the webbridge
remains a challenge though, and do consider using rosauth as described by this post. roslibpy
users should also be aware that the authenticate function has yet to be implemented, so do keep this in consideration during planning. Finally, since roslibpy
uses autobahn
, it is unlikely that wss://username:password@address:port
would work as authentication without catering for additional development effort.
Do take note of the bandwidth and domain limitations for ngrok
on the free tier. “Static” domains are also available as part of the paid plan, and you might be able to automate some of the configurations by getting the public_url
in the ngrok agent api.
Comments or discussions may be posted here.