There is nothing new about port knocking to hide remote access to a remote system or network. However its usually implemented as a hack thats done on a single host thats sitting at a remote site. If your running a Cisco router the only method to get port knocking working is to create an EEM applet. I have seen several port knocking EEM applets online, but none of them seem very good and they usually work by swapping out a less secure ACL for a more secure one.

After watching my server logs  get obliterated by some knuckle head trying to brute force their way into it, I decided to get port knocking working on a Cisco router. The following EEM applet uses an extended ACL thats tied to the inbound WAN interface of the router. The ACL has a permit statement that will log a certain packet type; the logs will be updated with a notification that contains the originating IP address. The EEM applet monitors the logs and will be triggered when it sees the ACL. The applet will then pull out the knocking IP address and temporarily add it to the same inbound ACL allowing enough time to establish a connection from the originating machine. After 15 seconds have passed, the script will drop the permit line that was added to the ACL.

!! SAMPLE ACL !!
 
ip access-LIST extended outside-in4
 remark *** KNOCK ***
 permit udp ANY ANY eq 65535 LOG
 remark *** TRUSTED ***
 permit tcp ANY ANY established
 remark *** DENIED ***
 deny   tcp ANY ANY
 remark *** PERMITED ***
 permit ip ANY ANY
 
!! WAN Interface !!
 
interface Cable-Modem0/1/0
 ip access-group outside-in4 in
 
!! KNOCK_ACL env Variable !!
 
event manager environment KNOCK_ACL outside-in4
 
!! Port Knocking EEM applet !!
 
event manager applet KNOCK
 event syslog pattern "%SEC-6-IPACCESSLOGP: list $KNOCK_ACL permitted *"
 action 1.0 regexp "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" $_syslog_msg ADDR
 action 1.1 regexp "\([0-9]+\)," "$_syslog_msg" PORT
 action 1.2 regexp "[0-9]+" "$PORT" PORT 
 action 2.0 syslog msg "Received a knock from $ADDR on port $PORT..."
 action 2.1 syslog msg "Adding $ADDR to the $KNOCK_ACL ACL"
 action 3.0 cli command "enable"
 action 3.1 cli command "configure terminal"
 action 3.2 cli command "ip access-list extended $KNOCK_ACL"
 action 3.3 cli command "1 permit tcp host $ADDR any eq 22"
 action 4.0 WAIT 15
 action 5.0 syslog msg "Removing $ADDR to the $KNOCK_ACL ACL"
 action 6.0 cli command "no permit tcp host $ADDR any eq 22"
 action 6.1 cli command "exit"

The only tricky thing in the above example is creating a good regex expression… Knocking with a UDP/65535 packet and immediately connecting to the routers WAN IP address will allow you to SSH into a server on the other side. The following is me crafting a simple UDP packet using hping3 under Linux.

$ sudo hping3 -2 ROUTERIP -p 65535 -c 1; ssh ROUTERIP

A few caveats:

  • Usually any/any ACL’s are not good, but in my case, this is a home router doing PAT and a DHCP client on the WAN interface.
  • Show active EEM policies: show event manager policy active
  • Show EEM history: show event manager history events
  • Validate the ACL is getting hit: show access-list outside-in4
  • The default EEM watchdog will terminate the applet after 20 seconds. MAXRUN will need to be changed if you want the applet to wait longer then 15 seconds before auto terminating.
  • The ACL can be modified to log packet options such as special ToS, DSCP values in addition to ports.
  • I recommend not using other log statements in the same ACL, doing so will require making a more custom applet.
  • If your trying to log into the router itself via an ACL on a TTY line be mindful of any service-polices you have bound to the control-plane.
18. August 2014 · Comments Off · Categories: Linux Admin, Linux Security

Required Debian/Ubuntu Packages


dmsetup Linux Kernel Device Mapper userspace library
cryptsetup-bin Disk encryption support – command line tools

tcplay Free and simple TrueCrypt Implementation based on dm-crypt

Filesystem Encryption


cryptsetup –cipher aes-xts-plain64 –key-size 512 –verify-passphrase luksFormat /dev/sdb1

* The LUKS-formatting command above has the following options:

–verify-passphrase – ensures the passphrase is entered twice to avoid an incorrect passphrase being used
-c aes -s 256 – uses 256-bit AES encryption
-h sha256 – uses the 256-bit SHA hashing algorithm

Creating a Filesystem


cryptsetup luksOpen /dev/sdb1 16GB

mkfs -t ext3 -m 1 -O dir_index,filetype,sparse_super /dev/mapper/16GB

* The mkfs options above are as follows:

-t ext3 – create an ext3 filesystem
-m 1 – reduce the reserved super-user space down from the default of 5% to 1% of the total size – useful for large filesystems
-O dir_index – speed-up lookups in large directories
-O filetype – store filetype info in directories
-O sparse_super – create fewer superblock backup copies – useful for large filesystems

Mounting a Filesystem


cryptsetup luksOpen /dev/sdb1 16GB
mount /dev/mapper/16GB /mnt

* To mount a truecrypt partition:

