A simple recipe for forwarding webhooks to your local development environment
If your web application integrates with third party services via Webhooks, you will likely have encountered the need to forward Webhook requests to a local development server.
My solution to this had long been a free utility called Localtunnel, which forwards requests from a randomly-generated public host (i.e. [random-prefix].localtunnel.me) to your local machine. A major problem with Localtunnel is that it will not provide you a persistent URL, so you end up having to constantly reconfigure services to point to newly-allocated/temporary URLs.
If you have a VPS or dedicated server, you can use SSH remote forwarding to accomplish the same thing that Localtunnel does, but maintain a persistent remote hostname and port. This way you can configure development Webhooks once for your third-party integrations and be set.
sshd configuration
In order for SSH remote forwarding of TCP traffic to work, you will need to make sure that the ssh daemon (sshd) on your remote host is appropriately configured (we are assuming a Unix/Posix server environment here). Shell into your remote host and check the sshd configuration (at /etc/ssh/sshd_config
for most Unix/Posix OSes). The two configuration items that you will need to confirm are set are the following:
1 2 |
GatewayPorts yes AllowTcpForwarding yes |
Note that if you only want to enable forwarding only for a single user (i.e. non-root user for host security) you can use a “Match User” rule in the file:
1 2 3 |
Match User someuser GatewayPorts yes AllowTcpForwarding yes |
Once you have saved the configuration file, you will need to restart sshd. On Ubuntu you do this with:
1 |
sudo service ssh restart |
The remote host should now be ready to forward TCP connections to you.
The local ssh tunnel
On your local machine, you will use ssh with the -R
flag. The simplified version is:
1 |
ssh -R 8888:localhost:5555 [email protected] |
This forwards traffic from port 8888 on the remote host to port 5555 on your local machine.
You likely also want to supply the -nNT
flags, as otherwise you will be logged in to a shell on the remote host in addition to having the tunnel created. You may also want to use the -v
flag for a verbose debug-style log if you encounter issues connecting or with the tunnel.
Since I use remote tunneling so often in development, I prefer to have the code in an executable shell script. I also like to do this because I otherwise tend to forget the ordering of the arguments (i.e. remote vs local port, which is not obvious at a glance). You can create an executable file anywhere in your PATH (I keep a user binaries directory at ~/bin on my PATH and keep the script in there). For my own purposes I’ve named the executable “tnl” (i.e. “tunnel”):
1 2 3 4 5 |
user=remoteuser server=remotehost.com remotePort=8888 localPort=5555 ssh ${user}@${server} -R ${remotePort}:localhost:${localPort} |
That’s it! When you run the tunnel script, you will now be able to access your local server running on port 5555 via the remote host at http://[remote-host]:8888. You want to be mindful to kill the tunnel session when you’re not using it and be generally conscious of the security of the local server you are running on the tunneled port, as you are by design exposing it on the internet.
1 Comment
Mark
December 31, 2022Do you know what steps need to be taken to tunnel from port 443 for https to my local machine following similar instructions? I'm tunneling to a django server running on port 8000 on my computer.