IRC notification Bot using Ruby Cinch

| No Comments | No TrackBacks
My RFID door controller written in Bash has been going for a month now, and has proven to be reasonably stable.  I wanted to add some kind of notification that people were entering/leaving the Maker space.  Since a portion of the group hangs out in the freenode IRC channel #grmakers I figured I'd hack up a quick command line to IRC bot.  This is common in the Java world for use with various continuous integration (CI) systems.  Both Logstash and irccat exist.  I don't have Java installed on the door controller, and doing so seemed like a bit of a hassle.  I do have Ruby, and Ruby has a very nice IRC bot builder gem called Cinch.

Cinch is primarily designed to be a bot, and respond to messagaes directed at it on the IRC channel.  With a lot of searching I got something working.  This script should be started up from daemontools or init.  It listens on a TCP port, and gates any text pasted into the TCP socket through to the IRC channel.  Note that this has no authentication or data validation, so only use this bound to localhost on a dedicated machine.


require 'socket'
require 'cinch'

MY_CHANNEL = "#door-bots"
MY_LISTENING_PORT = 2000

class MonitorBot
  include Cinch::Plugin

  listen_to :monitor_msg, :method => :send_msg

  def send_msg(m, msg)
     Channel(MY_CHANNEL).send "#{msg}"
  end

end

bot = Cinch::Bot.new do
  configure do |c|
    c.nick            = "door"
    c.realname        = "Door Bot"
    c.user            = "myuser"
    c.server          = "irc.freenode.org"
    #c.port            = 7000
    #c.ssl             = true
    c.channels        = [MY_CHANNEL]
    c.verbose         = false
    c.plugins.plugins = [MonitorBot]
  end
end

def server(bot)
  print "Thread Start\n"
  server = TCPServer.new '127.0.0.1', MY_LISTENING_PORT
  loop do
    Thread.start(server.accept) do |client|
      message = client.gets
      bot.handlers.dispatch(:monitor_msg, nil, message)
      client.puts "Ok\n"
      client.close
    end #Thread.Start
  end #loop
end

Thread.new { server(bot) }
bot.start

Sending text to the channel is easiest to do using Netcat:
echo "Hello from the command line" | nc localhost 2000
Some GRMakers members pointed out existing solutions that I missed that would have been far easier to implement. Eric Raymond wrote irker which works similarly to the above but is more full featured and accepts commands as JSON. Even better suited to command-line scripting is "ii" which creates a virtual filesystem with input and output pipes created dynamically for each joined channel.  

Simple Door Access in bash

| No Comments | No TrackBacks
RFID Door Access controller using Raspberry Pi, AdaFruit PN532 RFID reader, and Wiring Pi and implemented as 29 lines of bash.  GPIO 17 (0 in WiringPi) is used to activate the door release and libnfc provides the nfc-poll command that scans for a card.

