MySQL takes forever to connect – what is happening?

Just experienced a problem with a MySQL installation, which made all eksternal connections (not to localhost) take a very long time to open, making the MySQL server reach the connection limit and rendering it completely useless.

The problem was that the primary DNS server had died. Apparently MySQL uses reverse DNS when checking connections, by default. This can be turned of my adding skip-name-resolve to the [mysqld] section of the /etc/mysql/my.cnf configuration file and restarting the service.

Setuid on scripts

Running scripts as another user might sound like a trivial task, as this is what setuid is supposed to solve. However, if you create a bash script, a php script or another type of script you will soon discover that they do not respond to the setuid flag. This is mainly because of security and the fact that the scripting languages usually have not implemented the setuid functionality at all.

The easiest way of accomplishing this is to create a wrapper program that runs your script for you. C is a good language for this. The following file is an example on how to run a php as setuid.

Wrapper.c

#include 
#include 
#include 

int main(void) {
    system("/usr/bin/php /home/www-config/bin/createConfig.php");
    return 0;
}

The script can be compiled with cc Wrapper.c -o Wrapper, if you have gcc installed. After compiling, you will need to set the setuid flag on the executable by issuing the chmod u+s Wrapper command. Now you can issue ./Wrapper to run the php script given.

Let’s pretend we have a Linux system with two users good and workaround. Log onto the system as user workaround and create compile Wrapper.c. After issuing chmod u+s Wrapper, do a ls -al and you should see something like the following:

total 40
drwxr-xr-x   4 workaround  workaround    136 Sep 21 11:04 .
drwxr-xr-x  22 workaround  workaround    748 Sep 21 11:03 ..
-rwsr-xr-x   1 workaround  workaround  12588 Sep 21 11:04 Wrapper
-rw-r--r--   1 workaround  workaround    195 Sep 21 11:04 Wrapper.c

Note the highlighted s in the permissions of the Wrapper file, this is the setuid flag. Now log into the good user and run this script. This will now be run as the workaround user, since the setuid flag is set and the file is owned by the workaround user.

You might be tempted to take the script name as an argument. Do not do this, as this severly decreases the security! If you really want to do simething like this, please use predefined commands and give the command line argument as the “command number 3”. This way no malicious user can execute all commands through this script.

For more information, I would recommend this article.

Privilege separation from the www-data user

So, I got a question down in the comment section and will respond to it here for better formatting 🙂 I have the following 3 files.

/home/www-config/bin/createConfig.php

<?php
mkdir("/home/www-config/mytestfolder");
?>

/home/www-config/bin/createConfig.c

#include 
#include 
#include 

int main(void) {
    system("/usr/bin/php /home/www-config/bin/createConfig.php");
    return 0;
}

/home/marius/public_html/test/index.php

<?php
exec("/home/www-config/bin/createConfig");
?>

I have compiled the createConfig.c file and set the setuid bit, as explained in the guide.

ls -al

marius@debiansrv:~/public_html/test$ ls -al /home/www-config/bin/
drwxr-xr-x 2 www-config www-config 4096 Oct 11 11:14 .
drwxr-xr-x 3 www-config www-config 4096 Oct 11 11:14 ..
-rwsr-xr-x 1 www-config www-config 6618 Sep 20 23:08 createConfig
-rwx------ 1 www-config www-config  163 Sep 20 23:08 createConfig.c
-rwx------ 1 www-config www-config   51 Oct 11 11:09 createConfig.php

Here is the output of ls -l before and after I use my browser to visit ~/marius/test/.

ls -l /home/www-config

# Before going to the url
drwxr-xr-x 2 www-config www-config 4096 Oct 11 11:14 bin

# After
drwxr-xr-x 2 www-config www-config 4096 Oct 11 11:14 bin
drwxr-xr-x 2 www-config www-data   4096 Oct 11 11:18 mytestfolder

I also tested this with the root user, which also worked.

Currently the best workaround for the AC3 DTS problem in Lion

This is now quite old and Plex and VLC have updated their API.

As many people have discovered the DTS sound subsystem is badly broken in Mac OS X 10.6.8, 10.7.0 and 10.7.1. When playing videos with AC3 encoded suround sound, the sound subsystem continues to pump out DTS encoded noise through it’s digital ports (spdif and hdmi). You can work around this problem by either restarting or putting the mac to sleep and waking it again.

One possibilty (which I actually currently use) is the nightly builds. These are not guaranteed to work, but the DTS issue have been resolved in these.

However, the best way i found to fix this problem is the following.

  1. Stop playback
  2. Open a Terminal (or ssh into the box)
  3. Run the command sudo killall coreaudiod && sleep 5 && say good workaround (you will be asked for your password)
  4. Start playback

In xbmc it looks although you need to stop the playback, run the command and then start the playback all over.

For the lazy people

Why bother to remember a command and type your password? Do the following.

  1. Open a Terminal
  2. Run the command sudo nano /bin/fixsound
  3. Paste the following file (see the box), and hit Ctrl + O to write the file and Ctrl + X to close it
  4. Run the command sudo chmod 6755 /bin/fixsound

/bin/fixsound

#!/bin/bash
sudo killall coreaudiod && sleep 5 && say good workaround

You should now be able to run the command fixsound to fix your sound!

Dynamic routing in Linux and BSD

Dynamic routing are becomming more and more common these days, but not on the server side. Actually, Windows 2008 Server no longer supports Open Shortest Path First (OSPF), even though 2003 server did. The most common way of implementing dynamic routing in larger networks, are in the Wide Area Network (WAN) between firewalls. In this guide I will show how to use OSPF in Linux by using the Quagga Software Routing Suite.

As usual I use Debian linux, so let’s start by installing Quagga.

apt-get install quagga

That was not very hard. Let’s take a look at the different configuration files located in /etc/quagga/.

/etc/quagga/daemons

This file enables and disables the different services available in the routing suite. There are several supported protocols such as RIP, BGP and OSPF.

zebra=yes
bgpd=no
ospfd=yes
ospf6d=no
ripd=no
ripngd=no
isisd=no

/etc/quagga/zebra.conf

Zebra is the service that transfers configuration from Quagga to the operating system. Zebra takes care of updating interface addresses, routing tables, hostname, etc.

!
hostname server01
log file /var/log/quagga/zebra.log
password cliSecretPassword
!
interface bond0
    ip address 10.0.0.5/24
    multicast
!
interface eth0
!
interface eth1
!
interface lo

As you can clearly see from this configuration file, the server has hostname server01 and has bonded the eth0 and eth1 to a new bond0 interface.

/etc/quagga/ospfd.conf

This file configures the OSPF service. This is not a very advanced setup.

!
service advanced-vty
log file /var/log/quagga/ospfd.log
!
interface bond0
        ip ospf authentication message-digest
        ip ospf message-digest-key 1 md5 SECRETPASS
!

# Loopback
#interface lo
#    ip ospf priority 0
#!

router ospf
        redistribute static
        network 10.0.0.0/24 area 0.0.0.0
        area 0.0.0.0 authentication message-digest

Here the OSPF service is instructed to join area 0.0.0.0 with key 1 set as SECRETPASS. Also, the service redistributes all static routes. In this example, the server is a stub area.

I will be posting more configuration later.

Automating your iptables

Ever wondered how to use iptables on debian, without using any GUI solution? Let me explain how I do it.

Usually I use two files /etc/iptables_secure.sh and /etc/iptables_open.sh. The secure script has firewall enabled, while the open script makes iptables accept all connections. Also, I use /etc/init.d/firewall to start and stop the firewall at boot.

First, start by creating the following three files.

/etc/iptables_secure.sh

#!/bin/sh

IPT="/sbin/iptables"

# Flush old rules, old custom tables
$IPT --flush
$IPT --delete-chain

# Set default policies for all three default chains
$IPT -P INPUT DROP
$IPT -P FORWARD DROP
$IPT -P OUTPUT ACCEPT

# Enable free use of loopback interfaces
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT

# All TCP sessions should begin with SYN
# $IPT -A INPUT -p tcp ! --syn -m state --state NEW -s 0.0.0.0/0 -j DROP

# Accept established connections
$IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

echo "Opening CARP"
$IPT -A INPUT --protocol 112 -j ACCEPT

# Brute force
# Limit the number of ssh connections to 6 per minute
$IPT -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
$IPT -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 6 --rttl --name SSH -j DROP

# Limit the number of ftp connections to 10 per minute
# $IPT -A INPUT -i eth0 -p tcp --dport 21 -m state --state NEW -m recent --set --name FTP
# $IPT -A INPUT -i eth0 -p tcp --dport 21 -m state --state NEW -m recent --update --seconds 60 --hitcount 10 --rttl --name FTP -j DROP

echo "Opening FTP"
$IPT -A INPUT -p tcp --dport 20 -m state --state NEW -j ACCEPT
$IPT -A INPUT -p tcp --dport 21 -m state --state NEW -j ACCEPT
$IPT -A INPUT -p tcp --sport 1024: --dport 1024:  -m state --state ESTABLISHED -j ACCEPT
$IPT -A OUTPUT -p tcp --sport 1024: --dport 1024:  -m state --state ESTABLISHED,RELATED -j ACCEPT


echo "Opening HTTP(S)"
$IPT -A INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT
$IPT -A INPUT -p tcp --dport 443 -m state --state NEW -j ACCEPT

echo "Opening SSH"
$IPT -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT

echo "Opening MySQL"
$IPT -A INPUT -p tcp --dport 3306 -m state --state NEW -j ACCEPT

echo "Opening port 7777 - ocfs2"
$IPT -A INPUT -p tcp --dport 7777 -m state --state NEW -j ACCEPT
$IPT -A INPUT -p udp --dport 7777 -j ACCEPT

echo "Opening NTP"
$IPT -A INPUT -p udp --dport 123 -j ACCEPT
$IPT -A INPUT -p tcp --dport 123 -m state --state NEW -j ACCEPT

