Fixing Dates in Image EXIF Tag Data from Linux

Posted on June 21st, 2009 in Tech Tips by gmendoza

I recently needed to organize a large number of old digital photos that had the wrong date embedded in their EXIF tag data. The camera I used many years ago would often lose track of time and would sometimes be set to the wrong year. Applications I now use to organize photos read this data and made my albums difficult to navigate. I came across a Linux command line utility called jhead that allows you to modify this information to whatever you wish, and its easy to use in scripts as well.  Installing was easy, because it’s currently in most repositories, including Ubuntu’s.

To read existing EXIF tag data, simply run jhead against an image without any options. As you can see from the example below, my date is set to the year 2022.

jhead image.jpg
File name : image.jpg
File size : 159390 bytes
File date : 2004:01:12 07:35:23
Camera make : Samsung
Camera model : Digimax 200
Date/Time : 2022:02:12 04:04:17
Resolution : 800 x 600
Flash used : Yes
Exposure time: 0.045 s (1/22)
Aperture : f/2.8

To clear all EXIF data from the file, use the -de option. Then recreate the EXIF fields with the -mkexif option, and check the data again. Notice the new Date/Time is set to the timestamp on the file.

jhead -de image.jpg
Modified: image.jpg

jhead -mkexif image.jpg
Modified: image.jpg

jhead image.jpg
File name : image.jpg
File size : 147751 bytes
File date : 2004:01:12 07:35:23
Date/Time : 2004:01:12 07:35:23
Resolution : 800 x 600

To change the entire timestamp manually, use the -ts option. Notice, there is no space between the -ts and the option. I could not trust the month and day, so I simply chaged the date to midnight on January 1, 2003.

jhead -ts2003:01:01-00:00:00 image.jpg
Modified: image.jpg

jhead image.jpg
File name : image.jpg
File size : 147751 bytes
File date : 2004:01:12 07:35:23
Date/Time : 2003:01:01 00:00:00
Resolution : 800 x 600

For many more options, check out the man page or visit the jhead site for more info.

Convert MKV to Xvid with Mencoder

Posted on April 9th, 2009 in Tech Tips by gmendoza

I recently wanted to convert some of my 720p and 1080p Matroska Video (MKV) files to the Xvid format so that I can play them on my Xbox 360 (check out ushare). I really wanted to make sure that the video quality and Dolby Digital 5.1 audio would remain intact, and was pleased to finally get the job done with mencoder.

The syntax is easy and is described as follows.

mencoder movie.mkv -channels 6 -ovc xvid -xvidencopts pass=1 -oac copy -o movie.avi

The Dolby Digital 5.1 (AC3) output was a major pain to figure out because by default, mencoder (and mplayer) only will select 2 audio channels. So increasing the value to 6 ensures you receive them all. Otherwise, you end up getting standard stereo out all channels.

There’s a ton of options that you can use, so just be sure to read the man pages for mencoder.

File Synchronization with Unison over SSH

Posted on April 9th, 2009 in Tech Tips by gmendoza

Previously, I posted on using rsync over SSH for file synchronization. While this works very well when pushing data in one direction, it’s not well suited for synchronizing modifications that are made on both sides. An excellent bidirectional utility for that type of job is Unison, which sports many of the same benefits as rsync, but has some distinct advantages for more complex synchronization scenarios.

A basic example would be to synchronize a local directory called “MyDocs” with a remote SSH server. From the following output, you can see that this directory contains four text files.

$ ls -ld ~/MyDocs
drwxr-xr-x 2 gmendoza gmendoza 4096 2009-04-09 16:05 /home/gmendoza/MyDocs

$ ls -l ~/MyDocs
total 12
-rw-r--r-- 1 gmendoza gmendoza 31 2009-04-09 16:09 file1.txt
-rw-r--r-- 1 gmendoza gmendoza 31 2009-04-09 16:09 file2.txt
-rw-r--r-- 1 gmendoza gmendoza 31 2009-04-09 16:09 file3.txt
-rw-r--r-- 1 gmendoza gmendoza 31 2009-04-09 16:09 file4.txt

