I arrived in Christchurch, New Zealand to receive my cold weather gear and training and was quickly ferried to McMurdo in a C-17 cargo plane which landed on an ice runway a few miles from the main base.

The station is very impressive, it houses over 1000 contractors and scientists in the peak of the summer, who support science across the continent. Its very comfortable here, with modern facilities, hot showers, and great food.

Everyone I have met has been amazing, interesting people from all over the US with different skill sets and backgrounds. Many of them have been working in Antarctica for many seasons.

The environment here is beautiful, the trails on Ross Island offer breathtaking views of the natural beauty of the environment. It is hard to capture in photographs, but I’ve included a few photos from my first few days here.

There is still so much to see and explore, and I’m truly grateful for this amazing experience!

Overview

Managing networking equipment can be difficult. Many organizations have hundreds or even thousands of routers, switches, and firewalls deployed, which can be quite a hassle to manage.

In the past network engineers programmed devices one by one – maybe using manually curated templates to create some level of consistency. But with this model, mistakes are almost inevitable, causing some devices to have slightly different configurations than others.

Modern organizations use configuration management and automation tools such as Ansible, Puppet, and Chef for centralizing their management of their Linux systems infrastructure – isn’t it time these technologies are applied to these organization’s underlying network infrastructure?

Ansible and a Juniper provided Python library, PyEZ are one possible method of bringing this type of automation to the networking world.

Ansible can be used to create Juniper configuration files via Jinja2 templates. Jinja2 is a templating language, which allows the user to create templates which can be populated dynamically with variables defined on a host or group basis.

Using templates, you can ensure all of your equipment has the exact same configuration. This can help reduce downtime due to incorrectly configured equipment, and allows you to know the state of all of your equipment.

These templates are written just like normal Junos code, but with the addition of logic statements (for, while, if, etc) and variables.

Here is a simple example of Jinja2 code, which replaces the system login banner configuration with another that includes the variable {{hostname}}.

Once your templates have been populated, Ansible can call the Juniper PyEZ Library to push these configuration files via NETCONF, a protocol used to “install, manipulate, and delete the configuration of network devices.”

Essentially NETCONF allows a user to program a network device without creating a interactive ssh session.

One of my favorite things about Junos is its “load replace” command – which allows the user to replace parts of the configuration and allowing idempotence, meaning no matter how many times we “load replace” we always end up with the same configuration.

Using Ansible and PyEZ, networking equipment configurations can be automatically generated and deployed centrally for ease of management and ensure an entirely consistent environment!

Getting Started

Great! So how should we get started with Ansible and PyEZ? I would begin by reading the excellent Juniper documentation here.

I’ve created a test environment which you can clone to try it out on my github account here. Keep reading if you’d like to test it out!

First we need to create a Python virtual environment with the following command.

Clone the git repository here into the ~/venv folder, which will pull down my test environment.

Once you have your virtual environment set up, we’ll need to activate it with the following command. You should see the name of the virtual environment appear in front of your bash prompt once you have activated it.

source ~/venv/ansible/bin/activate

Next we need to install the dependencies, using the Python package manager, pip.

pip install -r ~/venv/ansible_junos/requirements.txt

Once we have the dependencies, we can run the actual Ansible playbook.

The example below is a simple playbook with two tasks.

The first task creates folders to store the generated configurations, and then calls a role (a sort of sub playbook) which generates the configuration from the Jinja2 template we saw above.

The second task takes the compiled Jinja2 code, and uses the PyEZ library to actually load the configuration on devices defined in the hostfile via NETCONF.

To compile the Jinja2 code and deploy it to the device, we use the “deploy” line of the Makefile like this:

make deploy

The deploy line first calls “clean” which removes all diffs, logs, and compiled configs. Then it calls ansible-playbook to run the deploy.yml playbook shown above, specifying the inventory file and the username to use when logging into the devices.

You’ll need to modify the hostfile with the address of your device, and enable netconf on the device as well before you try this at home.

We are running a provider level MPLS network on Juniper gear at my current organization, so to get a better understanding of the ins and outs of MPLS I created a small lab to play with.

I didn’t have any spare MX series routers, so instead I used three physical SRX 240s configured to be packet-based to simulate a router.

The lab design has two Provider Edge routers (R1 and R3) with two customer VRFs each, and one Core router (R2) to illustrate a BGP free core network.

I used OSPF on the 192.168.x.x networks to learn the 172.16.0.x loopback addresses for MP-BGP. LDP is used on the 192.168.x.x interfaces for label distribution. The customer ranges are in the 10.x.x.x address space.

I very creatively used Route Distinguisher 1 and 2 for customers 1 and 2 respectively.