(Edited Nov 2. I was reminded that the backtick (`) has been deprecated for the more POSIX friendly $() operator. Fixed but not tested.) 
 
#!/bin/bash

FILENAME='/home/pi/door_basher/allowed_tags.txt'
LOGNAME='/home/pi/door_basher/access_log.txt'

gpio mode 0 out
gpio write 0 0


while true; do 
   TIMESTAMP=`date`
   NFC=$(nfc-poll 2>&1 |grep "UID")

   if [ $? -eq 0 ] ; then
       CARDID=$(echo $NFC|cut -f2 -d ":"|sed  -e 's/[ \t]//g')
       NAME=$(egrep "^$CARDID" $FILENAME) 
       if [ $? -eq 0 ] ; then
          NAME=$(egrep "^$CARDID" $FILENAME|awk -F $'\t' '{ print $2;}') 
          echo "$TIMESTAMP ALLOW $NAME ($CARDID)" | tee -a $LOGNAME 
          gpio write 0 1
          sleep 10
          gpio write 0 0
       else 
          echo "$TIMESTAMP DENIED $NAME ($CARDID)" | tee -a $LOGNAME
          sleep 2
       fi
    fi
done

The allowed_tags.txt file is a tab delimited list of the MiFare card UIDs and the username. For centralized management use a cron job to update this file from a central webpage and to upload the access log.
7e33456e      Mark Farver
763a45df       User Two
It may be wise to start this with init or damontools, so it will always be running. It could probably use some more testing and thought. It does not do a very good job of guaranteeing the door will be re-locked if the script crashes or is aborted.

Custom GrrCON conference badge

| No Comments | No TrackBacks
Finished the admission badges for the GrrCON hacking convention here in Grand Rapids.  I modified the basic Arduino Uno design, converting it to run off a battery, adding a LED signboard, and putting it on a custom PCB that matches the conference logo.  

To keep costs low I ran the processor and LEDs direct from the battery. This was a mistake.  I should have used a boost regulator, the conference chose white and purple LEDs for some of the badges.  These need much higher forward voltages (2.5 and 2.7V, respectively).   Without a boost regulator the battery life is quite short, as it drops below the LED voltage pretty quickly.  Future version will use something like the Microchip MCP1623 to boost the voltage and keep it steady as the battery discharges. 

USB video playback on Sony Bravia TVs

| No Comments | No TrackBacks
I was trying to play a video from a USB stick on a Sony Bravia TV KDL-55EX500.  

The TV is a little picky about the video format.  I spent a few minutes figuring out what combination of resolution and video settings were needed to get full screen playback.  The TV seems to like MPEG-2 video and 1920x1088 resolution. The command-line for Linux's avconv command was this:

 
avconv -i input.mpg -f mpeg -target ntsc-dvd  -s 1920x1088 output.mpg

I also wanted to turn off the annoying "Bong" noise the TV makes in startup but couldn't find it anywhere in the settings menu. Turns out Sony added that option back in later firmware. If you upgrade the TVs firmware to the latest version you can turn it off.

Juniper JunOS USB partition table rescan

| No Comments | No TrackBacks
As an update to my upgrading Juniper EX switches from USB.  Upgrading from a USB thumb drive works well, but if you don't have one handy you might try to use another "dual use" mass storage device like a phone or Kindle.  Problem is the delay while that device initializes causes JunOS to fail to read the partition table.  You will have a /dev/da1 entry, but no /dev/da1s1:

umass1: Amazon Amazon Kindle, rev 2.00/1.00, addr 3
da1 at umass-sim1 bus 1 target 0 lun 0
da1:  Removable Direct Access SCSI-2 device
da1: 40.000MB/s transfers
da1: Attempt to query device size failed: NOT READY, Medium not present
(da1:umass-sim1:1:0:0): READ CAPACITY. CDB: 25 0 0 0 0 0 0 0 0 0
(da1:umass-sim1:1:0:0): CAM Status: SCSI Status Error
(da1:umass-sim1:1:0:0): SCSI Status: Check Condition
(da1:umass-sim1:1:0:0): UNIT ATTENTION asc:28,0
(da1:umass-sim1:1:0:0): Not ready to ready change, medium may have changed
(da1:umass-sim1:1:0:0): Retrying Command (per Sense Data)
The workaround seems to be to issue a "camcontrol rescan da1" to rescan the parition table.

This issue only shows up on some versions of Junos, and the camcontrol command is also only available on some versions of Junos. 
I found a new trick in iptables I wasn't aware of.  Turns out iptables tracks all connections, even ones that are not going to be NAT'd.  On a busy webserver or router this means iptables is wasting resources tracking connections when it should be just routing.

The raw table in iptables can be used to set a NOTRACK flag on a packet, and that packet will not traverse the ip_conntrack stuff.

So for a busy webserver, you could disable tracking for web connection states:
iptables -t raw -A PREROUTING -d <server IP> -p tcp --dport 80 -j NOTRACK
iptables -t raw -A PREROUTING -s <server IP> -p tcp --sport 80 -j NOTRACK

Or on a machine that is routing between several internal networks and also NATing external connections you could disable tracking for the internal to internal stuff.
iptables -t raw -A PREROUTING -s 172.16.0.0/16 -d 172.16.0.0/16 -j NOTRACK

On one of our core Linux routers the number of ip_conntrack entries dropped from an average of 65-70k down to about 2k. 

Upgrading Juniper EX series switches from USB.

| No Comments | No TrackBacks

This is for my notes. Generally I use this to upgrade the firmware of an EX4200 switch to the same JunOS version as the rest of a virtual chassis, BEFORE connecting the VC cables.  I'm doing this from memory, so if there are any mistakes let me know.

You will need to have access to a shell. The "root" user logs into shell automatically, other users should run "start shell"

From the shell run these commands:

 # mkdir /mnt/usb

Insert the USB stick (FAT32 formatted) into the port at the back of the switch. It should have the firmware on it, generally in a file named something like "jinstall-ex-10.3R3.4-domestic-signed.tgz"

 # mount -t msdosfs /dev/da1s1 /mnt/usb"

Note that tab completion works on Junos, to save some typing just enter the frist few characters of the filename and hit "tab"

 # cp /mnt/usb/jinstall-ex-10.3R3.4-domestic-signed.tgz /var/tmp 

If the switch is running firmware older than 10.3 you should upgrade the loader too:

 # cp /mnt/usb/jloader-ex-3242-11.3I20110326_0802_hmerge-signed.tgz /var/tmp
 # umount /mnt/usb
 # cli
At the ">" cli prompt: If the firmware on the switch is older than 10.3 you will need to install the updated jloader
 > request system software add /var/tmp/jloader-ex-3242-11.3I20110326_0802_hmerge-signed.tgz
then:
 > request system software add /var/tmp/jinstall-ex-10.3R3.4-domestic-signed.tgz reboot

Dual IP stack for twice the love

| No Comments | No TrackBacks
Several weeks too late for world IPV6 day: My first directly connected dual stack router (no tunnel). In this case a Juniper MX-80 connected to TW Telecom.
mfarver@RTR2> ping 2001:470:1f0e:d23::1
16 bytes from 2001:470:1f0e:d23::1, icmp_seq=0 hlim=62 time=46.032 ms
16 bytes from 2001:470:1f0e:d23::1, icmp_seq=1 hlim=62 time=45.363 ms
16 bytes from 2001:470:1f0e:d23::1, icmp_seq=2 hlim=62 time=44.284 ms

LLDP: Your guide to the land of lost servers

| No Comments | No TrackBacks

We often use LLDP (Link Layer Discovery Protocol) to find out which switches are uplinked to other switches. Each switch sends identification packets to the opposing switch identifying its name and the port number it is broadcasting from.

Juniper EX Example

user@core1> show lldp neighbors    
Local Interface    Parent Interface    Chassis Id          Port info     System Name
ge-2/0/7.0         -                   00:26:f2:50:85:c0   47           data_sw1 
ge-2/0/14.0        ae15.0              00:26:f5:b1:3d:40   1            data_sw2 
ge-2/0/2.0         ae9.0               b4:39:d7:89:48:40   1            pub_sw1
ge-1/0/12.0        ae31.0              b4:39:d3:1a:2c:c0   1            pub_sw2 
ge-2/0/12.0        ae31.0              b4:39:d2:1a:2c:c0   2            pub_sw2

Makes it a little simpler to audit the wire maps. I wondered if it would be possible to have servers broadcast as well.

Turns out they can. RHEL6 ships with lldpd already ready to go. Just install the package and start the daemon. We are running CentOS 5 still, and I wasn’t able to find a recent package for that. Eventually I found a src RPM for lldpd 0.4.2 and just updated it. You can find the updated version here.

HP Procurve Example

SW2# show lldp info remote

 LLDP Remote Devices Information
  LocalPort | ChassisId                 PortId PortDescr SysName               
  --------- + ------------------------- ------ --------- ----------------------
  2         | 50 c5 8f b7 33 c0         36     vme.0     pub-sw1              
  19        | 78 2b cf 16 14 f0         78 ... eth2      cache-1.example.com
  20        | 78 2b cf 15 a0 2f         78 ... eth2      web-3.example.com
  21        | 78 2b cf 16 7c 24         78 ... eth2      web-2.example.com
  22        | 78 2b cf 15 bf 9e         78 ... eth2      web-1.example.com

You can query LLDP info manually as noted above, or you can get it via SNMP MIB: lldpRemoteSystemsData 1.0.8802.1.1.2.1.4. Interestingly it looks like you might be able to get remote IP information this way. The lldpd daemon also supports CDP for Cisco environments and a few other features that we don’t use. Windows hosts can broadcast the same data using the haneWIN LLDP Agent. Adding LLDP support is a simple add to your Puppet or Chef recipes, and makes a handy backup to manual wiremaps that your network team will appreciate.

With rainbows, black is the most worrisome color

| No Comments | No TrackBacks
This has been at the back of my mind for years now.  Every company I've worked with stored MD5 hashed credit card numbers in the DB so "search by CC number" works.  As far as I know no one has released a rainbow table of all of the common credit card number prefixes hashed, but its getting way too easy to do so.  33.1 billions hashes per second.... yikes.

http://blog.zorinaq.com/?e=42

Back of the envelope, this system could calculate hashes for all of the Mastercard or Visa prefixes in 20 days or so.. faster if it concentrates on the most common BIN numbers.  Discover cards would take less than a week.

So reconsider if you really need a "search by CC number" function.  If you do switch to a more computationally expensive hash.   Consider adding a site specific salt so an attacker needs to generate a unique set of tables for your site.

Find recent content on the main index or look in the archives to find all content.

Powered by Movable Type 4.24-en