Comment 30 for bug 308181

Revision history for this message
In , D7dvttp02 (d7dvttp02) wrote :

At the risk of triggering stupendous wrath, but maybe some real discussion, too,
I want to suggest a dastardly hack in lieu of the DNS SRV support envisioned in
this bug report. It seems clear that:

- DNS SRV records have been around for a long time -- even this bug has been
around for a long time, but nobody seems to be implementing it for HTTP, even
though may other, newer protocols have been supporting the DNS SRV records long
since. Even Microsoft can't seem to implement this thing.

- A careful look at the name resolution process might offer an explanation of
why the current SRV proposed standard is not getting implemented in the world of
the interactive web. No matter how you look at it, if you have to query for an
SRV record, and then query for an A record, you have two round trips through the
DNS. Even if everything is working perfectly, the name resolution process will
take (nominally) twice as long if you have to go through an SRV resolution step.
 You could imagine fixing the problem by allowing IP addresses in SRV records
(this is not what the present standard says, and there are in general good
reasons for that), but even then, it is hard to optimize the process of looking
for records that usually won't be there. Negative caching is a hard problem.
(In other words, you have added a full-scale, uncacheable DNS query to every
lousy URL you want to resolve. A web browser that needs to build a complex page
from several URLs would have a hard time presenting a reasonably responsive
experience to the user even if all servers that need to say "no SRV record here"
are configured properly and don't drop the unknown request on the floor.)

- Doing SRV lookups is hard from a programming perspective. It goes against the
grain of the facilities provided in the standard C library. You almost need to
provide an SRV lookup library, and the more libraries you depend on, the less
portable your result.

- Mozilla is the cutting edge of browser development. If we could find a better
way to do it and write an RFC and maybe get Microsoft on board if it was simple
enough, we would have taken care of 95% of browsers out there and the rest would
take care of themselves.

- DNS SRV is wonderful for load balancing, but it's overkill if you just want to
run on an alternate port. (If we can consider the space of TCP and UDP ports to
be part of the address space of an IPv4 network, instead of worrying about
exhausting a 32 bit space, we now have 48 bits, which is a fair amount of
breathing room for the time between now and when IPv6 happens.)

I'm going to propose a simple flag that could be inserted in a set of DNS A
records to indicate that the name describes a service instead of a host and
provide the port where the service can be connected to. It will have the
advantages that:

- It is less than a dozen lines to add (or remove) in only one place,
- It is ridiculously portable,
- It imposes negligible performance/bandwidth/processing penalty/overhead,
- It solves the problem of naming a service on an alternate port, and
- It is safe in that it will not be triggered unexpectedly (keep reading).

Disadvantages:
- I'm proposing it here for the first time (yes, I know I need to write an RFC),
while DNS SRV has been around forever. Then again, it might actually be safe
enough to implement without killing performance.
- It does nothing to address the load balancing issue.
- It is supremely crufty (but look how popular NATs are!)

Let me formalize the idea.

The space of loopback addresses comprises a whole /8 (Class A) network but only
contains one address. However, because of the way it implemented on virtually
all machines, it necessarily gobbles up a full /8 that can never be routed
anywhere on the internet, no matter how much we want the address space back. If
you want to try some weird stuff, add aliases to 127.0.0.2, to 127.0.0.3, and to
the like to your loopback interface. You can't do anything with them, and you
can't really tighten up the subnet mask, either. Therefore, any IP address in
the range 127.0.0.2 to 127.255.255.254 (127.255.255.255 is a loopback
broadcast!) is loony and won't occur as an address to route to on the public
internet except perhaps from machines so grossly misconfigured as to be beyond
the scope of the discussion.

Therefore, it is safe to add A records in the form 127.x.y.z to DNS A record
sets for domain names used only for one service (like www.foo.com) for use as a
flag to indicate special information (in this case, an alternate port) for the
connection. Machines that don't know what to do with the extra information will
try to connect to the weird loopback address in its turn and quickly discover
that it doesn't go anywhere. DNS servers that don't provide the extra
information don't waste anybody's time. And there is practically no chance of
encountering domain name A records that point into this space because they
cannot possibly be useful for anything (that is, unless we define something
useful here). The bonus is that there is practically no penalty to check for it
(which cannot be said about other solutions).

I propose the following definitions for A records in the form 127.x.y.z:
x = 6 (This is the IP protocol number for TCP. It can be generalized to 17 for
UDP later, or maybe even something else. At a minimum, it avoids conflicting
with 127.0.0.1 and 127.255.255.255.)
y = port number divided by 256, discarding remainder
z = remainder of port number divided by 256 (port number modulo 256)

As an example, an A record flag for the name of a webserver that is located on
port 8080 would be 127.6.31.144. A complete example might be:

www IN A 12.23.34.45 ;First IP address on first network
        IN A 54.43.32.21 ;Second IP address on second network
        IN A 127.6.31.144 ;Alternate port flag for NAT

This needs no change in DNS server machinery, routers, operating systems,
standard libraries, or anything except the actual application that uses it. The
actual application (in this case, a web browser) need only have the following
code (here, pseudocode) added in between the call that returns the list of IP
addresses for a domain name and the code that loops through the list of IP
addresses, trying to make a connection:

FOR index = 1 TO A_record_count
IF host_byte_order(A_record[index]) .BITAND. 0xFFFF0000 .EQUALS. 0x7F060000 THEN
connection_port=network_byte_order(to_16_bits(host_byte_order(A_record[index])))
A_record[index] = A_record[A_record_count]
A_record_count = A_record_count - 1
ENDIF
NEXT index

(Mind my one-based arrays if you convert this to C/C++.)

The hack is utterly heinous, I know, and it does nothing about load balancing
(more flags?), but it should be obvious that this approach is unique in its
ability to allow alternate ports with no additional DNS lookup overhead. (You
can't say, "no overhead" if you have to go and lookup another kind of DNS RR,
regardless how cool the RR might be.)

I propose this hack, not because I think that it is better than DNS SRV in
general, but because I think that DNS SRV implementation is stalled in the HTTP
sphere due to irresolvable performance problems, and this might be better than
nothing.

(I'm just looking for a bit of discussion at this point. Implementation, as
above, is trivial, and the above comments could form the basis of an
Experimental RFC. Such a kludge as this really ought to be discussed, however,
before being unilaterally checked into the source tree, no matter how safe it
might be.)