Let me rephrase your question as an example to make sure I've understood it correctly.
You have various services, let's say HTTP, IMAP, LDAP, etc... and you want them all to be reachable by connecting to "example.com" (no subdomain). But those services aren't all on the same host. It would be better if the clients used subdomains like "www.example.com", "imap.example.com", and so on because then you could just map those names in DNS to the appropriate address, but they aren't going to do that (at least some of the time), they're going to use plain "example.com". So whatever host answers at "example.com" is going to have to dispatch requests to the actual host that handles each service.
You can use a plain TCP forwarder, like an xinetd redirect as Sirex suggests, but with that comes all the usual problems of TCP forwarders: on the host that services the request
the IP connection appears to come from the forwarding server, not the original client, so the logs and other things end up wrong.
Application-level proxy servers (reverse proxy) are also an option for those protocols that have them. But you really actually wanted to send the whole TCP/UDP connection to the other server, not introduce a proxy server. Right.
Well, now that Linux supports DNAT for IPv6 you probably want to just use that.
Alternatively, if you are using some kind of hardware load balancer, that can probably do the job for you.
The better alternative would have been DNS SRV records. Those allow clients to look up not just a hostname in the DNS but a hostname + service name together, and get back a raw hostname or IP address plus a port number where they can connect. That allows you to map "example.com" for HTTP to one IP address and "example.com" for LDAP to a different IP address.
Unfortunately, though the SRV record standard is more than 15 years old, it never got much takeup, and clients just don't use it. So it's not an option. Actually, it is frequently used together with a select few protocols like SIP, but virtually all web browsers and IMAP clients and clients for most other protocols completely ignore it.
This question is pretty interesting and I must admit that I've never seen this behavior. In doing some fiddling around to try and understand it better, I took a snippet of nslookup querying for one of my W2K8R2 RDS servers from another W2K8R2 server and I also captured a snippet of an RDP session to the same RDS server from the same test server. Nslookup showed no delay in returning the IPv6 record and the nslookup showed my test server querying for the IPv4 record before querying for the IPv6 record. The time delta in the capture shows no appreciable delay (that I can ascertain) in either query.
EDIT
Now you're on to something.
Make sure you're capturing traffic for the Microsoft 6To4 adapter, otherwise you won't see IPv6:
Here's the nslookup result for my RDS server. Make note of the IPv6 addresses:
Now here's a snippet of my capture:
And finally, here's a snippet from netstat showing the connection:
So clearly, as you've confirmed, DNS resolution isn't the problem. The problem is that the RDP connection prefers IPv6 over IPv4 (which is the default for Windows - Windows prefers IPv6 over IPv4) and because IPv6 isn't functioning properly it's causing the delay (as you've stated) when falling back from IPv6 to IPv4. You could fix this by configuring the clients to prefer IPv4 over IPv6, but I think that would merely be masking the problem. The better solution would be to figure out why IPv6 isn't working and fix that. I don't know enough about IPv6 to help but my guess is that the IPv6 records being returned by DNS are "local" addresses valid only on the subnet where the RDS hosts exist and since the clients are in a different subnet, they can't reach those IPv6 addresses.
Best Answer
You can control address selection with
/etc/gai.conf
. The configuration file is well documented, and already contains the defaults, so you can just begin tweaking.The interesting defaults here are:
The last line gives the lowest preference to all IPv4 addresses.
If you want to give a higher preference to all IPv4, you could change it to:
If you only wanted to give higher preference to specific IPv4 addresses or blocks, you can specify them as well. Remember that you have to use an IPv4-mapped IPv6 in hex.
So, to give preference to 203.0.113.0/24 over all IPv6, you would add:
Restart running applications to have them pick up changes you make.
On Debian derived systems,
/etc/gai.conf
is already present. On Red Hat derived systems, it is absent, but a sample file is located at/usr/share/doc/glibc-common-*/gai.conf
; just copy it to/etc
.