Install MySQL Proxy On CentOS

This tutorial explains how you can install MySQL Proxy on a CentOS 5 (x86_64). MySQL Proxy is a simple program that sits between your client and MySQL server that can monitor, analyze and transform their communication. Its flexibility allows an unlimited number of uses; common include: load balancing, failover; query analysis, filtering and application modification, and many others.

At a minimum Centos 5 final x86_64 install:

yum
install gcc.x86_64 libevent.x86_64 libevent-devel.x86_64
readline.x86_64 readline-devel.x86_64 ncurses.x86_64
ncurses-devel.x86_64 glib2.x86_64 glib2-devel.x86_64


cd /usr/local/src/


wget http://www.lua.org/ftp/lua-5.1.3.tar.gz

tar zxvf lua-5.1.3.tar.gz


cd lua-5.1.3

make linux

make install


wget
http://dev.mysql.com/get/Downloads/MySQL-Cluster-6.2/mysql-5.1.23-ndb-6.2.15-linux-x86_64-glibc23.tar.gz/\
from/http://www.mirrorservice.org/sites/ftp.mysql.com/


tar xzvf mysql-5.1.23-ndb-6.2.15-linux-x86_64-glibc23.tar.gz

ln -s mysql-5.1.23-ndb-6.2.15-linux-x86_64-glibc23 mysql

PATH=$PATH:/usr/local/mysql/bin

export PATH


Edit your .profile to make this permanent:


# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:/usr/local/mysql/bin:$HOME/bin

export PATH
unset USERNAME

wget
http://dev.mysql.com/get/Downloads/MySQL-Proxy/mysql-proxy-0.6.1.tar.gz/from/http://www.mirrorservice.org/sites/ftp.mysql.com/


tar zxvf mysql-proxy-0.6.1.tar.gz

cd mysql-proxy-0.6.1


./configure LDFLAGS="-lm -ldl" LUA_CFLAGS="-I/usr/local/include/" LUA_LIBS=/usr/local/lib/liblua.a


make

make install


Let's create a sample LUA script so you can see some logs.


mkdir /var/log/mysql-proxy/

mkdir -p /usr/local/mysql/lua-scripts/


vi /usr/local/mysql/lua-scripts/simple-log.lua




Script modified to get IP and to use proxy.connection.server.thread_id.)


local log_file = '/var/log/mysql-proxy/mysql.log'
local fh = io.open(log_file, "a+")

function read_query( packet )
if string.byte(packet) == proxy.COM_QUERY then
local query = string.sub(packet, 2)
fh:write( string.format("%s %6d -- %s :IP %s :USER: %s\n",
os.date('%Y-%m-%d %H:%M:%S'),
proxy.connection.server.thread_id,
query,
proxy.connection.client.address,
proxy.connection.client.username))
fh:flush()
end
end

Now start up your proxy using the variable --proxy-backend-addresses to point the proxy at your servers.


/usr/local/sbin/mysql-proxy
--proxy-lua-script=/usr/local/mysql/lua-scripts/simple-log.lua
--proxy-backend-addresses=192.168.1.33:3306
--proxy-backend-addresses=192.168.1.34:3306 --daemon


192.168.1.33 and 192.168.1.34 are the MySQL nodes that the proxy will be connecting to.


Allow connections for the proxy through your firewall:


### ALLOWED TO CONNECT TO MYSQL PROXY
###
### LOCAL ADMINS
-A INPUT -s SRC-IP -d DST-IP -p tcp -m state --state NEW -m tcp --dport 4040 -j ACCEPT

Where DST-IP is my proxy server and SRC-IP is my local box (client machine).


Now
from your local box (not the mysql-proxy server) try and connect to the
backend databases through the proxy ( user with relevent permissions
must exist in the db).


mysql -u dba_admin -p -h PROXY-SERVER -P 4040


Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 16 to server version: 5.1.23-ndb-6.2.15

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.


mysql> show databases;



+--------------------+
| Database |
+--------------------+
| information_schema |
| Imap_Forms |
| mysql |
| test |
+--------------------+

4 rows in set (0.01 sec)


mysql> quit


Bye


N.B. The proxy uses the port 4040 instead of 3306.


Test the mysql-proxy admin interface from the mysql-proxy server:


mysql -u root -p -h 127.0.0.1 -P 4041


Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 1

Server version: 5.1.20-agent MySQL Enterprise Agent

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.


