Posts Tagged ‘tech’

Raspberry Pi as a Deliciously Simple VPN Endpoint

July 8th, 2014 No comments

Just wrote this up for , figured I’d paste it down here too so I can say I’ve posted something this year.


Being the networking nerd I am, I have a pretty big network at home.  And as the denizens of the Packet Pushers IRC channel know, I do a lot of work with VPNs.  One of my use cases is sharing the resources on my home network.  My friends, family, and coworkers sometimes like to use my network for any number of reasons.  As such, my internet router performs a decent amount of VPN duty.  Historically when someone wants to connect their network to mine, and they don’t have the knowledge or resources to handle their end of the connection, I’d dig out an old netbook or something to use as a termination point.  Preconfigure a few things on it, ship it out to them, make a couple changes on their “Best Buy Grade” router, and be done with it.  But this isn’t a great solution.  Wasting a netbook/laptop for the sake of bringing up a LAN-to-LAN tunnel is a bit silly.

Recently I got a Raspberry Pi to play with.  I figured for 35 bucks I couldn’t go wrong.  I think I’ve bought cappuccinos more expensive.  My idea was that if I could get it to bring up a VPN and pass packets at a decent speed, it’d be a great solution for a super cheap super easy remote VPN endpoint.  Turns out it works pretty good in this role, quite a bit more flexible than I’d planned on:

  • Dynamic WAN IP of the network it’s living on
  • Dynamic LAN IP of the unit itself
  • Automatic establishing of VPN to head-end
  • Unique IP to ping/ssh to, regardless of DHCP address
  • No need to port-forward anything to the device
  • No need to change routing to get return traffic back to your network


First, we need to enable packet forwarding on the Pi so we can actually pass traffic through it:

sudo sysctl net.ipv4.ip_forward=1

and to make the above persistent through reboot, add “net.ipv4.ip_forward=1″  to /etc/sysctl.conf .


Install the a few packages.  Some error messages may come up during the install but they can probably be safely ignored.  I don’t recall if ssh is on the raspberry pi by default, so I’m tossing it down there just in case.  Openswan checks for support on a lot of different options whether or not you’re going to use them.  The other packages support openswan.

sudo apt-get install openssh-server openswan uml-utilities chkconfig

I noticed that by default “PermitRootLogin” was set to “Yes” in /etc/ssh/sshd_config .  If you plan on port-forwarding TCP/22 to the device, you should probably edit this and set it to “No”


Next, add “tun” to the end of the /etc/modules file, so that after reboot we can create a tun0 interface.  Edit /etc/network/interfaces and add the following chunk after the section for eth0:

auto tun0
iface tun0 inet static
  pre-up /usr/sbin/tunctl -t tun0
  up ifconfig tun0 up

In my case I’m using as my unique “loopback” to hit from my head-end network.  This gives me a pre-determined IP to hit, regardless of what the local address ends up being.  To get traffic passing to/from this properly, we have to add a static route.  I do this with an “@reboot” cronjob.  I’m sure there’s a more graceful way to do it, but you want something like the following to be run a few seconds after boot when the tunnel interface has been brought up:

route add -net gw


Time to get to the IPSec config!  I’m using PSK auth for simplicity of this scenario.  Drop the key at the end of the /etc/ipsec.secrets file.  In this scenario the head end vpn endpoint is and the local IP isn’t important.  “%any” will let you have a dynamic local address.


It’s strongly advised to use a big pre-shared-key here.  I reccommend doing something like “man sendmail | sha512sum” and using the hash as a PSK.  Obviously, pipe a different manpage than I did here.


Configure a profile in /etc/ipsec.conf to handle traffic from whatever your local address is to your local network  to the network you’re interested in on the head end, in this case.  Set the ID on the far end to be the same thing as the peer hostname.  :

version 2.0
config setup
conn tunnelipsec-
 type= tunnel
 authby= secret
 left=%defaultreoute             # auto-configured as local interface IP
 #leftsubnet=      # local network, commented out initially          # remote peer hostname or IP address
 rightsubnet=       # network behind the head end
 rightid=""      # this makes setting the PSK much easier
 ike=aes128-sha1;modp1536        # This is the phase 1 policy.  
 phase2alg=aes128-sha1           # This is the phase 2 policy.
 keyexchange= ike
 pfs= yes
 auto= start