tcplay -m 16GB -d /dev/sdc1
dmsetup remove 16GB

Change Passwords on a Filesystem


LUKS supports eight key slots per partition.

To add and remove keys from the slots:

cryptsetup luksAddKey
/and/
cryptsetup luksRemoveKey

Which slots have keys:

cryptsetup luksDump

Headers on a Filesystem


cryptsetup luksHeaderBackup /dev/sdb1 –header-backup-file /tmp/somefile

Replace luksHeaderBackup with luksHeaderRestore to restore the old keys again.

* Note that the header backup should be saved to a secure place (preferably another LUKS partition on a USB stick)

Unmount a Filesystem


Use umount first then,

cryptsetup luksClose 16GB
/or/
dmsetup remove 16GB
/or/
dmsetup remove_all

* dmsetup remove_all will flush all mapped block devices.

Source & Additional Documentation


https://help.ubuntu.com/community/EncryptedFilesystemsOnRemovableStorage
http://superuser.com/questions/431820/how-to-change-pass-phrase-of-full-disk-encryption
http://askubuntu.com/questions/95137/how-to-change-luks-passphrase
http://www.linuxcommand.org/man_pages/cryptsetup8.html

There are a lot of programs out there that will locate duplicate files on a filesystem. I however, prefer to use standard system utilities on my home system. So I wrote a quick shell script to identify duplicate files and either create hard links between them or prompt me on which files to delete outright.

Feel free to review, modify or use this script however you see fit. Remember you do so at your own risk!

#!/bin/bash
## Created by: deaves
# Identify duplicate files in current working directory by file hash and take user specified action.
#
## Requires: dialog, findutils
 
# Required script variables.
filehash_dump="/tmp/$USER-$$.hash"
dialog_select="/tmp/$USER-$$.select"
report_file="$HOME/uDupeReport-$$.txt"
 
# FUNCTION: End Script if error.
DIE() {
 echo "ERROR: Validate \"$_\" is installed and working on your system."
 exit 0
}
 
# Validate script requirements are meet.
type -p dialog > /dev/null || DIE
 
# Create the filehash_dump file containing MD5 finger prints.
find ./ -type f -exec md5sum $1 {} \; | tee "$filehash_dump"
 
# Prompt user for next action to take w/6 hour wait before continuing on.
echo
read -t 21600 -p "DELETE or LINK duplicate files?
If NO response create a report: $report_file
Type command in CAPS: " OPT
echo
 
# Begin loop with all file hashes.
awk '{print $1}' "$filehash_dump" | sort | uniq | while read HASH
 do
 COUNT=0
 
 # Read all the files of the hash into an Array.
 eval FILES=( "$(grep ^"$HASH" "$filehash_dump" | sed 's/'"$HASH"'  //g;s/^/"/g;s/$/"/g')" )
 
if [ "$OPT" == "DELETE" ]; then
 
 # If more than a single file exists then take action.
 if [ "${#FILES[@]}" -gt "1" ]; then
 
  # Prompt user on which file to keep and store it in dialog_select.
  dialog --backtitle "$0 - uDupe File Killer" \
    --title "Select the file to keep. All others files will be deleted!" \
    --menu "HASH: $HASH\nTYPE:$(file "${FILES[${COUNT}]}" | awk -F': ' '{$1=""; print}')" \
    17 70 14 \
  $(while [ "$COUNT" -lt "${#FILES[@]}" ]; do
   printf " $COUNT "
   printf "${FILES[${COUNT}]}" | sed 's/ /_/g'
   let COUNT++
  done) 2> "$dialog_select"
 
  # Trap error code from dialog & perform actions.
  if [ "$?" == "0" ]; then
 
   # User selected a file.
   ANS=`cat "$dialog_select"`; rm "$dialog_select"
   unset FILES[${ANS}]
 
   # Perform action against unselected files.
   for file in "${FILES[@]}"; do
    rm "$file"
   done
 
  else
 
   # User choose to cancel.
   rm "$dialog_select"
   rm "$filehash_dump"
   break
 
  fi
 
 fi
 
elif [ "$OPT" == "LINK" ]; then
 
 # hardLink all the duplicate files to save disk space.
 if [ "${#FILES[@]}" -gt "1" ]; then
  echo "Creating hardlink: $HASH"
  echo " > ${FILES[0]}"
  ORIG="${FILES[0]}"; unset FILES[0]
  for file in "${FILES[@]}"; do
   echo " > $file"
   rm "$file"
   ln "$ORIG" "$file"
  done
 fi
 
else
 
 # Just Report all the duplicate files.
 [ ! -f "$report_file" ] && { printf "uDupe Report: $(pwd)\n$(date)\n\n" > "$report_file" ;}
 if [ "${#FILES[@]}" -gt "1" ]; then
  echo "HASH: $HASH"
  echo "TYPE:$(file "${FILES[${COUNT}]}" | awk -F': ' '{$1=""; print}')"
  for file in "${FILES[@]}"; do
   echo " > $file"
  done
  echo
 fi | tee -a "$report_file"
 
fi
 
done
 
