Configure simple DNS server on RHEL 6

Sometimes when setting up hardware for a customer, it makes things a lot easier if I can simulate their network in our lab.  This allows me to deploy the solution plug and play without having to re-ip a bunch of stuff or wait until I’m on their network to do most of the install.  A couple problems I’ve come across are access to the internet for patches/updates and DNS.

 

I’ve generally used an old netgear or linksys router to front the customer’s internal network inside my lab environment and just connect it to the back of our cable modem.  This solves the first problem- internet access.  The other problem is a bit more involved, since you have to have a DNS server on that network (preferrably on the same IP address as in the real network when it’s deployed) I’ve taken to using Linux as a stepping stone.  It’s really simple to install Linux or grab one that’s already there and plug it into my private sandbox.  Once that’s done, you just need to install and configure a DNS server.  Here is the step by step process (your IP network will be different, just substitute where appropriate). FYI- I’m running Oracle Linux 6.7 with the Red Hat Compatible Kernel for this tutorial. CentOS 6.7 and RHEL 6.7 are no different other than the repositories you point to in order to get your patches.

Let’s install BIND (Berkley Internet Name Domain) better known as DNS

# yum install -y bind bind-utils
[root@tempDNS ~]# yum install -y bind bind-utils
Loaded plugins: refresh-packagekit, security, ulninfo
Setting up Install Process
public_ol6_latest                                                                                            | 1.4 kB     00:00
Resolving Dependencies
--> Running transaction check
---> Package bind.x86_64 32:9.8.2-0.62.rc1.el6_9.2 will be installed
--> Processing Dependency: bind-libs = 32:9.8.2-0.62.rc1.el6_9.2 for package: 32:bind-9.8.2-0.62.rc1.el6_9.2.x86_64
---> Package bind-utils.x86_64 32:9.8.2-0.37.rc1.el6 will be updated
---> Package bind-utils.x86_64 32:9.8.2-0.62.rc1.el6_9.2 will be an update
--> Running transaction check
---> Package bind-libs.x86_64 32:9.8.2-0.37.rc1.el6 will be updated
---> Package bind-libs.x86_64 32:9.8.2-0.62.rc1.el6_9.2 will be an update
--> Finished Dependency Resolution

Dependencies Resolved

====================================================================================================================================
 Package                   Arch                  Version                                     Repository                        Size
====================================================================================================================================
Installing:
 bind                      x86_64                32:9.8.2-0.62.rc1.el6_9.2                   public_ol6_latest                4.0 M
Updating:
 bind-utils                x86_64                32:9.8.2-0.62.rc1.el6_9.2                   public_ol6_latest                188 k
Updating for dependencies:
 bind-libs                 x86_64                32:9.8.2-0.62.rc1.el6_9.2                   public_ol6_latest                891 k

Transaction Summary
====================================================================================================================================
Install       1 Package(s)
Upgrade       2 Package(s)

Total download size: 5.1 M
Downloading Packages:
(1/3): bind-9.8.2-0.62.rc1.el6_9.2.x86_64.rpm                                                                | 4.0 MB     00:00
(2/3): bind-libs-9.8.2-0.62.rc1.el6_9.2.x86_64.rpm                                                           | 891 kB     00:00
(3/3): bind-utils-9.8.2-0.62.rc1.el6_9.2.x86_64.rpm                                                          | 188 kB     00:00
------------------------------------------------------------------------------------------------------------------------------------
Total                                                                                               3.8 MB/s | 5.1 MB     00:01
warning: rpmts_HdrFromFdno: Header V3 RSA/SHA256 Signature, key ID ec551f03: NOKEY
Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-oracle
Importing GPG key 0xEC551F03:
 Userid : Oracle OSS group (Open Source Software group) 
 Package: 6:oraclelinux-release-6Server-7.0.5.x86_64 (@anaconda-OracleLinuxServer-201507280245.x86_64/6.7)
 From   : /etc/pki/rpm-gpg/RPM-GPG-KEY-oracle
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
  Updating   : 32:bind-libs-9.8.2-0.62.rc1.el6_9.2.x86_64                                                                       1/5
  Updating   : 32:bind-utils-9.8.2-0.62.rc1.el6_9.2.x86_64                                                                      2/5
  Installing : 32:bind-9.8.2-0.62.rc1.el6_9.2.x86_64                                                                            3/5
  Cleanup    : 32:bind-utils-9.8.2-0.37.rc1.el6.x86_64                                                                          4/5
  Cleanup    : 32:bind-libs-9.8.2-0.37.rc1.el6.x86_64                                                                           5/5
  Verifying  : 32:bind-utils-9.8.2-0.62.rc1.el6_9.2.x86_64                                                                      1/5
  Verifying  : 32:bind-9.8.2-0.62.rc1.el6_9.2.x86_64                                                                            2/5
  Verifying  : 32:bind-libs-9.8.2-0.62.rc1.el6_9.2.x86_64                                                                       3/5
  Verifying  : 32:bind-libs-9.8.2-0.37.rc1.el6.x86_64                                                                           4/5
  Verifying  : 32:bind-utils-9.8.2-0.37.rc1.el6.x86_64                                                                          5/5