conn tunnelipsec-
 type= tunnel
 authby= secret
 keyexchange= ike
 pfs= yes
 auto= start

Next is getting traffic in and out of the tunnel on the remote side.

sudo service ipsec start

This is all you need to get the remote device going.  with these settings, specifically with “start= auto” configured, the device will start trying to connect right away.


Return traffic depends a bit on the other end.  If you can get away with putting a static route on the Pi’s default gateway saying “everything destined to the network on the other end of the VPN, send traffic to the Raspberry Pi here”.  But if that’s not an option, or you want to just play some more, we can use iptables (which is in the default Raspbian install) to source NAT the traffic to the ethernet interface’s IP.  This makes some windows machines behave more nicely since it looks like all VPN traffic is LAN traffic.  There are 2 options to perform the source NAT (replace <eth0 addr> with the address of eth0):

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source <eth0 addr>

Both options perform basically the same function, but from what I gather the second option is easier on CPU.

So let’s get to our router config.  The setup below is written to be a very simple way of handling remote peers with dynamic addresses.  This is how I have my head end router configured for the earlier example config.  call me out if I forgot something.  I have so much crypto config on this device it’s sometimes hard to pick out all the pieces for one particular connection

crypto isakmp policy 5
 encr aes 128
 hash sha
 authentication pre-share
 group 5
! "address" means "anyone can auth via this key"
crypto keyring spokes
 pre-shared-key address key 6 DERPDERPDERPDERPDERP
! similarly, here matches all peers 
crypto isakmp profile sites
 keyring spokes
 match identity address
crypto ipsec transform-set ESP-AES-128-SHA esp-aes esp-sha-hmac
crypto dynamic-map vpnmap-dynamic 5
 set transform-set ESP-AES-128-SHA 
 set pfs group5
 set isakmp-profile sites
crypto map vpnmap 1000 ipsec-isakmp dynamic vpnmap-dynamic
interface GigabitEthernet0/0
 description Outside interface
 crypto map vpnmap

Obviously there are some security implications here.  Since the profile will match connections from any device, and the defined key matches any device, if someone out there has your PSK they can hook up pretty easily.  So make sure you have proper security controls in place in and behind the head end router.

So there you have it.  This should be enough of a framework to get up and running using Raspberry Pi as a remote IPSec endpoint for a LAN-to-LAN tunnel.  In my testing, I got 15-20 mbps to pass through the tunnel with iperf, which isn’t bad considering the platform.  To my knowledge this is absolutely the cheapest way to throw a VPN spoke out onto the internet.  And if you haven’t played with Raspberry Pi yet, and you’re a networking nerd, it’s a great way to blow 35 bucks and have a little fun playing with a new toy.

Categories: Technical Tags: , , , ,

Attn – Media, unwashed masses: Stop saying “cyber”

October 24th, 2011 No comments

As the title says, please stop saying “cyber”. It means nothing. More specifically, what it does mean is “blah blah networks and/or security”. In the industry, this is so non-specific that it essentially means nothing anyways.

As a security engineer, I get pretty sick of seeing/hearing the term “cyber” thrown around to describe pretty much anything I do. Cyber security, cyber attack, cyber defense. Our team doesn’t sit down in a conference room discussing “how are the cyber defenses on company X holding up?”, or “company Y has been experiencing a higher number of cyber-threats recently”. Nobody says crap like that in real life. I decided to see how little the term actually gets thrown around. I know we never use it verbally except while making “air quotes” with our fingers and making fun of the sorts of people who DO actually say it. But I thought I should at least check my email to see if it ever sneaks its way in unnoticed.

I have 9001 emails in my inbox from the last six months or so when I last hit the “I cant send email anymore because I have too much crap in my inbox” button. 102 matched the search term “cyber”.