The first time you run Unison for this particular directory structure, both sides will create a local index and hash table. You’ll get a warning and will be prompted with a message, asking you to hit the space bar if you accept. If the root directory on the remote side does not exist yet, you’ll also be prompted to accept the changes.

$ unison MyDocs ssh://host2/MyDocs
Contacting server...
Connected [//host1//home/gmendoza/MyDocs -> //host2//home/gmendoza/MyDocs]
Looking for changes
Warning: No archive files were found for these roots, whose canonical names are:
	/home/gmendoza/MyDocs
	//host2//home/gmendoza/MyDocs
(snipped for brevity...)
Press return to continue.[]    Waiting for changes from server
Reconciling changes

local          host2
dir      ---->            /  [f] 

Proceed with propagating updates? [] y
Propagating updates

UNISON 2.27.57 started propagating changes at 16:14:30 on 09 Apr 2009
[BGN] Copying  from /home/gmendoza/MyDocs to //host2//home/gmendoza/MyDocs
[END] Copying
UNISON 2.27.57 finished propagating changes at 16:14:30 on 09 Apr 2009

Saving synchronizer state
Synchronization complete  (1 item transferred, 0 skipped, 0 failures)

Subsequent synchronizations are shown as the following.

$ unison MyDocs ssh://host2/MyDocs
Contacting server...
Connected [//host1//home/gmendoza/MyDocs -> //host2//home/gmendoza/MyDocs]
Looking for changes
  Waiting for changes from server
Reconciling changes
Nothing to do: replicas have not changed since last sync.

For the following example, I have modified file1.txt on host1, and file2.txt on host2. Both file3.txt and file4.txt have been modified on each side. The great thing about unison is that when there is a conflict, you have the opportunity to view the differences and select which direction you wish to synchronize. Pressing the “x” key displays some basic information about the files that differ. In this case, I have chosen the files with the most recent timestamp. You choose the file direction by pressing the greater and less-than symbols, “>” and “<".

$ unison MyDocs ssh://host2/MyDocs
(snipped)
local          host2
changed  <-?-> changed    file3.txt  [] x
local        : changed file       modified on 2009-04-09 at 16:16:29  size 50
host2  : changed file       modified on 2009-04-09 at 16:16:43  size 55
changed  <==== changed    file3.txt  [] <
changed  <-?-> changed    file4.txt  [] x
local        : changed file       modified on 2009-04-09 at 16:17:20  size 56
host2  : changed file       modified on 2009-04-09 at 16:16:59  size 41
changed  ====> changed    file4.txt  [] >
changed  ---->            file1.txt  [f]
         <---- changed    file2.txt  [f] 

Proceed with propagating updates? [] y
Propagating updates

UNISON 2.27.57 started propagating changes at 16:18:27 on 09 Apr 2009
[BGN] Updating file file3.txt from //host2//home/gmendoza/MyDocs to /home/gmendoza/MyDocs
[BGN] Updating file file4.txt from /home/gmendoza/MyDocs to //host2//home/gmendoza/MyDocs
[BGN] Updating file file1.txt from /home/gmendoza/MyDocs to //host2//home/gmendoza/MyDocs
[BGN] Updating file file2.txt from //host2//home/gmendoza/MyDocs to /home/gmendoza/MyDocs
[END] Updating file file3.txt
[END] Updating file file2.txt
[END] Updating file file4.txt
[END] Updating file file1.txt
UNISON 2.27.57 finished propagating changes at 16:18:27 on 09 Apr 2009

Saving synchronizer state
Synchronization complete  (4 items transferred, 0 skipped, 0 failures)

Unison also has a GTK front end for the graphically inclined. Be sure to check out all the documentation for a full understanding of syntax.

File Synchronization with Rsync over SSH

Posted on April 6th, 2009 in Tech Tips by gmendoza

To quickly synchronize files between two systems, rsync is an excellent tool that not only decreases the amount of time it takes to transfer files through a data deduplication algorithm, but can also be used transparently over SSH. The beauty of running rsync over SSH is that it does not require the rsyncd server to be running before a synchronization request and the connection is both authenticated and encrypted. All that is required is for the remote host you are connecting to be running the OpenSSH server component and of course the rsync application.

I use rsync the most for synchronizing my “Music” and “Documents” folders between a number of my systems at home and at work. All of these systems have these folders in the root of my home directory.

ls -ld ~/Music ~/Documents
drwxr-xr-x 16 gmendoza gmendoza 4096 2009-04-06 23:23 /home/gmendoza/Documents
drwxr-xr-x  9 gmendoza gmendoza 4096 2009-04-06 23:23 /home/gmendoza/Music

To push my recent changes from my local system (host1) to my remote system called (host2), I use the following commands.

rsync -avPe ssh ~/Music host2:~/
rsync -avPe ssh ~/Documents host2:~/

Notice, “Music” and “Documents” are specified without a trailing “/”, e.g. “Music/” or “Documents/”. This is important, because otherwise, it would copy only the contents of the folder to the remote home directory, and not the folder itself, which is described in more detail in the rsync man page.

Instead of running the above commands twice, you can also specify multiple files all in a single line.

rsync -avPe ssh ~/Music ~/Documents host2:~/

To synchronize changes made on the remote system to my local system, just reverse the commands. Notice the periods at the end of the line, which specifies the destination as the local working directory. Also, instead of wasting space by entering the host twice, you can use standard syntax to specify ranges or sets of files. In this case, I use curly brackets to specify the two directories on the remote host that share the same parent directory should be copied to my local working directory.

rsync -avPe ssh host2:~/{Music,Documents} .

I’ll also use the “delete” option to remove any files and folders the have been removed from the source system.

rsync --delete -avPe ssh ~/Music host2:~/

By default, rsync compares files extremely fast using a “quick check” algorithm based on the file size or in the last modified time (per the rsync man page). While I was updating my Music collection, I noticed that rsync was not detecting my ID3 tag modifications. By using the “-c” option, rsync will compare files using a 128 bit MD4 checksum as a more definitive change detection method. While this will slow the process down significantly, there’s obvious accuracy benefits in using the checksum method.

rsync -acvPe ssh Music host2:~/

Also, as you may have noticed rsync is strictly a unidirectional utility. This means that it only sends or receives data in a single direction, and it will clobber or delete any file or folder with the same name in the direction your are sending the data. For a great bidirectional utility, check out unison, which I will cover in an upcoming article.

Line wrapping text made easy with fold

Posted on April 6th, 2009 in Tech Tips by gmendoza

Line wrapping text from the command line is easy with the fold utility, which of course is provided by the Free Software Foundation.  By default, the fold command will wrap text at 80 characters, but you can of course specify the width manually.  I prefer using the -s option, which will break only on spaces, making sure not to break in the middle of a word.

For example, the following command will concatenate a text file to standard output, adding line breaks  only at spaces or at 72 characters, whichever comes first.

fold -s -w 72 textfile.txt

This can also be useful if you want to clearsign a message with Gnupg, but wish to line wrap it beforehand.

fold -s -w 72 textfile.txt | gpg --clearsign -u user@email.com

Add redirection if you wish to output the results to a file.

fold -s -w 72 textfile.txt > newfile.txt

As mentioned here, the fmt command also provides the same primary features of fold, but is much better. Not only does it wrap long lines, but it also fills out short lines as well. There are additional options that are worth looking into. Be sure to check out the man page!

man fmt

Create Encrypted CD’s and DVD’s in Linux

Posted on November 26th, 2008 in Tech Tips by gmendoza

When backing up data to a CD or DVD, you may find it useful to encrypt the entire disc just in case the media falls into the wrong hands. Some people may advise compressing your files within tar/gzip archive and use PGP to encrypt the data, burning the resulting data to disc. The challenge, however, is how easy it is to work with the data after the burn process. You are typically required to decrypt and extract the archive to your hard disk if you wish to access the files within.

A much more flexible method for Linux users is to encrypt the entire CD or DVD with an AES symmetric key, and work with the data by simply mounting the disc. This means you don’t have to copy the files, they are simply presented to you as you would expect with an unencrypted disc.

Prerequisites

Prerequisites include loading the Cryptoloop kernel module and the installation of the Loop-AES toolset. Installing these packages in Ubuntu/Debian and loading the cryptoloop module is a snap.

sudo apt-get install aespipe loop-aes-utils
sudo modprobe cryptoloop

Verify that cryptoloop and AES kernel modules are loaded with lsmod.

lsmod | grep cryptoloop
cryptoloop             10880  0
loop                   23180  1 cryptoloop

lsmod | grep aes
aes_i586               15744  2
aes_generic            35880  1 aes_i586

If you had to load these modules by hand, make sure to add them to /etc/modules so that they are loaded on boot up.

Create, burn and mount encrypted images

To create a standard CD image, use genisofs (formally known as mkisofs), pipe the output to aespipe, and redirect the final output to an ISO file. Notice that we have specified that aespipe will use AES256 encryption, and it will has you to enter a password twice. Don’t lose it! ;)

genisoimage -quiet -r Documents/ | aespipe -T -e aes256 > documents.iso
Password: (enter password)
Retype password: (enter password)

Mount the image using the encryption option. The mounting process will ask you for the passphrase.

sudo mount -o loop,encryption=aes256 documents.iso /mnt
Password: (enter password)

Burn the disc image, replacing /dev/dvdrw with the appropriate value for your system. wodim was formerly known as cdrecord, so feel free to replace it with any command you are familiar with.

wodim dev=/dev/dvdrw documents.iso

Mount the CD/DVD using the same mount options as previously demonstrated.

sudo mount -o loop,encryption=aes256 /dev/dvdrw /mnt
Password: (enter password)

Work with your files as you would with any normal CD or DVD.

ls -l /mnt/
total 0
-r--r--r-- 1 root root 0 2008-11-26 17:09 secretfile1.txt
-r--r--r-- 1 root root 0 2008-11-26 17:09 secretfile2.txt
-r--r--r-- 1 root root 0 2008-11-26 17:09 secretfile3.txt
-r--r--r-- 1 root root 0 2008-11-26 17:09 secretfile4.txt

Backup and Restore Package Lists in Ubuntu

Posted on October 19th, 2008 in Tech Tips by gmendoza

Here’s a simple tutorial on how to backup a list of all your installed repository applications, and restore them to another machine, perhaps even the same machine after a clean installation.  This can save you an incredible amount of time, especially when this task must be repeated often.  Of course, being that Ubuntu is based on Debian, this will work for any Debian based platform.

First, from a computer with all the applications preinstalled, retrieve your installed package list and redirect the output to a file called packages.txt.  Save this package list somewhere so that you can use it for the restore process.

sudo dpkg --get-selections > packages.txt

To restore all the applications from your list, you must follow a three step process very carefully.

sudo dpkg --clear-selections
sudo dpkg --set-selections < packages.txt
sudo aptitude install

You will be prompted to install all the new applications in the list.

Another example of what this process allows you to do is create a baseline of all the applications after a clean installation of Ubuntu.  Let’s say you would like to remove any applications installed since the clean install, perform the exact same process, and any package not defined in that list will be removed.

sudo dpkg --get-selections > clean-install-package-list.txt
sudo dpkg --clear-selections
sudo dpkg --set-selections < clean-install-package-list.txt
sudo aptitude install

The very first command of “–clear-selections” marks all currently installed packages to the state “deinstall”.  When you restore the list of applications using “–set-selections”, only packages ommited from the list will remain in the “deinstall” state.  Aptitude will honor the deinstall state and remove the extra packages, leaving you only with packages from the list. Most excellent. :-)

