Friday, September 9, 2016

Configuring Wifi on Ubuntu Server 16.04.x LTS

This is the tale of how I set up the wifi interface on Ubuntu server 16.04 LTS as part of a leaf router with a wifi backbone and an ethernet sub-net.

Finding Device Names in Ubuntu 16.04.x

In this latest LTS release, Ubuntu no longer uses the traditional interface device names like "eth0" or "wlan0" for some reason. I'm sure there is some explanation for this, but it does mean that the new names must be discovered. This information can be found by searching the output of the "dmesg" command for the old names:

     dmesg | grep eth0
    dmesg | grep wlan0
    
In both cases there will be a line that states (in part) for example: ".. renamed from eth0 ..". Those lines will reveal the current names of the devices. Just to keep things interesting, one system I upgraded in-place from Mint 17.3 to Mint 18 (based on Ubuntu 16.04.x) kept the traditional device names. Go figure.

Configuring Network Interfaces, Old School

Since the server distribution does not use NetworkManager and has no GUI, network interfaces must be configured the old-fashioned way: by creating and editing configuration files.

The first thing is to take care of the /etc/network/interfaces file, which defines the network interfaces. My interfaces file looks like this:

  =======================================================================

  # This file describes the network interfaces available on your system
  # and how to activate them. For more information, see interfaces(5).

  source /etc/network/interfaces.d/*

  # The loopback network interface
  auto lo
  iface lo inet loopback

  # Ethernet NIC is the "leaf" sub-net, needs static address -jrl
  auto enp9s0
  iface enp9s0 inet static
  address 10.10.1.1
  netmask 255.255.255.0
  broadcast 10.10.1.255

  # Just define the wifi interface, don't bring it up prematurely -jrl
  # auto wlp12s0
  iface wlp12s0 inet dhcp

  =======================================================================

The ethernet interface (enp9s0 formerly known as eth0) will be my "leaf" subnet and needs a static IP address because it will become the default router address for the sub-net clients, as well as the DHCP server for those clients.

The wifi interface (wlp12s0 formerly known as wlan0) is merely defined here, and not initialized. Initializing this interface requires several additional steps. In this example the wifi NIC will be a DHCP client of the main network, but static assignment is another option. This NIC receives a static dhcp address assignment from the DHCP server on the main network (eventually). This is important, since this router does not implement NAT it's address must be known to the default router on the main network as the gateway to the leaf subnet. Notice in particular that the line "auto wlp12s0" is commented out, this is because otherwise the system boot sequence will "block" for 5 min. and 10 sec. while it tries (and fails) to initialize the wifi interface. The "auto" line doesn't have to be there, I left it commented as a reminder.

The next step is to prepare what is needed to configure and initialize the wifi interface. This will require the generation of a configuration file for the "wpasupplicant" utility that will be used to establish an association between the local wifi NIC and the wifi access point on the main network. The first step is to generate the skeleton of wpasupplicant configuration file. This is done with the "wpa_passphrase" utility. This utility takes two arguments: the SSID of the network you wish to join, and the WPA passphrase that is needed for that network. In this example, the SSID is "CoreNet" and the WPA passphrase is "SuperSecretPassword":

wpa_passphrase CoreNet SuperSecretPassword >/etc/wpa_supplicant/wpa_supplicant.conf

The command line above is performed as root or with sudo. After the file is created, restrict the permissions, you don't want the passphrase (or the generated key) to be world readable. When first generated, the skeleton file looks like this:

network={
ssid="CoreNet"
#psk="SuperSecretPassword"
psk=e098eb13f5467b23b186f013a211f6399aebc6e462758898d71d23e0949cf370
}

I added a couple of directives and took out the clear-text of the key so the final file looks like this:

network={
ssid="CoreNet"
scan_ssid=1
key_mgmt=WPA-PSK
psk=e098eb13f5467b23b186f013a211f6399aebc6e462758898d71d23e0949cf370
}

Once this file is finalized, we are ready to begin initializing the NIC. First step, bring the interface "up"

ifconfig wlp12s0 up

Next we invoke wpasupplicant with the configuration file we generated:

wpa_supplicant -Dwext -i wlp12s0 -c /etc/wpa_supplicant/wpa_supplicant.conf -B

We are almost there. At this point the interface is associated with the access point for "CoreNet", but we have no IP address. We obtain our IP parameters from the DHCP server on the main network through the use of the "dhclient" utility:

dhclient wlp12s0

Now we should be in business.

Once the "interfaces" and "wpa_supplicant.conf" files are properly set up, we can automate the initialization at boot time by placing the needed commands in the /etc/rc.local file, which on my system looks like this:

  =======================================================================

  #!/bin/sh -e
  #
  # rc.local
  #
  # This script is executed at the end of each multiuser runlevel.
  # Make sure that the script will "exit 0" on success or any other
  # value on error.
  #
  # In order to enable or disable this script just change the execution
  # bits.
  #
  # By default this script does nothing.
  #
  # wait until things settle down -jrl
  sleep 10

  # initialize wifi interface the hard way -jrl
  #
  ifconfig wlp12s0 up
  wpa_supplicant -Dwext -i wlp12s0 -c /etc/wpa_supplicant/wpa_supplicant.conf -B
  dhclient wlp12s0


  exit 0

  =======================================================================

There may be slicker ways of bringing up a WPA protected wifi interface on Ubuntu server, but this worked for me.

The most useful documentation I found were the manual pages for "wpa_passphrase", "wpa_supplicant.conf" and "wpa_supplicant". Here are some online links for those pages:

http://linux.die.net/man/8/wpa_passphrase

http://linux.die.net/man/5/wpa_supplicant.conf

http://linux.die.net/man/8/wpa_supplicant



Thursday, August 11, 2016

Secure Video Calling on Linux: Wire

I have used Skype for video calling since before it was bought by Microsoft. At the time it was the most widely used video calling service that had a Linux client. Since that time the Linux client has been neglected: the 32-bit-only Linux client is v4.3.0.37, while the 64-bit Mac client is v7.33.306. The Linux client lacks several key capabilities, such as group video calling. Ironically I like the user interface on Linux better than either the Windows or Mac clients. As I write this Microsoft has announced that they are working on a major upgrade to the Linux client. That client is in Alpha development stage right now and the video calling capability has not yet been added. It looks as if Linux will always be a secondary platform (at best) for any Microsoft development.

So I have been looking into possible alternatives for cross platform video calling. Since I already had a Google account, Google Hangouts is an acceptable alternative and in some ways better than Skype and allows group video calls. Hangouts does not have a native client for desktop systems, it is web based and will run on anything that can run Google Chrome (or other modern browsers). There are native clients for iOS and Android. The wide adoption of Hangouts is probably second only to Skype. Most of the people that I video call already have GMail accounts, so that removes one barrier: no new account ID an password to keep track of.

One aspect of video calling that is important to me is privacy. In this regard Skype is a loser, as demonstrated in this Ars Technica story.

Hangouts is probably better, but I really don't know how far to trust Google. So far the benefits outweigh the risks, but I would prefer a system that is more secure. This led me to investigate Wire.com.

Wire.com was started by some of the founders of the original Skype project, before it was sold ultimately to Microsoft. It's primary goals were to establish secure communications: instant messaging, audio and video calling, and file transfer. Wire is cross-platform, it runs natively on Windows, Mac, iOS, and Android plus it has a web-based client that runs on modern browsers including those on Linux. Strong, open-source, end-to-end encryption is used with all Wire's protocols. You can read all about it in their "Wired Security Whitepaper".

Oh yeah, another important feature of Wire is that their servers are hosted in Switzerland, where the laws favor the protection of privacy. They take pains in their operation to preserve your privacy, spelled out in their "Wire Privacy Whitepaper".

While the Wire web client's navigation is not what I could wish, I was able to get everything to work without too much trouble. One thing that is missing from Wire that both Skype and Hangouts have is a "presence" indicator for your contacts. You can't tell when any of your contacts are actually on-line. I suspect that has something to do with maintaining privacy, but it means that you may have to arrange a time in which you and your contacts will be on-line and ready to receive calls. Or you can just try ringing them in Wire; like what we used to do when the best form of communication was a telephone call. I have yet to try out group calling, but that is something supported with Wire.

So now I have two useful, up-to-date, alternatives to Skype: Google Hangouts and Wire. Since both have web clients, I can even use them on my Chromebook as well as my Linux Mint desktop. Skype has never been available to Chromebook users, though their Linux client, once fully operational, might allow them to incorporate Linux support into their web service, allowing the Linux-based ChromeOS to finally use Skype (fingers crossed, but I'm not holding my breath).

Now to convince my Skype correspondents to use Wire or Hangouts, or both.

Update (12 Oct. 2016)

Wire.com has just released a beta version of a Linux desktop client app. On Mint it is installed from a .deb file and works pretty well. One quirk: it identifies itself as "Wire for Windows", but it is identified also as running on a Linux desktop. The version number is "newer" than the Mac desktop client (v2.11.2661 vs. v2.10.2652). 

Tuesday, February 2, 2016

Dual-Stack OSPF Routing with Quagga

In order to better learn about IPv6 I wanted to set up dual-stack routing on a virtual network. I chose to implement Quagga with OSPFv2 for IPv4 routing and OSPFv3 for IPv6 routing. I did this primarily because the price was right (free) and it could be implemented on a regular Ubuntu server that could also be used for other network support protocols (DHCP, DNS, multicast routing etc.). As usual everything here was implemented using VirutalBox on a Linux Mint host. What follows are examples of how to set up Quagga for dual-stack routing.

I chose OSPF because it was a robust, modern Internal Gateway Protocol (IGP) that was relatively easy to set up. I make no claim that the example presented here is perfect or even optimal, I only claim that I tried to keep it simple and that it works for me. I'm writing this for two reasons: to preserve what I have learned (my memory isn't what it used to be) and because a concrete example would have been helpful while I was learning this, so I thought I would supply one for those learning this stuff themselves.

In order to better follow this exercise, below is a diagram of the virtual network used. Note: the IPv6 prefixes are not my actual prefixes (I'd rather not share those publicly) but dummy addresses utilizing IPv6 "Unique Local IPv6 Unicast Addresses" (RFC 4193).  Such addresses can't actually be routed over the Internet. My real IPv6 addresses route just fine.










The three hosts that are the focus of this discussion:

  • gator.jrl.home is a pfSense dual-stack router with BIND add-on
  • route1.jrl.home is Ubuntu server v14.04.3 with Quagga and DHCP server
  • route66.jrl.home is Ubuntu server v14.04.3 with Quagga and DHCP relay

It's important to know the static IP addresses for these hosts:

Router Addresses


















All addressing and routing on "Net 0" on the diagram are statically assigned (no DHCP or OSPF routing). The pfSense router (gator) had static routes for Nets 1 - 3 added (for both protocols) and in addition new firewall rules added to allow hosts on the new networks to access gator and pass Internet traffic as well as local traffic on Net 0.

After installing "route1" and "route66" from ISO images files and updating them static addresses were assigned to all interfaces and packet forwarding was enabled through /etc/sysctl.conf, setting the following:

  • net.ipv4.conf.all.forwarding=1
  • net.ipv6.conf.all.forwarding=1
This turns your server from a multi-homed host into a router. After this step it's time to install Quagga from the repositories and edit some configuration files.

In the /etc/quagga directory on each router there are 5 text files. For the examples presented here only 4 of them need to be altered or created. You can leave debian.conf untouched it just tells the quagga processes where to run their terminal processes (more on this later).

The zebra.conf file is the one that requires the most information. Here is the sample zebra.conf file for route1

zebra.conf for route1.jrl.home


The IPv4 information should be familiar to anyone setting up Linux on a network. Some of the IPv6 addresses used here are all "Link-local" addresses for the interface in question, which can be discovered by using "ifconfig". IPv6 link-local addresses begin with "fe80". Routing information is passed from router to router using the link-local addresses in OSPFv3.

Near the bottom of each interface definition there are 4 IPv6-related directives that could use some explanation.
  • no ipv6 nd suppress-ra - means do not suppress IPv6 router advertisements
  • ipv6 nd managed-config-flag - means that DHCPv6 is in use for addressing
  • ipv6 nd other-config-flag - means that DHCPv6 info other than addresses are in use
  • ipv6 nd prefix fdf8:fade:deaf:5150::/64 - means advertise this prefix

Unlike DHCPv4, DHCPv6 does not "handle" routing information. That function is left to the router advertisement daemon that is part of an IPv6 router (in this case quagga). The IPv6 protocol has a powerful Stateless Autoconfiguration (SLAAC)  capability that does not rely on DHCP for addressing. Address assignment and routing information are configured automatically. What does not get assigned automatically are: addresses of the DNS servers, the host's domain name, and alternate search domains etc. As set up in these examples, each workstation will end up with one IPv4 address and four IPv6 addresses:
  • Link-local address derived from the hardware address and assigned by the kernel
  • SLAAC address also derived from the hardware address and the prefix from the router
  • A privacy address that is dynamic, random and combined with the prefix from the router
  • A managed address supplied by the DHCPv6 service
Depending on your operating system any of the three "global" (non link-local)  IPv6 addresses can be used by applications to contact remote systems. On my systems the default is to utilize the "privacy address" when contacting remote systems. Since that address is dynamic and random (on every reboot for instance) it makes it harder to track you on the Internet. Any of the 3 global addresses can be used by other systems to contact your workstation (i.e. ping6).

DHCPv6 is not required for automatic IPv6 address assignment, as long as the host being configured "knows" it's own domain and the addresses of it's DNS servers (usually by static assignment). It is also possible to distribute only that information (domain name and DNS server addresses) using DHCPv6 and leave the automatic addressing to SLAAC with information supplied by the router advertisements. The "ipv6 nd other-config-flag" directive is there for exactly this sort of setup.

To continue with the configuration of route1, let's look at the /etc/quagga/ospfd.conf file:

ospfd.conf for route1.jrl.home
This is pretty simple it just places the interfaces (represented by their IPv4 addresses) into the same OSPF routing area, then redistributes any learned routes and any statically configured routes into that area. This is all that is needed to configure the OSPFv2 daemon (IPv4 routing daemon) in quagga.

Now let's look at the OSPFv3 (OSPF for IPv6) routing configuration for route1 contained in the /etc/quagga/ospf6d.conf file:

ospf6d.conf for route1.jrl.home
This accomplishes the same thing for IPv6 as ospfd.conf did for IPv4. This time the interfaces are designated explicitly by their kernel names (instead of indirectly as in ospfd.conf). My guess is that the OSPFv3 was developed later and perhaps by another developer who "did it his way". I find this way "cleaner".

The same configuration files need to be created for route66 and they look very much the same as the OSPF configuration for route1:

ospfd.conf and ospf6d.conf for route66.jrl.home


The zebra.conf file is unique for route66, since it reflects the actual hardware in use, with unique hardware and IP addresses:

zebra.conf file for route66.conf

Finally there are two files that are the same on both route1 and route66 the /etc/quagga/daemons and /etc/quagga/debian.conf files:

daemons and debian.conf file for both route1 and route66
















The "daemons" file determines which daemons within the quagga suite should actually run and the debian.conf file describes how and where the various  protocol daemons should  listen for terminal connections. Each of the protocols in use (ospfd and ospf6d  as well as zebra in our case) has a command-line interface accessible via telnet. It has some similarities to the command interface on cisco routers. Each of the three daemons runs on a different port on the localhost interface of each router:
  • telnet localhost 2601 - will get you to the command interface of the zebra daemon
  • telnet localhost 2604 - will get you to the command interface of the ospfv2 daemon
  • telnet localhost 2606 - will get you to the command interface of the ospfv3 daemon
Those "enable password" statements at the top of the configuation files (zebra.conf, ospfd.conf and ospf6d.conf) set the passwords you will have to supply to actually get to those command interfaces.

Once logged in, typing a question mark will get some help with the commands. Once you have (re-)started the quagga daemons on both routers, you should be in business.

There are resources on the web for learning Quagga. One site is here: http://www.nongnu.org/quagga/docs.html