Thursday, 3 July 2014

Howto install OpenWRT on Netgear DG834 or DG834G (v1 or v2)

Got a spare Netgear DG834 or DG834G? Want to try OpenWRT? Want an easy process?

This assume you are running Ubuntu.


Try this:



0. Before you start...

0.1 Ensure router power plug is secure.
0.2 Ensure LAN cable is clicked into both router and computer.
0.3 Ensure your router is working by opening http://192.168.0.1 (or whatever IP address you have changed it to)

1. Backup router config in case you want to restore factory firmware.

2. Factory default router to ensure it's IP address is 192.168.0.1

2.1 Power on router.
2.2 Hold in reset button until test light (tick) flashes.
2.3 Wait for router to reboot (I think - might have to power cycle it).

3. Run my script to turn on telnet, backup partitions, extract environment file, patch ADAM2 to turn off checksum test, download OpenWRT, split into 2 parts, install patched ADAM2 and OpenWRT parts...

Note: This is not conventional and may not work. But unless you have some hardware fault or power failure, you can fairly easily recover your Netgear using a Netgear image and a small C program called nftp. I'll add instructions below.

3.1 mkdir
3.2 cd
3.3 save my script here
3.4 Run my script like this: 

bash ./pc-setup-wrt-v2.bash

... and follow my instructions.

4. Boot into OpenWRT

4.1 Power cycle router.
4.2 Connect ethernet port - may take 1-2 minutes first time.
4.3 Browse to http://192.168.1.1
4.4 Follow instructions to set password.

Done.

My Script

Save as pc-setup-wrt-v2.bash

#!/bin/bash

# Factory default router
#   Power on. Hold in reset button until test light (tick) turns on.

# Setup PC ethernet interface use DHCP. Disconnect. Connect - should get 192.168.0.2?
#   router should be 192.168.0.1

# test by pointing browser to 192.168.0.1 - should get Netgear Setup Wizard screen
# route del default

# info stuff here

# MTDx partitions using 3.??.32? - seems to have 5 mtdx
# mtd0  0x900d0000,0x903e0000  ROOTFS
# mtd1  0x90020000,0x900d0000  Kernel
# mtd2  0x90000000,0x90020000  ADAM2
# mtd3  0x903e0000,0x903f0000  Probably Netgear firmware config
# mtd4  0x903f0000,0x90400000  Probably ADAM2 config

# Ordered
# mtd2  0x90000000,0x90020000  ADAM2
# mtd1  0x90020000,0x900d0000  Kernel
# mtd0  0x900d0000,0x903e0000  ROOTFS
# mtd3  0x903e0000,0x903f0000  Probably Netgear firmware config
# mtd4  0x903f0000,0x90400000  Prob. ADAM2 config

echo "Install needed packages..."
sudo apt-get install wget
sudo apt-get install expect
sudo apt-get install mini-httpd

echo "Get openwrt image - this is for mtd0 and mtd1 so it needs to be split..."

which wget || { echo "ERROR: wget not installed"; exit 1; }

OPENWRT="openwrt-ar7-squashfs.bin"

[[ -f ${OPENWRT} ]] \
  || wget "http://downloads.openwrt.org/backfire/10.03.1/ar7/${OPENWRT}"

echo "Configure this script..."

# ip address of router - should be 192.168.0.1 after factory reboot
ROUTER="192.168.0.1"

# ip address on this host - should not need to change
HOST="192.168.0.10"

# port on this host that has ethernet cable to router plugged in - should be same
ETH="eth0"

echo "Configure this script (ROUTER, HOST, and ETH) variables."
echo "Disconnect from all other networks."
echo "Next time you run this it will reconfigure your ETH port and "
echo "connect to your router."
echo
echo "If you have configured variables correctly, comment out next line."
exit 0

echo "Split OpenWRT image file..."

OPEN0="ow-mtd0.bin"
OPEN1="ow-mtd1.bin"

which dd || { echo "ERROR: dd not installed"; exit 1; }