Installed:
  bind.x86_64 32:9.8.2-0.62.rc1.el6_9.2

Updated:
  bind-utils.x86_64 32:9.8.2-0.62.rc1.el6_9.2

Dependency Updated:
  bind-libs.x86_64 32:9.8.2-0.62.rc1.el6_9.2

Complete!

Ok, now that we have that done, let’s do a system update to make sure we have all the latest bits and bytes. If this is a production system, consult your companys policy on updates and patches before doing this. I don’t want to be responsible for making the other applications on this server potentially not work for any reason.

[root@tempDNS ~]# yum update -y
Loaded plugins: refresh-packagekit, security, ulninfo
Setting up Update Process
Resolving Dependencies
--> Running transaction check
---> Package ConsoleKit.x86_64 0:0.4.1-3.el6 will be updated
---> Package ConsoleKit.x86_64 0:0.4.1-6.el6 will be an update
---> Package ConsoleKit-libs.x86_64 0:0.4.1-3.el6 will be updated
..
..
..
Complete!

At this point, I generally recommend a reboot so any updates that had prerequisites for a reboot are taken care of. Also it just makes sure the system is at a known good place for our work.

Let’s edit the /etc/named.conf file and replace the options section with our own custom code:

options {
    listen-on port 53 { 127.0.0.1; 192.168.1.50; };
        #listen-on-v6 port 53 { ::1; };
        directory   "/var/named";
        dump-file   "/var/named/data/cache_dump.db";
        statistics-file "/var/named/data/named_stats.txt";
        memstatistics-file "/var/named/data/named_mem_stats.txt";
        allow-query { any; };
        allow-transfer     { localhost; };
        recursion yes;

        dnssec-enable yes;
        dnssec-validation yes;
        dnssec-lookaside auto;

        /* Path to ISC DLV key */
        bindkeys-file "/etc/named.iscdlv.key";

        managed-keys-directory "/var/named/dynamic";
};

Note above that I have added my local IP address to the end of the listen-on line. Now let’s add a couple zone files.

zone "mydomain.com" IN {
                type master;
                file "mydomain.com.zone";
                allow-update { none; };
};

zone "1.168.192.in-addr.arpa" IN {
                type master;
                file "1.168.192.in-addr.arpa";
                allow-update { none; };
};

Obviously change the domain name to your own on the zone line and the file line. Leave the .zone at the end though.

Here are the two files you want to put into /var/named/

mydomain.com

$TTL 86400
@   IN  SOA     ns1.mydomain.com. root.mydomain.com. (
        2017062601  ;Serial
        3600        ;Refresh
        1800        ;Retry
        604800      ;Expire
        86400       ;Minimum TTL
)
; Specify our nameserver
                IN      NS              ns1.mydomain.com.

; Resolve nameserver hostname to IP
ns1             IN      A               192.168.1.50

; Define hostname -> IP pairs which you wish to resolve
gateway         IN      A               192.168.1.1

1.168.192.in-addr.arpa

$TTL 86400
@       IN      SOA     ns1.mydomain.com.        root.mydomain.com. (
                        2017062601
                        21600      ; refresh after 6 hours
                        3600       ; retry after 1 hour
                        604800     ; expire after 1 week
                        86400 )    ; minimum TTL of 1 day
;
@       IN      NS      ns1.mydomain.com.
;
1       IN      PTR     gateway.mydomain.com.

There are a few things I’d like you to note.

1) You have to update the serial number any time you make a change to the zone file (forward or reverse). I usually use the format YYYYMMDD## where ## is a sequential number starting with 01. This way if you make multiple updates on the same day, the root servers on the internet will know which version is current.

2) Take notice of the . at the end of the entries in the reverse zone file. These have to be there- they terminate the domain hierarchy and tell the server that this is the root so it doesn’t try to keep looking any further.

