Wednesday, December 23, 2015

Installing and configuring Raspbian Jessie on a Raspberry Pi B+

I blogged before about configuring a Raspberry Pi B+ with Raspbian Wheezy. Here are some notes I took today while going through the whole process again, but this time with the latest Raspbian version, Jessie, from 2015-11-21. Many steps are the same, but I will add instructions for configuring a wireless connection.

1) Bought micro SD card. Note: DO NOT get a regular SD card for the B+ because it will not fit in the SD card slot. You need a micro SD card.

2) Inserted the SD card via an SD USB adaptor in my MacBook Pro.

3) Went to the command line and ran df to see which volume the SD card was mounted as. In my case, it was /dev/disk2s1.

4) Unmounted the SD card from my Mac. I initially tried 'sudo umount /dev/disk2s1' but the system told me to use 'diskutil unmount', so the command that worked for me was:

$ diskutil unmount /dev/disk2s1

5) Downloaded 2015-11-21-raspbian-jessie.zip from  https://downloads.raspberrypi.org/raspbian/images. Unzipped it to obtain the image file 2015-11-21-raspbian-jessie.img

6) Used dd to copy the image from my Mac to the SD card. Thanks to an anonymous commenter on my previous blog post, I specified the target of the dd command as the raw device /dev/rdisk2. Note: DO NOT specify the target as /dev/disk2s1 or /dev/rdisk2s1. Either /dev/disk2 or /dev/rdisk2 will work, but copying to the raw device is faster. Here is the dd command I used:

$ sudo dd if=2015-11-21-raspbian-jessie.img of=/dev/rdisk2 bs=1m
3752+0 records in
3752+0 records out
3934257152 bytes transferred in 233.218961 secs (16869371 bytes/sec)

7) I unmounted the SD card from my Mac one more time:

$ diskutil unmount /dev/disk2s1

8) I inserted the SD card into my Raspberry Pi. I also inserted a USB WiFi adapter (I used the Wi-Pi 802.11n adapter). My Pi was also connected to a USB keyboard, to a USB mouse and to a monitor via HDMI. 

9) I powered up the Pi. It went through the Raspbian Jessie boot process uneventfully, and it brought up the X Windows GUI interface (which is the default in Jessie, as opposed to the console in Wheezy). At this point, I configured the Pi to boot back into console mode by going to Menu -> Preferences -> Raspberry Pi Configuration and changing the Boot option from "To Desktop" to "To CLI". While in the configuration dialog, I also changed the default password for user pi, and unchecked the autologin option.

10) I rebooted the Pi and this time it booted up in console mode and stopped at the login prompt. I logged in as user pi.

11) I spent the next 30 minutes googling around to find out how to make the wireless interface work. It's always been a chore for me to get wlan to work on a Pi, hence the following instructions (based on this really good blog post).

12) Edit /etc/network/interfaces:

(i)  change "auto l0" to "auto wlan0"
(ii) change "iface wlan0 inet manual" to "iface wlan0 inet dhcp"

13) Edit /etc/wpa_supplicant/wpa_supplicant.conf and add this at the end:

network={
  ssid="your_ssid"
  psk="your_ssid_password"
}

14) Rebooted the Pi and ran ifconfig. At this point I could see wlan0 configured properly with an IP address.

Hope these instructions work for you. Merry Christmas!

Monday, December 07, 2015

Protecting your site for free with Let's Encrypt SSL certificates and acmetool

The buzz level around Let's Encrypt has been more elevated lately, due to their opening up their service as a public beta. If you don't know what Let's Encrypt is, it's a Certificate Authority which provides SSL certificates free of charge. The twist is that they implement a protocol called ACME ("Automated Certificate Management Environment") for automating the management of domain-validation certificates, based on a simple JSON-over-HTTPS interface. Read more technical details about Let's Encrypt here.

The certificates from Let's Encrypt have a short life of 90 days, and this is done on purpose so that they encourage web site administrators to renew them programatically and automatically. In what follows, I'll walk you through how to obtain and install Let's Encrypt certificates for nginx on Ubuntu. I will use a tool called acmetool, and not the official Let's Encrypt client tools, because acmetool generates standalone SSL keys and certs and doesn't try to reconfigure a given web server automatically in order to use them (like the letsencrypt client tools do). I like this separation of concerns. Plus acmetool is written in Go, so you just deploy it as a binary and you're off to the races.

1) Configure nginx to serve your domain name

I will assume you want to protect www.mydomain.com with SSL certificates from Let's Encrypt. The very first step, which I assume you have already taken, is to configure nginx to serve www.mydomain.com on port 80. I also assume the document root is /var/www/mydomain.

2) Install acmetool

$ sudo apt-get install libcap-dev
$ git clone https://github.com/hlandau/acme 
$ cd acme
$ make && sudo make install

3) Run "acmetool quickstart" to configure ACME

The ACME protocol requires a verification of your ownership of mydomain.com. There are multiple ways to prove that ownership and the one I chose below was to let the ACME agent (in this case acmetool) to drop a file under the nginx document root. As part of the verification, the ACME agent will also generate a keypair under the covers, and sign a nonce sent from the ACME server with the private key, in order to prove possession of the keypair.
# acmetool quickstart

------------------------- Select ACME Server -----------------------
Please choose an ACME server from which to request certificates. Your principal choices are the Let's Encrypt Live Server, and the Let's Encrypt Staging Server.

