Monday, December 12, 2016

Ubiquiti Networks UniFi Controller in an Ubuntu LXD Machine Container



I've been one of DD-WRT's biggest fans, for more than 10 years.  I've always flashed my router with custom firmware, fine-tuned my wired and wireless networks, and locked down a VPN back home.  I've genuinely always loved tinkering with network gear.

A couple of weeks ago, I decided to re-deploy my home network.  I've been hearing about Ubiquiti Networks from my colleagues at Canonical, where we use Ubiquiti gear for our many and varied company events.  Moreover, it seems a number of us have taken to running the same kits in our home offices.

So I ordered a Ubiquiti UniFi Security Gateway (USG) and a pair of Dual Radio PRO Wireless Access Points, and I couldn't be more pleased with the end result!  Screaming fast wireless access, beautiful command line and web interfaces, and a fantastic product.

There's something quite unique about the UniFi Controller -- the server that "controls" your router, gateway, and access points.  Rather than being built into the USG itself, you run the server somewhere else.

Sure you can buy their hardware appliance (which I'm sure is nice).  But you can just as easily run it on an Ubuntu machine yourself.  That machine could be a physical machine on your network, a virtual machine locally or in the cloud, or it could be an LXD machine container.

I opted for the latter.  I'm happily running the UniFi Controller in a LXD machine container, and it's easy for you to setup, too.

I'm running Ubuntu 16.04 LTS 64-bit on an Intel NUC somewhere in my house.  It happens to be running Ubuntu Desktop, as it's attached to one of the TVs in my house, as a media playing device.  In it's spare time, it's a server I use for LXD, Docker, and other development purposes.

I've configured the network on the machine to "bridge" LXD to my USG router, which happens to be running DHCP and DNS.  I'm going to move that to a MAAS server, but that's a post for another day.

Here's /etc/network/interfaces on that machine:

kirkland@masterbr:~⟫ cat /etc/network/interfaces
# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet manual

auto br0
iface br0 inet dhcp
        bridge_ports eth0
        bridge_stp off
        bridge_fd 0
        bridge_maxwait 0

So eth0 is bridged, to br0.  ifconfig looks like this:

kirkland@masterbr:~⟫ ifconfig eth0
eth0      Link encap:Ethernet  HWaddr ec:a8:6b:fb:a1:f2  
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1111309 errors:0 dropped:8294 overruns:0 frame:0
          TX packets:539270 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:850773437 (850.7 MB)  TX bytes:85706158 (85.7 MB)
          Interrupt:20 Memory:f7c00000-f7c20000 

kirkland@masterbr:~⟫ ifconfig br0
br0       Link encap:Ethernet  HWaddr ec:a8:6b:fb:a1:f2  
          inet addr:10.0.0.8  Bcast:10.0.0.255  Mask:255.255.255.0
          inet6 addr: fe80::eea8:6bff:fefb:a1f2/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:435576 errors:0 dropped:0 overruns:0 frame:0
          TX packets:182097 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:325950072 (325.9 MB)  TX bytes:35439980 (35.4 MB)

And I've configured LXD to have its default profile instances draw their IP address from br0, rather than from the default, internally NAT'd dnsmasq lxdbr0.

kirkland@masterbr:/etc⟫ lxc profile show default
name: default
config: {}
description: Default LXD profile
devices:
  eth0:
    name: eth0
    nictype: bridged
    parent: br0
    type: nic

Now, let's launch a LXD container running Ubuntu 16.04 LTS.

kirkland@masterbr:~⟫ lxc launch ubuntu:xenial unifi-controller
Creating unifi-controller
Starting unifi-controller
kirkland@masterbr:~⟫ lxc list
+------------------+---------+-------------------+------+------------+-----------+
|       NAME       |  STATE  |       IPV4        | IPV6 |    TYPE    | SNAPSHOTS |
+------------------+---------+-------------------+------+------------+-----------+
| unifi-controller | RUNNING | 10.0.0.183 (eth0) |      | PERSISTENT | 0         |
+------------------+---------+-------------------+------+------------+-----------+

It's important to notice that this container drew an IP address on my 10.0.0.0/24 LAN.  It will need this, to detect, federate, and manage the Ubiquiti hardware.

Now, let's exec into it, and import our SSH keys, so that we can SSH into it later.

kirkland@masterbr:~⟫ lxc exec unifi-controller bash
root@unifi-controller:~# ssh-import-id kirkland
2016-12-09 21:56:36,558 INFO Authorized key ['4096', 'd3:dd:e4:72:25:18:f3:ea:93:10:1a:5b:9f:bc:ef:5e', 'kirkland@x220', '(RSA)']
2016-12-09 21:56:36,568 INFO Authorized key ['2048', '69:57:f9:b6:11:73:48:ae:11:10:b5:18:26:7c:15:9d', 'kirkland@mac', '(RSA)']
2016-12-09 21:56:36,569 INFO [2] SSH keys [Authorized]
root@unifi-controller:~# exit
exit
kirkland@masterbr:~⟫ ssh root@10.0.0.183
The authenticity of host '10.0.0.183 (10.0.0.183)' can't be established.
ECDSA key fingerprint is SHA256:we0zAxifd0dcnAE2tVE53NFbQCop61f+MmHGsyGj0Xg.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '10.0.0.183' (ECDSA) to the list of known hosts.
root@unifi-controller:~#

Now, let's add the Unifi repository and install the deb and all its dependencies.  It's a big pile of Java and MongoDB, which I'm happy to keep nicely "contained" in this LXD instance!

root@unifi-controller:~# echo deb http://www.ubnt.com/downloads/unifi/debian stable ubiquiti
deb http://www.ubnt.com/downloads/unifi/debian stable ubiquiti
root@unifi-controller:~# echo "deb http://www.ubnt.com/downloads/unifi/debian stable ubiquiti" | sudo tee -a /etc/apt/sources.list
deb http://www.ubnt.com/downloads/unifi/debian stable ubiquiti
root@unifi-controller:~# apt-key adv --keyserver keyserver.ubuntu.com --recv C0A52C50
Executing: gpg --ignore-time-conflict --no-options --no-default-keyring --homedir /tmp/tmp.hhgdd0ssJQ --no-auto-check-trustdb --trust-model always --keyring /etc/apt/trusted.gpg --primary-keyring /etc/apt/trusted.gpg --keyserver keyserver.ubuntu.com --recv C0A52C50
gpg: requesting key C0A52C50 from hkp server keyserver.ubuntu.com
gpg: key C0A52C50: public key "UniFi Developers " imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
root@unifi-controller:~# apt update >/dev/null 2>&1
root@unifi-controller:~# apt install unifi
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following package was automatically installed and is no longer required:
  os-prober
Use 'apt-get autoremove' to remove it.
The following extra packages will be installed:
  binutils ca-certificates-java default-jre-headless fontconfig-config
  fonts-dejavu-core java-common jsvc libasyncns0 libavahi-client3
  libavahi-common-data libavahi-common3 libboost-filesystem1.54.0
  libboost-program-options1.54.0 libboost-system1.54.0 libboost-thread1.54.0
  libcommons-daemon-java libcups2 libflac8 libfontconfig1 libgoogle-perftools4
  libjpeg-turbo8 libjpeg8 liblcms2-2 libnspr4 libnss3 libnss3-nssdb libogg0
  libpcrecpp0 libpcsclite1 libpulse0 libsctp1 libsnappy1 libsndfile1
  libtcmalloc-minimal4 libunwind8 libv8-3.14.5 libvorbis0a libvorbisenc2
  lksctp-tools mongodb-clients mongodb-server openjdk-7-jre-headless tzdata
  tzdata-java
Suggested packages:
  binutils-doc default-jre equivs java-virtual-machine cups-common
  liblcms2-utils pcscd pulseaudio icedtea-7-jre-jamvm libnss-mdns
  sun-java6-fonts fonts-dejavu-extra fonts-ipafont-gothic fonts-ipafont-mincho
  ttf-wqy-microhei ttf-wqy-zenhei ttf-indic-fonts-core ttf-telugu-fonts
  ttf-oriya-fonts ttf-kannada-fonts ttf-bengali-fonts
The following NEW packages will be installed:
  binutils ca-certificates-java default-jre-headless fontconfig-config
  fonts-dejavu-core java-common jsvc libasyncns0 libavahi-client3
  libavahi-common-data libavahi-common3 libboost-filesystem1.54.0
  libboost-program-options1.54.0 libboost-system1.54.0 libboost-thread1.54.0
  libcommons-daemon-java libcups2 libflac8 libfontconfig1 libgoogle-perftools4
  libjpeg-turbo8 libjpeg8 liblcms2-2 libnspr4 libnss3 libnss3-nssdb libogg0
  libpcrecpp0 libpcsclite1 libpulse0 libsctp1 libsnappy1 libsndfile1
  libtcmalloc-minimal4 libunwind8 libv8-3.14.5 libvorbis0a libvorbisenc2
  lksctp-tools mongodb-clients mongodb-server openjdk-7-jre-headless
  tzdata-java unifi
The following packages will be upgraded:
  tzdata
1 upgraded, 44 newly installed, 0 to remove and 10 not upgraded.
Need to get 133 MB of archives.
After this operation, 287 MB of additional disk space will be used.
Do you want to continue? [Y/n] y
...
done.

Finally, we point a web browser at this server, http://10.0.0.183:8443/ in my case, and run through the UniFi setup there.

Enjoy!

:-Dustin

Thursday, December 8, 2016

Ubuntu 16.04 LTS Security: A Comprehensive Overview


From Linux kernel livepatches to encryption to ASLR to compiler optimizations and configuration hardening, we strive to ensure that Ubuntu 16.04 LTS is the most secure Linux distribution out of the box.

These slides try to briefly explain:

  • what we do to secure Ubuntu
  • how the underlying technology works
  • when the features took effect in Ubuntu

I hope you find this slide deck informative and useful!  The information herein is largely collected from the Ubuntu Security Features wiki page, where you can always find up to date information.



Cheers,
Dustin

Wednesday, December 7, 2016

A Touch of Class at Sir Ludovic, Bucharest, Romania

A few weeks ago, I traveled to Bucharest, Romania for a busy week of work, planning the Ubuntu 17.04 (Zesty) cycle.

I did have a Saturday and Sunday to myself, which I spent mostly walking around the beautiful, old city. After visiting the Romanian Athenaeum, I quite randomly stumbled into one truly unique experience. I passed a window shop for "Sir Ludovic Master Suit Maker" which somehow caught my eye.



I travel quite a bit on business, and you'll typically find me wearing a casual sports coat, a button up shirt, nice jeans, cowboy boots, and sometimes cuff links. But occasionally, I feel a little under-dressed, especially in New York City, where a dashing suit still rules the room.

Frankly, everything I know about style and fashion I learned from Derek Zoolander. Just kidding. Mostly.

Anyway, I owned two suits. One that I bought in 2004, for that post-college streak of weddings, and a seersucker suit (which is dandy in New Orleans and Austin, but a bit irreverent for serious client meetings on Wall Street).

So I stepped into Sir Ludovic, merely as a curiosity, and walked out with the most rewarding experience of my week in Romania. Augustin Ladar, the master tailor and proprietor of the shop, greeted me at the door. We then spent the better part of 3 hours, selecting every detail, from the fabrics, to the buttons, to the stylistic differences in the cut and the fit.




Better yet, I absorbed a wealth of knowledge on style and fashion: when to wear blue and when to wear grey, why some people wear pin stripes and others wear checks, authoritative versus friendly style, European versus American versus Asian cuts, what the heck herringbone is, how to tell if the other guy is also wearing hand tailored attire, and so on...

Augustin measured me for two custom tailored suits and two bespoke shirts, on a Saturday. I picked them up 6 days later on a Friday afternoon (paying a rush service fee).

Wow. Simply, wow. Splendid Italian wool fabric, superb buttons, eye-catching color shifting inner linings, and an impeccably precise fit.









I'm headed to New York for my third trip since, and I've never felt more comfortable and confident in these graceful, classy suits. A belated thanks to Augustin. Fabulous work!



Cheers,
Dustin