3) In my example above, I also have an entry for gateway.mydomain.com which has an IP address of 192.168.1.1. This is not normally something you would need or want to do but I wanted to show the syntax of how to do it.

4) For every record you want to add to DNS, it’s a good idea to make sure you also add a reverse record. This lets you do an nslookup or dig against the IP address and it will return the name. A lot of stuff will break or at the very least give you problems if it’s not in place so just get in the habit of doing it.

That’s pretty much it. There are a lot of other nuances that I don’t need to get into here. I almost didn’t write this because there are so many tutorials out there that IMHO are written better than mine. Mainly I wanted to keep it for my own use so I know right where to go when I need to install a quick and dirty DNS server. Hopefully one of you will benefit from this.

Enjoy!!

SSH Tunneling with PuTTY

From time to time I have a need to connect to a system inside another remote network (usually my work).  Normally I just ssh in and then jump to the machine I need to be on.  That’s all fine and dandy if you don’t need a GUI.  What if you need to be on the GUI console of the target machine inside the firewall and the firewall doesn’t allow the port you need to use?

 

Enter VNC and PuTTY.  You aren’t limited to doing this with PuTTY or VNC.  It’s just that a majority of my work is done from a windows machine and I refuse to install the bloated CYGWIN app on my machine just to get an ssh command line session.  Bah.. that’s a story for another day.  Anyway- SSH tunnels can be a bit confusing to the lay person so I thought I’d do a graphical illustration to help that out.

 

In this scenario, I will be using my laptop at home to connect into a landing pad UNIX machine at work.  I will then open a tunnel to another machine inside the remote network that will establish a connection to the VNC server running on that machine.  I won’t go into how to set up a VNC Server on linux as there are plenty of tutorials out there that will cover it.  The one thing I will say is make sure you use a password when you start it up.  This is a visual example of what the connection looks like:

 

capture

 

Here are some enlarged views so you can see what’s going on.  First we start PuTTY on the laptop.  I’ll show an example of what options you need to select inside the Putty connection later.  Once the tunnel is in place, fire up your favorite VNC client and point it to 127.0.0.1 or localhost on port 59001:

capture1

We pointed our VNC client to the address and port of the tunnel we just created, so the traffic is sent through the tunnel into the external Landing Pad and being forwarded on into the remote network:

capture2

Finally, the tunnel terminates on the server inside the remote network and connects the tunnel to port 5901 on that machine:

capture3

 

It may seem odd to connect your VNC client to the laptop’s localhost address in order to reach the target machine.  This is because you’re sending that traffic through the SSH tunnel that we set up rather than pointing it directly to the server you want to reach.

 

Now I’ll show you how to configure PuTTY to create the tunnel.  First, fire up Putty and populate the username and IP address of the landing pad server in our example (substitute yours of course).  Leave the port at 22:

capture4

 

Next, scroll down on the left hand side in the Category window and select Tunnels.  Here, populate the source port (59001 in my example), the IP address of the final destination server along with the port you want to connect to on that machine (5901 in my example).  Remember, you aren’t putting the IP address of the landing pad here- we want the target server in the Destination field. Once you have the Source port and Destination fields filled in, click Add and it will pop into the window as seen below:

capture5

 

To establish the tunnel, click Open. This will launch the PuTTY terminal and prompt you for your password.  In this screenshot, I’m using root to log in however generally it’s a good idea to use a non-privileged user to log into any machine:

 

capture6

Once you see the user prompt and you’re logged in, the tunnel is now in place.  Keep in mind that this SSH session you have open is the only thing keeping that tunnel open.  If you log out of the shell, it also tears down the tunnel so keep this window open while you’re using the tunnel.

 

The next step is to launch a VNC Viewer on your laptop and point it to your local machine on port 59001:

capture7

Click the connect button and you should see the next window prompting you for the password you set up earlier:

capture8

Finally, once you click OK you will be brought to your VNC Desktop on the machine inside the remote network!

capture9

 

So let’s take a step back and review what we’ve effectively done here:

 

Start VNC server:

We have to start a VNC server on the target computer, along with configuring a password to keep everyone else out.  This would have to be done separately.

 

Establish Tunnel:

We first establish the tunnel from the laptop, through the landing pad and finally to the remote server.  I’m making the obvious assumption here that you have the landing pad accessible to the internet on port 22 and that you have an SSH server running that will accept such connections.  You’re effectively logging into the landing pad just like you would on any other day.  The difference here is that we’re also telling PuTTY to set up a tunnel for us pointing to the remote server as well.  Aside from that- your login session will look and feel just the same.

 

Launch VNC Client:

