William's random thoughts

General thoughts related to my various projects

Fri, 02 Sep 2011

mod_tcpwrapper -- tcpwrapper support for Lighttpd


As mentioned in a previous post I have recently moved to a Debian squeeze box. This squeeze install is inside of an OpenVZ container so (as far as I know) I can't use tools like fail2ban to edit firewall rules. tcpwrappers works pretty good though as long as your services support it.

I'm already using the denyhosts package to ban people attempting to brute force the ssh service. so I figured I would set up lighty to use tcpwrappers as well.

When I did I found out that lighttpd does not currently have any tcp wrapper support. so I made this little lighttpd module to implement it. Here is the diff between my code and the mod_skeleton.c file it is based off of

wschaub@deep13TP:/tmp/mod_tcpwrapper$ diff -u ../lighttpd-1.4.28/src/mod_skeleton.c mod_tcpwrapper.c 
--- ../lighttpd-1.4.28/src/mod_skeleton.c	2010-08-17 05:04:38.000000000 -0400
+++ mod_tcpwrapper.c	2011-09-02 18:03:26.000000000 -0400
@@ -7,16 +7,15 @@
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
+#include <tcpd.h>
 
 /**
- * this is a skeleton for a lighttpd plugin
- *
- * just replaces every occurance of 'skeleton' by your plugin name
- *
- * e.g. in vim:
- *
- *   :%s/skeleton/myhandler/
+ * mod_tcpwrapper by William Schaub <wschaub@steubentech.com>
+ * This module works like mod_access only it has no configuration parameters
+ * Instead it uses the TCP wrapper library to allow/deny access to the lighttpd
+ * daemon in /etc/hosts.allow and /etc/hosts.deny
  *
+ * This module is under the same license as Lighttpd
  */
 
 
@@ -55,7 +54,7 @@
 }
 
 /* init the plugin data */
-INIT_FUNC(mod_skeleton_init) {
+INIT_FUNC(mod_tcpwrapper_init) {
 	plugin_data *p;
 
 	p = calloc(1, sizeof(*p));
@@ -66,7 +65,7 @@
 }
 
 /* detroy the plugin data */
-FREE_FUNC(mod_skeleton_free) {
+FREE_FUNC(mod_tcpwrapper_free) {
 	plugin_data *p = p_d;
 
 	UNUSED(srv);
@@ -97,12 +96,12 @@
 
 /* handle plugin config and check values */
 
-SETDEFAULTS_FUNC(mod_skeleton_set_defaults) {
+SETDEFAULTS_FUNC(mod_tcpwrapper_set_defaults) {
 	plugin_data *p = p_d;
 	size_t i = 0;
 
 	config_values_t cv[] = {
-		{ "skeleton.array",             NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
+		{ "tcpwrapper.array",             NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
 		{ NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
 	};
 
@@ -130,7 +129,7 @@
 
 #define PATCH(x) \
 	p->conf.x = s->x;
-static int mod_skeleton_patch_connection(server *srv, connection *con, plugin_data *p) {
+static int mod_tcpwrapper_patch_connection(server *srv, connection *con, plugin_data *p) {
 	size_t i, j;
 	plugin_config *s = p->config_storage[0];
 
@@ -148,7 +147,7 @@
 		for (j = 0; j < dc->value->used; j++) {
 			data_unset *du = dc->value->data[j];
 
-			if (buffer_is_equal_string(du->key, CONST_STR_LEN("skeleton.array"))) {
+			if (buffer_is_equal_string(du->key, CONST_STR_LEN("tcpwrapper.array"))) {
 				PATCH(match);
 			}
 		}
@@ -158,10 +157,11 @@
 }
 #undef PATCH
 
-URIHANDLER_FUNC(mod_skeleton_uri_handler) {
+URIHANDLER_FUNC(mod_tcpwrapper_uri_handler) {
 	plugin_data *p = p_d;
 	int s_len;
 	size_t k, i;
+	struct request_info request;
 
 	UNUSED(srv);
 
@@ -169,38 +169,33 @@
 
 	if (con->uri.path->used == 0) return HANDLER_GO_ON;
 
-	mod_skeleton_patch_connection(srv, con, p);
-
-	s_len = con->uri.path->used - 1;
+	mod_tcpwrapper_patch_connection(srv, con, p);
 
-	for (k = 0; k < p->conf.match->used; k++) {
-		data_string *ds = (data_string *)p->conf.match->data[k];
-		int ct_len = ds->value->used - 1;
+	/* init the request struct using the fd of our current connection */
+	request_init(&request, RQ_DAEMON,"lighttpd", RQ_FILE,con->fd, 0);
 
-		if (ct_len > s_len) continue;
-		if (ds->value->used == 0) continue;
-
-		if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
+	/* Fill in the fromhost bits of the request struct */
+	fromhost(&request);
+	/* Access blocked by tcp wrappers */
+	if(!hosts_access(&request)) {
 			con->http_status = 403;
-
 			return HANDLER_FINISHED;
-		}
 	}
 
-	/* not found */
+	/* Access allowed */
 	return HANDLER_GO_ON;
 }
 
 /* this function is called at dlopen() time and inits the callbacks */
 
-int mod_skeleton_plugin_init(plugin *p) {
+int mod_tcpwrapper_plugin_init(plugin *p) {
 	p->version     = LIGHTTPD_VERSION_ID;
-	p->name        = buffer_init_string("skeleton");
+	p->name        = buffer_init_string("tcpwrapper");
 
-	p->init        = mod_skeleton_init;
-	p->handle_uri_clean  = mod_skeleton_uri_handler;
-	p->set_defaults  = mod_skeleton_set_defaults;
-	p->cleanup     = mod_skeleton_free;
+	p->init        = mod_tcpwrapper_init;
+	p->handle_uri_clean  = mod_tcpwrapper_uri_handler;
+	p->set_defaults  = mod_tcpwrapper_set_defaults;
+	p->cleanup     = mod_tcpwrapper_free;
 
 	p->data        = NULL;

You can download a tarball with the source code, config files and instructions as well as pre-compiled modules for i386 and sparc (compiled for Debian squeeze) at this link mod_tcpwrapper.tgz

[/lighttpd] permanent link RSS feed


I retired my last Solaris machine yesterday.


I have been using Solaris (both on the desktop and on the server) mainly on SPARC hardware since the late 90s. I think it was a great platform and still could be if Oracle didn't pretty much own it. Sometime last year they closed Security patches to the public and wanted insane amounts of money per machine just for the ability to download patches.

This web server ran Solaris 10 Until some time after noon yesterday when I moved it to the most recent Debian stable release. I was thinking of making it a FreeBSD server instead but since I have been doing a lot of work on Debian and Debian based systems lately it seems like a nice fit. Particularly with it's long release cycle and long term support with security patches.

I really want to get back into FreeBSD again sometime though, Hopefully I will have an excuse to do so soon.

As far as Debian goes I'm really impressed with it, I've been running it on my old ThinkPad T41 and on my SunBlade 2000 and I really have no complaints about it. It's very well put together and most of the packages are well thought out and integrated into the system. Everything that goes into the system has to follow a strict policy which is well documented, most everything you need by design is installed into /usr/share/doc/packagenamehere. I couldn't be happier, particularly now that I don't have to compile the majority of the packages that I use anymore.

[/solaris] permanent link RSS feed


Archives: