Skip to content

Expose remoteRotator to the Internet

Tobias Wellnitz edited this page Jan 28, 2018 · 5 revisions

Sometimes we want to control our rotators through the internet. Exposing remoteRotator directly to the internet is not a good idea and should be avoided. The prefered way to make the remoteRotator web interface available to the internet is to put a webserver in front of remoteRotator. There are plenty of production grade, open source web servers available. Just to name a few: Caddy, lighttpd, nginx,...

This tutorial will use Caddy, as it a lightweight, modern and easy to use webserver.

Download Caddy

Head over to Caddy's download site and fetch a copy of the version needed for your operating system / CPU architecture.

basic caddyfile for remoteRotator

Each Caddy instance is configured through a Caddyfile. So let's create a simple caddy file for:

  • caddy webserver exposed to the internet on port 8080
  • one local remoteRotator instance listening on http port 7070 on the same machine
  • username & password protection (username: tobias, password: mypwd)
  • logging to a local file called "/tmp/caddy_access.log"
  • using gzip compressing

open a new file with your favourite editor:

$ vim ./caddyfile

And copy the following content into the file:

:8080 {
        gzip
        log /tmp/caddy_access.log
        basicauth "tobias" mypwd {
                realm "remoteRotator"
                /
        }
        proxy / localhost:7070
        proxy /ws localhost:7070 {
                websocket
                transparent
        }
}

Key is that we are using caddy as a reverse proxy. We have to declare two sections, one for the http traffic and another one for the websocket.

Now we can execute in one shell our local instance of remoteRotator (adapt to your needs) and in another shell caddy:

$ ./remoteRotator server lan -n "40m Yagi" -t "dummy" -w "0.0.0.0"
no config file found
2018/01/21 18:36:36 added rotator (40m Yagi)
2018/01/21 18:36:36 listening on 0.0.0.0:7070 for HTTP connections
$ caddy --conf ./caddyfile
Activating privacy features... done.
http://:8080

Now you just have to make sure that the port 8080 from your home router is redirected to the machine where caddy is running on. You will find plenty of tutorials on the internet on how to do this.

With this we can access in a browser our rotator through the internet. If you don't know the IP which has been assigned to you by your ISP, checkout whatismyip.com.

When trying to access our remoteRotator we are prompted to enter our username & password:

After the successful authentication, we can access our rotator. Sweet!

DNS & Securing our connection

Although the setup above works, it has some flaws which we want to fix:

  1. Using a proper domain name so that we don't have to use the IP address anymore.
  2. Use TLS encryption so that our data (incl username & password) are properly encrypted when send over the wire.

Setup DNS

There are plenty of tutorials on the internet how to obtain a domain name. You might want to consider using a dynamic DNS service like no-ip.com. Because most ISPs re-assign you a new IP Address every now and then, a dynDNS service will automatically update the DNS entry to your home network (or wherever caddy & remoteRotator are running). We will assume that you have already a DNS name and the DNS A record pointing to the IP Address where caddy is running.

TLS

The nice thing about caddy is, that it will request & and install automatically a free TLS certificate from Let's encrypt for our webserver. Sweet!

Let's also add another rotator and use remoteRotator's web aggregator.

So let's update our caddyfile:

rotators.dh1tw.de {
        tls {
                alpn http/1.1
        }
        gzip
        /tmp/caddy_access.log
        basicauth "tobias" mypwd {
                realm "remoteRotator"
                /
        }
        proxy / localhost:7000
        proxy /ws localhost:7000 {
                websocket
                transparent
        }
}

For this tutorial I've create the subdomain rotators.dh1tw.de and pointed the DNS A record to my servers IP address (you do this on the site of your hosting provider). Caddy will listen now on port 80 and 443. We also force caddy to use HTTP 1.1 since HTTP2 & websockets don't work well together. Accessing the lower 1024 ports requires typically privilege escalation. On Linux we can give caddy permission to bind to port 80 and 443 without being root using setcap.

Let's check were the binary is located:

$ which caddy
/usr/local/bin/caddy

Allow caddy to access ports below 1024 without elevated privileges:

$ sudo setcap cap_net_bind_service=+ep /usr/local/bin/caddy

Now let's fire up our two rotators, the web aggregator and caddy each in their own shell:

$ ./remoteRotator server lan -n "40m Yagi" -t "dummy" -w "0.0.0.0"
no config file found
2018/01/21 18:42:33 added rotator (40m Yagi)
2018/01/21 18:42:33 listening on 0.0.0.0:7070 for HTTP connections
$ ./remoteRotator server lan -n "20m Yagi" -t "dummy" -w "0.0.0.0" -k 7071
no config file found
2018/01/21 18:42:36 added rotator (20m Yagi)
2018/01/21 18:42:36 listening on 0.0.0.0:7071 for HTTP connections
$ ./remoteRotator web
no config file found
2018/01/21 20:43:03 listening on 127.0.0.1:7000 for HTTP connections

When we start caddy for the first time with a FQDN, we are prompted to supply our email address for the Let's Encrypt TLS certificate. This is just needed once.

$ caddy --conf ./caddyfile
Activating privacy features...
Your sites will be served over HTTPS automatically using Let's Encrypt.
By continuing, you agree to the Let's Encrypt Subscriber Agreement at:
  https://acme-v01.api.letsencrypt.org/terms
Please enter your email address so you can recover your account if needed.
You can leave it blank, but you'll lose the ability to recover your account.
Email address: tobias@dh1tw.de
 done.
https://rotators.dh1tw.de
http://rotators.dh1tw.de

When browsing to our domain, the connection has now the TLS padlock next to the URL.

Unfortunately, there is a small caveat: While this works fine with Chrome & Firefox, Safari doesn't support BasicAuth through websockets.

You can’t perform that action at this time.