We then start the VNC client on our laptop.  Normally, we would point it directly to the server we want to VNC into.  In our case, we created a tunnel that terminates on your laptop at port 59001.  So we connect our VNC client to the laptop (localhost or 127.0.0.1 should work) and point it to port 59001 instead of the standard port 5901.  The VNC client doesn’t care how the traffic is getting to the VNC server, it just does its job.

Think of this SSH tunnel as kind of a wormhole if that type of thing were to actually exist.  The traditional method of connecting to your remote endpoint would be similar to pointing our space shuttle towards the Andromeda galaxy which is about 2.5 million light years away.  It’s essentially not possible to get there- similar to a firewall that is blocking us.  But what if there were a wormhole that terminated near Earth that ended in the Andromeda galaxy?  If we were to point our space shuttle into the wormhole, theoretically we would pop out the other side at our target.

 

If you do plan on doing something like this, make sure you network administrator is ok with it.  They may detect the traffic as malicious if they’re not sure where it’s coming from and you may wind up in trouble.  I hope this helps give a basic understanding of how SSH Tunnels work.

 

 

 

 

 

Internet Ping Meter (part 2 of 2)

Onto the fun stuff!  Below is the python script that does most of the heavy lifting.  Remember with Python, indentation is critical.  It’s actually used to delimit things like functions rather than more traditional delimiters like {}.  Best practice is to use spaces, not tabs for indentation because they can be inconsistent and cause problems.  To avoid this, I like to use an IDE such as notepad++ or the Arduino IDE. It does a great job of taking care of the spacing and indentation. It will even go through the entire script and fix any indentation errors you have automatically. Highly recommended. FYI- You’ll also need to install the PySerial module for this to work:

#!/usr/bin/python

##
## Internet Ping Meter v1.0 - Eric Steed
##
## 01/03/17 - first version - EPS
##
import serial
import sys
import subprocess
import time
latency = 0
ping_targets="8.8.8.8 4.2.2.2 208.67.220.220"
retVal = 0
failLevel = 0
lastLEDStatus = ""

##
## Define array variable alertLevel[] and assign color codes to be sent to the NeoPixel.
## Based on the number of total ping failures, iterate the failLevel by one and
## send the appropriate color code.
##
clearLED = "ic"
alertLevel = []
alertLevel = ["h","g","f","e","d"]

##
## Open the serial port to talk to the NeoPixel. Have to wait for it to initialize
## before we start sending signals
##
port = serial.Serial("/dev/ttyACM0", baudrate=9600, timeout=1)
time.sleep(3)

##
## Green = h
## Greenish Yellow = g
## Yellow = f
## Orange = e
## Red = d
## Black = i
##
## LED #'s
##
## 1-9 = 1-9
## 10 = a
## 11 = b
## 12 = c
##
##
## I'm using a NeoPixel ring with 12 LED Segments to indicate the average latency of
## multiple established servers on the internet.  This way I can tell visually if
## my internet connection is slow, or even down.
##
## To control the NeoPixel, I've assigned specific characters to indicate how many
## LED's to illuminate and what color.  When we tell the NeoPixel to illuminate a
## given number of LED's, we have to account for the fact that the last command
## string that was sent is persistent in that the LED stays lit even when the next
## command string comes in.  For example, if reading 1 determines that 4 LED's
## should be lit, then reading 2 calls for 3 LED's, you wouldn't be able to see that
## because all 4 LED's were still illuminated from the previous cycle.
##
## To account for this, we send an instruction to "illuminate" all 12 LED's with
## the color Black before sending the actual value desired.  This is done by
## assigning a value of 'ic' to the variable clearLED.  I've also added some logic
## at the end of the infinite while loop that says don't send any instructions
## unless there's been a change since the last one.  This gets rid of the blinking
## effect that I was seeing on every update- rather annoying!
##

##
## I'm using the subprocess library for now unless I can get the native Python ping library
## to do it for me.  If stdout is null for a given target, return 0.
##
def doPing(host):
    import os,platform
    pingOutput = subprocess.Popen(["ping -c 1 -w 1 " + host + " | grep rtt | awk -F/ '{print $5}' | awk -F. '{print $1}'"], stdout=subprocess.PIPE, shell=True)
    (out, err) = pingOutput.communicate()
    if (out.rstrip('\n') == ''):
        return 0
    else:
        return out.rstrip('\n')