- A little more than half was vendor spam from companies I deal with, promoting new products, services, and whatnot else.
- A little less than half was internal emails from our global or pre-sales groups, discussing news or vendor spam.
- To my surprise there was in fact a single legitimate ticket email in the last 6 months with the term “cyber” in it.

I had to look into that one ticket to find out what the deal was. It was a ticket for a BlueCoat issue, and nowhere did the term cyber seem to appear. However there was a sysinfo attached (like a “show tech” for BlueCoat boxen), and tucked in there was a reference to a russian domain name containing the word “cyber”. That’s what had matched.

Close call, but in the end I was right. Nobody in my workplace actually uses the term “cyber” in referene to what goes on in the realm of network security.

Categories: Non-Technical Tags: , , , , ,

Tech History: Cisco’s Name and Logo

September 26th, 2011 1 comment

The other day I was driving around with Emily, and I mentioned to her the origin of the name and logo of Cisco Systems.  I can’t remember how it came up, but it did.  I’m constantly tinkering with stuff in my lab, so she knows what the logo looks like even though it isn’t her field at all.  Her mind was a little blown when she made the connection between the logo and its origins.  I mentioned this to a couple coworkers, and they hadn’t heard the history behind it either.  Their minds were also a little blown.  So I thought I’d post it here, because that’s what the internet is for.  Posting random crap, I mean…  Not Cisco history.

1) Cisco: short for San Fransisco.

Found this snippet below a couple websites, with sources leading back to  The link was identical on the sites, but was broken.  And cisco’s search function only really returns technical articles regardless of how hard I searched.   but…

Cisco Systems is the world leader in manufacturing of Network related equipment. The name “Cisco” is not an acronym, but an abbreviation of San Francisco. According to John Morgridge, employee 34 and the company’s first president, the founders hit on the name and logo while driving to Sacramento to register the company — they saw the Golden Gate Bridge framed in the sunlight.

The name cisco Systems (with the lowercase “c”) continued in use within the engineering community at the company long after the official company name was changed to Cisco Systems, Inc. Users of Cisco products can still see the name ciscoSystems occasionally in bug reports and IOS messages.

2) Cisco’s logo IS the Golden Gate Bridge

Exhibit A:

Exhibit B:

From the internets as well, a different but similar account of the above story:

According to John Morgridge, the company’s first president, the founders Len Bosack and Sandy Lerner hit on the name and logo while driving to Sacramento to register the company. They saw the Golden Gate Bridge framed in the sunlight. The logo was seen by them as a modified version of the past that would shape the future. Plus it looked really “cool”. They hoped the logo would convey something about creating an authentic life and making a living at something you believe in, in a place you love, with people you really like to be with.

I couldn’t find any working links back to in the 15 minutes I spent searching around, but many sites mirror the same story. Wikipedia references what appears to be one of the sources over at So while I can’t link a solid article from Cisco at the moment, my magic 8-ball tells me “all signs point to yes”

If Ping, Then Bling

June 19th, 2011 No comments

There’s something soothing about a visual heartbeat.

So I was chilling at the Starbucks near me this morning. In fact, I still am right now. It’s pretty sweet that they offer free wifi, but it tends to be laggy and unreliable due to having gobs of leeches like me suckiing it up. I’m often in the middle of waiting for a web page to reload or an ssh session to do something, and I wonder to myself “frick, am I even still connected?”. So I wrote a little script to help keep me from having to think much (my favorite kind of scripts).

I basically wanted a script that would make something blink on my laptop for a moment on each successful return of an ICMP echo request (ping). Sort of a visual heartbeat. While ping is a terrible measure of whether your layer 3 path will support TCP, without a layer 3 path you will get no ping. So it’s good enough. I decided to use the “standby” light, since it wouldn’t be doing a whole lot while the laptop was actually running. Capslock, numlock, etc. It can be any light as long as it typically holds one state or the other. I’m posting a version of the script here that’s much simpler and uses the ThinkPad’s “ThinkLight” as the bling source. I think it’s easier to take away from this script exactly what’s going on and how to modify it to your liking.

I’m actually fairly happy to have been annoyed just enough by the connection at Starbucks to get motivated to write this. As a network engineer I’m constantly on the road trying to connect to this or that, or what I’m doing depends on constant connectivity to thus or thus. Not having to check a bunch of terminal windows for heartbeats will be great.