# Script is finished, delete the filehash_dump file.
[ -e "$filehash_dump" ] && { rm "$filehash_dump" ; }
06. January 2012 · Comments Off · Categories: Linux Scripts
#!/bin/bash
## Created By: deaves
# Quickly update or delete a zonefile host entry.
#
## Requires: dnsutils, netcat, sshfp (python script)
 
DOMAIN="foo.com"
SERVER="ns.foo.com"
 
##### Begin Script #####
 
function DELETE () {
### Purge DNS entry for HOST ###
nsupdate << _EOF_
  server ${SERVER}
  update delete ${HOST}.${DOMAIN} A
  update delete ${HOST}.${DOMAIN} SSHFP
  send
_EOF_
}
 
function UPDATE () {
### Update DNS record for HOST ###
nsupdate << _EOF_
  server $SERVER
  update add $HOST.$DOMAIN 3600 A $IPv4
  `netcat -zv $IPv4 22 2> /dev/null && sshfp -s $IPv4 2> /dev/null | awk '{print "update add '$HOST.$DOMAIN' 3600",$2,$3,$4,$5,$6}'`
  send
_EOF_
}
 
function usage () {
  ### Display the script arguments.
  printf "Usage: $0 [-du] -h <HOST> -i <IP>\n\n"
  printf "Requires one option!\n"
  printf "\t-d: Delete DNS <HOST> A and SSHFP records\n"
  printf "\t-u: Update DNS <HOST> A and SSHFP records\n\n"
}
 
while getopts "duh:i:" ARG; do
  case "${ARG}" in
    d) [ -z $ACTION ] && { ACTION="D"; };;
    u) [ -z $ACTION ] && { ACTION="U"; };;
    h) HOST="$OPTARG";;
    i) IPv4="$OPTARG";;
    ?) echo "Invalid option -$OPTARG"; exit 1;;
  esac
done 2> /dev/null
 
[ -n "$ACTION" ] && { echo "$ACTION: $HOST ($IPv4)" ; }
 
if [ "$ACTION" == "U" ]; then
  [ -z "$IPv4" ] && { echo "Error: Missing IP" && exit 1; }
  DELETE
  UPDATE
elif [ "$ACTION" == "D" ]; then
  [ -z "$HOST" ] && { echo "Error: Missing HOST" && exit 1; }
  DELETE
else
  usage && exit 1;
fi
30. December 2011 · Comments Off · Categories: Linux Scripts, Networking
#!/bin/bash
## Created by: deaves
# Parse all router configs in a directory and dump all DHCP pool settings to STDOUT.
# Output will be a tab-separated XLS.
#
## Requires: ipcalc (http://jodies.de/ipcalc)
 
[ -z "$1" ] &amp;&amp; { echo "Please give input"; exit 1;}
 
let COUNT=0
 
printf "hostname\tpool\tnetwork\tdomain-name\tdefault-router\tdns-server\tnetbios-name-server\tnetbios-node-type\tlease\tclient_host\tclient_identifier\toption_0\toption_1\toption_2\tdhcp_excludes\t\t\n"
 
