[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Chroot'ed MySQL [Was: Re: Chroot'ed apache + PHP + chroot'ed MySQL - Non-working php-mysql extension, and sendmail]



Hi misc@,

I got quite a few requests on the chroot'ed mysql howto, so I thought
that by posting it on the list, I could also help others in the future
searching the archives.
This howto works on openBSD (tested on 2.8-3.2), but probably works the
same (pwd_mkdb) in the other *BSD's. In Linux you'll have to make a
shadow file (i guess) instead.


Best regards,
  Espen Wang


Here is the Howto:


I'm going to expect that we're using some kinda 2.23 version of mysqld,
as I don't have experience with any other.
I also expect mysql is to be chroot'ed into /var/mysql
Last, I expect user mysql (uid: 93) and group mysql (gid: 93) to exists.


First off, we need to set up the directory structure inside the chroot
I like to set file permissions as tight as possible, and so I do.

[root_(_at_)_bree /]# mkdir /var/mysql
[root_(_at_)_bree /]# chown root.wheel /var/mysql
[root_(_at_)_bree /]# cd /var/mysql
[root_(_at_)_bree mysql]# mkdir etc tmp data
[root_(_at_)_bree mysql]# chown root.wheel etc
[root_(_at_)_bree mysql]# chown root.mysql tmp data
[root_(_at_)_bree mysql]# chmod 711 etc
[root_(_at_)_bree mysql]# chmod 770 tmp data
[root_(_at_)_bree mysql]#

Then, etc/ needs to be populated with a master.passwd and group files
I'll only put user and group "mysql" inside, as everything else is
unneccesary.

The group file is easy:

[root_(_at_)_bree mysql]# cat /var/mysql/etc/group 
mysql:*:93:
[root_(_at_)_bree mysql]# 

The master.passwd is a tiny bit trickier:

[root_(_at_)_bree mysql]# cat /var/mysql/etc/master.passwd 
mysql:*:93:93:daemon:0:0:MySQL Account:/nonexistent:/sbin/nologin
[root_(_at_)_bree mysql]#

Then, we build a passwd database into the etc/ dir, with the following
command:

[root_(_at_)_bree mysql]# pwd_mkdb -sd /var/mysql/etc
/var/mysql/etc/master.passwd
[root_(_at_)_bree mysql]#

We should now get a new file; /var/mysql/etc/spwd.db, and the
permissions on both master.passwd and spwd.db should be set right.
You can now remove master.passwd, but I like to keep it in case I ever
have to change uid or gid. (laziness)

You should now have a directory structure kinda like this:

[root_(_at_)_bree mysql]# ls -la . *
.:
total 10
drwxr-xr-x   5 root  wheel  512 Oct 31 01:10 .
drwxr-xr-x  28 root  wheel  512 Oct 31 00:00 ..
drwxrwx---   6 root  mysql  512 Oct 31 00:43 data
drwx--x--x   2 root  wheel  512 Oct 31 00:34 etc
drwxrwx---   2 root  mysql  512 Oct 31 00:54 tmp

data:
total 4
drwxrwx---  6 root   mysql    512 Oct 31 00:43 .
drwxr-xr-x  5 root   wheel    512 Oct 31 01:10 ..

etc:
total 56
drwx--x--x  2 root  wheel    512 Oct 31 00:34 .
drwxr-xr-x  5 root  wheel    512 Oct 31 01:10 ..
-rw-r--r--  1 root  wheel     12 Oct 31 00:33 group
-rw-------  1 root  wheel     66 Oct 30 23:50 master.passwd
-rw-------  1 root  wheel  40960 Oct 30 23:55 spwd.db

tmp:
total 4
drwxrwx---  2 root   mysql  512 Oct 31 00:54 .
drwxr-xr-x  5 root   wheel  512 Oct 31 01:10 ..
[root_(_at_)_bree mysql]# 

Next is mysql config.
I put all the options into /etc/my.cnf, so I don't have to start mysql
with an infinitive amount of parameters.

[root_(_at_)_bree mysql]# cat /etc/my.cnf
[mysqld]
chroot=/var/mysql
datadir=/var/mysql/data
tmpdir=/tmp
socket=/tmp/mysql.sock
pid-file=/tmp/mysqld.pid
user=mysql
skip-networking
#bind-address=127.0.0.1
skip-innodb

[safe_mysqld]
err-log=/var/log/mysqld.log

[mysqladmin]
socket=/var/mysql/tmp/mysql.sock

[client]
socket=/var/mysql/tmp/mysql.sock
[root_(_at_)_bree mysql]#

chroot and datadir should explain themselves.
tmpdir, socket and pid-file are inside the chroot.
i prefer skip-networking, and only use sockets, but feel free to do
whatever suits your needs.

err-log in [safe_mysqld] makes us able to log to a file outside the
chroot.
socket in [mysqladmin] and [client] tells the two tools where to find
the socket file.

Ofcourse, you can always hard-code the options as default, when
./configure'ing, but I wasn't that clever at the time :)

Now you can populate the data/ dir with your existing databases, if any.
Remember to chown mysql.mysql dir/, and chmod 700 dir/.
To load up mysqld, run this command: /usr/local/bin/safe_mysqld
--defaults-file=/etc/my.cnf &
You should now have a running chroot'ed mysql. If it fails, have a look
at tail /var/log/mysqld.log, and you'll probably find the error.

Don't forget to tell all your mysql-using applications where to find the
socket (PHP, for instance).

Just before you go on playing with your chroot'ed mysql, take the time
to read the following snip from the manpages about the chroot option:
       --chroot=path
              Chroot  mysqld  daemon  during startup. Recommended
              security measure. It will somewhat limit LOAD  DATA
              INFILE and SELECT ... INTO OUTFILE though.


-- 
Espen Wang               /"\
http://www.shells.no/    \ /      ASCII Ribbon Campaign
espen_(_at_)_shells_(_dot_)_no           X  Against HTML Mail and News
dizz_(_at_)_efnet               / \



Visit your host, monkey.org