OpenBSD httpd FastCGI

httpd is the OpenBSD built-in Webserver. It has support for FastCGI which is a protocol that allows Web servers to execute external programs through a FastCGI Server. In OpenBSD, the FastCGI Server is called slowcgi and also is in the default installation. So it is possible to build a dynamic website or API without installing additional packages.

First, we create a simple httpd.conf:

# /etc/httpd.conf
server "default" {
        listen on * port 80

        location "/cgi-bin/*" {
                fastcgi
                root "/"
        }
}

Next, we check the config, enable and start httpd:

rcctl configtest httpd
rcctl enable 
rcctl start httpd

Because we need a FastCGI Server, we also enable and start slowcgi:

rcctl enable slowcgi
rcctl start slowcgi

Shell Example

# /var/www/cgi-bin/shell.cgi
#!/bin/sh

echo "Content-Type: text/html";
echo "";

echo "<html>";
echo "<head>";
echo "<title>Test :)</title>";
echo "</head>";
echo "<body>";
echo "<h1>Test :)</h1>";
echo "</body>";
echo "</html>";

After creating the Script, we need to change the user and group to www because httpd and slowcgi run with that user. We also need to make the script executeable for the user. 500 means read and execute for the User only.

chown www:www /var/www/cgi-bin/shell.cgi
chmod 500 /var/www/cgi-bin/shell.cgi

Because httpd and slowcgi are chrooted to /var/www, they cannot access the whole filesystem. That they can execute the script they need /bin/sh so we need to copy it to /var/www.

cp /bin/sh /var/www/bin/

Now you can open your browser and go to http://[IP]/cgi-bin/shell.cgi to see the Page.

Perl example

You can do a lot with a Shell Script but for bigger things, it is nicer to have a more complete programming language like Perl.

# /var/www/cgi-bin/perl.cgi
#!/usr/bin/perl

print "Content-Type: text/html\n\n";

print "<html>\n";
print "<head>\n";
print "<title>Test :)</title>\n";
print "</head>\n";
print "<body>\n";
print "<h1>Test :)</h1>\n";
print "</body>\n";
print "</html>\n";

Again we need to set the User/Group and the Execute bit like in the Shell example.

chown www:www /var/www/cgi-bin/perl.cgi
chmod 500 /var/www/cgi-bin/perl.cgi

But the interpreter is not as easy as in the Shell example above. Perl needs a lot more.

which perl

ldd /usr/bin/perl
mkdir /var/www/usr
mkdir /var/www/usr/bin
mkdir /var/www/usr/lib
mkdir /var/www/usr/libexec
cp /usr/bin/perl /var/www/usr/bin/perl
cp /usr/lib/libperl.so.23.0 /var/www/usr/lib/libperl.so.23.0
cp /usr/lib/libm.so.10.1 /var/www/usr/lib/libm.so.10.1
cp /usr/lib/libc.so.99.0 /var/www/usr/lib/libc.so.99.0
cp /usr/libexec/ld.so /var/www/usr/libexec/ld.so

Now you can open your browser and go to http://[IP]/cgi-bin/perl.cgi to see the Page.

When I learn things like that, I am always very impressed by how much is possible with the default OpenBSD installation.

04 August 2024 - Philipp Keschl