Friday, December 17, 2010

Generate DNS Import from Solarwinds Orion NCM

It's nice to have entries in your internal DNS for router interface names; it makes stuff like traceroute a whole lot easier to read. Many small-to-mid-size companies use Solarwinds products for network management.

This perl script takes the output that you get from using Solarwinds Network Configuration Manager to run the "show ip interface brief | exclude unassigned" command on a group of Cisco IOS devices and massages it into a format that looks like this:

hostname-interfaceName-interfaceNumber a.b.c.d

where a.b.c.d is the IP address assigned to the interface. This format is suitable for import into many DNS servers.

This code doesn't attempt to abbreviate interface names at all, but it could easily be modified to do so.

I run this on Windows using Cygwin and it works fine. The only caveat is that you need to have the dig command installed.

#!/usr/bin/perl
#
# takes output from a Solarwinds Orion NCM command script
# that runs "show ip interface brief | exclude unassigned"
# and produces a "hostname IP" output for import into DNS
# this makes traceroutes more readable
#
# usage: ./interface2dns.pl < inputfile.txt
# inputfile.txt will look like this
# when produced by Orion NCM 6.x:
#
# routerA.test.com  (10.38.16.126)
# Interface   IP-Address      OK? Method Status Protocol   
# Loopback0   172.29.255.1    YES NVRAM  up     up     
# Vlan163     10.38.16.126    YES NVRAM  up     up     
# Vlan165     10.38.16.117    YES NVRAM  up     up  
#
#
while (<>){
   
    chomp; # remove newline characters

# find the line with the hostname in it by searching

# for the "(" character
if ($_=~/\(/) {

    # split that line on the . character
    @hostnameFields = split /\./,$_;
    # hostname is the first element before the first .
    $hostname=$hostnameFields[0];

}

# identify lines with "up" in them to remove garbage
if ($_=~/\s+up\s+/) {

    #split the good lines into space-separated fields
    @fields=split  /\s+/,$_;
   
    #find RFC1918-like addresses only
    if ($fields[1]=~/^10\.|172\.|192\./){
     
        # skip IP addresses that are already in DNS
          unless (`dig -x $fields[1] +short`) {
     
          #substitute - for / and : in dns names
          $fields[0]=~s/\/|:/-/g;
 
          #print in "hostname-interface ipaddr" format
          print "$hostname-$fields[0] $fields[1]\n";    
         }
     }
}
}

Monday, December 6, 2010

Encrypted GRE Tunnel with ASA for Encryption Offload

I have a requirement to connect two internal routers over a high-speed, 3rd party, non-Internet network. The two routers need to run EIGRP with each other. We want to encrypt the link, but the routers don't support IPSec in their current configuration. Purchasing IPSec acceleration hardware for them is expensive, but we happen to have two ASAs in inventory that aren't currently in production.

The simplest solution for this is to connect the two routers with a GRE tunnel, then use the ASAs to encrypt the GRE traffic.

While I've worked with ASAs quite a bit as stateful packet filters and as remote access VPN headends, it's been a really long time since I've used one in a point-to-point VPN. I thought I'd blog about the lab proof-of-concept so that I don't forget everything about the configuration.

My lab topology looks like this:

R4---ASA1---ASA2---R5

R4 and R5 have a standard GRE tunnel configured between them, running EIGRP to advertise their loopbacks. The tunnel destination is statically routed.

On R4:

interface Loopback0
ip address 4.4.4.4 255.255.255.0

!
interface FastEthernet0/0
description link to ASA1
ip address 1.1.1.4 255.255.255.0

!
interface Tunnel50
description GRE tunnel to R5, will be encrypted by ASA1

ip address 50.1.1.4 255.255.255.0
tunnel source FastEthernet0/0
tunnel destination 2.2.2.5
!

ip route 2.2.2.5 255.255.255.255 1.1.1.1
!

router eigrp 1
network 4.0.0.0

network 50.1.1.0 0.0.0.255


On R5:

interface Loopback0
ip address 5.5.5.5 255.255.255.0

!
interface FastEthernet0/0

description link to ASA2

ip address 2.2.2.5 255.255.255.0

!

interface Tunnel50

description GRE tunnel to R4, will be encrypted by ASA2

ip address 50.1.1.5 255.255.255.0
tunnel source FastEthernet0/0

tunnel destination 1.1.1.4
!

router eigrp 1

network 5.0.0.0

network 50.1.1.0 0.0.0.255

no auto-summary


[Note: the difference in the EIGRP configs isn't a mistake. The lab routers are running two different images, one of which has auto-summary disabled by default. The other has it enabled by default, so I had to explicitly turn it off.]

This is a pretty standard GRE configuration that is used all the time to make a virtual point-to-point circuit across any other network. I'm intentionally leaving out the MTU complications for now.

Here's the interface configuration for ASA1:

interface Ethernet0/2
description link to R4
nameif inside
security-level 100

ip address 1.1.1.1 255.255.255.0

!
interface Ethernet0/1

description link to ASA2 representing 3rd party network
nameif outside
security-level 0
ip address 100.1.1.1 255.255.255.0

and here's the same configuration from ASA2:

interface Ethernet0/2
description link to R5
nameif inside
security-level 100
ip address 2.2.2.1 255.255.255.0

!
interface Ethernet0/1

description link to ASA1 representing 3rd party network
nameif outside
security-level 0

ip address 100.1.1.2 255.255.255.0


Next, we need to configure IPSec on the ASAs. This is pretty similar to doing the same thing on a IOS router, with a couple of differences:
crypto ipsec transform-set ESP_3DES esp-3des esp-sha-hmac
crypto ipsec security-association lifetime seconds 28800

crypto ipsec security-association lifetime kilobytes 4608000

crypto map P2P_CRYPTO_CM 10 match address R5_PHYSICAL

crypto map P2P_CRYPTO_CM 10 set peer 100.1.1.1

crypto map P2P_CRYPTO_CM 10 set transform-set ESP_3DES

crypto map P2P_CRYPTO_CM interface outside
crypto isakmp enable outside
crypto isakmp policy 10
authentication pre-share
encryption 3des
hash sha
group 2
lifetime 86400
!
access-list R5_PHYSICAL extended permit ip host 2.2.2.5 host 1.1.1.4

When I first set this up, I forgot the unfamiliar crypto isakmp enable outside command, and it took me a few minutes of looking at debugs to figure out why the ASA was dropping the IKE Phase 1 packets.

The other part that's different from the IOS configuration is the presence of a "tunnel-group" that defines the tunnel type and the IKE pre-shared key:

tunnel-group 100.1.1.1 type ipsec-l2l
tunnel-group 100.1.1.1 ipsec-attributes
pre-shared-key *****

I also needed to turn off NAT control so that the ASA wouldn't drop packets without a pre-defined NAT translation:

no nat-control

The configuration on the other ASA is identical, except that the crypto ACL and peer addresses are reversed, just like they would be in an IOS configuration.

Thursday, December 2, 2010

Detecting a Transparent Proxy with Wireshark/Tshark

Recently I got pulled into a debate between two colleagues who were troubleshooting a problem where some users could access a website over SSL, and others couldn't. One person was arguing that the problem was caused by client misconfiguration, and the other was arguing that it wasn't. Following my mantra "when in doubt, capture packets", we captured some traffic and had a look. I'm not going to go through the entire troubleshooting process; rather I'm going to focus on what was ultimately causing the problem. Here's the packet sequence, output from Tshark with some of the TCP details removed to make it fit:

921 13.795492 10.100.100.192 -> 184.86.133.186 TCP 50306 > https [SYN]
926 13.837731 184.86.133.186 -> 10.100.100.192 TCP https > 50306 [SYN, ACK]
927 13.837753 10.100.100.192 -> 184.86.133.186 TCP 50306 > https [ACK]
928 13.838086 10.100.100.192 -> 184.86.133.186 SSL Client Hello
932 13.840253 184.86.133.186 -> 10.100.100.192 TCP https > 50306 [RST]
943 13.879563 184.86.133.186 -> 10.100.100.192 TCP https > 50306 [ACK]
944 13.879588 10.100.100.192 -> 184.86.133.186 TCP 50306 > https [RST]
945 13.880052 184.86.133.186 -> 10.100.100.192 TCP https > 50306 [RST]
946 13.881491 184.86.133.186 -> 10.100.100.192 TLSv1 Server Hello
947 13.881513 10.100.100.192 -> 184.86.133.186 TCP 50306 > https [RST]
948 13.881535 184.86.133.186 -> 10.100.100.192 TLSv1 Certificate, Server Hello Done
949 13.881545 10.100.100.192 -> 184.86.133.186 TCP 50306 > https [RST]
950 13.881554 184.86.133.186 -> 10.100.100.192 TCP https > 50306 [RST]
953 13.882063 184.86.133.186 -> 10.100.100.192 TCP https > 50306 [RST]


The key thing to note here is the delta between the SYN and SYN/ACK: about 42ms. When I was viewing this in Wireshark I set a packet time reference on packet #921, using the "Ctrl T" keyboard shortcut; this makes it easier to see the delta values.

I then set another time reference on packet 931, the TLSv1 Client Hello. Immediately following this, less than 1 millisecond later, we see a RST come back from the server. Red flag! Since we already established the probable latency between the hosts as ~42ms using the SYN - SYN/ACK pair, this is extremely suspicious.

A few packets later, we see a TLSv1 Server Hello message inbound, AFTER the RST. The delta? Approximately 42ms, exactly what we'd expect.

I immediately inferred from this that a transparent proxy content filter was spoofing the RST due to something that it deemed to be objectionable content, and for whatever reason it wasn't notifying the user.

I talked to the administrator for the content filter, and indeed, a policy had been incorrectly applied to some users that blocked the content in question.

Another win for packet capture.