for CONFIG in $1/*; do
 
 ### Get router hostname
 RTRHOST=`grep ^"hostname" "${CONFIG}" | awk '{print $NF}'`
 
 ### Collect variables
 cat "${CONFIG}" | sed 's\   \^\g;s\;\_\g' | while read LINE; do
  eval ARRAY=( `echo '$LINE'` )
 
  ### DHCP pool name and excludes
  if [ "${ARRAY[0]} ${ARRAY[1]} ${ARRAY[2]}" == "ip dhcp pool" ]; then
   echo "dPOOL=\"`echo $LINE | awk '{print $NF}'`\"" &gt;&gt; "/tmp/${UID}-${PPID}.tmp"
   echo "dEXCLUDES=\"`cat ${CONFIG} | grep ^"ip dhcp excluded-address" | sed 's/ /-/g;s/ip-dhcp-excluded-address-/, /' | tr -d '[:cntrl:]' | cut -d' ' -f2-`\"" &gt;&gt; "/tmp/${UID}-${PPID}.tmp"
  fi
 
  ### Pull out DHCP Variables
  [ "${ARRAY[0]}" == "^network" ] &amp;&amp; { echo "dNETWORK=\"`ipcalc ${ARRAY[1]} ${ARRAY[2]} | grep ^Network | awk '{print $2}'`\"" &gt;&gt; "/tmp/${UID}-${PPID}.tmp" ;}
  [ "${ARRAY[0]}" == "^option" ] &amp;&amp; { echo "dOPTION${COUNT}=\"`echo $LINE | cut -d' ' -f2-`\"" &gt;&gt; "/tmp/${UID}-${PPID}.tmp" ; let COUNT++ ;}
  [ "${ARRAY[0]}" == "^default-router" ] &amp;&amp; { echo "dDEFAULTROUTER=\"`echo $LINE | cut -d' ' -f2-`\"" &gt;&gt; "/tmp/${UID}-${PPID}.tmp" ;}
  [ "${ARRAY[0]}" == "^dns-server" ] &amp;&amp; { echo "dDNSSERVER=\"`echo $LINE | cut -d' ' -f2-`\"" &gt;&gt; "/tmp/${UID}-${PPID}.tmp" ;}
  [ "${ARRAY[0]}" == "^netbios-name-server" ] &amp;&amp; { echo "dNBNAMESERVER=\"`echo $LINE | cut -d' ' -f2-`\"" &gt;&gt; "/tmp/${UID}-${PPID}.tmp" ;}
  [ "${ARRAY[0]}" == "^netbios-node-type" ] &amp;&amp; { echo "dNBNODETYPE=\"`echo $LINE | cut -d' ' -f2-`\"" &gt;&gt; "/tmp/${UID}-${PPID}.tmp" ;}
  [ "${ARRAY[0]}" == "^domain-name" ] &amp;&amp; { echo "dDOMAINNAME=\"`echo $LINE | cut -d' ' -f2-`\"" &gt;&gt; "/tmp/${UID}-${PPID}.tmp" ;}
  [ "${ARRAY[0]}" == "^lease" ] &amp;&amp; { echo "dLEASE=\"`echo $LINE | cut -d' ' -f2-`\"" &gt;&gt; "/tmp/${UID}-${PPID}.tmp" ;}
  [ "${ARRAY[0]}" == "^host" ] &amp;&amp; { echo "dCLIENTHOST=\"`echo ${ARRAY[1]}`\"" &gt;&gt; "/tmp/${UID}-${PPID}.tmp" ;}
  [ "${ARRAY[0]}" == "^client-identifier" ] &amp;&amp; { echo "dCLIENTIDENT=\"`echo $LINE | cut -d' ' -f2-`\"" &gt;&gt; "/tmp/${UID}-${PPID}.tmp" ;}
  [ "${ARRAY[0]}" == "^hardware-address" ] &amp;&amp; { echo "dCLIENTIDENT=\"`echo $LINE | cut -d' ' -f2-`\"" &gt;&gt; "/tmp/${UID}-${PPID}.tmp" ;}
 
  ### Done; dump scope to STDOUT
  if [ "${ARRAY[0]}" == "!" ] &amp;&amp; [ -e "/tmp/${UID}-${PPID}.tmp" ]; then
   . "/tmp/${UID}-${PPID}.tmp"
 
   printf "${RTRHOST}\t${dPOOL}\t${dNETWORK}\t${dDOMAINNAME}\t${dDEFAULTROUTER}\t${dDNSSERVER}\t${dNBNAMESERVER}\t${dNBNODETYPE}\t${dLEASE}\t${dCLIENTHOST}\t${dCLIENTIDENT}\t${dOPTION0}\t${dOPTION1}\t${dOPTION2}\t${dEXCLUDES}\t\t\n"
 
   let COUNT=0
   unset dPOOL dNETWORK dDOMAINNAME dDEFAULTROUTER dDNSSERVER dNBNAMESERVER dNBNODETYPE dLEASE dCLIENTHOST dCLIENTIDENT dOPTION0 dOPTION1 dOPTION2 dEXCLUDES
   rm "/tmp/${UID}-${PPID}.tmp"
  fi
 
 done
 
 unset RTRHOST
done
26. June 2011 · Comments Off · Categories: Linux Scripts, Networking
#!/bin/sh
## Created by: deaves
### Perform DNSSEC update on a DD-WRT router. ###
# This script will install bind-client and bind-tools if not already installed.
# Under normal use this script will create an additional nvram variable "wan_ipaddr_old",
# this variable is used to prevent updating the bind server if the WAN IP has not changed.
#
# CRON: */15 * * * * root DNSupdate.sh
#
## Requires: DD-WRT v24-sp2 (mega) with 3M /jffs
 
## Log last run - Debug.
#date &gt; "/jffs/tmp/nsupdate.run"
 
SERVER=""
DOMAIN=""
KEYFILE="/jffs/"
 
### Run nsupdate ###
if [ -s "/jffs/usr/bin/nsupdate" ]; then
 
 # Getting required nvram vars.
 router_name="$(nvram get router_name)"
 wan_ipaddr="$(nvram get wan_ipaddr)"
 wan_ipaddr_old="$(nvram get wan_ipaddr_old)"
 
 # Only perform nsupdate if ip has changed and wan_ipaddr is valid.
 if [ "${wan_ipaddr}" != "${wan_ipaddr_old}" ] &amp;&amp; [ "${wan_ipaddr}" != "0.0.0.0" ]; then
 
/jffs/usr/bin/nsupdate &lt;&lt; _EOF_
  server ${SERVER}
  key `awk '{print $1,$NF}' ${KEYFILE}`
  update delete ${router_name}.${DOMAIN} A
  update add ${router_name}.${DOMAIN} 3600 A ${wan_ipaddr}
  send
_EOF_
 
  nvram set wan_ipaddr_old="${wan_ipaddr}"
 fi
 