mysql> select * from proxy_connections;


+------+--------+-------+------+
| id | type | state | db |
+------+--------+-------+------+
| 0 | server | 0 | |
| 1 | proxy | 0 | |
| 2 | server | 10 | |
+------+--------+-------+------+

3 rows in set (0.00 sec)


mysql>quit


bye


Job done! Now read on:




Read more...

Intrusion Detection For PHP

This tutorial explains how to set up PHPIDS on a web server with Apache2 and PHP5. PHPIDS (PHP-Intrusion Detection System) is a simple to use, well structured, fast and state-of-the-art layer of security for your PHP based web application. The IDS or bands or filters sanitizes any malicious input, it recognizes when an attacker tries to break your site and reacts exactly how you want. On the basis of a set of highly approved and tested filtering rules any attack is a digital impact rating which makes it easy to decide what type of action should follow the hacking attempt. It may be the simple logging to send an urgent email to the development team, displaying a warning message to the attacker or even to terminate the user session.


1 Preliminary Note

I have tested this on a Debian Etch LAMP system with Apache2 and PHP5 and the IP address 192.168.0.100. The Apache user and group on Debian Etch is www-data, so if you are on a different distribution, the Apache user and group might be different. The location of php.ini (/etc/php5/apache2/php.ini on Debian Etch) might differ as well.


I'm using a virtual host with the document root /var/www/web1/web in this example.

2 Installing PHPIDS
For security reasons, I want to install PHPIDS outside of the document root, so I create the directory /var/www/web1/phpids:

mkdir /var/www/web1/phpids

Then I install PHPIDS as follows (at the time of this writing the latest version was 0.4.7) - of all the contents of the phpids-0.4.7.tar.gz file, we only need the lib/ directory:


cd /tmp

wget http://php-ids.org/files/phpids-0.4.7.tar.gz

tar xvfz phpids-0.4.7.tar.gz

cd phpids-0.4.7

mv lib/ /var/www/web1/phpids/

Now I change to the directory /var/www/web1/phpids/lib/IDS...


cd /var/www/web1/phpids/lib/IDS

... and make the tmp/ directory (which will hold the PHPIDS log file) writable for the Apache user and group:

chown -R www-data:www-data tmp/

Next we configure the PHPIDS configuration file (Config.ini):

cd Config/

vi Config.ini


I'm using the default configuration here, all I did was to adjust the paths:

; PHPIDS Config.ini

; General configuration settings

; !!!DO NOT PLACE THIS FILE INSIDE THE WEB-ROOT IF DATABASE CONNECTION DATA WAS ADDED!!!

[General]

filter_type = xml
filter_path = /var/www/web1/phpids/lib/IDS/default_filter.xml
tmp_path = /var/www/web1/phpids/lib/IDS/tmp
scan_keys = false

exceptions[] = __utmz
exceptions[] = __utmc

; If you use the PHPIDS logger you can define specific configuration here

[Logging]

; file logging
path = /var/www/web1/phpids/lib/IDS/tmp/phpids_log.txt

; email logging

; note that enabling safemode you can prevent spam attempts,
; see documentation
recipients[] = test@test.com.invalid
subject = "PHPIDS detected an intrusion attempt!"
header = "From: <PHPIDS> info@php-ids.org"
safemode = true
allowed_rate = 15

; database logging

wrapper = "mysql:host=localhost;port=3306;dbname=phpids"
user = phpids_user
password = 123456
table = intrusions

; If you would like to use other methods than file caching you can configure them here

[Caching]

; caching: session|file|database|memcached|none
caching = file
expiration_time = 600

; file cache
path = /var/www/web1/phpids/lib/IDS/tmp/default_filter.cache

; database cache
wrapper = "mysql:host=localhost;port=3306;dbname=phpids"
user = phpids_user
password = 123456
table = cache

; memcached
;host = localhost
;port = 11211
;key_prefix = PHPIDS
;tmp_path = /var/www/web1/phpids/lib/IDS/tmp/memcache.timestamp


3 Using PHPIDS
We will now create the file /var/www/web1/web/phpids.php which will call PHPIDS for us (we will later on prepend that file to all our PHP files so that our PHP files can make use of PHPIDS automatically):


vi /var/www/web1/web/phpids.php

<?php
set_include_path(
get_include_path()
. PATH_SEPARATOR
. '/var/www/web1/phpids/lib'
);