You can use the Let's Encrypt Live Server to get real certificates.

The Let's Encrypt Staging Server does not issue publically trusted certificates. It is useful for development purposes, as it has far higher rate limits than the live server.

  1) Let's Encrypt Live Server - I want live certificates
  2) Let's Encrypt Staging Server - I want test certificates
  3) Enter an ACME server URL

I chose option 1 (Let's Encrypt Live Server).

----------------- Select Challenge Conveyance Method ---------------
acmetool needs to be able to convey challenge responses to the ACME server in order to prove its control of the domains for which you issue certificates. These authorizations expire rapidly, as do ACME-issued certificates (Let's Encrypt certificates have a 90 day lifetime), thus it is essential that the completion of these challenges is a) automated and b) functioning properly. There are several options by which challenges can be facilitated:

WEBROOT: The webroot option installs challenge files to a given directory. You must configure your web server so that the files will be available at <http://[HOST]/.well-known/acme-challenge/>. For example, if your webroot is "/var/www", specifying a webroot of "/var/www/.well-known/acme-challenge" is likely to work well. The directory will be created automatically if it does not already exist.

PROXY: The proxy option requires you to configure your web server to proxy requests for paths under /.well-known/acme-challenge/ to a special web server running on port 402, which will serve challenges appropriately.

REDIRECTOR: The redirector option runs a special web server daemon on port 80. This means that you cannot run your own web server on port 80. The redirector redirects all HTTP requests to the equivalent HTTPS URL, so this is useful if you want to enforce use of HTTPS. You will need to configure your web server to not listen on port 80, and you will need to configure your system to run "acmetool redirector" as a daemon. If your system uses systemd, an appropriate unit file can automatically be installed.

LISTEN: Directly listen on port 80 or 443, whichever is available, in order to complete challenges. This is useful only for development purposes.

  1) WEBROOT - Place challenges in a directory
  2) PROXY - I'll proxy challenge requests to an HTTP server
  3) REDIRECTOR - I want to use acmetool's redirect-to-HTTPS functionality
  4) LISTEN - Listen on port 80 or 443 (only useful for development purposes)

I chose option 1 (WEBROOT).

------------------------- Enter Webroot Path -----------------------
Please enter the path at which challenges should be stored.

If your webroot path is /var/www, you would enter /var/www/.well-known/acme-challenge here.
The directory will be created if it does not exist.

Webroot paths vary by OS; please consult your web server configuration.

I indicated /var/www/mydomain/.well-known/acme-challenge as the directory where the challenge will be stored.

------------------------- Quickstart Complete ----------------------
The quickstart process is complete.

Ensure your chosen challenge conveyance method is configured properly before attempting to request certificates. You can find more information about how to configure your system for each method in the acmetool documentation: https://github.com/hlandau/acme.t/blob/master/doc/WSCONFIG.md

To request a certificate, run:

$ sudo acmetool want example.com www.example.com

If the certificate is successfully obtained, it will be placed in /var/lib/acme/live/example.com/{cert,chain,fullchain,privkey}.

Press Return to continue.

4) Obtain the Let's Encrypt SSL key and certificates for www.mydomain.com

As the quickstart output indicates above, we need to run:

# acmetool want www.mydomain.com

This should run with no errors and drop the following files in /var/lib/acme/live/www.mydomain.com: cert, chain, fullchain, privkey and url.

5) Configure nginx to use the Let's Encrypt SSL key and certificate chain

I found a good resource for specifying secure (as of Dec. 2015) SSL configurations for a variety of software, including nginx: cipherli.st.

Here is the nginx configuration pertaining to SSL that I used, pointing to the SSL key and certificate chain retrieved by acmetool from Let's Encrypt:

        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;

        ssl_certificate     /var/lib/acme/live/www.mydomain.com/fullchain;
        ssl_certificate_key /var/lib/acme/live/www.mydomain.com/privkey;

        ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_session_cache shared:SSL:10m;
        add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
        add_header X-Frame-Options DENY;
        add_header X-Content-Type-Options nosniff;
        ssl_session_tickets off; # Requires nginx >= 1.5.9
        ssl_stapling on; # Requires nginx >= 1.3.7
        ssl_stapling_verify on; # Requires nginx => 1.3.7

At this point, if you hit www.mydomain.com over SSL, you should be able to inspect the SSL certificate and see that it's considered valid by your browser (I tested it in Chrome, Firefox and Safari). The Issuer Name has Organization Name "Let's Encrypt" and Common Name "Let's Encrypt Authority X1".

6) Configure cron job for SSL certificate renewal

Let's Encrypt certificates expire in 90 days after the issue date, so you need to renew them more often than you are used to with regular SSL certificates. I added this line to my crontab on the server that handles www.mydomain.com:

# m h  dom mon dow   command
0 0 1 * * /usr/local/bin/acmetool reconcile --batch; service nginx restart

This runs the acmetool "reconcile" command in batch mode (with no input required from the user) at midnight on the 1st day of every month, then restarts nginx just in case the certificate has changed. If the Let's Encrypt SSL certificate is 30 days away from expiring, acmetool reconcile will renew it.

I think Let's Encrypt is a great service, and you should start using it if you're not already!



Modifying EC2 security groups via AWS Lambda functions

One task that comes up again and again is adding, removing or updating source CIDR blocks in various security groups in an EC2 infrastructur...