VirtualBox Host Interface Networking with NAT

Posted on September 21st, 2008 in Tech Tips by gmendoza

Here’s a detailed tutorial on VirtualBox host interface networking with NAT for multiple guests.  I typically run a number of guests simultaneously for labs and product testing, so they all need internet access through my host, as well as full communication directly with each other.

The built in NAT interface of VirtualBox isn’t very flexible for what we want to do, so here’s a summary what what we will do. We’ll create three TAP interfaces, one for each guest, since TAP interfaces cannot be shared by multiple guests. These interfaces will serve as each guest’s default gateway, but all of the guests will use the same address space and subnet mask. For full communication between the guests, we’ll add appropriate host routes and enable proxy ARP on the host. Nothing will need to be configured on the guests accept for their IP address, subnet mask, default gateway, and DNS if needed.

Here’s a diagram of the virtual topology, which hopefully will make things a little more clear.

VirtualBox Host Interface NAT Topology

VirtualBox Host Interface NAT Topology

Getting Started

You’ll need to install the User Mode Linux utilities first, if you have done so already.

sudo apt-get install uml-utilities

TAP interfaces

Let’s create three TAP interfaces.

sudo tunctl -u $USER
sudo tunctl -u $USER
sudo tunctl -u $USER

Assign IP addresses to the TAP interfaces.

