Learning Puppet with Raspberry Pi (Part One)

Puppet is, in my humble opinion, the best configuration management tool available. Written in Ruby and released under the Apache 2.0 license. It allows you to manage configurations on as little a single node to an entire network of nodes, from *nix or Windows servers and desktops to Juniper firewalls, routers, and switches.

Here I want to show the basics of getting Puppet up and running using two Raspberry Pi’s. They [Raspberry Pi’s] make great lab nodes with their inexpensive cost, small size, and Linux distribution support. I am running Raspbian Wheezy, built for the Raspberry Pi, Ruby 1.8, Ruby Interactive 1.8, and Puppet 2.7.

In this scenario there are two nodes, alpha (192.168.10.10) and bravo (192.168.11.10). Alpha is going to be the Puppet Master, compiling a Catalog, or detailed data about how the node should be configured, and sends this to the Puppet agent. Bravo is going to be the Puppet agent node, which sends facts about its current state to the Puppet Master which is used to generate the catalog.

Before anything else make sure your system is up-to-date system:
[email protected] ~ $ sudo apt-get update && sudo apt-get upgrade

Install Ruby 1.8 (ruby1.8) as well as Ruby Interactive 1.8 (ri1.8). Ruby Interface isn’t required but is helpful for debugging on-the-fly Ruby scripts.
[email protected] ~ $ sudo apt-get install ruby1.8 ri1.8

You can verify the Ruby installation and version:
[email protected] ~ $ ruby -v
ruby 1.8.7 (2012-02-08 patchlevel 358) [arm-linux-eabihf]

Next comes the Puppet installation, starting with the PuppetMaster (alpha) node:
[email protected] ~ $ sudo apt-get install puppetmaster
Reading package lists... Done
Building dependency tree
Reading state information... Done
...
The following NEW packages will be installed:
augeas-lenses bind9-host facter geoip-database libaugeas-ruby1.8 libaugeas0
libbind9-80 libdns88 libgeoip1 libisc84 libisccc80 libisccfg82 liblwres80
lsb-release puppet-common puppetmaster puppetmaster-common ruby-json
ruby-shadow
0 upgraded, 19 newly installed, 0 to remove and 0 not upgraded.
Need to get 4,825 kB of archives.
After this operation, 13.0 MB of additional disk space will be used.
Do you want to continue [Y/n]?

Once the Puppet Master is installed there are some commands we need to run in order to generate the users on the system.

On each Puppet node we will need to install Ruby and Puppet:
[email protected] ~ $ sudo apt-get install ruby1.8 puppet

You can find more information on Puppet on YouTube.

Route-Based Site-to-Site VPN on Juniper SRX Security Gateways

My inaugural post! I wanted to start with something that has become fundamental to network connectivity and security; Virtual Private Networks (VPN). In this scenario Site-to-Site VPNs on Juniper SRX security gateways, a.k.a. firewalls.

We have two networks, an office and a lab, in two cities, Milwaukee (office) and Chicago (lab).

Using Firewall Filters and Counters as a tcpdump Alternative in Junos

Junos is truly a great Network Operating System, the best in my opinion. When it comes to being able to sniff traffic directly from an interface though it falls short. I imagine this is because the control and forwarding planes are completely separate. A few weeks ago we had an issue where traffic was entering the firewall, being processed by the Services Processing Cards (SPCs) to the point we saw a log entry that the session was setup, but we did not see it egress the firewall. We wanted a way to quickly ascertain if the packet is leaving the device. This is where firewall filters and counters come in handy. Because they are applied directly to an interface, they are processed first when the packet comes in and last as the packet leaves the device.

First we are going to create a filter unique to the traffic we want to monitor, this is much like the options we would pass to tcpdump to filter traffic. We create a firewall filter called PACKET-EGRESS and create two terms. The first term sets the criteria we want to match and the second term permits the traffic. I cannot stress the importance of the second term, if you forget it you will drop all traffic as firewall filters implicitly deny traffic!


set firewall filter PACKET-HTTP-COUNT term 1 from source-address 192.168.1.73/32
set firewall filter PACKET-HTTP-COUNT term 1 from destination-address 8.8.8.8/32
set firewall filter PACKET-HTTP-COUNT term 1 from destination-port 80
set firewall filter PACKET-HTTP-COUNT term 1 then count PACKET-EGRESS-COUNT
set firewall filter PACKET-HTTP-COUNT term 2 then accept