### Install requiured tools if needed. Requires 3M available. ###
elif [ ! -s "/jffs/usr/bin/nsupdate" ] &amp;&amp; [ "$(df | grep "jffs"$ | awk '{print $4}')" -ge "3000" ]; then
 
 cd /jffs; mkdir -p /jffs/tmp/ipkg
 
 # Fetch and install each required package.
 for PKG in libgcc_4.1.2-14.3_mipsel.ipk uclibc_0.9.29-14.3_mipsel.ipk libopenssl_0.9.8i-3.2_mipsel.ipk bind-libs_9.5.0-P1-1.1_mipsel.ipk bind-client_9.5.0-P1-1.1_mipsel.ipk bind-tools_9.5.0-P1-1.1_mipsel.ipk; do
 
  printf "\rDownloading: ${PKG}     "
  [ ! -e "/jffs/${PKG}" ] &amp;&amp; { wget "http://downloads.openwrt.org/kamikaze/8.09.2/brcm47xx/packages/${PKG}" &amp;&gt; /dev/null || printf " [ERROR]\n" ;}
 
  printf "\rInstalling: ${PKG}     "
  [ -e "/jffs/${PKG}" ] &amp;&amp; { ipkg install "/jffs/${PKG}" &amp;&gt; /dev/null &amp;&amp; rm "/jffs/${PKG}" || printf " [ERROR]\n" ;}
 
 done
 
 printf "\rFinished installing bind-client and bind-tools.          \n"
 
### Notify user if at a loss ###
else
 printf "Not enough free space to install bind-client and bind tools.\n"
fi
 
### Done ###
21. March 2011 · Comments Off · Categories: Linux Admin

After about a month of waiting the DreamPlug and JTAG module that I ordered was finally delivered. So far as a dedicated home server goes, the specs, physical size, price and longterm energy saving made it almost a no-brainer to purchase. However once it arrived it did not take me very long to realize that the preinstalled Ubuntu version on it was already obsolete and was not going to be supported. Without fully realizing what I was doing I quickly bricked the HostOS in an attempt to force a release update via a “do-release-upgrade” courtesy of the update-manager-core utilities. So there I was, frustrated, with a new brick of a system, and was forced to try to do a restore only to find out that there was no documentation out on the Internet to assist. I decided to document what all it took to get the DreamPlug back up and working and to install Debian on it, so hopefully I can save someone from all the pain and anguish I suffered while trying to get past the learning curve it took to get the system up and working..

Before we begin

There are a few websites and concepts that are absolutely critical with getting the DreamPlug working…

  • http://code.google.com/p/dreamplug/
    This site contains everything you need to create a USB recovery stick to restore the host OS on the device. After installing Debian I needed to boot from the USB recovery stick to modify the boot partition and make changes to /etc/fstab. !Make sure you download everything on this site and keep it in a safe place!
  • http://www.cyrius.com/debian/kirkwood/sheevaplug/install.html
    This site has very good information on working on the guru/shivaplug as well as working with U-Boot. Although a lot of the information on this site is superfluous and obsolete, it still contains a lot of awesome information which was absolutely critical for figuring things out.
  • ftp://ftp.debian.org/debian/dists/squeeze/main/installer-armel/current/images/kirkwood/netboot/marvell/sheevaplug/uInitrd
    uInitrd is the Debian installer which you will need if you want to get Debian working on the DreamPlug. !Do not download “uImage” file from there; because it does not work and you will be using the the uImage file from the code.google.com/p/dreamplug/ site!
  • http://git.marvell.com/
    Marvell’s source tree. If you wish to recompile your kernel I would recommend using the kernel from here /git clone git://git.marvell.com/orion.git/ instead of kernel.org (at least untill the DreamPlug becomes better supported).

One thing that tripped me up for a while was understanding how everything works together on the DreamPlug. These are things that are are universal between the DreamPlug the ShivaPlug, GuruPlug and several other ARM systems. U-Boot – U-Boot is nothing more then a boot loader; in the same way Grub or Lilo is. Its the closest you will be getting to a BIOS and being comfortable with it is critical in case something goes wrong and you need to do some troubleshooting.

U-Boot keeps its own set of environmental variables that tell it what and how to do things. To view, modify and delete those variables you need to use: printenv, setenv, saveenv … Before making any changes, I strongly advise doing a printenv and making a backup of what is listed.

The internal storage device is tied to USB, to access things like the built in storage, SD cards or memory sticks from U-Boot you need to start USB by doing a: usb start … To view connected usb drives and partitions do a: “usb devices” and “usb partitions” . This is important when trying to figure out how to reference devices to load your kernel.

Researching on the Internet I found some versions of U-Boot support kernels located on EXT2 partitions. The version of U-Boot that comes with the DreamPlug U-Boot 2011.06-02334-g8f495d9-dirty (Mar 01 2011 – 06:57:05) does not support EXT2, only FAT, so your /boot partition will need to be setup and formated accordingly. This will make the Debian install a little tricky because the Debian installer does not like FAT partitions; which I will explain how I got around later.

Creating and booting from a recovery USB stick