sudo ip addr add 192.168.20.1/32 dev tap0
sudo ip addr add 192.168.20.2/32 dev tap1
sudo ip addr add 192.168.20.3/32 dev tap2
sudo ip link set tap0 up
sudo ip link set tap1 up
sudo ip link set tap2 up

Routing Requirements

Enable routing and add host routes for each of the guest IP addresses.

sudo sysctl net.ipv4.ip_forward=1
sudo route add -host 192.168.20.201 dev tap0
sudo route add -host 192.168.20.202 dev tap1
sudo route add -host 192.168.20.203 dev tap2

Proxy ARP

Enable proxy ARP on all TAP interfaces so that all the guests can communicate with each other.

sudo sysctl net.ipv4.conf.tap0.proxy_arp=1
sudo sysctl net.ipv4.conf.tap1.proxy_arp=1
sudo sysctl net.ipv4.conf.tap2.proxy_arp=1

Notice, it is NOT necessary to enable proxy ARP on the public interface, since we will be using NAT for guests to access the public network and internet.

NAT Configuration

First flush all iptables rules and enable NAT on the public interface. For brevity, I’ll just show eth0, but if you have multiple interfaces, feel free to use the same command for each of them.

sudo iptables --flush
sudo iptables -t nat --flush
sudo iptables -t nat -A POSTROUTING --out-interface eth0 -j MASQUERADE
sudo iptables -A FORWARD --in-interface eth0 -j ACCEPT