##
## Get average latency from all of the ping targets. Had to cast the output of
## doPing() into an integer to be able to do math against it
##
while True:
    count=0
    for x in ping_targets.split():
        retVal = int(doPing(x))
        #print "latency = [{0}]".format(retVal)
        # print "type = [{0}]".format(type(retVal))
        if (retVal > 0):
            latency += retVal
            count+=1

    ##
    ## If count is zero, that means we were not able to successfully ping
    ## any of the targets and we should start incrementing the failure count.
    ## Furthermore, if we have been incrementing failLevel and we are now
    ## able to ping, reset the failLevel back to 0 at that time.
    ##
    if (count == 0):
        # Increase failure level
        #print "Failed to ping any host"
        failLevel += 1
        if (failLevel > 4):
            failLevel = 4

    else:
        latency=(latency/count)
        failLevel = 0

    ##
    ## Set LEDStatus to the appropriate value based on latency and failure count
    ##

    #print "Average Latency = [{0}]".format(latency)

            if (latency > 1) and (latency <= 10):                 #print "1-10"                 LEDStatus = clearLED + alertLevel[failLevel] + "1"         elif (latency >= 11) and (latency <= 20):                 #print "11-20"                 LEDStatus = clearLED + alertLevel[failLevel] + "2"         elif (latency >= 21) and (latency <= 30):                 #print "21-30"                 LEDStatus = clearLED + alertLevel[failLevel] + "3"         elif (latency >= 31) and (latency <= 40):                 #print "31-40"                 LEDStatus = clearLED + alertLevel[failLevel] + "4"         elif (latency >= 41) and (latency <= 50):                 #print "41-50"                 LEDStatus = clearLED + alertLevel[failLevel] + "5"         elif (latency >= 51) and (latency <= 60):                 #print "51-60"                 LEDStatus = clearLED + alertLevel[failLevel] + "6"         elif (latency >= 61) and (latency <= 70):                 #print "61-70"                 LEDStatus = clearLED + alertLevel[failLevel] + "7"         elif (latency >= 71) and (latency <= 80):                 #print "71-80"                 LEDStatus = clearLED + alertLevel[failLevel] + "8"         elif (latency >= 81) and (latency <= 90):                 #print "81-90"                 LEDStatus = clearLED + alertLevel[failLevel] + "9"         elif (latency >= 91) and (latency <= 100):
                #print "91-100"
                LEDStatus = clearLED + alertLevel[failLevel] + "a"

        else:
                #print "latency greater than 101"
                LEDStatus = clearLED + alertLevel[failLevel] + "c"

    ##
    ## If the latency is within a different range than the last iteration, send
    ## the command to update the LED count on the NeoPixel.  Otherwise you get
    ## a rather annoying blinking effect as the LED's are updated even if it's the
    ## same measurement as the last time.
    ##
    if (LEDStatus != lastLEDStatus):
        port.write(LEDStatus)
        lastLEDStatus = LEDStatus

    #time.sleep(5)
    #print LEDStatus
    latency = 0

I left the debugging code in the script if you want to uncomment them and watch the terminal as the script runs to see what’s going on. Most of the script is fairly straightforward so I won’t dwell too much on explaining it step by step.

Now, onto the Arduino code. I’m using the Arduino basically as a driver for the NeoPixel. Again- I could have probably just used the Pi by itself, but what fun would that be?

#include <Adafruit_NeoPixel.h>

//
// Internet Ping Meter v1.0 - Eric Steed
//
// 01/03/17 - first version - EPS
//
// Set up variables
byte leds = 0;
uint8_t delayVal = 30;

// Set the PIN number that the NeoPixel is connected to
#define PIN   7

// How bright are the LED's (0-255)
#define INTENSITY 60

// Set color to Green to start
uint8_t  r = 0;
uint8_t  g = INTENSITY;
uint8_t  b = 0;

// Set the number of pixels on the NeoPixel
#define NUMPIXELS   12

// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

// Initialize everything and prepare to start
void setup()
{
  uint8_t i;

  // Set up the serial port for communication
  Serial.begin(9600);
  Serial.println("Started Serial Monitor");

  // This initializes the NeoPixel library.
  pixels.begin();

  // This sets all the pixels to "off"
  for (i = 0; i < NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(0, 0, 0));
    pixels.show();
  }

  // Cycle each pixel through the primary colors to make sure they work, then turn them all off
  // Red
  for (i = 0; i < NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(INTENSITY, 0, 0));
    pixels.show();
    delay(delayVal);
  }

  // Green
  for (i = 0; i < NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(0, INTENSITY, 0));
    pixels.show();
    delay(delayVal);
  }

  // Blue
  for (i = 0; i < NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(0, 0, INTENSITY));
    pixels.show();
    delay(delayVal);
  }

  // White
  for (i = 0; i < NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(INTENSITY, INTENSITY, INTENSITY));
    pixels.show();
    delay(delayVal);
  }

  // Turn off all LED's
  for (i = 0; i < NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(0, 0, 0));
    pixels.show();
  }
}