dd if=${OPENWRT} of=${OPEN1} count=720896 bs=1
dd if=${OPENWRT} of=${OPEN0}  skip=720896 bs=1

echo "Reconfigure ETH port..."

which ifconfig || { echo "ERROR: ifconfig not installed"; exit 1; }

sudo ifconfig ${ETH} ${HOST} netmask 255.255.255.0

echo "Turn on telnet - assumes your reouter has been factory defaulted..."

LOGIN="--user=admin --password=password"

wget -v -O debug.log ${LOGIN} "http://${ROUTER}/setup.cgi?todo=debug"

echo "Telnet to router, and do some heavy stuff - but nothing dangerous...yet..."

# Assign an IP address to ADAM2 (patch)
# Backup each MTD Block to RAM
# Spawn a HTTP Daemon to download MTD Backups
which expect || { echo "ERROR: expect not installed"; exit 1; }
which telnet || { echo "ERROR: telnet not installed"; exit 1; }

expect >telnet.log <
set timeout 30
set send_human {.1 .3 1 .05 2}
spawn telnet ${ROUTER};                             expect "# "; sleep 1;
send_error "Telnet script\n";
send -h "cat /proc/sys/dev/adam2/environment | grep -v \"^my\" > /proc/sys/dev/adam2/environment\r";
                                                     expect "# "; sleep 1;
send -h "echo \"my_ipaddress ${ROUTER}\" > /proc/sys/dev/adam2/environment\r";
                                                     expect "# "; sleep 1;
send_error "Cat environment file...\n";
send -h "cat /proc/sys/dev/adam2/environment\r";    expect "# "; sleep 1;
send_error "Copy partitions to tmp...\n";
send -h "dd if=/dev/mtdblock/0 of=/tmp/mtd0.bin\r"; expect "# "; sleep 1;
send -h "dd if=/dev/mtdblock/1 of=/tmp/mtd1.bin\r"; expect "# "; sleep 1;
send -h "dd if=/dev/mtdblock/2 of=/tmp/mtd2.bin\r"; expect "# "; sleep 1;
send -h "dd if=/dev/mtdblock/3 of=/tmp/mtd3.bin\r"; expect "# "; sleep 1;
send -h "dd if=/dev/mtdblock/4 of=/tmp/mtd4.bin\r"; expect "# "; sleep 1;
send_error "Copy environment file...\n";
send -h "cat /proc/sys/dev/adam2/environment > /tmp/environment.bak\r";                                                     expect "# "; sleep 1;
send -h "cd /tmp\r";                                expect "# "; sleep 1;
send_error "Start web server...\n";send -h "mini_httpd -p 1080\r";                     expect "# "; sleep 1;
send -h "exit\r";
EOF

echo "Pull files from router..."
wget ${LOGIN} -O mtd0.bin        "http://${ROUTER}:1080/mtd0.bin"
wget ${LOGIN} -O mtd1.bin        "http://${ROUTER}:1080/mtd1.bin"
wget ${LOGIN} -O mtd2.bin        "http://${ROUTER}:1080/mtd2.bin"
wget ${LOGIN} -O mtd3.bin        "http://${ROUTER}:1080/mtd3.bin"
wget ${LOGIN} -O mtd4.bin        "http://${ROUTER}:1080/mtd4.bin"
wget ${LOGIN} -O environment.bak "http://${ROUTER}:1080/environment.bak"

echo "See if correct ADAM2 versio is installed..."

which grep || { echo "ERROR: grep not installed"; exit 1; }

grep "bootloaderVersion.*0.18.01" environment.bak \
  || { echo "HALT: Boot loader version is not 0.18.01"; exit 1; }

echo "See if ADAM2 is already patched..."

ADAM2NEW="mtd2.bin.new"

which md5sum || { echo "ERROR: md5sum not installed"; exit 1; }

MDS2=$( md5sum mtd2.bin | cut -d' ' -f1 )

