Tuesday 10 May 2011

Adding a module to initrd.gz


The frequent reason why your kernel can't boot is because of a improper created initrd image. Here is a small description of what you can do if you encounter a similar problem.

Contents

 [hide]

[edit]What is initrd image

Your boot loader usually supports initrd instruction. For example, in GRUB:
OpenVZ (2.6.8-022stab077)
        root (hd0,0)
        kernel /vmlinuz-2.6.8-022stab077 ro root=LABEL=/ console=tty0
        initrd /initrd-2.6.8-022stab077.img
GRUB loads initrd-2.6.8-022stab077.img file at a certain address in memory. When kernel boots, it checks for initrd image, and if it exists starts init script that resides on this image. init script is usually written in nash (a sort of bash-like shell, just smaller). When init script on initrd image is finished, kernel usually calls standard System V init process (/sbin/init, etc.)

[edit]Why initrd image is necessary

Suppose your root partion resides on some SCSI device and driver for this SCSI devices is compiled as a kernel module. Of course this module is required at boot time to have access to the root partion — but it is not in the kernel. Thus the need for an initrd image.
Additionally after udev subsystem become common, somebody has to start udev to create device nodes. This is initrd's duty too.

[edit]Typical problem

Consider a real problem. After booting the kernel we get the following:
...
Creating root device
mkrootdev: label / not found
Mounting root filesystem
mount: error 2 mounting ext3
mount: error 2 mounting none
Switching to new root
switchroot: mount failed: 22
umount /initrd/dev failed: 2
Kernel panic - not sysncing: Attempted to kill init!
This can appear if there is no module loaded for device, where root partion resides. To solve the problem, extract the initrd image.

[edit]Extracting initrd image

Initrd image is just cpio-gzip archive. So to extract it:
$ mkdir initrd
$ cd initrd
$ gzip -dc /boot/initrd-2.6.16-026test014.4-smp.cpio | cpio -id
$ ls -1
bin
dev
etc
init
initrd-2.6.16-026test014.4-smp.cpio
lib
loopfs
proc
sbin
sys
sysroot

[edit]Analyzing init script

$ cat init
#!/bin/nash

mount -t proc /proc /proc
setquiet
echo Mounted /proc filesystem
echo Mounting sysfs
mount -t sysfs none /sys
echo Creating /dev
mount -o mode=0755 -t tmpfs none /dev
mknod /dev/console c 5 1
mknod /dev/null c 1 3
mknod /dev/zero c 1 5
mkdir /dev/pts
mkdir /dev/shm
echo Starting udev
/sbin/udevstart
echo -n "/sbin/hotplug" > /proc/sys/kernel/hotplug
echo "Loading mptbase.ko module"
insmod /lib/mptbase.ko
echo "Loading mptscsih.ko module"
insmod /lib/mptscsih.ko
/sbin/udevstart
echo Creating root device
mkrootdev /dev/root
umount /sys
echo Mounting root filesystem
mount -o defaults --ro -t ext3 /dev/root /sysroot
mount -t tmpfs --bind /dev /sysroot/dev
echo Switching to new root
switchroot /sysroot
umount /initrd/dev
We can see that init tries to load modules mptbase.ko and mptscsih.ko. Check for presense of these modules on initrd image:
$ ls -1 ./lib/
mptbase.ko
mptscsih.ko
So they are here... But on the node in question there is a device supported by driver in another module: mptspi.ko! After adding it to the image and into init script everything should work.

[edit]Creating initrd

We just have to cpio and gzip directory cpio:
$ find ./ | cpio -H newc -o > /boot/new-initrd.cpio
1354 blocks
$ cd /boot
$ gzip new-initrd.cpio
$ mv new-initrd.cpio.gz new-initrd.img
Next, try to boot your kernel with newly created initrd image.

[edit]Who create initrd by default?

