IoT devices on the home network rely on the router to be accessible from the internet. It functions as a remote proxy and translates between HTTPS used on the internet and HTTP on the local area network.
Reverse proxy
Wildcard CNAME record
A CNAME record maps a domain name to another domain name. In this case the “other” domain name is the DDNS name of our router. By using a wildcard CNAME, such as *.home.domain.com
, we can match requests for non-existent sub-domain domain names to home.domain.com
. If we would open https://ir.home.domain.com
in a browser, the DNS server will give the IP address of home.domain.com
to the browser. The browser will then sent an HTTP request to that IP address requesting the page ir.home.domain.com
.
Add the CNAME records to your DNS configuration
home.domain.com 3600 IN CNAME dyndns.com *.home.domain.com 3600 IN CNAME dyndns.com
Remember to replace domain.com
with your domain name, and dyndns.com
with the dynamic DNS address of your router.
Access Router (pound)
The wildcard CNAME is only part of the equation. Since we configured home.domain.com
to map to the IP address of the access router, this router will need to forward HTTP requests to the real IR device on our home network. We do this using a reverse proxy.
A reverse proxy uses the Host:
field from the HTTP header, to determine where to forward the request to. This allows a server may use a single IP address or interface to accept requests for multiple DNS host names.
We choose the pound
implementation because it seemed versatile. We installed pound
on the /jffs
partition, so that it will survive firmware updates. This guide is written for a Kong build of DD-WRT, but should work with any firmware that has access to lighttpd
. You will need a JFFS partition and need to use command line tools via ssh/telnet.
To get up and running, we need the binaries, a script that starts it and configuration files. These files are available through this GitHub page. The scripts are based on Frater’s post.
- Enable JFFS partition. From the router’s GUI, enable JFFS (Administration » Management). On first use, check the box to “clean internal flash storage”. Reboot as needed.
-
Pound binaries. Our router’s firmware didn’t include
pound
binaries, so we copied it from an older firmware (kongac’s r33010M)scp rtr2:/usr/sbin/pound rtr2:usr/sbin/poundctl /jffs/sbin/ scp rtr2:/usr/lib/libssl.so.1.0.0 rtr2:/usr/lib/libcrypto.so.1.0.0 /jffs/lib
-
Install startup script. Copy the script
/jffs/sbin/pound.sh
and its helperwrite_pound_cfg
from GitHub. -
Configure port to listen on. The file
/jffs/etc/pound/pound.pt1
specifies what port to listen at. The example below uses port 81 since port 80 is already in use for the DD-WRT UI.TimeOut 120 Alive 30 Control "/tmp/pound.ctl" ListenHTTP Address 0.0.0.0 Port 81
-
Configure forward rules. The file
/jffs/etc/pound/pound.pt2
specifies where to forward the HTTP request to. In the example below, we do route both on URL and Host.Service "ir-url" # route home.domain.com/ir to 10.0.1.234:80 Url "/ir.*" BackEnd Address 10.0.1.234 Port 80 End End Service "ir-host" # route ir.home.domain.com to 10.0.1.234:80 HeadRequire "Host:.ir.home.domain.com.*" BackEnd Address 10.0.1.234 Port 80 End End End
-
Start
pound
using/jffs/sbin/pound.sh start
-
Give it a spin by pointing a web browser to either
http://home.domain.com:81/ir
http://ir.home.domain.com:81/
Transport Layer Security
With a way to contact our IR device from the internet, let’s secure the connection using TLS with a free certificates from Let’s Encrypt by loosely following Neilpang’s instructions. We use a slightly modified acme.sh
script that fixes a mistake in the regular expression [ticket968] and to avoid problems with binding to a non-existing IPV6 address, we added -4
to the call to openssl
. The modified script can be found here.
-
Get CA certificates using
opkg
mkdir /jffs/opt; mount --bind /jffs/opt /opt # mount /opt on /jffs/opt ( nvram get rc_startup; echo "mount --bind /jffs/opt /opt" ) \ > /tmp/a; nvram set rc_startup="$(cat /tmp/a); nvram commit" bootstrap # install opkg (for CA-certificates) opkg update; opkg install ca-certificates # install CA certificates
- Make port 443 available. Disable the existing service on that port (Administration » Web Management » disable HTTPS for web access), and open port 443 on the firewall (Administration » Commands » Firewall » Edit; add the line “iptables -I INPUT 1 -p tcp -m state –state NEW -m tcp –dport 443 -j ACCEPT”).
-
Try to request a certificate. Remember to replace
domain.com
with your domain name.cd /jffs/usr/ssl ./acme.sh --issue --tls -d home.domain.com \ --home /jffs/usr/ssl --ca-path /opt/etc/ssl/certs \ --pre-hook "/jffs/sbin/pound.sh stop" \ --post-hook "/jffs/sbin/pound.sh start" --test
If all goes well, remove the--test
parameter and request the certificate for real. -
Automatically renew the certificate, by setting up a cron job to update the certificate before it expires (Administration » Management » Additional Cron Jobs).
# sundays @2:02am, renew/install SSL certificates if necessary (restarting pound) 2 2 * * 0 root /jffs/usr/ssl/acme.sh --cron --home /jffs/usr/ssl >/jffs/usr/ssl/cron.log 2>&1
-
Create
host.pem
by Combine the SSL Private Key, the signed x.509 certificate, and all the certificates in the chain of trust in/jffs/etc/pound/host.pem
so thatpound
can use them./acme.sh --install-cert -d home.domain.com --home /jffs/usr/ssl \ --cert-file /jffs/etc/pound/host.crt \ --key-file /jffs/etc/pound/host.key \ --fullchain-file /jffs/etc/pound/fullchain.crt \ --reloadcmd "cat /jffs/etc/pound/host.key /jffs/etc/pound/host.crt \ /jffs/etc/pound/intermediate-ca.pem \ > /jffs/etc/pound/host.pem ; \ /jffs/sbin/pound.sh restart"
-
Configure
pound
for HTTPS instead of HTTP, by modifying the configuration file/jffs/etc/pound/pound.pt1
.TimeOut 120 Alive 30 Control "/tmp/pound.ctl" ListenHTTPS Address 0.0.0.0 Port 443 Cert "host.pem"
-
Restart
pound
using/jffs/sbin/pound.sh restart
-
Give it a spin by pointing a web browser to either
https://home.domain.com/ir
https://ir.home.domain.com/
This is what I need but it seems cmplicated to update the firmware of the router. Do you know about any router that has reverse proxy support built in from start?
No sorry. It just really depends who build the firmware.