# - If ping, then bling.

# Typically you've got to be root to mess with changing sysfs/proc values
if [ "$(id -u)" != "0" ]; then
   echo "This script must be run as root"
   exit 1

# Script spits out tons of crap if there are no args.  saving sanity.
if [ -z $1 ] ; then
  echo "Please supply an IP address or hostname to ping"
  exit 1

while true ;
  # we're already seeing the bling from the ping, we don't need stdout too.
  # dialing in a longish return time since this is a "are we still connected" test
  # and not a "how fast is my connection" test.
  ping -c1 -W3 $1 > /dev/null
  if [ $? -eq 0 ] ; then
    state_before=$(head -1 /proc/acpi/ibm/light | awk '{ print $2 }')
    echo "on" > /proc/acpi/ibm/light
    sleep 0.2
    echo "off" > /proc/acpi/ibm/light
    echo $state_before > /proc/acpi/ibm/light
    sleep 0.8

exit 0
Categories: Uncategorized Tags: , , ,

Netting the Botnets with Cisco ASA Without a License

May 14th, 2011 4 comments

So I was tinkering with my ASA the other day. I was interested in this neat Botnet Traffic Filter thingy they’d been clamoring about. Cisco frequently pitches how their products are made with magic and rainbows and cruelty-free unicorn meat, and I tend to be a bit skeptical. But a lot of people have been talking about it recently in my circles, and I really can’t help but tinker with things anyways.

After some reading, Cisco words it like the Botnet Filter is pretty much useless without a proper license. However it is enabled and ready to use in all ASAs 8.2(x) and above… the license only activates the subscription service, the base functionality works just fine. Below is a script I wrote to manually apply and update blacklists using the Botnet Filter on an ASA without bothering with a subscription license. It’s a bash script which does most of the work and depends additionally on the expect scripting interpreter for operating on the ASA itself. The script looks for an external tftp server but can be easily written to use a local /tftpboot directory instead. Older versions of the script failed seldom but in amusingly spectacular ways, so the current version is somewhat lengthy due to the sanity checks I built into it.

A big problem with blacklists tends to be keeping them current. A stale blacklist is worse than useless as the IPs may belong to legitimate sites after some time. I’ve used the lists over at Emerging Threats for a while now, and they’re very frequently updated. The script can be easily modified for use with any published or local list.. 5 minutes of work adapted this script from using the C&C list to the larger “-ALL” list. Just do some find/replace magic and modify the regex syntax that changes ACL entries into dynamic-filter formatted “address x.x.x.x m.a.s.k” lines.

I apologize in advance for the terrible line wrapping in the code, I need to find a new theme. Note that the box running this is OpenBSD, you’ll probably have to change your bash path. UUOC police: It’s my cat and I’ll do what I want with it.

Ez-wget links to the below script and the larger “-ALL” variant as a modification example.



# - written by Iggdawg
# This script uses a feature in the Cisco ASA Botnet Filter feature. Although
# a licensed feature that requires a paid subscription, this feature also
# allows administrators to use the "dynamic-filter blacklist" directive for
# manual blacklisting.  Emerging Threats (
# publishes well maintained blacklists from many sources. This script applies
# that list as a manual blacklist on the ASA, and keeps it up to date with diffs
# rather than removing and re-applying the list every time to change as little
# as possible with each transaction.

# Variables, modify to your liking
export PATH

# NOTE: I use scp with certificates to ransport stuff to the tftp server.
# Expect the script to fail if you're not set up to do this.
TFTPSERV="tftp server IP address"
FWIP="firewall IP address"
USERNAME="tftp server user"
FWUSERNAME="firewall user"
PASSWORD="firewall password"
ENPASSWORD="firewall enable password"
FWHOSTNAME="firewall hostname"

#Blacklist Revisions
touch $BASEPATH/emerging-PIX-CC.rev
Rev0="$(cat $BASEPATH/emerging-PIX-CC.rev)"
Rev1="$(lynx --source"

# script depends on expect, check for it