// Main loop
//
// When sending LED signals, send the color code first, then the number of LED's to
// turn on.  For example 6 Green LED's would be h6, 11 Red LED's would be db, all
// 12 LED's to Black would be ic
void loop()
{
  uint8_t i;
  if (Serial.available())
  {
    char ch = Serial.read();
    // Serial.print("ch = ");
    // Serial.println(ch);
    int led = ch - '0';

    // Serial.print("led = ");
    // Serial.println(led);

    // Set Color of LED based on how many fails in a row
    //RED = 52(d)
    //ORANGE = 53(e)
    //YELLOW = 54(f)
    //YELLOW-GREEN = 55(g)
    //GREEN = 56(h)
    //BLACK = 57(i)

    switch (led) {
      // Set color to RED
      case 52: {
          r = INTENSITY;
          g = 0;
          b = 0;
        }
        break;

      // Set color to ORANGE
      case 53: {
          r = INTENSITY;
          g = (INTENSITY / 2);
          b = 0;
        }
        break;

      // Set color to YELLOW
      case 54: {
          r = INTENSITY;
          g = INTENSITY;
          b = 0;
        }
        break;

      // Set color to YELLOW-GREEN
      case 55: {
          r = (INTENSITY / 2);
          g = INTENSITY;
          b = 0;
        }
        break;

      // Set color to GREEN
      case 56: {
          r = 0;
          g = INTENSITY;
          b = 0;
        }
        break;

      // Set color to BLACK
      case 57: {
          r = 0;
          g = 0;
          b = 0;
        }
        break;

      // To save on code, if we receive a 0 through a 9, turn on that
      // number of LED's
      case 0 ... 9:
        for (i = 0; i < led; i++) {
          pixels.setPixelColor(i, pixels.Color(r, g, b));
          pixels.show();
        }
        break;

      // If we receive an "a", turn on 10 LED's
      case 49:
        for (i = 0; i < 10; i++) {
          pixels.setPixelColor(i, pixels.Color(r, g, b));
          pixels.show();
        }
        break;

      // If we receive a "b", turn on 11 LED's
      case 50:

        for (i = 0; i < 11; i++) {
          pixels.setPixelColor(i, pixels.Color(r, g, b));
          pixels.show();
        }
        break;

      // If we receive a "c", turn on 12 LED's
      case 51:

        for (i = 0; i < 12; i++) {
          pixels.setPixelColor(i, pixels.Color(r, g, b));
          pixels.show();
        }
        break;

      // For testing, insert a delay if we see a ,
      case -4:
        delay(delayVal * 10);
        break;

      default:
        // if nothing else matches, do the default
        // default is optional
        break;
    }
    // I had to add this bit of code to fix a problem where the Arduino buffer
    // apparently filled up after a very short time.  It would set the LED's on
    // but then pause for 2-3 seconds before it would receive the next command.
    // This tells the Arduino to flush out the buffer immediately.
    Serial.flush();
  }
}

If it’s not already evident, I’m not very adept at either Python or Arduino coding. I’m just starting out. The most frustrating thing for me is stumbling across syntax issues with code. 9 times out of 10, I know it’s possible to do something but I just can’t get the syntax right or use the correct modules. All this comes with time so maybe in a year, this code would be half or 1/3 the size it is right now.

Once you have everything installed and tested (you can turn on and off the LED’s), you have to connect the Pi to your network. I would consider this device to be a single purpose device and not put anything else on it that could interfere with the script and timing. They’re cheap enough that you should be able to justify this.

 

You can find this code on Github at https://github.com/esteed/Internet-Ping-Meter.  Please feel free to make modifications and generate a pull request- I’m always looking for a better mousetrap!

 

I hope this has helped you even a little bit. I had a great time setting it up and I look forward to making enhancements. The first one will be to indicate current upstream and downstream throughput using white and blue LED’s basically overlaid on the top of the latency indicators. Wish me luck!!

Internet Ping Meter (part 1 of 2)

THE INTERNET IS DOWN!!

How many of you “home IT support technicians” have heard this before?  I hear it a lot, so I decided to create a device that would notify me visually when problems occur.  Sometimes it winds up being a flaky wifi router that either reboots or just needs to take a breath.  Other times, it’s our Comcast connection in which case I can’t do anything other than call and file an outage.  The kids seem to have a hard time with understanding that even though I’ve explained it to them a hundred times.

