Wednesday, October 31, 2007

MaraDNS Halloween snapshot

I have uploaded a new snapshot of MaraDNS today. This snapshot is a snapshot of the work I have done so far porting Deadwood to Windows. The UDP client works; the TCP client, however, has problems which I am still debugging.

Windows sockets are somewhat different from *NIX sockets; I have been reading the Winsock Programmer's FAQ and have downloaded Visual Studio C++ express with all of the MSDN documentation, which will hopefully give me the Windows version of things like "man 2 select".

Some of the *NIX code looks different since I'm making Deadwood portable. There is not a fcntl() visible in the main code; instead I have a macro, make_socket_nonblock() which does the right thing in both *NIX and Windows. There are some other changes: Sockets are not ints, but SOCKETs in Windows; you don't close() a socket, but closesocket() it. An error for sockets is INVALID_SOCKET. There's no inet_aton(), much less inet_pton(), so I just wrote a wrapper for inet_addr() that acts like inet_pton(). The socket code now looks like a strange mixture of Windows and *NIX socket code, with #defines in DwSocket.h making the Windows code look like *NIX code, and making the *NIX code look like Windows code.

My current project is to fix the TCP code in Windows.

As an aside, XP service pack 2 only has one loopback IP address, but Microsoft has a hotfix that fixes this issue; I needed to do this so I can test MaraDNS when offline.

You know, it's a mystery to me why IPV6, out of its 340282366920938463463374607431768211456 possible IPs, only allocates one for loopback. I mean, they could have allocated 16 IPV6 IPs for loopback; I'm sure 340282366920938463463374607431768211440 IPs is enough for non-loopback use.

Anyway, the latest snapshot can be downloaded here.

- Sam

Monday, October 29, 2007

MaraDNS snapshot update: Deadwood now has TCP support

I have added TCP load balancing support to Deadwood. Let me clarify that: Deadwood now compiles two programs, DwMain, which is the UDP DNS load balancer, and DwTcp, which is currently a general-purpose simple TCP load balancer.

What DwTcp does is quite simple: It listens on a user-settable port (53, or DNS, by default). When a client connects to it, DwTcp connects to the upstream TCP server on a user-settable port (again, 53 by default) and any data the client sends over TCP is sent, unchanged, to the upstream server, and any data upstream sends over TCP is sent, unchanged, back to the client.

DwTcp is currently not DNS-specific. It could be used as a HTTP or even SMTP load balancer. The main problem with DwTcp is, when used as a load balancer, is that the servers behind DwTcp will not be able to determine the IP connections come from--they will see the DwTcp server's IP, and DwTcp does not log connections.

My plan is to integrate the TCP code back in to DwMain, making DwMain both a TCP and UDP DNS load balancer. I have written the DwTcp code in a manner that should not make this too difficult to do.

I also plan on making the TCP code do some useful DNS-specific things. One useful feature, for example, would be to look at the incoming TCP packet. If the request is not an AXFR or IXFR request, send the question over UDP and, if the UDP reply is not truncated, convert the UDP reply back in to a TCP reply. If the packet is truncated, try again over TCP.

However, other things are more important. I am currently working on Winsock support and getting the code to run as a native Windows binary with MinGW32. Both the UDP and TCP code compile in Windows, but the socket() call fails in the TCP code. Since I didn't have Winsock documentation at home, I couldn't resolve the issue.

After finishing that, I want to add ip-based ACL support which will allow the load balancers to restrict the range of IP addresses that can connect to the load balancer.

Thursday, October 25, 2007

MaraDNS snapshot update

Jean-Jacques Sarton and myself have added IPV6 support to Deadwood. This is an optional compile-time flag, since a number of systems don't have IPV6 support yet (Cygwin and Mingw32, *cough* *cough*). In order to enable IPV6 support, add '-DIPV6' to the flags when compiling Deadwood, as in:

export FLAGS='-Os -DIPV6'
make

The IPV6 support adds, in DeLi Linux 0.7.2, 356 bytes to the code when disabled, and 708 bytes to the code when enabled. The binary is now 14,448 bytes in size when compiled in DeLi 0.7.2 with the '-Os' flag, IPv6 disabled, and the binary stripped. With IPv6 enabled, the binary is 14,800 bytes in size. Of course, keep in mind that uClibc is also bigger when it has IPv6 support.

In addition, it would seem that, somewhere in the 1.2 development cycle, I broke the echoing of the RD ("Recursion Desired") bit in the DNS header. This has been restored. Also, looking at that code, I realized it wasn't thread-safe, so I made the code thread safe. Also, it would seme that not only do some brain-dead embedded DNS programs check the RD bit in the DNS header, they also check the RA ("Recursion Available") bit (neither bit should be looked at whem getting a DNS reply, but oh well). So, I've hacked things so MaraDNS replies with a packet with the RA bit off if sending an authoritative reply, and the RA on if sending a recrusive reply. Not 100% ananally RFC-compliant, but should fix the problems seen with braindead DNS programs.

And yes, the RD and RA fixes have been backported to the 1.2 branch, and should be a part of the next 1.2 release (mid-December, barring a critical security problem).

The MaraDNS snapshot can be downloaded here

Monday, October 22, 2007

MaraDNS snapshot update

Well, I've implemented a secure random number generator for the new Deadwood code. Last time, with MaraDNS, I used AES, which became an AES variant in late 2001. The problem with AES is that it may have cache timing issues with some CPUs, since it uses table lookups to get indexes based on key information. I revised the code to work around this, at the expense of making the code about three times slower. Also, the code is fairly large and block ciphers are not the best building block for making random streams.