Now that our criteria are set the next step is to apply the firewall filter to an interface. We could apply to to the ingress interface if we wanted to ensure traffic is reaching the device or on the egress interface if we want to ensure traffic is leaving the device. In this example we will apply it to the egress interface.


set interfaces reth15 unit 40 family inet filter output PACKET-EGRESS

Applying the firewall filter to an interface via input would measure traffic that has reached the interface whereas applying the firewall filter to an interface via output would measure traffic that has transited an interface.

Using apply-groups to Log a Default Deny Policy on Juniper SRX Firewalls

It is a requirement, and in some cases it is the law, to log session denies on firewalls for accountability. On the Juniper SRX firewalls there is no boolean option to log default drops, instead you have to create a policy that explicitly denies and then logs via then log session-init. This becomes an issue when creating new global policies as they are always applied to the bottom and therefore below the policy we create to explicitly deny and log traffic.¬†We have been pushing Juniper via a Feature Enhancement Request to include logging in as part of the default set security policies default-policy stanza so we didn’t have to worry about managing a default drop policy.

Until that time a co-worker and good friend of mine, Doug Didier (@KegedViolence), had a great idea to use apply-groups to manage the global policy as they are by default applied last. To do this we create a group, called in this case DENY-WITH-LOGGING, and then create our default deny and log policy under that.


[email protected]# set groups DENY-WITH-LOGGING security policies global policy DENY-WITH-LOGGING match source-address any
[email protected]# set groups DENY-WITH-LOGGING security policies global policy DENY-WITH-LOGGING match destination-address any
[email protected]# set groups DENY-WITH-LOGGING security policies global policy DENY-WITH-LOGGING match application any
[email protected]# set groups DENY-WITH-LOGGING security policies global policy DENY-WITH-LOGGING then deny
[email protected]# set groups DENY-WITH-LOGGING security policies global policy DENY-WITH-LOGGING then log session-init

Side note, notice there is no set groups DENY-WITH-LOGGING security policies global policy DENY-WITH-LOGGING then log session-close as the session does not get setup on a wing and therefor there is no session to close.

We then apply this group to the security policies section of the configuration.

[email protected]# set security policies apply-groups DENY-WITH-LOGGING

After commiting the change there are two ways to validate this. First from the configuration we can display inheritance in the configuration.

[email protected]# show security policies global | display inheritance 
policy ICMP {
    match {
        source-address any;
        destination-address any;
        application junos-icmp-all;
    }
    then {
        permit;
        log {
            session-init;
            session-close;
        }
    }
}
##
## 'DENY-WITH-LOGGING' was inherited from group 'DENY-WITH-LOGGING'
##
policy DENY-WITH-LOGGING {
    ##
    ## 'match' was inherited from group 'DENY-WITH-LOGGING'
    ##
    match {
        ##
        ## 'any' was inherited from group 'DENY-WITH-LOGGING'
        ##
        source-address any;
        ##
        ## 'any' was inherited from group 'DENY-WITH-LOGGING'
        ##
        destination-address any;
        ##
        ## 'any' was inherited from group 'DENY-WITH-LOGGING'
        ##
        application any;
    }
    ##
    ## 'then' was inherited from group 'DENY-WITH-LOGGING'
    ##
    then {
        ##
        ## 'deny' was inherited from group 'DENY-WITH-LOGGING'
        ##
        deny;
        ##
        ## 'log' was inherited from group 'DENY-WITH-LOGGING'
        ##
        log {
            ##
            ## 'session-init' was inherited from group 'DENY-WITH-LOGGING'
            ##
            session-init;
        }
    }
}

Secondly we can can also validate this in operational mode.

[email protected]> show security policies global 
Global policies:
  Policy: ICMP, State: enabled, Index: 29, Scope Policy: 0, Sequence number: 1
    Source addresses: any
    Destination addresses: any
    Applications: junos-icmp-all
    Action: permit, log
  Policy: DENY-WITH-LOGGING, State: enabled, Index: 30, Scope Policy: 0, Sequence number: 2
    Source addresses: any
    Destination addresses: any
    Applications: any
    Action: deny, log

Though you could also do this in a zone-to-zone fashion this is the type of time that global policies were designed to handle. Whether you manage ten or ten thousand security policies you will realize what a time and troubleshooting saver this can be.