A little background on the reason for this project.  At the company I work for, we employ a WAN load balancer which uses a series of pings to major internet presences such as google, AT&T or OpenDNS servers.  Basically the device pings each of those addresses once per second and based on specific criteria, can determine if one of the two internet connections is down and can take appropriate action.

This is what made me decide to develop my version of the ping meter.  There are a number of projects like this for the raspberry pi that involve some sort of visual representation.  I wanted to put together a project that incorporated both the raspberry pi, an arduino board and the NeoPixel ring.  This was mainly a project for me to learn how to integrate multiple devices.  Honestly I could probably have done this without the Arduino but I wanted to challenge myself a little.

At this point, I have the device working the way I want.  My next challenge is to package the device into something more aesthetically pleasing.  WAF (Wife Acceptance Factor) is an important aspect to any geek project like this if it’s gonna be displayed somewhere that’s visible.  I’m thinking maybe a small picture frame or maybe some sort of glass object that looks nice.

Here is a list of the parts you’ll need:

  • Raspberry Pi (any model should work)
  • Arduino board (I used an UNO but even that is overkill)
  • NeoPixel LED ring (12 LED segments)
  • Micro SD card (at least 4gb)
  • USB Type A to USB type B (printer/scanner cable)
  • 5V Micro USB power source (iPad charging brick is perfect)

I haven’t tested using a Pi Zero yet but I don’t see why it wouldn’t work.  I also have an Arduino Trinket (5v version) that I’m trying to use for this however out of the box it doesn’t support serial communication.  For size reasons, this combination would be perfect for just about any implementation where room is an issue.  You could just as easily use a larger NeoPixel ring or even a strip with some very minor code modifications.

There are two programs that are used to make this system work.  One is the “firmware” that you load onto the Arduino board itself.  The other is the python script that runs on the Pi.  Basically I use the Pi to ping 3 different IP addresses, and use the NeoPixel ring to display the average ping latency in LED segments.  If I can’t ping all three then I start to progressively change the color of the LED’s from green to red.  Throughout this project I learned a lot about programming in python, Arduino and interacting with external physical devices.  I first started by just getting the LED’s to turn on and off.  I borrowed a lot of code from examples and implemented the same routines to get the NeoPixel to do what I wanted to.

I tried to sprinkle comments throughout the code to explain what I’m doing and why.  Most of these were added after I made a breakthrough in something that was kicking my ass for awhile so I would know how to fix the problem the next time around.  I won’t focus a lot on how to install the OS on your Pi or how to download code to the Arduino- there are a LOT of helpful resources on the internet that can walk you through it.  Also, in the spirit of this being a learning exercise for me- I think it’s valuable for someone starting out fresh to do the research and have a basic understanding of what’s going on rather than just copying and pasting code.  If you’re trying to put this together and run into problems, feel free to comment on the article and I’ll do my best to answer questions.

In the next article, I’ll show you the code and how it all works.  Stay tuned!

Windows Wifi troubleshooting tools

Have you ever tried connecting your laptop to a Wifi network and for one reason or another it failed?  It can be extremely frustrating, even to a seasoned vet who knows their way around Windows.  The big problem is that you get virtually no information from the connection failure.  No logs, no error codes, nothing.

There is a reporting tool that is built into windows 8 and newer that will compile a very detailed report showing each connection attempt, its status and a ton of other stuff.  Here’s how to run the report and where it gets put:

 

  • Open a command prompt as administrator
  • Run the following command
    • netsh wlan show wlanreport
  • Note the path where the html file is generated.  It should be C:\ProgramData\Microsoft\Windows\WlanReport\wlan-report-latest.html
  • Open your favorite web browser and point it to that file.  voila!

 

Here’s a snippet of what some of the report looks like:

capture

 

There is a LOT more information below this including extremely detailed information about all the network adapters on the system, the system itself and some script output.  If you click on the items in the session list above, it will bring you to a detailed log of that session and why it was able to or not able to connect.

 

Suffice it to say this is an invaluable tool to review logs and information all in one place.

Hands on with FireEye

images

I recently had a chance to get some soak time with some of FireEye’s suite of cyber security hardware at a customer site.  They deployed NX, HX and CM appliances into their network.  DTI (Dynamic Threat Intelligence) was also purchased, I’ll go into that more in a later post.  Following is an eye chart of FireEye’s comprehensive suite of products as well as a more in depth description of the products that were deployed at this particular customer site:

 