require_once 'IDS/Init.php';
$request = array(
'REQUEST' => $_REQUEST,
'GET' => $_GET,
'POST' => $_POST,
'COOKIE' => $_COOKIE
);
$init = IDS_Init::init('/var/www/web1/phpids/lib/IDS/Config/Config.ini');
$ids = new IDS_Monitor($request, $init);
$result = $ids->run();

if (!$result->isEmpty()) {
// Take a look at the result object
echo $result;
require_once 'IDS/Log/File.php';
require_once 'IDS/Log/Composite.php';

$compositeLog = new IDS_Log_Composite();
$compositeLog->addLogger(IDS_Log_File::getInstance($init));
$compositeLog->execute($result);
}
?>


Now when you call that file in a browser, (e.g. http://192.168.0.100/phpids.php), you will see a blank page. But if you try to append some malicious parameters to the URL (e.g. http://192.168.0.100/phpids.php?test=%22%3EXXX%3Cscript%3Ealert(1)%3C/script%3E), PHPIDS will detect this and print its findings in the browser:


Now we have to find a way to make our PHP scripts use PHPIDS. Of course, you don't want to modify all your PHP scripts (you could have hundreds of them...). Fortunately, there's a better way: we can tell PHP to prepend a PHP script whenever a PHP script is called. For example, if we call the script info.php in a browser, PHP would first execute phpids.php and then info.php, and we don't even have to modify info.php.

We can do this by using PHP's auto_prepend_file parameter. We can either set this in our php.ini (this is a global setting which is valid for all PHP web sites on the server), or in an .htaccess file (this is a setting valid only for the web site in question):




php.ini
Open your php.ini (e.g. /etc/php5/apache2/php.ini), and set auto_prepend_file to /var/www/web1/web/phpids.php:

vi /etc/php5/apache2/php.ini

[...]
auto_prepend_file = /var/www/web1/web/phpids.php
[...]

Restart Apache afterwards:

/etc/init.d/apache2 restart

.htaccess
Instead of modifying php.ini (which is a global change, i.e., the change is valid for all web sites that use PHP on the server), you can instead use an .htaccess file (so the setting would be valid only for the web site for which you create the .htaccess file):

vi /var/www/web1/web/.htaccess

php_value auto_prepend_file /var/www/web1/web/phpids.php

Please make sure that the vhost for the web site in /var/www/web1/web contains something like this (otherwise the php_value line in the .htaccess file will be ignored) (if you have to modify the vhost, please don't forget to restart Apache):


<Directory /var/www/web1/web/>
AllowOverride All
</Directory>




Now we create a simple PHP file, /var/www/web1/web/info.php:


vi /var/www/web1/web/info.php

<?php
phpinfo();
?>


Call that file in a browser (http://192.168.0.100/info.php), and you should see the normal phpinfo() output.

Now append some malicious parameters to the URL (e.g. http://192.168.0.100/info.php?test=%22%3EXXX%3Cscript%3Ealert(1)%3C/script%3E), and you should find a PHPIDS report before the phpinfo() output (because /var/www/web1/web/phpids.php was executed before /var/www/web1/web/info.php):


PHPIDS logs to /var/www/web1/phpids/lib/IDS/tmp/phpids_log.txt, so you should see something in the log now:

cat /var/www/web1/phpids/lib/IDS/tmp/phpids_log.txt

"192.168.0.200",2008-06-04T17:36:08+02:00,54,"xss csrf id rfe lfi","REQUEST.test=%5C%22%3EXXX%3Cscript%3Ealert%281%29%3C%2Fscript%3E GET.test=%5C%22%3EXXX%3Cscript%3Ealert%281%29%3C%2Fscript%3E",
"%2Finfo.php%3Ftest%3D%2522%253EXXX%253Cscript%253Ealert%281%29%253C%2Fscript%253E"

Now by observing that log you learn what hackers are trying to do to your PHP applications, and you can try to harden your applications.

To add another level of security, we can stop our PHP scripts from executing if PHPIDS find that they are under attack: we simply add something like die('<h1>Go away!</h1>'); to the if (!$result->isEmpty()) {} section of the /var/www/web1/web/phpids.php script:


vi /var/www/web1/web/phpids.php

<?php
set_include_path(
get_include_path()
. PATH_SEPARATOR
. '/var/www/web1/phpids/lib'
);

require_once 'IDS/Init.php';
$request = array(
'REQUEST' => $_REQUEST,
'GET' => $_GET,
'POST' => $_POST,
'COOKIE' => $_COOKIE
);
$init = IDS_Init::init('/var/www/web1/phpids/lib/IDS/Config/Config.ini');
$ids = new IDS_Monitor($request, $init);
$result = $ids->run();

if (!$result->isEmpty()) {
// Take a look at the result object
echo $result;
require_once 'IDS/Log/File.php';
require_once 'IDS/Log/Composite.php';

$compositeLog = new IDS_Log_Composite();
$compositeLog->addLogger(IDS_Log_File::getInstance($init));
$compositeLog->execute($result);

die('<h1>Go away!</h1>');
}
?>


If there's no attack, the scripts are executed, but if PHPIDS finds an attack, it prevents the scripts from being executed and displays a message to the hackers:


4 Links


Read more...

New Version of OpenSUSE Released

OpenSUSE has released its latest version alias 11.0 today. This version will contain fresh innovations and new features. Some of them being the inclusion of KDE 4.04, marks a new theme installation, the latest Linux kernel (2.6.25.4) and a series of characteristics of OpenSUSE.

For a list of new features, read the release notes. And then go see screenshots of the installer to get an idea of how easy it is to be installed on your machine.


Read more...

Set Up WebDAV With MySQL Authentication On Apache2

The guide explains how to set up WebDAV MySQL Authentication (using mod_auth_mysql) Apache2 on a server Debian Etch. WebDAV means Web-based Distributed Authoring and versioning and is a set of extensions to the HTTP protocol which allows users to edit files directly on the Apache server so they do not need to be downloaded or sent via FTP. Of course, WebDAV may also be used to send and download files.

1 Preliminary Note

I'm using a Debian Etch server with the hostname server1.example.com and the IP address 192.168.0.100 here.

2 Installing Apache2, WebDAV, MySQL, mod_auth_mysql
Unfortunately libapache2-mod-auth-mysql is available as a Debian package only for Debian Lenny (testing) and Sid (unstable), but not for Etch. Therefore we will install the libapache2-mod-auth-mysql package from Lenny. To do this, open /etc/apt/sources.list and add the line deb http://ftp2.de.debian.org/debian/ lenny main; your /etc/apt/sources.list could then look like this:


vi /etc/apt/sources.list

deb http://ftp2.de.debian.org/debian/ etch main
deb-src http://ftp2.de.debian.org/debian/ etch main

deb http://ftp2.de.debian.org/debian/ lenny main

deb http://security.debian.org/ etch/updates main contrib
deb-src http://security.debian.org/ etch/updates main contrib

Of course (in order not to mess up our system), we want to install packages from Lenny only if there's no appropriate package from Etch - if there are packages from Etch and Lenny, we want to install the one from Etch. To do this, we give packages from Etch a higher priority in /etc/apt/preferences:


vi /etc/apt/preferences

Package: *
Pin: release a=etch
Pin-Priority: 700

Package: *
Pin: release a=lenny
Pin-Priority: 650

(The terms etch and lenny refer to the appropriate terms in /etc/apt/sources.list; if you're using stable and testing there, you must use stable and testing instead of etch and lenny in /etc/apt/preferences as well.)

Afterwards, we update our packages database:

apt-get update

If you're getting an error like this:


Segmentation faultsts... 96%

or this one:

E: Dynamic MMap ran out of room

open /etc/apt/apt.conf and add a line for APT::Cache-Limit with a very high value, e.g. like this:

vi /etc/apt/apt.conf

APT::Cache-Limit "100000000";

Then run

apt-get update

again and upgrade the installed packages:


apt-get upgrade

(If you see any questions, you can accept the default values.)

To install Apache2, WebDAV, MySQL, and mod_auth_mysql, we run:

apt-get install apache2 mysql-server mysql-client libapache2-mod-auth-mysql

Create a password for the MySQL user root (replace yourrootsqlpassword with the password you want to use):

mysqladmin -u root password yourrootsqlpassword

Then check with


netstat -tap | grep mysql

on which addresses MySQL is listening. If the output looks like this:

tcp 0 0 localhost.localdo:mysql *:* LISTEN 2713/mysqld


which means MySQL is listening on localhost.localdomain only, then you're safe with the password you set before. But if the output looks like this:


tcp 0 0 *:mysql *:* LISTEN 2713/mysqld

you should set a MySQL password for your hostname, too, because otherwise anybody can access your database and modify data:

mysqladmin -h server1.example.com -u root password yourrootsqlpassword

Afterwards, enable the WebDAV and mod_auth_mysql modules:

a2enmod dav_fs

a2enmod dav

a2enmod auth_mysql

Reload Apache:

/etc/init.d/apache2 force-reload

3 Creating A Virtual Host
I will now create a default Apache vhost in the directory /var/www/web1/web. For this purpose, I will modify the default Apache vhost configuration in /etc/apache2/sites-available/default. If you already have a vhost for which you'd like to enable WebDAV, you must adjust this tutorial to your situation.

First, we create the directory /var/www/web1/web and make the Apache user (www-data) the owner of that directory:


mkdir -p /var/www/web1/web

chown www-data /var/www/web1/web

Then we back up the default Apache vhost configuration (/etc/apache2/sites-available/default) and create our own one:

mv /etc/apache2/sites-available/default /etc/apache2/sites-available/default_orig

vi /etc/apache2/sites-available/default

NameVirtualHost *
<VirtualHost *>
ServerAdmin webmaster@localhost

DocumentRoot /var/www/web1/web/
<Directory /var/www/web1/web/>
Options Indexes MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>

</VirtualHost>

Then reload Apache:

/etc/init.d/apache2 reload


Read more...

Unlock Encrypted Root Partition

Systems fully encrypted to prevent others from obtaining your data from physical access. The rational of an encryption system is that you do not worry about what you encrypt and what not, because everything (except for / boot), will be encrypted.

However, the problem I encountered so far, how could I restart my computer from a distance? I would be obliged to be in front of the computer and enter the password. I asked at this stage how I could restart the computer remotely.

On Debian Administrator then I found an article written by Wulf (Coulmann Wolfram), in which he creates an initrd with Dropbear light as ssh server and unlock a script. However, the script still has some bugs and is not suitable for Ubuntu. In comments There are some changes (in particular comment # 31 and # 29), which will also work on Ubuntu.

The Script

Well, here's the script: dropbear

#!/bin/bash
# We add dropbear to the initrd to be able
# mount crypted partitions from remote
# copyright Wulf Coulmann
# GNU GPL
# http://www.gnu.org/licenses/gpl.html
#
# Download me here: http://gpl.coulmann.de/dropbear
# get infos about this script here:
# http://gpl.coulmann.de/ssh_luks_unlock.html
# Modified by Anonymous 2008
# Modified By Geoffroy RABOUIN 26/05/2008
# Modified by hyper_ch 15/06/2008
### INSTRUCTIONS FOR UBUNTU ###
# 0. Enable root login
# 1. Install killall, busybox and dropbear:
# ~# sudo apt-get install psmisc busybox dropbear
# 2. Edit network configuration below and copy contents
# of this file to /etc/initramfs-tools/hooks/dropbear
# 3. Save the script and make it executable:
# ~# sudo chmod +x /etc/initramfs-tools/hooks/dropbear
# 4. Create new initrd:
# ~# sudo mkinitramfs -o /boot/netboot
# 5. Edit /boot/grub/menu.lst and add your new initrd as the first entry
# 6. Delete the dropbear script the hooks folder
# ~# sudo rm /etc/initramfs-tools/hooks/dropbear
# 7. Profit!
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
# Begin real processing below this line
# load the prepared functions of debians initramfs enviroment
source /usr/share/initramfs-tools/hook-functions
# build the directories
DIRS='/lib /bin /usr/bin /usr/sbin/ /proc/ /root/.ssh/ /var/ /var/run/ /etc/dropbear/'
for now in $DIRS ; do
if [ ! -e ${DESTDIR}$now ]
then
mkdir -p ${DESTDIR}$now
fi
done
# copy the ssh-daemon and librarys
copy_exec /usr/sbin/dropbear /usr/sbin/
copy_exec /usr/bin/passwd /usr/bin/
copy_exec /bin/login /bin/
copy_exec /usr/bin/killall /usr/bin/
copy_exec /sbin/route /sbin/
copy_exec /usr/bin/awk /usr/bin/
#copy_exec /usr/bin/strace /usr/bin/
#copy_exec /bin/nc /bin/
copy_exec /usr/bin/wc /usr/bin/
# some librarys are not autoincluded by copy_exec
copy_exec /lib/libnss_compat.so.2 /lib/
copy_exec /usr/lib/libz.so.1 /usr/lib/
copy_exec /etc/ld.so.cache /etc/
copy_exec /lib/libutil.so.1 /lib/
# we copy config and key files
cp -pr /etc/dropbear/dropbear_dss_host_key ${DESTDIR}/etc/dropbear/
cp -pr /etc/dropbear/dropbear_rsa_host_key ${DESTDIR}/etc/dropbear/
cp -pr /etc/passwd ${DESTDIR}/etc/
cp -pr /etc/shadow ${DESTDIR}/etc/
cp -pr /etc/group ${DESTDIR}/etc/
if [ -e /root/.ssh/authorized_keys ]
then
cp -pr /root/.ssh/authorized_keys ${DESTDIR}/root/.ssh/
fi
cp -pr /etc/nsswitch.conf ${DESTDIR}/etc/
cp -pr /etc/localtime ${DESTDIR}/etc/
cp -pr /lib/tls ${DESTDIR}/lib/
# we don't have bash in our initrd
# also we only add the root account
cat /etc/passwd | grep root | sed s/\\/bash/\\/sh/ > ${DESTDIR}/etc/passwd
cat /etc/shadow | grep root > ${DESTDIR}/etc/shadow
cat /etc/group | grep root > ${DESTDIR}/etc/group
cat >${DESTDIR}/scripts/local-top/network_ssh << 'EOF'
#!/bin/sh
# we start the network and ssh-server
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
# Begin real processing below this line
# build up helpful environment
[ -d /dev ] || mkdir -m 0755 /dev
[ -d /root ] || mkdir --mode=0700 /root
[ -d /tmp ] || mkdir /tmp
[ -d /sys ] || {
mkdir /sys
mount -t sysfs -o nodev,noexec,nosuid none /sys
}
[ -d /proc ] || {
mkdir /proc
mount -t proc -o nodev,noexec,nosuid none /proc
}
mkdir -p /var/lock
mkdir -p /var/log
touch /var/log/lastlog
mkdir /dev/pts
mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts
/bin/sleep 5
################# CHANGE THE LINES BELOW #################
# The network setup: edit ip address and gateway to match your needs
ifconfig eth0 172.16.2.128 netmask 255.255.255.0
route add default gw 172.16.2.2
################# CHANGE THE LINES ABOVE #################
# display the network settings for double check
ifconfig
# If you like to use dhcp make sure you include dhclient or pump in
# /etc/initramfs-tools/hooks/dropbear via
# copy_exec /sbin/dhclient
# for debugging ssh-server you may run it in forgound
# /usr/sbin/dropbear -E -F
# for more debugging you may run it with strace
# therfor you have to include strace and nc at top of
# /etc/initramfs-tools/hooks/dropbear via
# copy_exec /usr/bin/strace
# copy_exec /usr/bin/nc
# then start nc on an other host and run
# /usr/sbin/dropbear -E -F 2>&1 | /bin/nc -vv <ip of="" other="" host=""> <nc port="" of="" other="" host="">
# e.g.:
# /usr/sbin/dropbear -E -F 2>&1 | /bin/nc -vv 192.168.1.2 8888
# We will use /dev/urandom because /dev/random gets easily blocked
mv /dev/random /dev/random.old
ln -s /dev/urandom /dev/random
# /usr/sbin/dropbear -E -F -b /etc/dropbear/banner -d /etc/dropbear/dropbear_dss_host_key -r /etc/dropbear/dropbear_rsa_host_key -p 22
/usr/sbin/dropbear -b /etc/dropbear/banner -d /etc/dropbear/dropbear_dss_host_key -r /etc/dropbear/dropbear_rsa_host_key -p 22
#ls -al
rm -f /dev/random
mv /dev/random.old /dev/random
EOF
chmod 700 ${DESTDIR}/scripts/local-top/network_ssh
cat >${DESTDIR}/etc/dropbear/banner << 'EOF'
To unlock root-partition run
unlock
EOF
# script to unlock luks via ssh
# dirty but effektive
cat >${DESTDIR}/usr/bin/unlock << 'EOF'
#!/bin/sh
/bin/sh /scripts/local-top/cryptroot
# Kill processes locking boot process
[ `ls /dev/mapper/ | grep -v control| wc -l | awk '{print $1}'` -gt 0 ] && {
for i in `ps | grep -E "cryptroot|cryptsetup" | awk '{ print $1 }'`
do
kill $i
done
}
/bin/sh /scripts/local-bottom/rm_dropbear
EOF
chmod 700 ${DESTDIR}/usr/bin/unlock
# make sure we exit dropbear at the end of the startup process
cat >${DESTDIR}/scripts/local-bottom/rm_dropbear << 'EOF'
#!/bin/sh
PREREQ=""
prereqs()
{
echo ""
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
# Begin real processing below this line
# we kill dropbear ssh-server
/usr/bin/killall dropbear
EOF
chmod 700 ${DESTDIR}/scripts/local-bottom/rm_dropbear


Step 0: Enable root login

First, you have to enable the root account.



sudo passwd root


The reason why I say that root must be enabled is, because I couldn't work out how to get the whole sudo permission stuff into the initrd. I'm sure there must be a way and if someone is willing to take up the challenge, please go ahead. However you can enable root login only during the creation of the initrd. Once it's created then the according stuff is saved in there and you can remove root login from the actual installation again. The root login is only required to log into dropbear and then run the unlock script. It's not used for anything else.


Step 1: Install required packages

Install those packages:




sudo apt-get install psmisc busybox dropbear


Step 2: Configure network

In the script change the network configuration to your needs. I have sofar only used static ips. The script itself provides also option for dhcp - however I did not try those.


################# CHANGE THE LINES BELOW #################
# The network setup: edit ip address and gateway to match your needs
ifconfig eth0 172.16.2.128 netmask 255.255.255.0
route add default gw 172.16.2.2
################# CHANGE THE LINES ABOVE #################

The above settings are just the values from my vmware machine on where I tested it.


Step 3: Save the script and make it executable:

Save the altered script to [I]/etc/initramfs-tools/hooks/dropbear[/I] and make it then executable:



sudo chmod +x /etc/initramfs-tools/hooks/dropbear


Step 4: Create new initrd

Run this command to create a new initrd with the name of "netboot". Of course you can rename "netboot" to anything you like.



sudo mkinitramfs -o /boot/netboot


Step 5: Edit /boot/grub/menu.lst and add your new initrd as the first entry

Now you have to edit grub's menu list to add the new init.rd.


Run:



sudo nano /boot/grub/menu.lst


to edit the menu.lst in nano.


Go to the end (or almost) and copy an existing kernel entry e.g.


title           Ubuntu 8.04.1, kernel 2.6.24-19-generic
root (hd0,1)
kernel /vmlinuz-2.6.24-19-generic root=/dev/mapper/sda4_crypt ro quiet splash
initrd /initrd.img-2.6.24-19-generic

Change it to something like:


title           Netboot
root (hd0,1)
kernel /vmlinuz-2.6.24-19-generic root=/dev/mapper/sda4_crypt ro quiet splash
initrd /netboot

Don't copy my example directly but use yours. That way the root hd entry and the mapper name are correct.


Finally, at the top of the menu.lst also change the default boot entry accordingly. If you have 7 kernel entries, then you will put a "6" there because it starts with 0 and you add the netboot one at the bottom.


Step 6: Delete the dropbear script in the hooks folder

When I tried it on my machine, after a kernel upgrade there were some problems (which may have resulted from my earlier tries with a buggy script). Just to make sure, delete the dropbear script from the folder.



sudo rm /etc/initramfs-tools/hooks/dropbear


Step 7: Profit!

That's it... it should be working now.


A few things to mention

- Well, in the script I currently call a ifconfig after the network configuration. I did that for bugtracing. You can of course delete that from the script.


- After you have now created the netboot initrd you can either change the root password again or disable root login. As the initrd is not encrypted it is possible to get the hash of the root password and so you want to use a different one from remote unlocking the crypto drives. I highly recommend changing the password or disabling root login in the actual machine.


Change root password



sudo passwd root


or delete the root password (disable root)



sudo passwd -l root


- Although the system is fully encrypted, there are still two possible attacks left to gain access to the data:


  (1) ColdBoot Attack by reading the crypto password from the ram blocks (not much you can't do against that without special hardware, see here)


  (2) The created initrd can be manipulated so that it logs the crypto password somewhere. As /boot is not encrypted an attacker may gain this way the password for the LUKS-devices. You could, to prevent that, make a bootable cd with the according kernels and initrds and implement some kind of hash check... maybe there are other methods... feedback is welcomed here.


- Most of this tutorial is not from me, just a few adapations and explanations. So thanks goes to Wolfram Coulmann and the others who modified the original script.


Read more...