As mentioned earlier, you will want to download everything from http://code.google.com/p/dreamplug/ because its got everything you need to create a recovery USB stick. Before extracting though you need to run fdisk against it and create 2 partitions: a FAT partition for uImage and uInitrd and another for the rootfs. The following is how I setup my partitions:

Mount Point    Device    Boot   Size   Id  System
/boot          /dev/sde1   *    165M    b  W95 FAT32
/              /dev/sde2        3.8G   83  Linux

Note: I would recommend making the FAT partition at least 100M because you will also want to store an archive of /lib/modules/`uname -r` and /lib/firmware from the recovery USB on there later.

Next, format the FAT32 partition as VFAT and copy uImage (from the google code site) and uInitrc from (from Debian’s site) to it. Format the Linux partition as EXT4 and extract dreamplug_rootfs.zip to it; making sure the directory tree starts at / … Go ahead and do a sync and umount on your USB stick and insert in into the DreamPlug.

The following is how to tell U-Boot how to boot into Ubuntu off the recovery stick you just created:

Marvell>> usb start
Marvell>> fatload usb 1:1 0x00800000 /uImage
Marvell>> setenv bootargs_console console=ttyS0,115200
Marvell>> setenv bootargs_root root=/dev/sdc2 rootdelay=10
Marvell>> setenv bootcmd 'setenv bootargs ${bootargs_console} ${bootargs_root}; run bootcmd_usb; bootm 0x00800000'
Marvell>> run bootcmd

Sometimes the USB reference on the fatload statement and the Linux root partition will differ; use the “usb partitions” command to confirm the device id that U-Boot uses to recognize the recovery stick.

Once you’ve booted in to Ubuntu, login as root/nosoup4u and setup your partitions as follows:

Disk /dev/sda: 1977 MB, 1977614336 bytes
61 heads, 62 sectors/track, 1021 cylinders
Units = cylinders of 3782 * 512 = 1936384 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0004e16e

Device    Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1          85      160704    b  W95 FAT32
/dev/sda2              86         946     1628151   83  Linux
/dev/sda4             947        1021      141825   82  Linux swap / Solaris

Go ahead and format the partitions as VFAT and EXT4. If you want to restore Ubuntu just copy uImage to /dev/sda1, restore dreamplug_rootfs to /dev/sda2 and make sure the bootcmd variable is setup properly in U-Boot (Ref: Finalizing U-Boot). If you are going to install Debian go ahead and copy uImage and iInitrd to /dev/sda1; you can skip doing any restores on /dev/sda2. You will also need to do a “tar cfjv modules-`uname -r`.tar.bz2 /lib/modules/`uname -r`” and “tar cfjv `hostname`-firmware.tar.bz2 /lib/firmware” copy the files to /dev/sda1; as we will be restoring it after Debian is installed.

Installing Debian on the DreamPlug

Once our partitions are preped boot back into U-Boot and run the following to start the Debian install:

Marvell>> usb start
Marvell>> fatload usb 0:1 0x00800000 /uImage
Marvell>> fatload usb 0:1 0x01100000 /uInitrd
Marvell>> setenv bootargs console=ttyS0,115200n8 base-installer/initramfs-tools/driver-policy=most
Marvell>> bootm 0x00800000 0x01100000

To reiterate from earlier, you are booting the kernel (uImage) posted at code.google.com/p/dreamplug and are using the Debian armel install image (uInitrd), after the setup you will continue to boot using the same kernel uImage. Follow all the steps as usual during the install with one exception; when you are prompted to setup your disk partitions select manual setup. Make sure you leave sda1 alone, sda2 mounts to / and sda4 is swap. Continue and let the setup complete as normal and then drop to a shell when the install completes. As a finalizing touch you need to do 2 things: modify /etc/fstab on sda2 and restore the two archives you made earlier of modules-*.tar.bz2 and `hostname`-firmware.tar.bz2 on sda2.

Finalizing U-Boot

Once you have Debian installed make sure you have modified your /etc/fstab you also still need to tell U-Boot what and how to boot the system. To boot there are 2 critical variables that are required: bootargs (which is passed to the kernel) and bootcmd (which is automatically ran when the system is powered on). The following is how I set my U-Boot vars:

Marvell>> setenv bootcmd_usb 'usb start; fatload usb 0:1 0x00800000 /uImage'
Marvell>> setenv bootargs_console console=ttyS0,115200
Marvell>> setenv bootargs_root root=/dev/sda2 rootdelay=10
Marvell>> setenv bootcmd 'setenv bootargs ${bootargs_console} ${bootargs_root}; run bootcmd_usb; bootm 0x00800000'
Marvell>> saveenv

Feel free to customize and clean up your env variables, if you need to delete a variable just do a “setenv <variable>“. Also nothing you change will be committed unless you do a “saveenv“. It never hurts to experiment a little, the quicker you lean how U-Boot works the easier things will be to fix if something breaks.

Getting things working

To get wireless working you will need to compile the uaptuil source code and copy the binary to /usr/local/sbin. You can download the source code from the following message board posting: http://plugcomputer.org/plugforum/index.php?topic=2196.msg13114#msg13114.

Additionally, for your reference, the following is a copy of my fstab:

# /etc/fstab: static file system information.
#
# <file system>  <mount point>   <type>  <options>      <dump>  <pass>

proc       /proc    proc    defaults                                0       0
/dev/sda2  /        ext4    errors=remount-ro                       0       1
/dev/sda1  /boot    vfat    auto,owner,rw,uid=0,gid=0,noexec        0       0
tmpfs      /tmp     tmpfs   defaults,noatime,nodiratime,mode=1777   0       0
/dev/sda4  none     swap    sw                                      0       0
12. February 2011 · Comments Off · Categories: Linux Scripts, Networking
#!/bin/bash
## Created by: deaves
# Parse a config file from a cisco router and dump output to stdout.
# Output is tab seperated so it can be opened in a spreadsheet.
#
## Requires: ipcalc (http://jodies.de/ipcalc)
 
[ -z "$1" ] &amp;&amp; { echo "Please give input"; exit 1;}
 
cat "$1" | grep -e ^"interface" -e ^" ip" -e ^" description" -e ^" service-policy" -e "!"$ | while read LINE; do
  eval ARRAY=( `echo '$LINE'` )
 
  ### INTERFACE ###
  if [ "${ARRAY[0]}" == "interface" ]; then
        INT[0]=`basename "$1"`
        INT[1]="${ARRAY[1]}"
 
        ### FR interface ###
        if [ "${ARRAY[2]}" == "point-to-point" ]; then
           INT[7]="${QOSsto}"
        else
           unset QOSsto
        fi
 
  ### INTERFACE DESCRIPTION ###
  elif [ "${ARRAY[0]}" == "description" ]; then
        INT[2]=`echo "${ARRAY[@]}" | awk -F'%' '{print $2}'`
        INT[3]=`echo "${ARRAY[@]}" | sed 's/description //;s/%.*//'`
 
  ### INTERFACE IP ###
  elif [ "${ARRAY[0]}" == "ip" ]; then
 
        ### ADDRESS ###
        if [ "${ARRAY[1]}" == "address" ]; then
           INT[5]=`ipcalc -nb ${ARRAY[2]} ${ARRAY[3]} | grep ^Network | awk '{print $NF}'`
           ROUTE=`ipcalc -nb ${ARRAY[2]} ${ARRAY[3]} | grep ^HostMax | awk '{print $NF}'`
 
           ### Static Routes ###
           INT[6]=`grep "${INT[1]} ${ROUTE}"$ "$1" | awk '{print $(NF-3),$(NF-2)}' | while read LINE; do
                ipcalc -nb ${LINE} | grep ^Network | awk '{print $NF" "}'
           done | tr -d '[:cntrl:]'`
 
        ### VRF ###
        elif [ "${ARRAY[1]}" == "vrf" ]; then
           INT[4]="${ARRAY[3]}"
        fi
 
  ### INTERFACE SERVICE-POLICY ###
  elif [ "${ARRAY[0]}" == "service-policy" ]; then
        # Using 2 variables to store QoS bit for FR interfaces.
        QOSsto="${ARRAY[2]}"
        INT[7]="${ARRAY[2]}"
 
  ### Print Result ###
  elif [ "${ARRAY[0]}" == "!" ] &amp;&amp; [ -n "${INT[5]}" ]; then
        printf "\"${INT[0]}\"\t\"${INT[1]}\"\t\"${INT[2]}\"\t\"${INT[3]}\"\t\"${INT[4]}\"\t\"${INT[5]}\"\t\"${INT[6]}\"\t\"${INT[7]}\"\n"
        unset INT
  fi
 
done
24. January 2011 · Comments Off · Categories: Linux Scripts
#!/bin/bash
## Created by: deaves
# Quiz a user from a question pool in a txt, tab seperated, spreadsheet.
#
# The following is how to format the rows in the input file:
#   ColumnA [Integer]: True Answer (D=0,E=1,F=2,...)
#   ColumnB [String]:  Answer Number
#   ColumnC [String]:  Question
#   ColumnD+[String]:  Answer
#
# FYI: If you have problems try using Open Office to create the spreadsheet,
# MS Office does not properly suround cells with quotes so it gives eval problems.
#
## Requires: dialog (Optional: TTS synthesizer)
 
## Comment out speakCMD var if no text/speach synth.
#speakCMD="flite -s duration_stretch=0.8"
#speakCMD="xclip -i -selection clipboard"
 