Now it’s just a matter of configuring each of your guests to use the appropriate host interface as shown in the screenshot below.

After assigning the guest to an interface, configure the guest operating system with the appropriate IP address and routing information. The following list will show the IP address configuration each guest should use for this example.

Guest 1
Host interface: tap0
IP Address: 192.168.20.201
Subnet Mask: 255.255.255.0
Gateway: 192.168.20.1
DNS: Any reachable DNS server.

Guest 2
Host interface: tap1
IP Address: 192.168.20.202
Subnet Mask: 255.255.255.0
Gateway: 192.168.20.2
DNS: Any reachable DNS server.

Guest 3
Host interface: tap2
IP Address: 192.168.20.203

Subnet Mask: 255.255.255.0
Gateway: 192.168.20.3
DNS: Any reachable DNS server.

And that’s it. Your guests should all be able to ping each other, and access the internet!

To make things easy, I have also created the following Bash shell script that creates and tears down the environment with ease. Modify settings to your liking.

#!/bin/bash
# tap-setup.sh
# By Gilbert Mendoza
 
# Change username accordingly
USER="gmendoza"
PROXY="tap0 tap1 tap2"
TAPS="tap0 tap1 tap2"
NAT_OUT="eth0 wlan0"
 
ip_setup(){
ip addr add 192.168.20.1/32 dev tap0
ip addr add 192.168.20.2/32 dev tap1
ip addr add 192.168.20.3/32 dev tap2
route add -host 192.168.20.201 dev tap0
route add -host 192.168.20.202 dev tap1
route add -host 192.168.20.203 dev tap2
}
 
nat_setup(){
iptables --flush
iptables -t nat --flush
for i in $NAT_OUT
 do
   iptables -t nat -A POSTROUTING --out-interface $i -j MASQUERADE
done
for i in $TAPS
 do
   iptables -A FORWARD --in-interface $i -j ACCEPT
done
}
 
tap_up(){
tunctl -u $USER
tunctl -u $USER
tunctl -u $USER
sysctl net.ipv4.ip_forward=1
for i in $PROXY
 do 
   sysctl net.ipv4.conf.$i.proxy_arp=1
done
for i in $TAPS
 do
   ip link set $i up
done
}
 