if [[ "$MDS2" == "d8a2f4623bf6f64b7427812f0e849aa7" ]]; then
  echo "mtd2.bin already patched"
  cp mtd2.bin ${ADAM2NEW}
else
  echo "mtd2.bin not patched"
  echo "Verify ADAM2 file..."
  MDS=$( md5sum mtd2.bin | cut -d' ' -f1 )
  if [[ "$MDS" != "0530bfdf00ec155f4182afd70da028c1" ]]; then
    echo "HALT: ADAM2 (mtd2.bin) MD5 sum does not match"
    exit 1
  fi
  echo "Patch ADAM2..."
  cp mtd2.bin ${ADAM2NEW}
  printf '\x00\x00\x00\x00' | dd of=${ADAM2NEW} bs=1 seek=14660 count=4 conv=notrunc 
  echo "Verify patched ADAM2..."
  MDS2=$( md5sum ${ADAM2NEW} | cut -d' ' -f1 )
  if [[ "$MDS2" != "d8a2f4623bf6f64b7427812f0e849aa7" ]]; then
    echo "HALT: Modified ADAM2 (${ADAM2NEW}) MD5 sum does not match"
    exit 1
  fi
fi

echo "Kill off any legacy http servers (if we have somehow left them running)..."
killall mini-httpd

echo "Start local web server..."
sudo mini-httpd -p 8000 || { echo "ERROR: mini-httpd did not start"; exit 1; }

echo "Download modified ADAM2 and OpenWRT files to router and install them..."

expect >flash.log <
set timeout 30
set send_human {.1 .3 1 .05 2}
spawn telnet ${ROUTER};                           expect "# "; sleep 1;
send_error "Telnet script to install modified ${ADAM2NEW}\n";
send -h "cd /tmp\r";                              expect "# "; sleep 1;
send -h "rm mtd0.bin\r";                          expect "# "; sleep 1;
send -h "rm mtd1.bin\r";                          expect "# "; sleep 1;
send -h "rm mtd2.bin\r";                          expect "# "; sleep 1;
send -h "rm mtd3.bin\r";                          expect "# "; sleep 1;
send -h "rm mtd4.bin\r";                          expect "# "; sleep 1;
send -h "rm ${ADAM2NEW}\r";                       expect "# "; sleep 1;
send_error "Download modified ${ADAM2NEW} from ${HOST}...\n";
send -h "wget http://${HOST}:8000/${ADAM2NEW}\r"; expect "# "; sleep 10;
send -h "dd if=${ADAM2NEW} bs=1 skip=110747 count=5\r";
expect {
  "DG834" { send_error "GOOD: ${ADAM2NEW} contains DG834 string\n"; };
  timeout { send_error "ERROR: TIMEOUT: Did not get DG834\n"; exit;  };
  "# "    { send_error "ERROR: Got prompt instead of DG834\n"; exit; };
}
sleep 1;
send_error "Install modified ${ADAM2NEW}...\n";
send -h "dd if=${ADAM2NEW} of=/dev/mtdblock/2\r"; expect "# "; sleep 20;
send -h "rm ${ADAM2NEW}\r";                       expect "# "; sleep 1;
send -h "rm ${OPEN0}\r";                          expect "# "; sleep 1;
send_error "Download ${OPEN0} from ${HOST}...\n";
send -h "wget http://${HOST}:8000/${OPEN0}\r";    expect "# "; sleep 10;
send_error "Install ${OPEN0}...\n";
send -h "dd if=${OPEN0} of=/dev/mtdblock/0\r";    expect "# "; sleep 20;
send -h "rm ${OPEN0}\r";                          expect "# "; sleep 1;
send -h "rm ${OPEN1}\r";                          expect "# "; sleep 1;
send_error "Download ${OPEN1} from ${HOST}...\n";
send -h "wget http://${HOST}:8000/${OPEN1}\r";    expect "# "; sleep 10;
send_error "Install ${OPEN1}...\n";
send -h "dd if=${OPEN1} of=/dev/mtdblock/1\r";    expect "# "; sleep 20;
send -h "rm ${OPEN1}\r";                          expect "# "; sleep 1;
send -h "reboot\r";
EOF