Usually there is an mkdinitrd package installed, that allows to create initrd image. You can use this program, it has a lot of options. OpenVZ kernel RPM-package (and “make install” target too) uses this program to create an initial (default) initrd image.

Wednesday 4 May 2011

DASH BASH

Well dash is being introduced and is more POSIX compliant than bash

Here's a link to show you the differences:

http://mywiki.wooledge.org/Bashism

Sunday 1 May 2011

Setting up OpenVPN on ubuntu / Mac os x

Since PPTP is inherently insecure, moving to something SSL or IPSEC based is far more perferrable....

OpenVPN on the Gateway

We'll begin with installing openVPN on the gateway:
sudo apt-get install openvpn easy-rsa
After that, make sure our openvpn config is always used:
/etc/default/openvpn
## Comment out everything and add:
# Start our openvpn.conf automatically:
AUTOSTART="all"
We'll need to edit some openvpn configuration files and generate some keys for the people we want to have access. There are some nice example configs, so we'll be using them. We'll need root access for the next dozen of instructions, so let's su and head to the openvpn config directory:
 
cd /etc/openvpn/
cp -r /usr/share/doc/openvpn/examples/easy-rsa/ .
Note the above directory may not exist in ubuntu 14, it may be in /usr/share/easy-rsa
 
Now that we got some examples to work with, let's edit them.
easy-rsa/2.0/vars
## Comment the line that starts with:
## export EASY_RSA
## And add this below:
export EASY_RSA=/etc/openvpn/easy-rsa/2.0

## You can also set some defaults for your certificates.
## Find the following variables and set them appropriately.
export KEY_COUNTRY=UK
export KEY_PROVINCE=SY
export KEY_CITY=London
export KEY_ORG="OpenVPN"
export KEY_EMAIL="waga@an.example"
Time to source that information into our current shell session:
source ./easy-rsa/2.0/vars
And build the necessary certificates. (Certificate Authority, Server key, Client key and Diffie Hellman.) You can probably rename your server and client(s) however you want, but need to remember the names for later configuration. Answer yes when asked if you want to sign the certificates and want to commit them.
When it asks for a Challenge Password, you can just leave it blank and enter.
The Common Name that is asked when building a server key needs to be the same as the argument given to the build-key-server command ('server' in our example).
The Common Name that is asked when building a client key needs to be the same as the argument given to the build-key command ('client1' in our example). Watch for the errors, and resolve using the prompts it gives you
./easy-rsa/2.0/clean-all
./easy-rsa/2.0/build-ca
./easy-rsa/2.0/build-key-server server
./easy-rsa/2.0/build-key client1
(to add another user simply change client1 for e.g. the username phil, bob, dave etc)
./easy-rsa/2.0/build-dh
We'll copy the generated keys over when we get to the Client steps. It's time now to set up the openvpn.conf we told OpenVPN to autostart:
/etc/openvpn/openvpn.conf
## Add: 
dev tun
proto tcp
## Change this port number if you want a non-standard port.
port 1194

ca /etc/openvpn/easy-rsa/2.0/keys/ca.crt
cert /etc/openvpn/easy-rsa/2.0/keys/server.crt
key /etc/openvpn/easy-rsa/2.0/keys/server.key
dh /etc/openvpn/easy-rsa/2.0/keys/dh1024.pem

user nobody
group nogroup
## Leave this as-is; it is the VPN virtual network address.
# i've set this to something else (192.168.xxx.xxx) since my 3rd DC uses this range
server 10.8.0.0 255.255.255.0

persist-key
persist-tun

status openvpn-status.log
log-append /var/log/openvpn
verb 3
client-to-client
# disable this or ALL traffic will be going through your VPN
#disabling allows split routing/split tunnelling
#push "redirect-gateway def1"
# enter your local LAN subnet here.... 
push "192.168.x.x 255.255.255.0"
 
# Remove comment if you want lzo compression
#comp-lzo
 

OpenVPN on the Client

On the client we need to install an OpenVPN client, for Mac OSX I use Tunnelblick which is currently hosted at Google code. After opening the .dmg file, copy the Tunnelblick.app file to your Applications. When this is done, let's transfer the client certificates from the gateway to the client, I prefer to use SCP for this.
You will probably need root ssh access to the file. If you don't have that, make sure you've copied the keys to your homedir instead. If you have created multiple client certificates, or changed the names of the certificates, then don't forget to scp those over as well.
scp root@your.gateway:/etc/openvpn/easy-rsa/2.0/keys/{ca.rt,client1.{crt,key}} ~/Library/openvpn && sudo chown $USER ~/Library/openvpn/{ca.rt,client1.{crt,key}}
Now that we have a client, we will need to configure it. Be sure to set your Gateway server's IP where it says YOUR-GATEWAY-IP-GOES-HERE and if you also picked a non-standard port, change that in this config as well. The same applies for any client certificates you've created on the gateway.
~/Library/openvpn/openvpn.conf
# We are a client, not a server/gateway.
client

# We use a TUN interface
dev tun

# We use the TCP protocol
proto tcp

# Name of the gateway's certificate
## 'server' if you followed our example.
remote-cert-tls server

# The hostname/IP and port of the server.
# You can have multiple remote entries
# to load balance between the servers.
## If you chose a non-standard port, change 1194 to the port you picked.
remote YOUR-GATEWAY-IP-GOES-HERE 1194          

# Keep trying indefinitely to resolve the
# host name of the OpenVPN server.  Very useful
# on machines which are not permanently connected
# to the internet such as laptops.
resolv-retry infinite

# Most clients don't need to bind to
# a specific local port number.
nobind

# Downgrade privileges after initialization (non-Windows only)
user nobody
group nobody

# Try to preserve some state across restarts.
persist-key
persist-tun

# SSL/TLS parms.
# See the server config file for more
# description.  It's best to use
# a separate .crt/.key file pair
# for each client.  A single ca
# file can be used for all clients.
## If you picked different names for your client certificates, change here
ca ca.crt
cert client1.crt
key client1.key

# Enable compression on the VPN link.
# Don't enable this unless it is also
# enabled in the server config file.
# comp-lzo

# Set log file verbosity.
verb 3

# Make sure the right gateway settings are used.
push "dhcp-options DNS 8.8.8.8"
#push "dhcp-options WINS 10.8.0.1"
#push "redirect-gateway"
 

Key files:

Here is an explanation of the relevant files:
FilenameNeeded ByPurposeSecret
ca.crtserver + all clientsRoot CA certificateNO
ca.keykey signing machine onlyRoot CA keyYES
dh{n}.pemserver onlyDiffie Hellman parametersNO
server.crtserver onlyServer CertificateNO
server.keyserver onlyServer KeyYES
client1.crtclient1 onlyClient1 CertificateNO
client1.keyclient1 onlyClient1 KeyYES
client2.crtclient2 onlyClient2 CertificateNO
client2.keyclient2 onlyClient2 KeyYES
client3.crtclient3 onlyClient3 CertificateNO
client3.keyclient3 onlyClient3 KeyYES

Routing issues after network switching:

I've encountered some problems when switching between local networks after having had the VPN on. It seems that after I've switch to a different LAN, I can't reach the gateway host from the new local network, thus not allowing me to set up the VPN from the second VPN. My guess is that not all routes are reset after disconnecting.

To find out what route seems to be incorrect use:
netstat -rn
In my case it was w.x.y.z/32, where w.x.y.z is my gateway's IP.
You can remove it via:
route delete w.x.y.z/32 

infact, I've changed the Applications/Utilities/Tunnelblick.app/Contents/Resources/client.down.tunnelblick.sh file so that the post script removes the VPN gateway from teh routing table.

IP=`ping -n -c 1 vpn-gw.mydomain.com | grep icmp_seq | cut -d " " -f 4 | cut -d ":" -f 1`
route delete $IP