I’ve been working extensively with Aruba Networks Mobility Controllers at my current job and I’ve put together some quick documentation to go over the basics of the CLI configuration.

While some parts of the Aruba configuration are easily managed from the GUI, I usually find it much easier to work with the Cisco-like CLI.

Parts of the Configuration

The Top of the Hierarchy – AP Groups

AP groups are the configuration that is ultimately assigned to APs. You can see this as the “root” of the configuration, as this section ultimately references many other sections of the configuration.

AP Groups define which SSIDs are broadcast, which channels are used, traffic shaping, HA information, and more. All subsequent configuration is referenced from AP Groups.

Here we see two virtual-aps (SSID Configuration) to broadcast, the radio-profiles (Radio Rates), ap-system-profiles (HA info), traffic-mgmt-profiles (QOS), and the regulatory-domain-profile (which wireless channels can be used).

Virtual AP Configuration Examples

Virtual AP Example 1: psktest (Basic WPA2 PSK):

This SSID is a simple WPA2 PSK network, where all users get assigned to the same vlan.

Virtual-AP Configuration

The Virtual-AP contains the configuration for an SSID.

Here we set the aaa-profile (which defines which ACLs get applied), the ssid-profile (ssid name & psk), and vlan assignment.

The broadcast-filter all option drops all multicast and broadcast traffic in the air. Band-steering tries to force clients onto the preferred 5 GHz band, but allows them to connect to 2.4 GHz if unable.

In the 802.1x authentication process, a RADIUS server is queried and upon successful authentication returns a variable which is used to place users in the correct user-role. In this way you can have different users assigned to different VLANs.

Virtual-AP Configuration

Here we place users in a NULL vlan (666) during the 802.1x authentication process, where they are essentially black holed until authentication completes.

Unlike our last config, this SSID is only broadcast on the “a band” (5 GHz).

First plug in your USB drive and create one big Linux partition. I used cfdisk for this; just delete the existing partition (/dev/sda1 on my router) and create a new primary partition. By default it selects the right partition type (Linux).

Next you need to create a file system on the USB drive. mkfs.ext4 will create an ext4 file system on the drive. I mounted the new file system under /mnt.

mkfs.ext4 -F /dev/sda1
mount /dev/sda1 /mnt

Next lets make sure the drive is mounted automatically on boot. We’ll need to make a /etc/config/fstab file for this, and then enable the fstab process on boot. I also made the directories Transmission will use in /mnt.

Once we’ve got the drive set up we can start configuring Transmission. We’ll need to create a Transmission config file which downloads torrents to our USB drive and we’ll need to configure Transmission to start automatically on boot.

After you’ve set up Transmission you can access it at 192.168.1.1:9091 and start downloading!

Most routers have very limited CPU and Memory resources. I saw not-so-stellar performance when downloading using OpenWRT, but seeding performance was pretty good – I was able to saturate my upload link.

I think this would be a great setup if you’d like to seed files for a long time, or if you’d like to download overnight while your main computer is off to save some electricity. Plus its really cool running BitTorrent directly on your router!

I created a script to set up an OpenWRT router with Transmission, hosted on my github account. It does everything aside from partition the USB drive for you, which you can do with cfdisk. Feel free to check out the script here.

The Buffalo router has an official DD-WRT build for it which ostensibly supports IPv6, and the TP-Link Official documentation also claims IPv6 support although neither worked for me, even with firmware updates.

I’ve loved using DD-WRT in the past, but its countless versions, or “builds” are extremely confusing. This article tries to somewhat clarify their release system. For starters, you have to search their outdated database for which build to use on each router, but look around in the forums and most people agree that these recommendations are typically outdated or wrong. Unlike OpenWRT, there are no “stable releases” so which version to use can be very confusing.

After doing some digging I decided to give OpenWRT a try. OpenWRT is a Linux based firewall distribution, which supports a large quantity of commercial home routers. It’s a full baked Linux distro – offering Web Management Interface, A simple configuration system, and is extremely versatile due to the large amount of packages available via its package manager, opkg. Best of all, it supported IPv6 right out of the box!

I installed the current stable release, Chaos Calmer 15.05, on both routers. The install was easy – The TP-Link was updated directly from the official firmware and I updated my Buffalo from DD-WRT from the command line.

The default LuCi Web interface is simple but intuitive. All the typical configuration options exist, such as port forwarding, static DHCP reservations, and wifi configuration (Hint: wifi is off by default).

Many more settings can be configured via simple configuration files, just enable the ssh server and fire up your editor of choice to make changes to the configuration files under /etc/config.

The real beauty was how easy it was to add functionality in OpenWRT – I wanted to set up a dynamic DNS agent and enable some statistics collection. No problem – just install a package via opkg and you’ll be set up in minutes.