From Matt Harrington on Sun, 02 Jan 2000 on the SAGE (USENIX Sysadmin's Guild) list
is the following true or false?
a client talks to a nameserver on port 53/tcp. the nameserver answers back on a random udp port greater than 1023.
It is false. An FAQ that will answer your question is at:
http://www.intac.com/~cdp/cptd-faq/section2.html#ports
... However, I'll also add some detail here.
First point: normal DNS resolution occurs over UDP.
The usual sequence for a UNIX client is something like this:
The application executes a call to "gethostbyname()" (a standard library function, which is linked into the libc on almost any UNIX platform). gethostbyname() in glibc (Linux libc version 6.x) is implemented to look at the contents of your /etc/nsswitch.conf file, and apply a set of rules from that to load NSS (name services systems) libraries. Most Linux systems are configured to use libnsscompat.so --- which uses NIS/NIS+, DNS and traditional UNIX files (/etc/hosts, /etc/networks). You can see all of the NSS libraries on most Linux systems using the command:
ls /lib/libnss*
... although you might have to look at the contents of /etc/ld.so.conf for a list of other directories in which other libnss libraries might exist.
Entries in /etc/nsswitch.conf will refer to these libraries (take the basename of the library file and trim off the "libnss" prefix to relate library name to the nsswitch.conf keyword).
Before I get back to describing the DNS IP protocols (your question) I'll mention that all this complexity and redirection is actually useful since it allows an admin to configure his Linux (or other GNU system) to use files, DNS, NIS, NIS+, as well as more obscure Hesiod, and new LDAP and NDS naming/directory services without having to recompiling any of the standard utilities on any system.
It's also important to realize that the Linux and UNIX doesn't have any sort of "resolver daemon" nor is this a function of the kernel (a system call or device driver or anything like that). This is just a set of libraries to which almost all other applications are linked.
When the system is configured to use DNS (as they almost all are) then the library functions open and read the /etc/resolv.conf file. This gives a list of DNS servers to which the resolver will direct its initial queries.
The query will be over UDP, with an arbitrary unprivileged source port and a destination port of 53 (which is the DNS query port listed in your /etc/services file).
The initial response should come from one of the DNS servers as listed in /etc/resolv.conf, and be directed back to (have a destination port equal to) the source of the query. The source of the response should also be port 53.
Notice that I mentioned "initial" queries and responses. That's because the DNS protocol allows a server to refer the client to some other DNS server. Thus there may be an initial response that amounts to: "I don't know, go ask ..."
Thus the standard packet filtering rules that you're thinking about require one to allow UDP traffic from port 53 to any unprivileged port in your domain.
Naturally this seems a bit too loose. One approach is to have the firewall track outstanding DNS requests maintaining a context state and only permitting responses back to host/port pairs that have outstanding DNS queries. This is call "stateful" packet inspection and it is one of the features that distinguishes a "firewall" from a simple "packet filter."
(Actually I hate to use the term "firewall" because it is so nebulous. However, I have to simplify a bit or I can't say anything).
A better approach is to configure your caching name server(s) so they never forward clients to other name servers. Thus you can have one or more "sacrificial" caching nameservers on your perimeter network, allow all DNS traffic to those, and have a set of rules on the interior router/packet filters that allows all DNS traffic from those to your hosts.
This is the architecture I recommend.
i can't seem to find the answer in various o'reilly books. of course, someone walked off with the DNS one.
the reason i ask is that i'm trying to write a cisco access list which blocks all traffic to my subnet. i still want to talk to the nameservers though, which are on another subnet. note: i don't even have access to the router. i'm just trying to make it easy for the overworked network guys to put this filter in place.
DNS only seems to work if the following line is in place...
access-list ### permit udp host ip.of.name.server any gt 1023
---matt
You could restrict this to require that the packets come from port 53.
Implicitly you are trying to use the architecture that I've recommended above. You're trying to limit the DNS traffic that comes into your subnet so that it all comes from a particular name server.
Note that this requires that you configure your caching name server so that it never "forwards" DNS requests (tells the client to go ask a different server). This is done by configuring the caching name server with it's own "forwarders" directive (providing it with a list of some nearby "better connected" nameservers), and by using the "slave" directive in BIND 8.x.
Hope that explains it O.K. If not you might consider posting a more detailed question to "Ask Mr. DNS" at Acme Byte and Wire (http://www.acmebw.com/askmr.htm).
Robert Hajime Lanning answered on Sun, 02 Jan 2000 on the SAGE (USENIX Sysadmin's Guild) list
Hmm. That message was to the SAGE (USENIX Sysadmin's Guild) (http://www.usenix.org/sage) list, and not to my "Answer Guy" persona as I'd initially thought.
DNS is udp not tcp
Zone transfers can be tcp.
Request: client (libresolv) random above 1023 -> server (named) port 53
Response: server port 53 -> client same port that request was sent from
name server to name server: 53 -> 53 53 <- 53
Mr. Robert Hajime Lanning answered Matt's question before I did. However, I didn't see that until I got further through my inbox.
Jim Duncan answered on Sun, 02 Jan 2000 on the SAGE (USENIX Sysadmin's Guild) list
Matt Harrington writes: is the following true or false?
a client talks to a nameserver on port 53/tcp. the nameserver answers back on a random udp port greater than 1023.
False. The nameserver should answer back to the source port of the query.
i can't seem to find the answer in various o'reilly books. of course, someone walked off with the DNS one.
the reason i ask is that i'm trying to write a cisco access list which blocks all traffic to my subnet. i still want to talk to the nameservers though, which are on another subnet. note: i don't even have access to the router. i'm just trying to make it easy for the overworked network guys to put this filter in place.
DNS only seems to work if the following line is in place...
access-list ### permit udp host ip.of.name.server any gt 1023
RFC 2181, Clarifications to the DNS Specification, says:
4.2. Port Number Selection
Replies to all queries must be directed to the port from which they were sent. When queries are received via TCP this is an inherent part of the transport protocol. For queries received by UDP the server must take note of the source port and use that as the destination port in the response. Replies should always be sent from the port to which they were directed. Except in extraordinary circumstances, this will be the well known port assigned for DNS queries [RFC1700].
So this means if the query came in to port 53 from source port nnnnn, it must go back out to port nnnnn, source port 53. And almost always, the destination port inbound and source port outbound will be 53.
If your goal is to allow outside resolvers and servers to query your own name servers, then you need to allow port 53, both UDP and TCP, through to the IP address of your name server, e.g.,
access-list ### permit udp host ip.of.name.server eq domain any access-list ### permit tcp host ip.of.name.server eq domain any
Why tcp? Because if the response is too large for a UDP packet, the rules say to retry using TCP. Also, TCP is typically used for zone transfers.
Some folks know the second rule but not the first -- a little knowledge is a dangerous thing -- and so they apply two rules like this:
access-list ### permit udp host ip.of.name.server eq domain any access-list ### permit tcp host ip.of.name.server eq domain host secondary.name.server
They may have additional lines like the second, one for each secondary name server providing fallback for their primary zones. But this is wrong because it neglects the case where TCP is called into play because the UDP response is too big for a single packet, and then things will begin to fail in strange ways.
I should point out that some folks may never see this behavior because they never see a response too big for UDP. Also, while there are a small number of different servers out there, there are a multitude of resolvers, and many of them are broken or not fully tested for situations like this. It's possible that if the response it too big, the resolver may break anyhow, regardless of the access-list configuration on the Cisco router.
It's easier, by the way, to provide access as in the first examples I list above because you're explicitly allowing the access to domain name service on the name server on the inbound interface. That's better than opening up a huge range of ports, outbound, to do the inverse with "gt 1023".
Hope this helps.
Jim
1 | 2 | 3 | 5 | |||||
5 | 6 | 7 | 8 | 9 | ||||
10 | 11 | 13 | 14 | 15 | 16 | 17 | ||
18 | 19 | 20 | 21 | 22 | 23 | 24 | ||
26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | |
34 | 36 | 37 | 38 | 39 | 42 | 41 | ||
42 | 43 | 44 | 45 | 46 | 47 | 48 |