tap_down(){
sysctl net.ipv4.ip_forward=0
iptables --flush
iptables -t nat --flush
for i in $PROXY
 do
   sysctl net.ipv4.conf.$i.proxy_arp=0
done
for i in $TAPS
 do
   tunctl -d $i
done
}
 
if [[ $EUID -ne 0 ]]; then
  echo "This script must be run as root" 1>&2
  exit 1
else
 
case "$1" in
 
start)
	tap_up
	ip_setup
	nat_setup
	;;
stop)
	tap_down
	;;
*)
	echo "Usage: $0 {start|stop}"
	;;
esac
 
fi
 
exit 0

Using it is as simple as the following.

sudo tap-setup.sh start
sudo tap-setup.sh stop

VirtualBox Wireless Bridging with DHCP

Posted on September 21st, 2008 in Tech Tips by gmendoza

In the following instructions, we’ll explore a couple of methods on how to let your VirtualBox guest use the DHCP services of your host’s wireless network.

In a previous post, I outlined how to bridge a VirtualBox guest across the wireless connection of your host.  But the process involved using static IP’s for your guest, because unlike a true bridge, your host is actually acting as a router, forwarding only unicast packets between the two networks.  This complicates your guests ability to use DHCP, since broadcasts are typically not forwarded by routers.  I’m going to demonstrate two methods that work around this limitation.  For the first method, we’ll be using two different DHCP relay agents. For the second method, we’ll simply use a Broadcast Relay Agent.

Network Assumptions

I’m going to assume we’re using a very simple setup typical to most small networks and wireless routers. Feel free to adjust the following values according to your own requirements.

Wireless Network ID: 192.168.1.0/24
Wireless Network DHCP Range: 192.168.1.2-100
Wireless Network DHCP Server: 192.168.1.1
Host Computer Wireless Interface: wlan0 (change accordingly)
Host Computer Wireless IP: Any IP (Doesn’t matter; You can use DHCP or static)
Host Computer TAP Interface IP: 192.168.1.150/32 (choose something outside DHCP range)
Guest Computer IP: DHCP/Dynamic

Getting Started

Enable IP forwarding on your host.

sudo sysctl net.ipv4.ip_forward=1

Install the User Mode Linux utilities, for the tunctl application.

sudo apt-get install uml-utilities

Create a TAP interface and give it a static IP address in the same address space as your wireless network.

sudo tunctl -u $USER
sudo ip addr add 192.168.1.150/32 dev tap0
sudo ip link set tap0 up

The IP address you choose for the TAP interface should be outside the DHCP range to prevent conflicts with other hosts. It’s very important that you don’t use the same subnet mask as your wireless interface, because you can run into unpredictable routing behavior on your host. I recommend using a 32-bit subnet mask as it is very clean and efficient. I like to use the ip command, but feel free to use ifconfig to accomplish the same thing.

Proxy ARP Required

Unlike in the previous post, unless you are reserving an IP address for your guest on the DHCP server, you may not know what IP address your guest will receive. In order for kernel based proxy ARP to work, you would need to manually add the assigned IP address to your routing table.

So to make things easy for you, parprouted comes to the rescue.

sudo apt-get install parprouted

When you run parprouted, it inspects ARP traffic on both sides of the network and adds IP addresses as host routes in the routing table. Run this command in one terminal so you can check out what’s happening in the background.

sudo parprouted -d wlan0 tap0

Method 1: DHCP Relay Agent

DHCP Relay Agents are commonly used on routed networks with centralized DHCP services. The relay agent is a service that is typically configured on a router and converts DHCP broadcasts into unicast messages directed at the DHCP servers IP address. For more detailed explanations on the matter, check out RFC 3046 and 1542.

Simon Kelley’s DHCP Helper (Option A)

I selected to discuss Simon Kelley’s DHCP Helper first because it really is a brilliantly simple and intuitive application. The primary advantage it has over ISC’s DHCP Relay is that you do not have to configure the application with the IP address of the DHCP server. You simply tell dhcp-helper which interface on which you want it to automatically discover the dhcp server via broadcast, and it does the rest for you!

