You may not need localtunnel or ngrok
It's become a custom amongst web developers to write »you may not need $insert_tool« posts. Continuing with that tradition, here's my stab at why you might not need localtunnel.me and ngrok.com.
Today's tool in question:
localtunnel exposes your localhost to the world for easy testing and sharing! No need to mess with DNS or deploy just to have others test out your changes.
As naming things is hard, we have a JavaScript localtunnel via npm, a python localtunnel via ruby gems and a go localtunnel available to us. And there are the prominent services localtunnel.me and ngrok.com
When I shared that on Twitter the other day, I got two responses going different directions. On the "positive" side there was Dirk being surprised localtunnel was now on npm and explaining how useful the tool is for conferences and demos. The "negative" side was Tobias, complaining how you don't need any of that, if you'd only understood SSH. What he neglected to mention is that you also need your own server that you can connect to via SSH.
Having my own root servers and dot wanting to die dumb I investigated SSH Reverse Tunneling and with a bit of help from Christian finally figured out what I needed to do.
Configuring sshd
Let's first check if we even need to configure anything at all. Connect to your server ($server
) and with privileges (su
or sudo
) run the following command:
the output looks like this (with yes
and no
depending on your current configuration):
allowtcpforwarding yes
We need to make sure both values are set to yes
in the sshf config file - usually located at /etc/ssh/sshd_config
, or /etc/sshd_config
if you're on a Mac.
User-Specific sshd Configuration
You can limit the privilege of port forwarding to your own user by using a Match User
statement:
Match User rrehm
AllowTcpForwarding yes
GatewayPorts yes
To verify the configuration specific to your user, run the following command providing your username and port to bind. The other options don't really matter, unless you've added more limitations to Match
(see Limit access to openssh features with the Match option for inspiration).
port=12345
sshd -T \
-C user=${user} \
-C host=* \
-C addr=* \
-C laddr=* \
-C lport=${port} | grep -E 'gatewayports|allowtcpforwarding'
again, this should output
allowtcpforwarding yes
Opening SSH Reverse Tunnels
With sshd configured, all we need to do is tell ssh
which port we want mapped:
server=example.org
remotePort=1234
localPort=80
ssh ${user}@${server} -R ${remotePort}:localhost:${localPort}
If you only want to bind the ports but not actually have a shell opened, add -N
:
when you're done, Control C will terminate the SSH connection and your local server will no longer be available remotely.
Making SSH Reverse Tunnels Reconnect Automatically
If you want your tunnel(s) to automatically reconnect (when switching WiFis, for example), have a look at autossh (available via brew install autossh
):
# it's usually a good idea to exit upon error
set -e
# your connection parameters
user=rrehm
server=example.org
remotePort=1234
localPort=80
# some stuff autossh needs to know
AUTOSSH_SERVER_ALIVE_INTERVAL=30
AUTOSSH_SERVER_ALIVE_COUNT=2
export AUTOSSH_POLL=30
export AUTOSSH_GATETIME=0
export AUTOSSH_LOGFILE="/tmp/autossh.log"
# clean up log file on start
touch "${AUTOSSH_LOGFILE}"
rm "${AUTOSSH_LOGFILE}" || true
autossh -f -M 0 \
-o "ExitOnForwardFailure yes" \
-o "ServerAliveInterval ${AUTOSSH_SERVER_ALIVE_INTERVAL}" \
-o "ServerAliveCountMax ${AUTOSSH_SERVER_ALIVE_COUNT}" \
-A ${user}@${server} \
-R ${remotePort}:localhost:${localPort}
Conclusion
You can expose local services on your remote servers, given you have a server you can SSH to. Using autossh
the tunnel can be re-established automatically when it collapses. While this solves most of my personal problems, it is still inferior to ngrok. The vanilla SSH approach knows nothing about the protocols in use. It simply forwards a port, regardless of the service (HTTP, MySQL, SMTP, …). With a simple ngrok http 8080
you'll have remote access to your local webserver through HTTP and HTTPS - even if your local webserver only sports HTTP.
The author does not allow comments to this entry
Comments
Display comments as Linear | Threaded