Adventures in Red Hat Enterprise Linux, CentOS, Fedora, OpenBSD and other open source solutions.

Using ssh keys

I discovered that I have quite a few ssh articles on my website, but none of them include how to simply setup SSH-keys. It's so simple and so convenient, lets have a closer look.

First, on your workstation, create ssh-keys using ssh-keygen. I use OpenBSD for this example, the output might slightly differ when using another operating system.

$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/username/.ssh/id_rsa):
Created directory '/home/username/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/username/.ssh/id_rsa.
Your public key has been saved in /home/username/.ssh/
The key fingerprint is:
00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 [email protected]

(The username, hostname and fingerprint have been obfuscated in this example.)

For the record:

  • /home/username/.ssh/id_rsa is your private key. Keep it secure
  • /home/username/.ssh/ is your public key. Distribute is to all machines your want to connect to.

Be sure to use a good passphrase, together with the private key it is the key to your locked world of machines you will connect to. Also; safe the keys to a secure location, like your USB-stick, or a CD-rom. Loosing the private key or its passphrase means you'd have to do this all over again.

Now you need to put the contents of your ~/.ssh/ file into ~/.ssh/authorized_keys on every machine you will want to connect to. Specifically; append your public key to the authorized_keys file, as there might be other public keys in there already. Use this ssh distribute script for it or do it manually.

From now on you can start using your ssh-key, but ssh will constantly prompt you for a passphrase. Annoying, so read on.

You can use an ssh-agent to manage your keys and enter your passphrase just once, as you add your private key to the agent. An article exists that describes these ssh-agent tricks.

That's it, good luck using your ssh-keys.

Serial connection from an apple

Here is a very simple trick to use serial connection on your apple, a usb port, a usb-serial converter and a serial cable.

  1. Install all drivers for that usb-serial converter.
  2. Open a terminal. (Find it with spotlight or in the finder.)
  3. Type: screen $device $speed. Where device is some /dev/tty.... device and speed something like 9600, 19200, etc.

See how great screen is?!

Using Putty and an HTTP proxy to ssh anywhere through firewalls

Do you ever have the situation (say at work using windows) where you would like to connect to a machine over ssh (say at home using Linux/UNIX) but it's not possible because of firewall rules? There might be an http-proxy server available that you could use. Be aware that applying this trick might be technically possible but not permitted. Probably best to discuss it with someone in your organization first. Here are the ingredients:
  1. A windows machine to be used as a client.
  2. A Linux/UNIX machine to be used as an ssh server.
  3. Get Putty or Portable Putty to your client.
  4. Find out what http proxy your organization is using on your client.
  5. Configure Putty to use that proxy on your client.

Finding out what proxy your organization uses.

There are a few options, going from easy to difficult, you don't have to do each, just one. See what works for you.
  1. Open Internet Explorer, click Tools Internet Options.... Go to the tab Connections and click LAN Settings.... In the Proxy server. area, you will find the proxy server and the port. If not; continue and try the next trick.
  2. On your windows machine, open a good website and click Start or whatever, then Run... and enter cmd. You will be presented with a crippled terminal. Type netstat -an and search for ESTABLISHED and 8080 or 3128 on one line, the IP can be found in the third column. Mine looks like this: TCP ESTABLISHED. The is my proxy server, 3128 the port.

Configuring Putty to use a proxy.

Now that you have the proxy server and the port, lets configure Putty.
  1. Open Putty and enter the Host Name where you would like to connect to.
  2. Open the plus before Connections and select Proxy. Enter the Proxy hostname and Port.
  3. Now select Open. You should be presented with a password challenge.
Congratulations, you are connected!

Screencast: the basics of shell scripting

Screenshot of a shell script.

Here is a first attempt to explain the basis of shell scripting in a screencast. This video is almost 25Mb, 16 minutes and includes explanation of:

  1. What is a shell script
  2. Why would you want to use a shell script
  3. What scripts could you use
  4. One sample script that warns a user when a disk is amost full

This screencast covers only simple things like: #!/bin/sh, chmod, df, echo, while-loop, if test, etc.

The format is .mp4, encoded in h.264, a tool like VLC will be able to play it.

"Automatically" upgrading OpenBSD

In my endless battle for automation, I have written a script that automatically upgrades OpenBSD one release further. This script is usable but requires more attention to be fully utilized. It was able to upgrade my Soekris 4801 from OpenBSD 4.1 to OpenBSD 4.2 without troubles!

The script runs through a few "stages":

  1. Check for new OpenBSD release, download kernels and extract firmware.
  2. Download other sets and extract them.
  3. Upgrade packages.

I recently found a scripts to update /etc from somebody else to cheat a bit.

