Last time I showed you how to expose a web service on a Raspberry Pi (or, actually, any kind of device) by using a reverse proxy from Pagekite. On your Pi, you just need a simple Python script. However, it also depends on the Pagekite server, which isn’t always convenient. There are limits to the free service, and you don’t control the entire thing. The good news is twofold: the same Python script you use to set up the client-side can also set up a server. The other good news is the entire thing is open source.
In practical terms, then, if you have a computer that is always on and has an IP address that can be found on the public internet, you can run your own Pagekite server (they call it a front end) and service your own backends.
As I mentioned, you are going to need a computer visible on the Internet. Well, technically a computer that is visible to all the clients you expect to use including the backend. It needs a few tools on it, including Python, but nothing exotic. You’ll also need control of your DNS–exactly how you do that will depend on how your server is set up. In my case, I have a server sitting in a rack in a data center so I have my own DNS server (named) running on it.
The Pagekite website has installation packages for RPM and deb packages. I suggest you start by installing that on your server, using the method that matches your packaging system. This will put a new directory called /etc/pagekite.d and also installs a startup script (/etc/init.d/pagekite).
However, the default setting is to exit and not start anything up. What’s more is that the example files are set up as though the computer wants to talk to the Pagekite frontend provided (pagekite.me). If you want to run your own, you are going to have to make some changes.
If you have a server on the Internet, there is some way to get names (like hackaday.com) into the DNS system to point to a specific IP address. In my case, I own the domain name hotsolder.com so I decided to make dyn.hotsolder.com be my Pagekite front end. I also wanted to be able to create subdomains like 3dprinter.dyn.hotsolder.com.
To do this, I needed a few configuration changes in my DNS:
dyn IN A 18.104.22.168 *.dyn IN A 22.214.171.124
Obviously, my IP address is the one shown. All the names are relative to hotsolder.com, so there’s no need to specify that on those two lines. If your hosting company handles your DNS, you’ll have to determine how to make similar changes. Or you can tell them you need two “A” records put in and they ought to know what that means. The upshot is that your host name (dyn.hotsolder.com or anything.dyn.hotsolder.com) goes to your server (the Pagekite server in the diagram below).
The Pagekite package will leave two important files in /etc/pagekite.d: 10_account.rc and 20_frontends.rc. The first file is why the service won’t start. The reality is, for using the script as a frontend, you don’t need this file at all. Just in case, I commented out all the lines, but you could just as well remove it. The line that prevents it from starting is the one that reads:
The other lines set up your connection to the pagekite.me servers. We aren’t going to do that, so you can remove those lines or the whole file.
The 20_frontends.rc file is supposed to connect to the remote frontend. In this case, we want to be the front end, so here’s what I put in there:
isfrontend ports=8080,80,443,2222 rawports=virtual protos=http,https,raw domain=http,https,http-8080,raw-2222:*.dyn.hotsolder.com:$$$SECRET$$$ domain=http,https,http-8080,raw-2222:dyn.hotsolder.com:$$$SECRET$$$
You can also set up a certificate file and point to it here, but if you want to do that, you can read the documentation (look for the –tl_default and –tls_endpoint options along with –fe_certname and –ca_certs). In fact, that same documentation is where you can learn about all the options like isfrontend and ports.
By default, the Pagekite script looks in ~/.pagekite.rc for settings. If you plan on using the Pagekite server, you are better off leaving this file alone and creating a new configuration. You can install the same package on the Pi or other client computer — remember, the same script is used on the frontend (the Internet-facing computer) and the backend (the computer running the server).
If you want to run from the command line, consider using:
pagekite --clean --optfile=/home/YOURUSERID/.pagekite.CUSTOM.rc
Obviously, you need to replace YOURUSERID and CUSTOM to suit your purposes. If you are using a package and having Pagekite start automatically, you need to look at /etc/pagekite.d. The 20_frontends.rc is where you can configure each frontend server you want to talk to.
Here’s part of my file:
webpath = dyn.hotsolder.com/8080:/:default:/tmp/httpd webpath = dyn.hotsolder.com/80:/:default:/home/alw/Photos frontend=dyn.hotsolder.com:443 service_on=http:dyn.hotsolder.com:localhost:builtin:@kitesecret service_cfg=dyn.hotsolder.com/80:indexes:True service_on=raw-2222:dyn.hotsolder.com:localhost:22:@kitesecret
The @kitesecret references a line further up (or in the 10_accounts file):
This has to match what is set up on the frontend, of course.
For http requests, everything works like you would expect. The service_on and service_cfg lines set up the built-in Web server (you don’t have to use it) and the documentation says these are subject to change. Otherwise, it is pretty simple to set up things.
The issue arises when you want to do a raw port. In my case, I want to expose the ssh server on port 22 to the outside world. Of course, my public computer already has an ssh server on that port. That’s no problem. Pagekite can convert incoming traffic on port 2222 to port 22 on the backend. Kind of.
The raw ports actually come through on an http port. To make ssh work (for example) you need to proxy from port 443 with netcat. The details are in the documentation, but the short version is you need the following configuration in ~/.ssh/config:
Host dyn.hotsolder.com CheckHostIP no ProxyCommand /bin/nc -X connect -x %h:443 %h %p
The Internet of Pi
If you control every network you connect to, this probably isn’t that interesting. If you don’t mind setting up VPNs on both sides, you also don’t need this sort of thing. However, if you need to deploy solutions behind firewalls or even on dynamic IP addresses, you might find the reverse proxy approach is just what you need.
There are always other ways to solve the problem, of course. You can use a dynamic IP provider to address dynamic IPs, for example. Tunneling through unknown firewalls is a bit more difficult, though.