echo "Shutdown local web server..."
killall mini-httpd

echo "All done."
echo
echo "Power cycle router."
echo "Reconnect ethernet interface - may take 1-2 minutes"
echo "Browse to http://192.168.1.1"
exit 0

Basic Configuration Steps


Save and Apply after each change.

If unsure, power cycle router.

Set password
Set timezone
Set dropbear (ssh) interface to lan

Edit LAN interface
  IP address (WARNING: This gives me most headaches - perhaps leave it alone for a while)
  (When you save and apply, you may need to disconnect/reconnect ethernet interface on pc)
  I set MTU to 1474

Add new (PPPoATM) interface
Set username and password
Set custom DNS servers to OpenDNS 208.67.222.222 and 208.67.220.220
Assign ADSL interface to WAN

Edit Wifi
  Enable
  Set SSID etc.
  Set to WEP and generate WEP hex key somehow.

No WPA???


Sunday, 12 January 2014

Virtualize an old Windows XP disk partition (howto convert disk partition to virtual disk for VirtualBox)

I dug out an old hard disk. I was curious: what gems are stored here?

Turns out there was nothing, but it was in interesting exercise in converting a single disk partition into a VM - something that is not trivial.

I plugged my old drive into a USB hard disk docking station and had a look. It contained Windows XP and Linux from an old PC dating from 2004-2007 I believe.

"Hey!" I thought. I could virtualize this for no good reason and show how easy it is using free and open source software.

Ubuntu Packages

I installed VirtualBox and mbr.

Create VirtualBox VM

  • Select New
  • Name your VM (say TEST)
  • Select Windows and Windows XP
  • Set memory size (default is ok)
  • Select 'do not add a virtual hard drive' - we will create this later in tis VM's directory.

Create Virtual Disk Drive

Open a terminal and change to your ~/VirtualBox\ VM/TEST directory for this example.

Copy and paste my script into your editor.

#!/bin/bash

DISK=/dev/sdd
PART=1

printf "Copy boot sector image...\n"
sudo dd if=$DISK of=mbr.img bs=512 count=1 || { printf "FAILED\n"; exit 1; }
printf "Done\n"

# put 'normal' mbr incase grub or something was used
printf "Replace MBR code..."
sudo install-mbr mbr.img -t 36 || { printf "FAILED\n"; exit 1; }
printf "Done\n"

printf "Copy disk (%s) partition %d...(at 10MB/s 1GB will take 100s)...\n" "$DISK" $PART
PARTIMG=part${PART}.img
sudo dd if=${DISK}${PART} of=$PARTIMG bs=512 || { printf "FAILED\n"; exit 1; }
sudo chown $USER:$USER $PARTIMG
printf "Done\n"

printf "Make VirtualBox VMDK image with MBR...\n"
sudo VBoxManage internalcommands createrawvmdk -filename ./disk.vmdk -rawdisk $DISK -partitions $PART -mbr ./mbr.img || { printf "FAILED\n"; exit 1; }
# VB needs this owned by user
sudo chown $USER:$USER disk-pt.vmdk
printf "Done\n"

# switch to partition image and zero starting offset
# eg.
# from this: RW 8514387 FLAT "/dev/sdd" 63
# to this: RW 8514387 FLAT "/home/phil/Development/pc-part2disk/part1.img" 0
 
printf "Modify VMDK files to use disk partition image...\n"
sudo cat disk.vmdk | sed "s@\"$DISK.*@\"./$PARTIMG\" 0@" > diskimage.vmdk
sudo chown $USER:$USER diskimage.vmdk
printf "Done\n"

# remove VB vmdk that points to physical drive - no longer required
sudo rm disk.vmdk

exit 0
 Change DISK and PART to suit your case. This example uses disk /dev/sdd and partition 1.

Also, run chmod +x