This time, I am using a new stream cipher/cryptographic hash algorithm called "Radio Gatun". Radio Gatun is a new and novel cryptographic primitive: It's a cryptographic hash that can take an input of any length, and generates, from that input, a hash of any desired length. It's also (if not officially) a stream cipher that can take a key of any desired length.

Radio Gatun is a derivative of a late 1990s stream cipher/hash construction called PANAMA. PANAMA's cryptographic hash creation was broken, but it's (as far as we know) still as secure stream cipher. Radio Gatun is not as fast as PANAMA, but appears (so far) to be both a secure cryptographic hash and a secure stream cipher primitive.

Radio Gatun, in theory, can use words of any length from one bit to 64 bits. In practice, test vectors only exist for the 32-bit and the 64-bit versions of Radio Gatun. The Deadwood code is using the 32-bit version of Radio Gatun, but this can be fairly easily changed to use the 64-bit (or, if one wants, the 16-bit or even 8-bit) version by changing two defines in DwRadioGatun.h, and rewriting the dwr_rng() function.

Radio Gatun is a good deal more compact than AES; the entire library fits in under 2k (2048 bytes) when compiled with -Os; compare this with the 12k or so the AES-derived library uses.

I have also created a basic SQA test, and fixed some bugs. There was a minor bug in the FSM definition that made it so dwood1rc parameters could not have numbers in them, making ipv4_bind_addresses not work; this has been fixed. Another bug is that I did not use the socket bound on port 53 to forward the remote reply back to the local user; this made Dig unhappy, since Dig checks the port number of the reply.

In addition, I have added "DwMain -f dwood1rc" style argument parsing.

Oh, oh, there's some under the hood changes. DwMain.c is now a very small file; DwSocket.c has all of the functions that use socket-specific code (and no functions that don't use socket code) and DwSys.c has the rest of the functions. This way, adding DNS-over-TCP, ipv6, and WinSock support only requires changing the DwSocket.c file.

The DwMain binary, when compiled in DeLi Linux 0.7.2 with the -Os flag and stripped, is currently 14,092 bytes in size.

Friday, October 19, 2007

MaraDNS 1.3.07.06 and 1.3.09 release

Today I release not one, but two versions of MaraDNS: MaraDNS 1.3.07.06 and MaraDNS 1.3.09. These are both beta-test versions of MaraDNS; the changelog is here. Downloads of these versions of MaraDNS are available here (Scroll down to see the 1.3 releases).

I also have made a tiny version of the Radio GatĂșn hash function available under the same license terms as MaraDNS (BSD w/o advertising clause), which is available here.

- Sam

Thursday, October 18, 2007

MaraDNS update; Ubuntu rant

OK, I have uploaded a new snapshot of MaraDNS today. This fixes a bug in the zoneserver where it did not properly inform the user they have an incorrect IP in their mararc file, and also, the Deadwood project now does something useful.

If you look in the directory deadwood-1 off of the Snapshot's directory, you will observe a number of files. This is a working (if very basic) DNS load balancer. Basically, use "make" to compile the code, and then edit the dwood1rc file to configure the load balancer. The dwood1rc file uses the same general format as a mararc file, but only supports the following three parameters:
  1. bind_address This is the IP address we bind to
  2. chroot_dir This is the directory the program will run from
  3. upstream_servers["."] this is a list of DNS servers that the load balancer will try to contact
Basically, what the server does is listen on the address specified in bind_address. When it gets a DNS query, it will make sure this query is a query (an not an answer), then send the query, as is, to one of the servers listed in upstream_servers["."]. It will then wait up to 7 seconds for an answer from the upstream server. When it gets a reply, it sets the "this is an answer" DNS bit, then sends the reply back to the original client.

The load balancer can only handle 32 pending replies from the upstream server before it will no longer process incoming replies. When the server is overload, it currently silently drops packets.

No attempt is made to randomize the query ID nor the source port of the query when forwarding the query.

Only ipv4 is supported; there is no ipv6 support. Only DNS-over-UDP is support; DNS-over-TCP is not supported.

I plan on, before moving on to implement caching, to add support for randomized query IDs and source ports, to add user-configurable maximum wait time and maximum allowed number of pending queries, to have the server send "server fail" DNS messages if the load balancer is overloaded, and supporting DNS-over-TCP.

In the meantime, people may want to look at the Deadwood code and give me suggestions on how I can improve this code. As always, the snapshot can be downloaded here


It would seem that Ubuntu does not come with a firewall by default. Ugh. I'm really disappointed that, not only does Ubuntu install a bunch of services that bind to ports, but they don't bother to install a firewall to protect the system. This is really insecure. What I have done is go in to /etc/rc2.d and turn off all of the services that bind to ports. I have also downloaded an article on installing a firewall in Ubuntu, and am working on getting a firewall going.

In the 1990s, RedHat had a lot of security problems. They finally woke up and RedHat and Fedora now come with a firewall when you install the OS. Ubuntu needs to learn from RedHat's lesson.

Wednesday, October 17, 2007

MaraDNS snapshot update

Jean-Jacques Sarton has added the ability for askmara-tcp to send IPv6 packets. I haven't tested the code, but MaraDNS compiles without any warnings. The updated snapshot can be downloaded here