Install dhcp-helper from your repositories, or download the latest source code here.

sudo apt-get install dhcp-helper

The service starts on installation automatically, listening on interface eth0. You’ll want to configure it in the file /etc/default/dhcp-helper. I am adding “-i wlan0” because by default it will listen on all other interfaces as well. This way, we limit the test to your VirtualBox guest.

DHCPHELPER_OPTS="-b wlan0 -i tap0"

Restart the service.

sudo /etc/init.d/dhcp-helper restart

Configure your VirtualBox guest to use tap0 as it’s network interface, and watch it pull an IP address from your DHCP server!

ISC’s DHCP Relay (Option B)

First of all, if you would rather use ISC’s DHCP Relay, you must remove dhcp-helper discussed in the previous section. It’s not as transparent as dhcp-helper, so I’m just mentioning it here for the sake of completeness.

Ubuntu and Debian repositories provide ISC’s DHCP relay agent in the dhcp3-relay package. For other distros, check your repositories accordingly.

sudo apt-get install dhcp3-relay

The installer will prompt you to add the IP address of your DHCP server and the interface you wish to listen on, etc. Simply leave them blank for now, as for this example, we’ll be testing things out from a command line. To test things out, run the following command from a separate terminal window, where the IP address is that of your DHCP server.

sudo dhcrelay3 -d -i wlan0 -i tap0 192.168.1.1

Configure your VirtualBox guest to use tap0 as it’s network interface, and watch it pull an IP address from your DHCP server!

Method 2: Broadcast Relay

Okay, so I’d love to take the credit for this one, but a reader from a previous post, Nick Knight, pointed me to a utility called bcrelay. Now this application is cool! It totally mitigates the need for a DHCP relay agent (so kill that process if you are running it), as bcrelay simply rewrites the layer-2 header and forwards broadcast messages between network interfaces. In the case of DHCP, the source MAC address of the packet is changed to your host machines address, but the DHCP header is untouched. So the DHCP server will still offer a brand new IP address to the guest.

Install and run the application from a separate terminal window. As a reminder, you still need to use parprouted though in another window.

sudo apt-get install bcrelay
sudo bcrelay -i tap0 -o wlan0

Configure your VirtualBox guest to use tap0 as it’s network interface, and watch it pull an IP address from your DHCP server!

Troubleshooting

If you really want to see all the action, use wireshark or tcpdump to inspect traffic. The following capture filter works well, in two separate terminals of course.

sudo tcpdump -eni tap0 udp port 67 or udp port 68 or arp or icmp
sudo tcpdump -eni wlan0 udp port 67 or udp port 68 or arp or icmp

Also, these commands are useful as well.

watch -n1 route -n
watch -n1 arp -an

If you need to figure out what is going wrong, be sure to stop all the components of the appropriate method and run them in the foreground in separate terminals. e.g. parprouted, bcrelay, dhcp-helper, dhcp3-relay. Most will give you clues as to what is failing.

Now.. I should mention, I ran into all sorts of issues when trying to get all of this to work. The methods that gave me the most trouble were the DHCP relay agents.

I have an Actiontec MI424WR router that royally screws up my DHCP relay agent’s packet exchange. I wasn’t getting any DHCP offers with unicast packets sent to the router. Apparently, during a typical non-relayed DHCP exchange, I was able to see that the router’s source MAC address was completely different in broadcast DHCP offer packets than what it’s IP address is actually associated with, so my unicast packets were probably being dropped by the router. I’m assuming this is some type of internal bridge interface dedicated for DHCP services or something, so I ended up having to install a separate DHCP server for this to work. ISC’s DHCP server worked completely normal, and I suspect this is entirely the routers fault.

Conclusion

If you do want to use this configuration regularly, I recommend the combination of parprouted and bcrelay or dhcp-helper. Both can be run in the background easily, and requires almost zero configuration if traveling between multiple networks.

However, as you have probably gathered, both methods described above are a bit complicated, and I don’t necessarily recommend it for every day use. I did it because I’m a geek, and I wanted to prove it could be done. While the process of setting up the entire environment could be made simpler with scripts, the challenges you will face on each wireless network might make the process of troubleshooting counterproductive. Many of the headaches you will face will be related to the wireless network hardware, such as centralized wireless solutions that restrict the number of MAC to IP addresses in order to prevent MITM attacks, and of course in some cases, charge you appropriately.

