Security for your Alexa-DTV

I have been working with “B Money” on a github project for connecting your Alexa device to control your DirecTV STB (https://github.com/bklavet/Echo-skill-to-control-Directv) and have been bothered by the general lack of security on the network communication as well as authentication.

As such, I have put together guide to help mitigate some of the risk of putting your DTV box on the Internet.

A few requirements I had going into this:

  1. Had to use HTTPS protocols for communicating across the Internet (from AWS/Lambda to my home)
  2. Had to support SOME level of basic authentication/authorization
  3. Should be relatively easy and cost-effective to setup

My solution can likely be expanded on and improved, but for ME, it is much better than the completely insecure method we have resorted to in the past.

Here is a quick summary of what you will need to follow this:

  1. Raspberry Pi Zero W (or other RPI with Wireless)
  2. 8GB MicroSD card
  3. Wireless network at home
  4. Router that supports port forwarding/NAT
  5. A home computer that you can write MicroSD cards from an image

If you have never done anything with an RPI, it is pretty straight-forward, but can be a bit daunting for those who have never used Linux before.

At a VERY high level, here are the steps:

  1. Install the latest Raspbian Linux image on your RPI and update it
  2. Install NGINX and other packages to setup security
  3. Setup user authentication
  4. Configure NGINX to be a reverse proxy (is between your DTV box and Amazon)
  5. Then update the Lambda service’s “index” file to let you communicate more securely

Installing Raspbian is actually very easy and I will try to take this step-by-step.

For this tutorial, I am running on Windows 10 laptop, so your mileage may vary on other platforms.  My guess is that if you are already running a Linux workstation you will probably be able to figure this out already.

  1. Download and install Win32DiskImager (https://sourceforge.net/projects/win32diskimager/)
  2. Download the Raspbian disk image ( https://www.raspberrypi.org/downloads/raspbian/)
    I recommend the “Raspbian Stretch Lite” version due to its size and lack of some of the normal bloat that comes on these.
  3. Insert your Blank microSD card into your system. You may need to use an adapter since most system don’t have microSD slots.
  4. Launch Win32DiskImager and browse to the Raspbian image you downloaded
  5. Be sure that the Target device is your microSD card.  It will try to find the right device, but just make sure since this process will destroy anything currently on it.
  6. Once Confirmed, click on the Write button and wait for it to finish

Okay, so now we have a microSD card with Raspbian on it.

Windows will assign it a drive letter and may actually pull up the contents of the drive.  If not, then just browse to that drive and go to the very root of that drive.

Since we are running this “headless” (no monitor or keyboard), we need to tell this image to enable SSH (for remote access) and to configure the wireless settings.  Fortunately there is an easy way to do this by simply dropping a few files at the root of the filesystem.

I have found the easiest way to do this is launch NotePad in windows.  The first file we will have NO CONTENT in it and be named “ssh”.  It is important that it contain no data and be named exactly “ssh”, not “ssh.txt” or “ssh.doc” or “ssh.anything”.

To do this, simply do the following:

  1. run Notepad and click File->SaveAs
  2. Now go find your microSD drive and select it.
  3. For the filename type “ssh” and for the “SaveAs Type”, select “All Files (*.*)”
  4. You should confirm that the file name is just “ssh”
  5. Save it.
  6. You can close notepad

You should now see a file names “ssh”

Now to automatically configure your wireless, lets go through the same process as we did above:

  1. run Notepad and copy this text into the new document.  Make sure you replace the “YOUR_WIRELESS_SID” with your actual Wireless SID and “YOUR_WIRELESS_KEY”, with your actual WPA key.
    country=US
    ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
    update_config=1
    
    network={
     ssid="YOUR_WIRELESS_SID"
     scan_ssid=1
     psk="YOUR_WIRELESS_KEY"
     key_mgmt=WPA-PSK
    }
  2. Click File->SaveAs
  3. Now go find your microSD drive and select it.
  4. For the filename type “wpa_supplicant.conf” and for the “SaveAs Type”, select “All Files (*.*)”
  5. You should confirm that the file name is “wpa_supplicant.conf”
  6. Save it.
  7. You can close notepad

So now we have a new microSD card with Raspbian on it plus 2 new files in the root of the drive.

You can safely eject the microSD and put it into your RPi.

Now just power up your RPi and let it run for a bit.  You may need to look on your Router to find the IP Address that got assigned to the RPi.  It would be a good idea to setup this address to be “reserved” for the RPi.

Once you know what the address is, we will need to SSH to it and complete the rest of the configuration.

I use a program called MobaXTerm to run SSH sessions, but you can also use a program like putty or other SSH client.  I won’t cover configuring those clients to connect as there are plenty of other guides online for that.

Once you can SSH to the RPI address, you will login for the very first time with the following credentials:

username: pi
password: raspberry

The VERY first thing you should do, once you have successfully logged in is to change the password.

Just type “passwd” and hit enter and you will be prompted for the current one (see above) and then to provide a new password.  Make it something you will remember and something that is secure.

Once changed we will be running some other commands to get this going.  If you have never used linux before, Welcome!  It will be important to type things in EXACTLY as they are shown. Linux is case sensitive and has different sytnax than windows command lines.

Let’s make sure it is up-to-date by typing the following and hitting enter:

sudo rpi-update

You should see some messages about updating some things and such.

Once done, we should reboot to finish it all up. Type the following and hit enter:

sudo shutdown -r now

This should disconnect your SSH session. Just wait a bit and try to re-establish your SSH connection.  Once you can, login with the “pi” user and the new password you set.

Now we will begin to get some additional packages installed that you will need for this project.  Type the following and then hit enter:

sudo apt-get install nginx

You will see some things working and will be asked if you want to install this.  Press “Y” and hit enter.

Now let’s get this package

sudo apt-get install apache2-utils

Same deal.. tell it you want to install it.

Now we will need to go edit some files.  There is a built-in text editor called “nano” that we will be using.  It is fairly simple to navigate by using the arrows, delete and backspace keys to delete things.  Your mouse pointer won’t help you out much here, so we will be doing some typing.

sudo nano /etc/nginx/sites-available/default

Using the arrow keys go down to line 8 and add a “#” (this is a comment symbol) like this:

#listen 80 default_server;
#listen [::]:80 default_server;

Now we will REMOVE the “#” on the following line and change “443” to be “8443”:

#listen 443 ssl default_server;

…becomes..

listen 8443 ssl default_server;

You should now look for a line that says:

server_name _;

Go just AFTER this and add some new lines of text.  You can either copy and paste them or just type them.  If typing them, make sure they are exactly like this (don’t forget the semi-colons “;” and the slashes should be “/” (on the same key as the “?”).

 ssl_certificate /etc/ssl/nginx.crt;
 ssl_certificate_key /etc/ssl/nginx.key;

You will now see a block of code that looks like this.  It may not be exactly what you see, but that isn’t important since we will be deleting some of it.

location /  {       
 try_files $uri $uri/ /index.php?q=$uri&$args;    
 }

You can delete everything inside of the curly braces (“{}”) and leave first and last lines from above.

Now make it look like this, but replace [address of DTV] with the local ip address of your DirecTV box. In the end it will look something like this:
proxy_pass http://192.168.1.10:8080;

location / { 
       proxy_pass http://[address of DTV]:8080; 
       auth_basic "Username and Password Required"; 
       auth_basic_user_file /etc/nginx/.htpasswd;       
    }

I know that was probably a LOT, but just review your work again and make sure that it looks like above.  If it doesn’t we will probably find out soon.

Once it looks good, type ctrl-x (Control Key and x) inside of Nano.

You will be asked if you want to save the file, go ahead and answer “Y” and hit then hit Enter.

Alright.  Take a break if you want for now.. We have a bit to go.

Welcome back..

Now we are going to create the user account that the Alexa service will use to authenticate to do its thing.

For the sake of this tutorial I am creating a user named “alexa_skill”.  if you want to use something different, now is the time to put that in.

type the following (and change the user name if you want) and hit Enter. Remember to be careful of slashes and spaces!:

sudo htpasswd -c /etc/nginx/.htpasswd alexa_skill

You will be prompted to enter a password for this account. Don’t use any of your normal passwords you use.  This one will actually be inside the code you upload to Lambda later on.  Make it secure and make it unique (as passwords should always be).  I would not use the special characters quote or doublequote.

In order to communicate over HTTPS, we must create a certificate. Run the following command and hit enter.

sudo mkdir -p /etc/ssl/certs

Now run this one (you may need to scroll to the right to get the whole thing):

sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/ssl/nginx.key -out /etc/ssl/nginx.crt

Once you hit enter on this last one, you will be asked for some “information”. I would just hit ENTER on each one. This will force it to take default values. If you do want to specify some of the info, please don’t put any personally identifiable info there. This information will be accessible by anyone who happens up on this certificate.

Once done we will restart NGINX.

sudo service nginx restart

If you have entered everything correctly, you should see no real response.  If you get errors, then something wasn’t entered correctly. In this case, no news is good news.

Let’s give this a spin by opening up your favorite web browser and entering the URL:

https://[address of your rpi]:8443/info/getLocations

Your browser will probably complain that the site can’t be trusted and such, you should be able to continue anyway (in Chrome)…  This is because we are using a “self-signed certificate” and to be expected.

If successful, you should be prompted for a username and password.  For my example, I would use “alexa_skill” and its password.

If the stars align and all is good, you should get something like this in the browser:

{
 "locations": [{
 "clientAddr": "0",
 "locationName": "LR",
 "tunerBond": true
 }],
 "status": {
 "code": 200,
 "commandResult": 0,
 "msg": "OK.",
 "query": "/info/getLocations"
 }
}

If that’s what you see, take a break and pat yourself on the back.  If not, please go back and review the files we have updated.

Now we have tell your Router about your new Reverse Proxy.

Each router interface config will be different, so consult your manual or the appropriate forums for assistance with this part.

You will want to configure a NAT (network address translation) or Port Forwarding rule that basically will forward all traffic that the router sees hitting port 8443 and send that traffic to the address of your RPi.  On my Router, these settings are buried in the Security settings under Gaming and Single port forwarding.

The important thing is to make sure that you are specifying port 8443 and the address of your RPi.

Once you have THAT configured, we can test this one more time.

now point to the following url, but put your EXTERNAL IP address in.  If you don’t what your external address is, just google “what’s my ip address” and it should tell you.

https://[YourExternal Address]:8443/info/getLocations

Once again you should prompted for your username and password.  If you are, then your router is properly forwarding traffic to your RPi.  If you aren’t, then something isn’t working right and you should review your configuration.

Okay.  If you are successful so far then congratulate yourself.  Lots of little configs and settings and such.

Now we are in the home-stretch and will just be updating our Lambda index file that you downloaded from GitHub.

You should follow this Video for a great tutorial:

 

Follow EVERYTHING you see here with a few exceptions.

In the video,  “B Money” talks about editing your “index” file.  To make this work with secure communications and passwords, you will need to make additional changes to this file.

Change line 1 to be this:

var http = require('https');

Find the line that has “port: 8080,” and change that to be “port: 8443,”

Find the following lines below

method: 'GET' //, //(remove first comment slashes if using the "auth" option below) 
   // auth: 'username:password' // this is used if going through authenticated proxy (this is BASIC AUTH)

and replace them with:

 method: 'GET', auth: 'alexa_skill:password' // this is used if going through authenticated proxy (this is BASIC AUTH)

Make sure you put the proper username and password in that you defined above.  Remember that I used “alexa_skill” as my user name.  This one section may look like this:
‘alexa_skill:this_isaBAD_pw’  (where “this_isaBAD_pw” is my very bad password)

Follow all other instructions that are highlighted in the video.

Good Luck!!!!

UPDATE – Dynamic DNS

Based on some conversations in the project github repo (https://github.com/bklavet/Echo-skill-to-control-Directv/issues/70#issuecomment-357949841)

The topic of having dynamic ip address assignments from your ISP could result in the skill suddenly stopping and forcing you to update the skill with your new API endpoint.

While some routers DO support Dynamic DNS providers like Dyn or NO-IP, not all of them do.  “bklavet” found a good article on adding NO-IP support to the RPi by following this guide: (http://sizious.com/2017/04/30/how-to-properly-install-no-ip-dynamic-update-client-duc-under-raspbian/)

I haven’t actually implement this, but “bklavet” worked through it following the instructions.

The benefit of NO-IP, as a provider, is that they have a free account you can signup for.  You will pick a custom full-qualified Domain Name based on some standard DNS zones.  It’s all very easy to setup and get your account working.

Let me know, in the comments, if you have other enhancements to suggest or questions.

Thanks!

GW

 

 

 

2 thoughts on “Security for your Alexa-DTV

Leave a comment