Poor Man's ngrok

Noah Petherbridge
kirsle
Posted by Noah Petherbridge on Thursday, May 04 2017 @ 10:23:08 AM

Recently, I was developing a Python/Flask app to implement Web Hooks for a third-party API that I was working with. The API recommended the use of ngrok during local development so that the server running on your local computer could be accessed publicly over the Internet (so that their API could reach yours).

ngrok is cool and all, but for their free plan they randomize the subdomain they give you every time you start the program. This meant I always had to log into my API account and change my Web Hook URL each day.

What ngrok is doing is nothing new: I've written about using SSH to forward ports between machines, and figured it should be easy enough for me to configure a subdomain on my own server that forwards traffic to another port that I could open when I need to.

I run the NGINX web server, so I just added some configuration for a subdomain that forwards all traffic to the local port 5000 on the web server:

server {
    server_name tun.kirsle.net;
    listen [::]:443 ssl;
    listen 443 ssl;

    ssl on;
    ssl_certificate /etc/letsencrypt/live/tun.kirsle.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/tun.kirsle.net/privkey.pem;

    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_dhparam /etc/ssl/dhparam.pem;

    # So the Let's Encrypt Acme client can use the webroot method
    location /.well-known {
        alias /var/www/html/.well-known;
    }

    location / {
        proxy_pass http://127.0.0.1:5000/;
    }
}

server {
    server_name tun.kirsle.net;
    listen [::]:80;
    listen 80;

    location / {
        proxy_pass http://127.0.0.1:5000/;
    }
}

This makes my tun.kirsle.net forward to localhost:5000 on the web server. When this port isn't currently bound to a remote SSH connection, nginx will return "502 Bad Gateway"

All that's missing now is a convenient client-side command to start/stop the tunnel when I want. For that, I added a function to my .bashrc:

# Poor Man's ngrok
tunup() {
    port=${1:-5000}
    echo "Forwarding kirsle.net:5000 to local port $port"
    ssh -R 5000:127.0.0.1:$port kirsle
}

So I can just run tunup to open the tunnel and close the SSH session when done. (I know there's a way to start SSH in the background/without an interactive shell, but I prefer to keep a shell open so I know when it gets disconnected). If I'm using a local port on my computer other than 5000, I can run e.g. tunup 8080 for the local port number.

Categories:

[ Blog ]

Comments

There are 0 comments on this page.

Add a Comment

Your name:
Your Email:
Message:
Comments can be formatted with Markdown, and you can use
emoticons in your comment.

If you can see this, don't touch the following fields.