The best solution for public hostspots and corporate networks is still good old fashioned NAT. :-) But this way sure is is a lot of fun and a good way to waste your weekend to impress all your other nerd buddies.

Ubuntu’s Uncomplicated Firewall (UFW)

Posted on September 20th, 2008 in Tech Tips by gmendoza

Introduced first in Ubuntu 8.04, UFW is Ubuntu’s “uncomplicated firewall”, a remarkably easy to use tool for creating simple iptables firewall rules. The goal behind UFW is to make it easy for administrators and even third party packages to work with firewall rules in a clean and consistent manner. When UFW is enabled, the default set of rules work very well for the average server or desktop platform, as it blocks all non-essential inbound network access without hobbling certain types of useful protocols and return traffic.

In the following example, we will set up a very simple firewall adequate for almost anyone.

First, let’s check the status of UFW, and the currently installed iptables rule set. The following displays that UFW is disabled and that there are no rules for iptables INPUT chain.

Check firewall status

sudo ufw status
Firewall not loaded

sudo iptables -L INPUT -n | column -t
Chain             INPUT  (policy  DROP)
target            prot   opt      source     destination

Enable UFW

Now, let’s enable UFW and examine the change to iptables’ INPUT chain.

sudo ufw enable
Firewall started and enabled on system startup

sudo iptables -L INPUT -n | column -t
Chain             INPUT  (policy  DROP)
target            prot   opt      source     destination
ufw-before-input  all    --       0.0.0.0/0  0.0.0.0/0
ufw-after-input   all    --       0.0.0.0/0  0.0.0.0/0

The default policy was changed to drop all traffic, and two new chains are referenced. For a much better understanding of what the default rules are, take a look at the files “/etc/ufw/before.rules” and “/etc/ufw/after.rules“.

Connection Tracking

For your convenience, UFW also enables some very useful connection tracking rules, which intelligently inspect outbound application traffic and dynamically allows the return traffic for you. By default, TCP, UDP, FTP and IRC connection tracking modules are loaded, but others may be added to the IPT_MODULES variable in the file “/etc/default/ufw“.

For example, I sometimes need to use TFTP for sending and receiving firmware to and from routers. So I typically add “nf_conntrack_tftp” to the variable IPT_MODULES.

IPT_MODULES="nf_conntrack_ftp nf_nat_ftp nf_conntrack_irc nf_nat_irc nf_conntrack_tftp"

Remember to reload UFW so that the conntrack module is loaded.

sudo /etc/init.d/ufw restart

Allowing inbound services

If your system runs server applications such as DNS, SSH, TFTP and web, then you can add them to your firewall rules using these very simple commands. If you don’t run servers on your machine, this step can be skipped.

sudo ufw allow 53
sudo ufw allow 22/tcp
sudo ufw allow 69/udp
sudo ufw allow 80/tcp

Notice that the first command I used did not specify UDP or TCP. When omitted, UFW adds both protocols. DNS uses TCP for larger DNS exchanges like zone transfers and huge replies, so you’ll probably want both.

UFW displays the results very nicely.

sudo ufw status
Firewall loaded

To                         Action  From
--                         ------  ----
53:tcp                     ALLOW   Anywhere
53:udp                     ALLOW   Anywhere
22:tcp                     ALLOW   Anywhere
69:udp                     ALLOW   Anywhere
80:tcp                     ALLOW   Anywhere

SYN cookies and more

UFW can be used to load kernel options, too. These are defined in “/etc/ufw/sysctl.conf“. For example, I wanted to enable SYN cookies which was added to thwart certain TCP DoS attacks. Modify the following line to 1 in order to enable the feature.

net/ipv4/tcp_syncookies=1

Logging can suck

Okay, if you’re on a busy network and don’t want to fill up your syslog, you might want to disable UFW’s logging.

sudo ufw logging off

And really that’s all there is to it. Be sure to check out the man page for some more examples and features you may be interested in.