Some uglinesses:

  • Solved - thanks Clint Pachl. It uses wget. Wget is not installed on every box.
  • Solved - using bc now. It does some nasty sed&awk tricks to determine the next release.
  • It does not apply specific changes per release as described in the OpenBSD upgrade guide
  • Solved - using binpatch now. Patches are not applied, only major releases.
  • It needs the user to configure what sets need to be upgraded. Would be nice if the script could figure this out autonomously.

The intention of this script is that you run it, reboot if the script requires you to and run it again. The script will guide you though this process.

Please let me know if it works for you, or you had to modify something!

#!/bin/sh -x

# This script updates OpenBSD in several stages:
# 1) Install new kernels and firmware if available.
# 2) Install other new sets. (comp, game, man but not etc.)
# 3) Install new packages.

# Set a server that provides your version and architecture.
# Select what sets to use.
sets="base comp man misc"
# Tell the script to store the sets in this location.
# Set a server where binpatches are stored. This URL should contain:
# "binpatch-$release-$machine-xxx.tgz" files.
# Set a directory where binpatches are stored. This script creates
# the specified directory when it does not exist.

# From here on: if you need to change something, the code
# is probably broken, send an email to [email protected]

# Store the release and architecture, it is being used intensively.
release=$(uname -r)
machine=$(uname -m)

# A function to confirm if the script should continue.
askuser() {
echo "Do you wish to continue? [y/n]"
read answer
case "$answer" in
   exit 1
   echo "Please answer \"yes\" or \"no\"."

# Check if that storage space exists.
if [ ! -d $storedirectory ] ; then
echo "The directory to store the sets in does not exist, creating it."
mkdir -p "$storedirectory"

# Caclulate the setnumber, almost the same as the release number, but without a dot.
setnumber=$(echo "$release" | awk 'BEGIN {FS="."} {print $1$2}')

# Check if this script left us the base that comes with our currently booted kernel.
if [ -f $storedirectory/base$setnumber.tgz ] ; then
echo "Continuing the upgrade to OpenBSD $(uname -r)."
for set in $sets ; do
  if [ ! -f $storedirectory/$set$setnumber.tgz ] ; then
   echo "Downloading and extrating $set$setnumber.tgz"
   ftp -o $storedirectory/$set$setnumber.tgz $distserver/pub/OpenBSD/"$release"/"$machine"/$set$setnumber.tgz
  tar -C / -xzpf $storedirectory/$set$setnumber.tgz
  rm $storedirectory/$set$setnumber.tgz
echo "Making devices in /dev."
cd /dev
# TODO check all changes required in etc per release and create a case statement.
echo "Check the Upgrade Guide, see what you still need to do:"
echo "$setnumber.html"
echo "Please reboot to activate the new userland tools. When this script runs again, it will upgrade packages."
exit 0
# There are no traces of a previous run, lets check if a newer verion of OpenBSD is available.
nextrelease=$(echo "ibase=9 ; $release+0.1"|bc)
echo "quit" | ftp -o /dev/null "$distserver/pub/OpenBSD/$nextrelease/" > /dev/null 2>&1
if [ $? = 0 ] ; then
  echo "You are using OpenBSD $release, but OpenBSD $nextrelease is available."
  nextsetnumber=$(echo "$release" | awk 'BEGIN { FS ="." } { print $1$2+1 }')
  echo "Downloading base$nextsetnumber.tgz to /."
  ftp -o $storedirectory/base$nextsetnumber.tgz $distserver/pub/OpenBSD/$nextrelease/"$machine"/base$nextsetnumber.tgz
  echo "Saving current kernel to /obsd."
  cp /bsd /obsd
  for kernel in bsd bsd.rd ; do
   echo "Downloading $kernel kernel."
   ftp -o /$kernel $distserver/pub/OpenBSD/$nextrelease/$machine/$kernel
  echo "Unpacking new firmware to /etc/firmware."
  tar -C / -xzpf $storedirectory/base$nextsetnumber.tgz ./etc/firmware
  echo "Please reboot to activate the new kernel. When this script runs again it will continue to install the new OpenBSD release."
  exit 0

# Check if (newer) binpatches are available.
if [ ! -d "$binpatchdir" ] ; then
echo "The $binpatchdir does not exist, creating it."
mkdir -p "$binpatchdir"
while [ "$status" = 0 ] ; do
while [ -f "$binpatchdir"/"$number"_* ] ; do
  number=$(printf "%03s\n" $(($number+1)))
ftp -o "$binpatchdir"/binpatch-"$release"-"$machine"-"$number".tgz "$binpatchserver"/binpatch-"$release"-"$machine"-$number.tgz > /dev/null 2>&1
if [ "$status" = 0 ] ; then
  echo "Binpatch $number will be installed."
  tar -xvzpf "$binpatchdir"/binpatch-"$release"-"$machine"-"$number".tgz -C /

# Finally update the packages.
export PKG_PATH="$distserver/pub/OpenBSD/$release/packages/$machine"
echo "Installing upgraded packages."
pkg_add -u -x

An article describing how to install openbsd fully automatically might also help you.

OpenSSH using stepstones

You might be working in an environment where you always ssh from your machine to the middle machine and then connect to the destination machine. What a waste of time, lets see how you could automate it. The middle machine is frequently referred to as stepstone host.


  • A workstation. In this example, the hostname is workstation.
  • A stepstone machine, the machine in the middel. The hostname is stepstone in this example.
  • The command nc (netcat) installed on the stepstone.
  • A destination machine, likely a server or your other workstation. (at work for example.) The hostname is destination in this example.

Implementing it

On your workstation, add this sniplet to ~/.ssh/config

Host destination
ServerAliveInterval 60
ProxyCommand ssh stepstone nc -w 180 %h %p

Replace destination with the machine your will eventually will connect to. Replace stepstone with the machine that is in the middle. Normally, you always login to that box first, then continue. the -w 180 and ServerAliveInterval 60 are hints that Peter S. has given, see comments below.

After you have altered your ~./ssh/config go ahead and try to connect directly to your destination machine.

workstation $ ssh destination
[email protected]'s password:
[email protected]'s password:
destination $

Wow your automated it! The only thing is these stupid passwords. Check out how to implement ssh-keys into your session and how to distribute keys. This is not required, but after a few days of password typing, you will want to setup ssh-keys properly.


Here is a sniplet of a more complicated configuration:

ServerAliveInterval 60

Host stepstone
User myotherusername

Host 192.168.1.*
User yourusername
Port 2222
ProxyCommand ssh stepstone nc -w 180 %h %p

Setting values without specifying a host, makes that value count for every host. The ServerAliveInterval is set for every host. If I connect to stepstone, I will use the username myotherusername. In the bottom declaration a * is used. This implies that all machines in the network will be using this part of the configuration. When logging in to a machine in the network, then you will use the username yourusername.
You can do many tricks with openssh, check out the manpage of ssh for more information.

Changes in Operating System land

What a good month for geeks like us that like to upgrade!

  • OpenBSD 4.2 is coming on 1st of November 2007 - party
  • Ubuntu Gutsy Gibbon 7.10 is already released since the 18th of October 2007 -party
  • Apple Mac OS X 10.5 Leopard is coming the 26th of October 2007 - party

November and December are scheduled to be the upgrade months!

Distribute SSH keys easily

You know it can be cumbersome to copy over your public ssh-key to every server you have ever been to, so you push the action "automate ssh login" further and further into your personal planning.

Now it's time to distribute keys for once and for all. Let's use a script to speed things up a bit.

Update, check out ssh-copy-id(1). It does the same thing but is packaged with a openssh, far better than custom scripts! Thanks Davee


# A script to push a key to the only argument, a remote server.

# Check if an argument was given.
if [ ! "$1" ] ; then
echo "Please specify a hostname to distribute the key to."
exit 1

# Check if all the local files are here.
if [ ! -f ~/.ssh/ ] ; then
echo "The local file ~/.ssh/ is missing. Please create it."
exit 1

# This command send the key, create a .ssh dir if required and set the
# correct permissions.
cat ~/.ssh/ | ssh -q "$1" "if [ ! -d ~/.ssh/ ] ; then mkdir ~/.ssh ; fi ; chmod 700 ~/.ssh/ ; cat - >> ~/.ssh/authorized_keys ; chmod 600 ~/.ssh/authorized_keys"

What this script does it copy over your public ssh key to a server and set the permissions of the directories correct. This can be difficult from time to time.

The script will ask you once for your password on the remote server and do everything in that one session.

Here is how you could use the script:

$ ./

Or if you have a list of server (extract them from ~/.ssh/known_hosts) you could use this list like this:

$ cat list-of-servers.txt | while read hostname ; do
>  ./ "$hostname"
> done

OpenBSD diskless install

Here is a recipe to boot OpenBSD (4.1) from an OpenBSD (4.1) box. This can be used to boot any machine that has no disks and supports pxeboot. The advantage is you save a little money on not buying hard-disks, but on the other hand, the "server" that serves everything must be always on.

This could be a good solution in a clustered environment.

Well, if you decide you would like to play, follow these instructions.

Install an OpenBSD system. This will be your boot-server. Just select generic settings that you prefer.

Here is the IP-scheme I have used:

netmask: (or /24)

When the install is done, modify these files on the boot server to look like this.

First, configure an IP-address.

# cat /etc/hostname.pcn0
# cat /etc/mygate
# cat /etc/resolv.conf
lookup file bind

Then make sure some daemons are started at boot time on the boot server.

# cat /etc/rc.conf.local
# For the PXEBOOT and the OS, DHCP is used.
# After PXEBOOT, the kernel uses rarp to discover its IP-address.
# Then bootparamd to figure out options for mounting things.
# And NFS to serve directories like /root, /usr and swap.
nfsd_flags="-tun 4"

For rarp, add an entry like this to represent the client "diskless". The first column, the mac-address will need to be changed to the mac-address of the client you would like to boot. You can find out a MAC-address of your client by typing ifconfig on it, but you then need some sort of an os. Try a livecd from whatever distribution you like.

# cat /etc/ethers
00:0c:29:ad:c8:32 diskless

Also add this machine to the hosts file. I gave my client the IP-address, change it to anything you like. This IP-address is the address the kernel will boot with.

# cat /etc/hosts diskless

Tell the clients kernel where to get the root directory and swap from.

# cat /etc/bootparams
diskless root= swap=

Configure DHCP. This is used by PXEBOOT, and by the running Operating System, but not by the kernels IP address. It is logical and wise to use the same IP address here and in /etc/ethers, /etc/hosts, but it's not required.

# cat /etc/dhcpd.conf
shared-network LOCAL-NET {
        option  domain-name "my.domain";
        option  domain-name-servers;

        subnet netmask {
                option routers;
                filename "pxeboot";

host diskless {
        hardware ethernet 00:0c:29:ad:c8:32;

Make sure tftp is started in inetd.conf. (I enables only the default, not the ipv6 version.)

# cat /etc/inetd.conf | grep tftp
tftp            dgram   udp     wait    root    /usr/libexec/tftpd      tftpd -s
#tftp           dgram   udp6    wait    root    /usr/libexec/tftpd      tftpd -s

The /tftpboot directory must contain the pxeboot code and an openbsd kernel called bsd. (By the way, replacing that bsd by bsd.rd makes this an install-server!) You can get these file form any openbsd mirror in the pub/OpenBSD/4.1/i386/ directory.

# ls /tftpboot

Now export a few filesystems in /etc/exports.

# cat /etc/exports
/export/diskless -maproot=root -alldirs diskless

And create the 128 megabytes swap space like this:

# mkdir -p /export/diskless/root
# dd if=/dev/zero bs=1m count=128 of=/export/diskless/swap

Now you will have to unpack some sets (the minimal base41.tgz and etc41.tgz) into the diskless root and create a few devices. The sets can be downloaded from one of the openbsd mirrors. The devices, like /dev/console also need to be created.

Be aware about the -p option in the tar extract, it preservers permissions and that is required.

# cd /export/diskless/root
# tar -xvzpf base41.tgz
# tar -xvzpf etc41.tgz
# cd dev
# ./MAKEDEV all
# cd ../

Also edit the /export/diskless/root/etc/fstab.     /       nfs     rw      0       0     none    swap    sw,nfsmntpt=/swap

At the end of this all, reboot the server to start everything.

# reboot

When the server is booted, boot up the client and see the magic! Here is an overview of what happens:

  1. The machine boots and runs the built in PXEBOOT.
  2. PXEBOOT will do a DHCP request.
  3. The DHCP server will tell the client it IP-address and what to boot (pxeboot).
  4. The /ftpboot/pxeboot is downloaded using tftp.
  5. The downloaded pxeboot is executed. This downloads the kernel (bsd) and start that kernel.
  6. The bsd kernel does a rarp (/etc/ethers, /etc/hosts, /etc/bootparams) request to find out who he is, and where to get the swap and root filesystem.
  7. The kernel mounts swap and root and starts /sbin/init.
  8. From here on init takes over and normal OpenBSD boot will proceed.

Now check if it boots, there is still a few things to do. Lets set a hostname in /export/diskless/root/myname and set the password.

# echo "diskless" > /export/diskless/root/etc/myname
# chroot /export/diskless/root
# passwd root
Changing local password for root.
New password:
Retype new password:
# exit

Now you are done! have fun with it!

I have installed this setup in a virtual host on my intel mac, you can download a packed-up version of the images and the configuration to peek around. The root password installed on these images is "OpenBSD"
The Vmware Fusion boot-server. (229 Mb packed)
The Vmware Fusion client. (27 Kb packed)

Efficient social networking

Yesterday I heard a lecture about marketing from Karen Romme.

One thing I remembered was this simple trick:

Whenever you go to a lecture/congress/information-event/etc. Stand up once to ask a question but introduce yourself like this: (Modified to my situation)
"Hi, I am Robert de Bock, a UNIX/Linux consultant. (insert question here)"

Chances are that somebody will approach you afterward. The person that comes to you could be interesting for your network...

Syndicate content