Skip to content

IPv6 and thttpd

thttpd is a simple, small, portable, fast, and secure HTTP server which supports both IPv4 & IPv6.

However one noticable omission in the handling of requests for thttpd is support for the X-Forwarded-For header - which is even noted upo nthe thttpd wikipedia entry.

There is a simple patch floating around which claims to fix this; but as I belatedly noticed tonight it only works for IPv4.

If you look at libhttpd.h of the thttpd source you'll see this:

typedef union {
    struct sockaddr sa;
    struct sockaddr_in sa_in;
#ifdef USE_IPV6
    struct sockaddr_in6 sa_in6;
    struct sockaddr_storage sa_stor;
#endif /* USE_IPV6 */
    } httpd_sockaddr;

As a quick hack I updated this structure to add the following member:

    char real_ip[200];

Now I could update that member when a client connects and later update it as a result of any X-Forwarded-For: headers which might be present in incoming requests. Finally I updated the logging to use this field rather than anything else and the job was complete.

Without this work if you're running as a proxy and you receive an IPv6 connection you'll see it reported as 127.0.0.1.

I'm sure my approach isn't as clean as it could be - due to the extra member- but it will suffice for now.

ObQuote: "This gun you're holding belonged to your father; he could conduct a symphony orchestra with it. " - Wanted

Comments On This Entry

  1. [gravitar] Dancho

    good job!

  2. [gravitar] Jon

    I remember thttpd! In the pre-2.0 apache days, pre hyperthreading, pre multi-core... IIRC it was interesting because it used an internal context switch mechanism to avoid the overheard of process creation. I'm skeptical that this is valuable in modern times. Does it do anything that lighttpd can't do better?

  3. [author] Steve Kemp

    It probably doesn't do anything that lighttpd cannot do - but at the time I decided upon it I was looking for:

    • Small & self-contained.
    • Fast.
    • Support for CGI scripts.

    I run around 10 thttpd instances, one for each virtual host on my system, each running under their own UID in their own chroot jail.

    It might not be the leanest, or best, but I still believe it has value. Still each to their own.