EXP="$(which expect)"

if [ $? -ne 0 ] ; then
  echo "Expect binary not found, exiting"
  exit 1
elif [ -e "$EXP" ] ; then
  echo "Expect binary found, running"

# check list revision

if [ -s $BASEPATH/emerging-PIX-CC.rev ] ; then
  if [ $Rev0 -ge $Rev1 ] ; then
    echo "Current revision $Rev1 matches last revision processed $Rev0, Exiting"
    exit 0
    echo "Current revision $Rev1 is newer than last revision processed $Rev0, Working"
  echo "No existing blacklist revision number. Possible file errors. Starting from scratch with $Rev1"
  echo "Snagging most current list:"
  wget -O $BASEPATH/emerging-PIX-CC.rules

  # update revision now so script won't re-run in case of some random failure:
  awk '/Rev/ {print $3}' $BASEPATH/emerging-PIX-CC.rules > $BASEPATH/emerging-PIX-CC.rev

  # start processing
  # rewrite ET-drop to ET-cc so the list is consistant, then parse
  sed 's/ET-drop/ET-cc/g' $BASEPATH/emerging-PIX-CC.rules | egrep "^access-list ET-cc deny" $BASEPATH/emerging-PIX-CC.rules | sed 's/access-list ET-cc deny ip/address/g;s/host //g;s/any/' | awk '{print $1,$2,$3}' > $BASEPATH/emerging-PIX-CC.rules.pix

  # can't verify current version, remove all old entries and apply current list.
  # this will be a temporary list, preserving "raw" list so diffs don't break next time
  echo "no dynamic-filter blacklist" > $BASEPATH/emerging-PIX-CC.rules.pix.tmp
  echo "dynamic-filter blacklist" >> $BASEPATH/emerging-PIX-CC.rules.pix.tmp
  cat $BASEPATH/emerging-PIX-CC.rules.pix >> $BASEPATH/emerging-PIX-CC.rules.pix.tmp

  chmod 666 $BASEPATH/emerging-PIX-CC.rules.pix.tmp
  chown nobody:nogroup $BASEPATH/emerging-PIX-CC.rules.pix.tmp

  echo "Sending files to TFTP server"

  echo "emerging-PIX-CC.rules.pix..."
  scp $BASEPATH/emerging-PIX-CC.rules.pix.tmp $USERNAME@$TFTPSERV:/tftpboot/emerging-PIX-CC.rules.pix.tmp

  # log into the firewall and tell it to snag the diffs
  # uncomment to call expect script from its own file
  #$EXP /some/script

  $EXP - << EndMark   spawn ssh -l $FWUSERNAME $FWIP   expect "*assword:"     exp_send -- "$PASSWORD\r"   expect "$FWHOSTNAME>"
    exp_send -- "enable\r"
  expect "Password:"
    exp_send -- "$ENPASSWORD\r"
  expect "$FWHOSTNAME#"
    exp_send -- "
  copy /noconfirm tftp://$TFTPSERV/emerging-PIX-CC.rules.pix.tmp running-config
  expect "$FWHOSTNAME#"
    exp_send -- "exit\r"

exit 0

echo ""
echo ""
echo ""
# If old revision exists but the list is missing, script will diff against an
# empty file and just use whole current list. ASA silently dismisses
# duplication of existing address entries, so this is not harmful.
if [ -e $BASEPATH/emerging-PIX-CC.rules.pix ] ; then
  mv $BASEPATH/emerging-PIX-CC.rules.pix $BASEPATH/emerging-PIX-CC.rules.pix.old
  echo "Revision file exists, but last blacklist file missing. Will apply whole list."
  touch $BASEPATH/emerging-PIX-CC.rules.pix.old

# clean up
echo "" > $BASEPATH/emerging-PIX-CC.rules.egress.pix

# grab current
echo "Snagging most current list:"
wget -O $BASEPATH/emerging-PIX-CC.rules

# update revision now so script won't re-run in case of some random failure:
echo "Updating revision"
awk '/Rev/ {print $3}' $BASEPATH/emerging-PIX-CC.rules > $BASEPATH/emerging-PIX-CC.rev

# start processing
# rewrite ET-drop to ET-cc so the list is consistant, then parse
sed 's/ET-drop/ET-cc/g' $BASEPATH/emerging-PIX-CC.rules | egrep "^access-list ET-cc deny" $BASEPATH/emerging-PIX-CC.rules | sed 's/access-list ET-cc deny ip/address/g;s/host //g;s/any/' | awk '{print $1,$2,$3}' >> $BASEPATH/emerging-PIX-CC.rules.pix

echo "Processing blacklist diffs"
diff $BASEPATH/emerging-PIX-CC.rules.pix $BASEPATH/emerging-PIX-CC.rules.pix.old | grep ^\< | sed 's/\< //g' > $BASEPATH/emerging-PIX-CC.rules.ingress
diff $BASEPATH/emerging-PIX-CC.rules.pix $BASEPATH/emerging-PIX-CC.rules.pix.old | grep ^\> | sed 's/\> //g' > $BASEPATH/emerging-PIX-CC.rules.egress

# check for errors in processing
echo "" > $BASEPATH/ingress.exceptions
echo "" > $BASEPATH/egress.exceptions

echo "Blacklist diff errors:"
echo ""

awk '{print $2}' $BASEPATH/emerging-PIX-CC.rules.egress | while read LINE ; do
  grep $LINE $BASEPATH/emerging-PIX-CC.rules.ingress > $BASEPATH/ingress.exceptions
echo "$BASEPATH/emerging-PIX-CC.rules.ingress:"
cat $BASEPATH/ingress.exceptions

awk '{print $2}' $BASEPATH/emerging-PIX-CC.rules.ingress | while read LINE; do
  grep $LINE $BASEPATH/emerging-PIX-CC.rules.egress > $BASEPATH/egress.exceptions

echo "$BASEPATH/emerging-PIX-CC.rules.egress:"
cat $BASEPATH/egress.exceptions

# bring it all together and dump it on a tftp server
echo "Combining diffs"

echo "dynamic-filter blacklist" > $BASEPATH/emerging-PIX-CC.rules.diff.pix

sed 's/^/no\ /g' < $BASEPATH/emerging-PIX-CC.rules.egress >> $BASEPATH/emerging-PIX-CC.rules.egress.pix
cat $BASEPATH/emerging-PIX-CC.rules.egress.pix $BASEPATH/emerging-PIX-CC.rules.ingress >> $BASEPATH/emerging-PIX-CC.rules.diff.pix

# some tftp servers are weird about permisssions
chmod 666 $BASEPATH/emerging-PIX-CC.rules.diff.pix
chown nobody:nogroup $BASEPATH/emerging-PIX-CC.rules.diff.pix

chmod 666 $BASEPATH/emerging-PIX-CC.rules.pix
chown nobody:nogroup $BASEPATH/emerging-PIX-CC.rules.pix

echo "Sending files to TFTP server"

echo "emerging-PIX-CC.rules.pix..."
scp $BASEPATH/emerging-PIX-CC.rules.pix $USERNAME@$TFTPSERV:/tftpboot/emerging-PIX-CC.rules.pix

echo "emerging-PIX-CC.rules.diff.pix..."
scp $BASEPATH/emerging-PIX-CC.rules.diff.pix $USERNAME@$TFTPSERV:/tftpboot/emerging-PIX-CC.rules.diff.pix

# log into the firewall and tell it to snag the diffs
# uncomment to call expect script from its own file
#$EXP /some/script

$EXP - << EndMark spawn ssh -l $FWUSERNAME $FWIP expect "*assword:"   exp_send -- "$PASSWORD\r" expect "$FWHOSTNAME>"
  exp_send -- "enable\r"
expect "Password:"
  exp_send -- "$ENPASSWORD\r"
expect "$FWHOSTNAME#"
  exp_send -- "
copy /noconfirm tftp://$TFTPSERV/emerging-PIX-CC.rules.diff.pix running-config
expect "$FWHOSTNAME#"
  exp_send -- "exit\r"

exit 0
Categories: Uncategorized Tags: , , ,