# echo "Opening all from same subnet"
# $IPT -A INPUT -p tcp -s 192.168.1.0/24 -m state --state NEW -j ACCEPT

# Accept inbound ICMP messages
echo "Opening ping and traceroute"
$IPT -A INPUT -p ICMP --icmp-type 8 -s 0.0.0.0/0 -j ACCEPT
$IPT -A INPUT -p ICMP --icmp-type 11 -s 0.0.0.0/0 -j ACCEPT

/etc/iptables_open.sh

#!/bin/sh
echo "Opening firewall"
IPT="/sbin/iptables"

# Flush old rules, old custom tables
$IPT --flush
$IPT --delete-chain

# Set default policies for all three default chains
$IPT -P INPUT ACCEPT
$IPT -P FORWARD ACCEPT
$IPT -P OUTPUT ACCEPT

# Enable free use of loopback interfaces
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT

/etc/init.d/firewall

#! /bin/sh
### BEGIN INIT INFO
# Provides:          firewall
# Required-Start:     $portmap
# Required-Stop:
# Should-Start:      udev-mtab
# Default-Start:     2
# Default-Stop:      0 6
# Short-Description:
# Description:
### END INIT INFO

. /lib/init/vars.sh
. /lib/lsb/init-functions

case "$1" in
    start)
        sh /etc/iptables_script.sh
        ;;
    restart|reload|force-reload)
        echo "Error: argument '$1' not supported" >&2
        exit 3
        ;;
    stop)
        sh /etc/iptables_open.sh
        ;;
    *)
        echo "Usage: $0 start|stop" >&2
        exit 3
        ;;
esac

Now use chmod to make /etc/init.d/firewall executable.

chmod +x /etc/init.d/firewall

You should now be able to issue /etc/init.d/firewall start and /etc/init.d/firewall stop in order to enable or disable the firewall. Also, in order to make the firewall start at boot time, issue the following command.

update-rc.d firewall defaults

Ask me if there is something you don’t understand!

Virtual hosting with Apache – the good way

There are so many amazingly bad guides to Apache and virtual hosting, so i decided to create a good one. This guide uses Apache2 running om Debian 6. I will not cover installation and stuff. Also, I cut right to the chase.

First, the NameVirtualHost property should just be declared once, and ports.conf is a good place to have it.

/etc/apache2/ports.conf

NameVirtualHost *:80
Listen 80

Second, do not place all virtual hosts in a single file, that’s not very dynamic. Look at this:

# ls /etc/apache2/sites-*
/etc/apache2/sites-available:
total 8
dr-xr-x--- 2 root           www-data     3896 Jun 26 15:33 .
dr-x------ 5 www-data        www-data     3896 Jun  8 13:15 ..
-rwxr-x--- 1 root           www-data     569  Apr 11 21:51 default
-rwxr-x--- 1 root           www-data     569  Apr 19 11:40 sub1.example.org
-rwxr-x--- 1 root           www-data     569  Apr 19 11:41 sub2.example.org
-rwxr-x--- 1 root           www-data     569  Jun 26 15:25 goodworkaround.com

/etc/apache2/sites-enabled:
total 0
dr-xr-x--- 2 www-data  www-data 3896 Jun 26 15:33 .
dr-x------ 5 www-data  www-data 3896 Jun  8 13:15 ..
lrwxrwxrwx 1 root   root  26 Apr 11 21:52 000-default -> ../sites-available/default
lrwxrwxrwx 1 root   root  41 Apr 19 11:49 sub1.example.org -> ../sites-available/sub1.example.org
lrwxrwxrwx 1 root   root  41 Apr 19 11:50 sub2.example.org -> ../sites-available/sub2.example.org
lrwxrwxrwx 1 root   root  37 Jun 26 15:29 goodworkaround.com -> ../sites-available/goodworkaround.com

So what am I doing that no one else is doing? I am symlinking, and I am splitting each domain or subdomain into separate files. Just use place all the domains in the sites-available folder, and symlink it from sites-enabled. This makes it easy to disable sites temporary, by just removing the symlink and reloading apache. Lets take a look one of those files.

/etc/apache2/sites-available/goodworkaround.com

<VirtualHost *:80>
        ServerAdmin webmaster@goodworkaround.com
        ServerName goodworkaround.com
        # ServerAlias www.goodworkaround.com

        DocumentRoot /home/mariussm/websites/goodworkaround.com

        <Directory />
                Options FollowSymLinks
                AllowOverride None
        </Directory>

        <Directory /home/mariussm/websites/goodworkaround.com>
                Options FollowSymLinks MultiViews
                AllowOverride All
                Order allow,deny
                allow from all
        </Directory>

        ErrorLog ${APACHE_LOG_DIR}/goodworkaround.com.error.log

        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn

        CustomLog ${APACHE_LOG_DIR}/goodworkaround.com.access.log combined

</VirtualHost>

As you can see, it listens on all interfaces (*:80) on port 80, cares only for the hostname goodworkaround.com and has a root folder. So hey, that’s the easy way.