### Begin Functions ###
function diaSTRING () {
  ### Retrun no variables; just create a dialog string.
  printf "dialog --stdout --backtitle \"${cTALLY}/${qTALLY}:\t${backTITLE}\" \\
   --title \"${qArray[1]}\" --menu \'${qArray[2]}\' 0 0 0 "
 
  # Count the total answer elements in the array.
  ansNUM=$(expr ${#qArray[@]} - 3)
  count=0    # The answer number the user sees.
  acount=2   # The true answer element in the array.
 
  # Generate the possible answers.
  while [ "${count}" -lt ${ansNUM} ] && [ -n "${qArray[${acount}]}" ]
  do
    let acount++
    printf "${count} \'${qArray[${acount}]}\' "
    let count++
  done
 
  unset count acount ansNUM   # Unset variables.
}
 
 
function diaRESULT () {
  ### Display the test results...
 
  # Display number of questions answered correctly when finished.
  if [ -z "${dANS}" -a -z "${REVIEW}" ]; then
    dialog --backtitle "${backTITLE}" --title "${quizFILE}" \
     --msgbox "You answered:\n ${cTALLY} questions out of ${qTALLY} correct" 0 0
 
  # Display correct answer if the wrong answer was selected.
  else
    dialog --backtitle "${backTITLE}" --title "${qArray[1]}" \
     --msgbox "Q: $(echo "${qArray[2]}")\n\nA: $(echo "${qArray[`expr ${qArray[0]} + 3`]}")" 0 0
  fi
}
 
 
function pick_Question () {
  ### Select question and build qArray...
  if [ -z ${QUESTION} ]; then
    QUESTION=$[ ( ${RANDOM} % ${QUESTIONS} ) + 1 ]
 
    # Do not ask the same question twice...
    [ -z ${lastQUESTION} ] && { lastQUESTION=0; }
    while [ ${QUESTION} = ${lastQUESTION} ]; do
      QUESTION=$[ ( ${RANDOM} % ${QUESTIONS} ) + 1 ]
    done
 
    lastQUESTION=${QUESTION}  # Remember the previous question.
  fi
 
  # Use eval to load the entire row into qArray...
  eval qArray=( `sed -n ${QUESTION}'p' "${quizFILE}" | 's/%/%%/g'` )
 
  # Unset the current randomly chosen question.
  [ -z ${REVIEW} ] && { unset QUESTION; }
}
 
 
function review_Questions () {
  ### Review each question in the entire pool.
  declare -i QUESTION=1
 
  while [ "${QUESTION}" != `expr ${QUESTIONS} + 1` ]; do
    pick_Question        # Load question into qArray.
    dANS="${qArray[0]}"  # Set the correct answer.
    speakTEXT &          # Read Q&A to the user.
    diaRESULT            # Display Q&A to the user.
 
    unset dANS qArray    # Unset variables.
    let QUESTION++       # Next question.
  done
}
 
 
function speakTEXT () {
  ### Use a text to speach synth to read the question & answer.
  ## If this function is unwanted leave the speakCMD variable blank.
 
  # Ask the question...
  if [ -n "${speakCMD}" ] && [ -z "${dANS}" ]; then
    echo "${qArray[2]}" | ${speakCMD}
 
  # Review the question & answer...
  elif [ -n "${speakCMD}" ] && [ -n "${REVIEW}" ]; then
    echo "Question, ${qArray[1]} . ${qArray[2]}" | ${speakCMD}
    echo "The Answer is, $(echo ${qArray[`expr ${qArray[0]} + 3`]})" | ${speakCMD}
 
  # Give the answer...
  elif [ -n "${speakCMD}" ]; then
    echo "The correct answer was: $(echo ${qArray[`expr ${qArray[0]} + 3`]})" | ${speakCMD}
  fi
}
 
 
function usage () {
  ### Display the script arguments.
  printf "Usage: $0 -f <FILE.txt> [-rs]\n\n"
  printf "Required...\n"
  printf "\t-f: Specify the file containing the question pool. (required)\n\n"
  printf "Optional...\n"
  printf "\t-r: Review all the questions in the pool.\n"
  printf "\t-s: Disable sound (if the speakCMD is defined).\n\n"
}
 
 
### Get passed arguments. ###
while getopts ":f:rs" ARG; do
  case "${ARG}" in
    f) quizFILE="${OPTARG}";;
    r) REVIEW="Y";;
    s) unset speakCMD;;
  esac
done
 
### Display command usage and exit ###
[ -z "${quizFILE}" ] && { usage && exit 1; }
 
### Variables that should not be changed ###
backTITLE="Dave's cute quiz script."
QUESTIONS=`wc -l "${quizFILE}" | awk '{print $1}'`
qTALLY=0   # Total questions asked...
cTALLY=0   # Total questions correct...
 
 
### Review all questions and exit script ###
[ "${REVIEW}" = "Y" ] && { review_Questions; exit 0; }
 
### Main Loop ###
while true; do
  pick_Question                               # Pick a Question.
  speakTEXT &                                 # Read the question.
  dANS=`bash -c "$(diaSTRING)"`               # Ask question and store response as "dANS".
 
  [ -z "${dANS}" ] && { diaRESULT && break; } # Break out of the loop if user selects cancel.
  let qTALLY++                                # Tally the total number of questions asked.
 
  if [ ${dANS} == "${qArray[0]}" ]; then      ### Response is correct ###
    let cTALLY++                              # Tally the questions answered correct.
 
  else                                        ### Response is wrong ###
    speakTEXT &                               # Speak the correct answer.
    diaRESULT                                 # Show the correct answer.
  fi
 
  unset dANS qArray                           # Unset loop variables at end of pass.
done
 
### Finish ###