1470248677864

NX

The NX appliance is responsible for monitoring and stopping web based attacks, zero day web exploits and multi-protocol callbacks.  What this means is that the appliance is constantly monitoring traffic coming into your network.  It looks for suspicious activity based on known exploits and how they work (i.e. modify the registry to turn off the firewall, turn off anti-virus or spawn multiple processes and delete the original executable to hide itself).  Once it finds something suspicious, it can analyze the behavior of the potential threat using it’s Multi-Vector Virtual Execution (MVX) engine.  The MVX engine will detonate the payload in an isolated and heavily instrumented VM environment where it can log exactly what the exploit does and how it does it.  Once it has this information and it has identified the exploit, it can automatically block it from getting into your network.

 

HX/HXD

The HX/HXD appliances are used to monitor endpoints (windows desktops/laptops, servers or even cellphones and tablets) for compromises.  It monitors all endpoints across the entire organization at once and is able to correlate suspicious activity.  Once a threat is identified, you then have the option of downloading a triage package that consists of detailed information about what the system was doing or even isolating or containing an endpoint from the network so it can’t cause any additional harm to the environment.  The appliances are typically deployed both in the internal network and the DMZ.  This gives the additional ability to protect remote endpoints that connect externally as well as internal ones.

 

CM

The CM appliance is basically the command center for FireEye that is able to communicate with all other appliances and provide a comprehensive view of what is going on.  It has the ability to reach into email, file storage, endpoint, network and mobile platforms and correlate activities in a single pane of glass.  One of the big benefits of this product is it’s ability to stop multi-vector attacks that span multiple platforms.  By deploying the FireEye NX, EX, FX, HX and AX series together with the FireEye CM series, the analysis of blended threats, such as pinpointing a spear-phishing email used to distribute malicious URLs, and correlating a perimeter alert to the endpoint, becomes possible.

 

The vast majority of customers that purchase HX appliances also purchase DTI for its obvious advantages.  The MVX engine is the really cool part of what FireEye has to offer.  Below is a description of MVX:

The FireEye Malware Protection System features dynamic, real-time analysis for advanced malware using our patent-pending, multi-flow Multi-Vector Virtual Execution (MVX) engine. The MVX engine captures and confirms zero-day, and targeted APT attacks by detonating suspicious files, Web objects, and email attachments within instrumented virtual machine environments.

The MVX engine performs multi-flow analysis to understand the full context of an advanced targeted attack. Stateful attack analysis is critical to trigger analysis of the entire attack lifecycle, from initial exploit to data exfiltration. This is why point products that focus on a single attack object (e.g., malware executable (EXE), dynamic linked library (DLL), or portable document format (PDF) file types) will miss the vast majority of advanced attacks as they are blind to the full attack lifecycle.

 

The customer was able to deploy the endpoint software to hundreds of agents automatically by using Group Policy profiles to push out the installer and run it silently.  Once that was done, we tested containment which essentially takes the machine off the network until you can decide how you want to react.  If the endpoint has been determined to be safe, you can then un-contain it through the GUI.
 
We did run into what seems to be a rather interesting glitch during testing of the containment process.  We contained a machine that was originally on the internal network.  We then placed it on the VPN and due to some initial configuration issues, it was unable to contact the HXD appliance to receive the un-contain instruction.  The result left the machine unable to communicate on the network and no way to fix it.  Surprisingly, we were able to revert to a previous system restore point when the agent hadn’t been installed yet.  Thus we circumvented the whole containment process.
 
I’ve not yet decided if this truly is a bad thing since by reverting back to a point before the agent install, it would essentially rid the machine of the exploit as well.  Regardless, I was a bit dismayed at how easy it was to bypass containment.  Assuming the end user was not malicious (they wouldn’t have infected their own machine) I’m not sure this is a really viable scenario.  One potential would be an exploit that was aware of the mechanics of how the agent works and communicates- in which case it could theoretically block communication to the HX.  This would manifest as an endpoint that hasn’t checked in for awhile and would probably arouse suspicion as well.
 
In summary- I’m extremely impressed with FireEye’s ability to detect and block very complex and coordinated attacks where other products fall down completely.  The MVX engine in particular is something to behold- the level of instrumentation of an exploit is truly incredible.  To take this a step further, if you purchase the AX appliance, this also gives you the ability to do forensics against the exploit including a video of the exploit during detonation (along with all the other telemetry that is captured).  This could prove to be invaluable to root cause analysis in situations where it’s required to determine exactly how an exploit works.